Skip to content

Commit 1e7bb2a

Browse files
committed
make content nonoptional, add server-side forward type shim
1 parent 3975c1a commit 1e7bb2a

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

src/client/index.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,7 @@ describe('outputSchema validation', () => {
843843
if (request.params.name === 'test-tool') {
844844
return {
845845
structuredContent: { result: 'success', count: 42 },
846+
content: [], // compatibility: remove in 1.12+
846847
};
847848
}
848849
throw new Error('Unknown tool');
@@ -918,6 +919,7 @@ describe('outputSchema validation', () => {
918919
// Return invalid structured content (count is string instead of number)
919920
return {
920921
structuredContent: { result: 'success', count: 'not a number' },
922+
content: [], // compatibility: remove in 1.12+
921923
};
922924
}
923925
throw new Error('Unknown tool');
@@ -1155,6 +1157,7 @@ describe('outputSchema validation', () => {
11551157
created: '2023-01-01T00:00:00Z',
11561158
},
11571159
},
1160+
content: [], // compatibility: remove in 1.12+
11581161
};
11591162
}
11601163
throw new Error('Unknown tool');
@@ -1235,6 +1238,7 @@ describe('outputSchema validation', () => {
12351238
name: 'John',
12361239
extraField: 'not allowed',
12371240
},
1241+
content: [], // compatibility: remove in 1.12+
12381242
};
12391243
}
12401244
throw new Error('Unknown tool');

src/server/mcp.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,36 @@ import {
4040
ServerRequest,
4141
ServerNotification,
4242
ToolAnnotations,
43+
ResultSchema,
44+
ContentListSchema,
45+
CallToolUnstructuredResultSchema,
46+
Infer,
4347
} from "../types.js";
4448
import { Completable, CompletableDef } from "./completable.js";
4549
import { UriTemplate, Variables } from "../shared/uriTemplate.js";
4650
import { RequestHandlerExtra } from "../shared/protocol.js";
4751
import { Transport } from "../shared/transport.js";
4852

53+
/**
54+
* In SDK versions 1.12 and forward, the `content` array will be optional for structured
55+
* tool call results. For convenience we use this type for defining tool callbacks on the
56+
* server side, but provide a backward-compatible schema for the client in 1.11.
57+
*/
58+
const CallToolStructuredResultSchema_forward = ResultSchema.extend({
59+
structuredContent: z.object({}).passthrough(),
60+
content: z.optional(ContentListSchema),
61+
isError: z.optional(z.boolean()),
62+
});
63+
64+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
65+
const CallToolResultSchema_forward = z.union([
66+
CallToolUnstructuredResultSchema,
67+
CallToolStructuredResultSchema_forward,
68+
]);
69+
70+
type CallToolResult_forward = Infer<typeof CallToolResultSchema_forward>;
71+
72+
4973
/**
5074
* High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
5175
* For advanced usage (like sending notifications or setting custom request handlers), use the underlying
@@ -153,7 +177,7 @@ export class McpServer {
153177
);
154178
}
155179

156-
let result: CallToolResult;
180+
let result: CallToolResult_forward;
157181

158182
if (tool.inputSchema) {
159183
const parseResult = await tool.inputSchema.safeParseAsync(
@@ -236,7 +260,7 @@ export class McpServer {
236260
}
237261
}
238262

239-
return result;
263+
return result as CallToolResult;
240264
},
241265
);
242266

@@ -1009,8 +1033,8 @@ export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
10091033
? (
10101034
args: z.objectOutputType<Args, ZodTypeAny>,
10111035
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
1012-
) => CallToolResult | Promise<CallToolResult>
1013-
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
1036+
) => CallToolResult_forward | Promise<CallToolResult_forward>
1037+
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult_forward | Promise<CallToolResult_forward>;
10141038

10151039
export type RegisteredTool = {
10161040
description?: string;

src/types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -924,14 +924,14 @@ export const CallToolStructuredResultSchema = ResultSchema.extend({
924924
/**
925925
* A list of content objects that represent the result of the tool call.
926926
*
927-
* If the Tool defines an outputSchema, this field MAY be present in the result.
927+
* Per the spec, if the Tool defines an outputSchema, this field MAY be present in the result.
928928
*
929-
* Tools may use this field to provide compatibility with older clients that
930-
* do not support structured content.
929+
* In this SDK we automatically generate backwards-compatible `content` for older clients,
930+
* so we define this field as non-optional for backwards compatibility in SDK versions 1.11.*.
931931
*
932932
* Clients that support structured content should ignore this field.
933933
*/
934-
content: z.optional(ContentListSchema),
934+
content: ContentListSchema,
935935

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

1322-
type Infer<Schema extends ZodTypeAny> = Flatten<z.infer<Schema>>;
1322+
export type Infer<Schema extends ZodTypeAny> = Flatten<z.infer<Schema>>;
13231323

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

0 commit comments

Comments
 (0)