Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/client/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ describe('outputSchema validation', () => {
if (request.params.name === 'test-tool') {
return {
structuredContent: { result: 'success', count: 42 },
content: [], // compatibility: remove in 1.12+
};
}
throw new Error('Unknown tool');
Expand Down Expand Up @@ -918,6 +919,7 @@ describe('outputSchema validation', () => {
// Return invalid structured content (count is string instead of number)
return {
structuredContent: { result: 'success', count: 'not a number' },
content: [], // compatibility: remove in 1.12+
};
}
throw new Error('Unknown tool');
Expand Down Expand Up @@ -1155,6 +1157,7 @@ describe('outputSchema validation', () => {
created: '2023-01-01T00:00:00Z',
},
},
content: [], // compatibility: remove in 1.12+
};
}
throw new Error('Unknown tool');
Expand Down Expand Up @@ -1235,6 +1238,7 @@ describe('outputSchema validation', () => {
name: 'John',
extraField: 'not allowed',
},
content: [], // compatibility: remove in 1.12+
};
}
throw new Error('Unknown tool');
Expand Down
32 changes: 28 additions & 4 deletions src/server/mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,36 @@ import {
ServerRequest,
ServerNotification,
ToolAnnotations,
ResultSchema,
ContentListSchema,
CallToolUnstructuredResultSchema,
Infer,
} from "../types.js";
import { Completable, CompletableDef } from "./completable.js";
import { UriTemplate, Variables } from "../shared/uriTemplate.js";
import { RequestHandlerExtra } from "../shared/protocol.js";
import { Transport } from "../shared/transport.js";

/**
* In SDK versions 1.12 and forward, the `content` array will be optional for structured
* tool call results. For convenience we use this type for defining tool callbacks on the
* server side, but provide a backward-compatible schema for the client in 1.11.
*/
const CallToolStructuredResultSchema_forward = ResultSchema.extend({
structuredContent: z.object({}).passthrough(),
content: z.optional(ContentListSchema),
isError: z.optional(z.boolean()),
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const CallToolResultSchema_forward = z.union([
CallToolUnstructuredResultSchema,
CallToolStructuredResultSchema_forward,
]);

type CallToolResult_forward = Infer<typeof CallToolResultSchema_forward>;


/**
* High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
* For advanced usage (like sending notifications or setting custom request handlers), use the underlying
Expand Down Expand Up @@ -153,7 +177,7 @@ export class McpServer {
);
}

let result: CallToolResult;
let result: CallToolResult_forward;

if (tool.inputSchema) {
const parseResult = await tool.inputSchema.safeParseAsync(
Expand Down Expand Up @@ -236,7 +260,7 @@ export class McpServer {
}
}

return result;
return result as CallToolResult;
},
);

Expand Down Expand Up @@ -1009,8 +1033,8 @@ export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
? (
args: z.objectOutputType<Args, ZodTypeAny>,
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
) => CallToolResult | Promise<CallToolResult>
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
) => CallToolResult_forward | Promise<CallToolResult_forward>
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult_forward | Promise<CallToolResult_forward>;

export type RegisteredTool = {
description?: string;
Expand Down
10 changes: 5 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -924,14 +924,14 @@ export const CallToolStructuredResultSchema = ResultSchema.extend({
/**
* A list of content objects that represent the result of the tool call.
*
* If the Tool defines an outputSchema, this field MAY be present in the result.
* Per the spec, if the Tool defines an outputSchema, this field MAY be present in the result.
*
* Tools may use this field to provide compatibility with older clients that
* do not support structured content.
* In this SDK we automatically generate backwards-compatible `content` for older clients,
* so we define this field as non-optional for backwards compatibility in SDK versions 1.11.*.
*
* Clients that support structured content should ignore this field.
*/
content: z.optional(ContentListSchema),
content: ContentListSchema,

/**
* Whether the tool call ended in an error.
Expand Down Expand Up @@ -1319,7 +1319,7 @@ type Flatten<T> = T extends Primitive
? { [K in keyof T]: Flatten<T[K]> }
: T;

type Infer<Schema extends ZodTypeAny> = Flatten<z.infer<Schema>>;
export type Infer<Schema extends ZodTypeAny> = Flatten<z.infer<Schema>>;

/* JSON-RPC types */
export type ProgressToken = Infer<typeof ProgressTokenSchema>;
Expand Down