Skip to content

Commit e226f6d

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

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-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: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,35 @@ 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+
const CallToolResultSchema_forward = z.union([
65+
CallToolUnstructuredResultSchema,
66+
CallToolStructuredResultSchema_forward,
67+
]);
68+
69+
type CallToolResult_forward = Infer<typeof CallToolResultSchema_forward>;
70+
71+
4972
/**
5073
* High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
5174
* For advanced usage (like sending notifications or setting custom request handlers), use the underlying
@@ -153,7 +176,7 @@ export class McpServer {
153176
);
154177
}
155178

156-
let result: CallToolResult;
179+
let result: CallToolResult_forward;
157180

158181
if (tool.inputSchema) {
159182
const parseResult = await tool.inputSchema.safeParseAsync(
@@ -236,7 +259,7 @@ export class McpServer {
236259
}
237260
}
238261

239-
return result;
262+
return result as CallToolResult;
240263
},
241264
);
242265

@@ -1009,8 +1032,8 @@ export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
10091032
? (
10101033
args: z.objectOutputType<Args, ZodTypeAny>,
10111034
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
1012-
) => CallToolResult | Promise<CallToolResult>
1013-
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
1035+
) => CallToolResult_forward | Promise<CallToolResult_forward>
1036+
: (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult_forward | Promise<CallToolResult_forward>;
10141037

10151038
export type RegisteredTool = {
10161039
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)