Skip to content

Commit 10591e7

Browse files
committed
feat: rename sendToolResult to sendResult and enhance input schema handling
- Renamed global.sendToolResult to global.sendResult for clarity. - Updated type definitions and documentation to reflect the new function name. - Introduced expandSimpleSchema function to normalize input schemas, improving parameter handling in the params function. - Enhanced examples in type definitions to demonstrate new shorthand schema usage.
1 parent e0fb40d commit 10591e7

File tree

4 files changed

+78
-14
lines changed

4 files changed

+78
-14
lines changed

src/api/kit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ global.sendResponse = (body: any, headers: Record<string, string> = {}) => {
318318
return global.sendWait(Channel.RESPONSE, response)
319319
}
320320

321-
global.sendToolResult = (content: string | CallToolResult) => {
321+
global.sendResult = (content: string | CallToolResult) => {
322322
// Format content according to MCP tool result specification
323323
let toolResult: CallToolResult;
324324

src/api/params.ts

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Tool } from '@modelcontextprotocol/sdk/types'
22

3-
// Extract the inputSchema type from the Tool type
3+
// Define InputSchema type matching MCP SDK specification
44
export type InputSchema = Tool['inputSchema']
55

66
// Re-export for convenience
@@ -18,9 +18,67 @@ function getParameterInfo(schema: InputSchema, name: string): any {
1818
return schema.properties[name] || {}
1919
}
2020

21+
// Helper to convert a "simple" schema (e.g. { name: "User name" })
22+
// into a full JSON-Schema compliant InputSchema. A value can be:
23+
// - string → treated as { type: "string", description: value }
24+
// - number → treated as { type: "number", description: String(value), default: value }
25+
// - boolean → treated as { type: "boolean", description: "", default: value }
26+
// - array → treated as { type: "array", description: "", default: value }
27+
// - object → assumed to already be a schema fragment for that property
28+
function expandSimpleSchema(simple: Record<string, any>): InputSchema {
29+
const properties: Record<string, any> = {}
30+
const required: string[] = []
31+
32+
for (const [key, val] of Object.entries(simple)) {
33+
// Skip special keys that would exist on a full schema
34+
if (key === 'type' || key === 'properties' || key === 'required') continue
35+
36+
let propSchema: any
37+
38+
if (typeof val === 'string') {
39+
propSchema = { type: 'string', description: val }
40+
required.push(key)
41+
} else if (typeof val === 'number') {
42+
propSchema = { type: 'number', description: String(val), default: val }
43+
required.push(key)
44+
} else if (typeof val === 'boolean') {
45+
propSchema = { type: 'boolean', description: '', default: val }
46+
required.push(key)
47+
} else if (Array.isArray(val)) {
48+
propSchema = { type: 'array', description: '', default: val }
49+
required.push(key)
50+
} else if (typeof val === 'object' && val !== null) {
51+
// Assume user provided a detailed schema for this property
52+
propSchema = val
53+
required.push(key)
54+
} else {
55+
// Fallback to string type
56+
propSchema = { type: 'string' }
57+
required.push(key)
58+
}
59+
60+
properties[key] = propSchema
61+
}
62+
63+
const fullSchema: InputSchema = {
64+
type: 'object',
65+
properties,
66+
}
67+
if (required.length) fullSchema.required = required
68+
return fullSchema
69+
}
70+
2171
export async function params<T = Record<string, any>>(
2272
inputSchema: InputSchema
2373
): Promise<T> {
74+
// Normalise input schema: if no properties exist we treat it as shorthand
75+
let schema: InputSchema
76+
if (inputSchema && (inputSchema as any).properties) {
77+
schema = inputSchema
78+
} else {
79+
schema = expandSimpleSchema(inputSchema as unknown as Record<string, any>)
80+
}
81+
2482
// Check if we're being called via MCP headers
2583
if (global.headers?.['X-MCP-Parameters']) {
2684
try {
@@ -32,7 +90,7 @@ export async function params<T = Record<string, any>>(
3290
}
3391

3492
// Check if all parameters are in headers (fallback)
35-
const parameterNames = getParameterNames(inputSchema)
93+
const parameterNames = getParameterNames(schema)
3694
if (
3795
global.headers &&
3896
parameterNames.length > 0 &&
@@ -54,10 +112,10 @@ export async function params<T = Record<string, any>>(
54112
}
55113

56114
// Parse CLI parameters
57-
const cliParams = await parseCliParameters(inputSchema)
58-
115+
const cliParams = await parseCliParameters(schema)
116+
59117
// Prompt for missing parameters
60-
return await promptForMissingParameters(inputSchema, cliParams || {})
118+
return await promptForMissingParameters(schema, cliParams || {})
61119
}
62120

63121
async function parseCliParameters<T>(schema: InputSchema): Promise<T | null> {
@@ -125,18 +183,18 @@ async function promptForMissingParameters<T>(schema: InputSchema, existingParams
125183
// Only prompt for parameters that are missing
126184
for (const [name, propSchema] of Object.entries(schema.properties)) {
127185
const paramInfo = propSchema as any
128-
186+
129187
// Skip if parameter already has a value
130188
if (result[name] !== undefined) {
131189
continue
132190
}
133-
191+
134192
// Skip if parameter has a default value and is not required
135193
if (paramInfo.default !== undefined && !requiredParams.includes(name)) {
136194
result[name] = paramInfo.default
137195
continue
138196
}
139-
197+
140198
// Prompt for missing parameter
141199
if (paramInfo.type === "string" && paramInfo.enum) {
142200
// Use select for enums

src/types/kit.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,12 @@ declare global {
13671367
* Returns the parameters when called, similar to arg() but with structured schema
13681368
* @example
13691369
* ```ts
1370+
* // --- Simple shorthand schema ---
1371+
* const { name } = await params({
1372+
* name: "Your name"
1373+
* })
1374+
*
1375+
* // --- Full JSON-Schema style ---
13701376
* const { operation, a, b } = await params({
13711377
* type: "object",
13721378
* properties: {
@@ -1380,7 +1386,7 @@ declare global {
13801386
* },
13811387
* required: ["operation", "a", "b"]
13821388
* })
1383-
*
1389+
*
13841390
* const result = operation === "add" ? a + b : a - b
13851391
* await sendResponse({ result })
13861392
* ```

src/types/kitapp.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,26 +1304,26 @@ declare global {
13041304
* @example
13051305
* ```ts
13061306
* // Send a simple string result
1307-
* await sendToolResult("Hello from MCP tool!")
1307+
* await sendResult("Hello from MCP tool!")
13081308
*
13091309
* // Send a structured MCP result
1310-
* await sendToolResult({
1310+
* await sendResult({
13111311
* content: [{
13121312
* type: 'text',
13131313
* text: 'Processed successfully'
13141314
* }]
13151315
* })
13161316
*
13171317
* // Send multiple content items
1318-
* await sendToolResult({
1318+
* await sendResult({
13191319
* content: [
13201320
* { type: 'text', text: 'Analysis complete.' },
13211321
* { type: 'image', data: imageBase64, mimeType: 'image/png' }
13221322
* ]
13231323
* })
13241324
* ```
13251325
*/
1326-
var sendToolResult: (content: string | CallToolResult) => Promise<any>
1326+
var sendResult: (content: string | CallToolResult) => Promise<any>
13271327
var sendWaitLong: (channel: Channel, value?: any, timeout?: number) => Promise<any>
13281328

13291329
var setFocused: SetFocused

0 commit comments

Comments
 (0)