Skip to content

Commit 265ad07

Browse files
ihrprbhosmer-ant
authored andcommitted
make content required
1 parent 69dbfac commit 265ad07

6 files changed

+52
-62
lines changed

src/examples/client/parallelToolCallsClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async function main(): Promise<void> {
6161
// Log the results from each tool call
6262
for (const [caller, result] of Object.entries(toolResults)) {
6363
console.log(`\n=== Tool result for ${caller} ===`);
64-
result.content?.forEach((item: { type: string; text?: string; }) => {
64+
result.content.forEach((item: { type: string; text?: string; }) => {
6565
if (item.type === 'text') {
6666
console.log(` ${item.text}`);
6767
} else {

src/examples/client/simpleStreamableHttp.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,12 @@ async function terminateSession(): Promise<void> {
264264
console.log('Terminating session with ID:', transport.sessionId);
265265
await transport.terminateSession();
266266
console.log('Session terminated successfully');
267-
267+
268268
// Check if sessionId was cleared after termination
269269
if (!transport.sessionId) {
270270
console.log('Session ID has been cleared');
271271
sessionId = undefined;
272-
272+
273273
// Also close the transport and clear client objects
274274
await transport.close();
275275
console.log('Transport closed after session termination');
@@ -341,7 +341,7 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<vo
341341
});
342342

343343
console.log('Tool result:');
344-
result.content?.forEach(item => {
344+
result.content.forEach(item => {
345345
if (item.type === 'text') {
346346
console.log(` ${item.text}`);
347347
} else {
@@ -456,7 +456,7 @@ async function cleanup(): Promise<void> {
456456
console.error('Error terminating session:', error);
457457
}
458458
}
459-
459+
460460
// Then close the transport
461461
await transport.close();
462462
} catch (error) {

src/examples/client/streamableHttpWithSseFallbackClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ async function startNotificationTool(client: Client): Promise<void> {
173173
const result = await client.request(request, CallToolResultSchema);
174174

175175
console.log('Tool result:');
176-
result.content?.forEach(item => {
176+
result.content.forEach(item => {
177177
if (item.type === 'text') {
178178
console.log(` ${item.text}`);
179179
} else {

src/examples/server/mcpServerOutputSchema.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ server.registerTool(
2020
"get_weather",
2121
{
2222
description: "Get weather information for a city",
23-
inputSchema:{
23+
inputSchema: {
2424
city: z.string().describe("City name"),
2525
country: z.string().describe("Country code (e.g., US, UK)")
2626
},
@@ -46,10 +46,11 @@ server.registerTool(
4646
const conditions = ["sunny", "cloudy", "rainy", "stormy", "snowy"][Math.floor(Math.random() * 5)];
4747

4848
return {
49+
content: [],
4950
structuredContent: {
5051
temperature: {
5152
celsius: temp_c,
52-
fahrenheit: Math.round((temp_c * 9/5 + 32) * 10) / 10
53+
fahrenheit: Math.round((temp_c * 9 / 5 + 32) * 10) / 10
5354
},
5455
conditions,
5556
humidity: Math.round(Math.random() * 100),

src/server/mcp.test.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ describe("tool()", () => {
398398
name: z.string(),
399399
value: z.number(),
400400
},
401-
callback: async ({name, value}) => ({
401+
callback: async ({ name, value }) => ({
402402
content: [
403403
{
404404
type: "text",
@@ -729,7 +729,7 @@ describe("tool()", () => {
729729
});
730730

731731
mcpServer.tool(
732-
"test",
732+
"test",
733733
{ name: z.string() },
734734
{ title: "Test Tool", readOnlyHint: true },
735735
async ({ name }) => ({
@@ -787,7 +787,7 @@ describe("tool()", () => {
787787
});
788788

789789
mcpServer.tool(
790-
"test",
790+
"test",
791791
"A tool with everything",
792792
{ name: z.string() },
793793
{ title: "Complete Test Tool", readOnlyHint: true, openWorldHint: false },
@@ -828,8 +828,8 @@ describe("tool()", () => {
828828
type: "object",
829829
properties: { name: { type: "string" } }
830830
});
831-
expect(result.tools[0].annotations).toEqual({
832-
title: "Complete Test Tool",
831+
expect(result.tools[0].annotations).toEqual({
832+
title: "Complete Test Tool",
833833
readOnlyHint: true,
834834
openWorldHint: false
835835
});
@@ -853,7 +853,7 @@ describe("tool()", () => {
853853
});
854854

855855
mcpServer.tool(
856-
"test",
856+
"test",
857857
"A tool with everything but empty params",
858858
{},
859859
{ title: "Complete Test Tool with empty params", readOnlyHint: true, openWorldHint: false },
@@ -894,8 +894,8 @@ describe("tool()", () => {
894894
type: "object",
895895
properties: {}
896896
});
897-
expect(result.tools[0].annotations).toEqual({
898-
title: "Complete Test Tool with empty params",
897+
expect(result.tools[0].annotations).toEqual({
898+
title: "Complete Test Tool with empty params",
899899
readOnlyHint: true,
900900
openWorldHint: false
901901
});
@@ -1077,9 +1077,9 @@ describe("tool()", () => {
10771077
input: z.string(),
10781078
},
10791079
outputSchema: {
1080-
processedInput: z.string(),
1081-
resultType: z.string(),
1082-
timestamp: z.string()
1080+
processedInput: z.string(),
1081+
resultType: z.string(),
1082+
timestamp: z.string()
10831083
},
10841084
},
10851085
async ({ input }) => ({
@@ -1088,6 +1088,16 @@ describe("tool()", () => {
10881088
resultType: "structured",
10891089
timestamp: "2023-01-01T00:00:00Z"
10901090
},
1091+
content: [
1092+
{
1093+
type: "text",
1094+
text: JSON.stringify({
1095+
processedInput: input,
1096+
resultType: "structured",
1097+
timestamp: "2023-01-01T00:00:00Z"
1098+
}),
1099+
},
1100+
]
10911101
})
10921102
);
10931103

@@ -1186,6 +1196,17 @@ describe("tool()", () => {
11861196
},
11871197
},
11881198
async ({ input }) => ({
1199+
content: [
1200+
{
1201+
type: "text",
1202+
text: JSON.stringify({
1203+
processedInput: input,
1204+
resultType: "structured",
1205+
// Missing required 'timestamp' field
1206+
someExtraField: "unexpected" // Extra field not in schema
1207+
}),
1208+
},
1209+
],
11891210
structuredContent: {
11901211
processedInput: input,
11911212
resultType: "structured",
@@ -2664,7 +2685,7 @@ describe("prompt()", () => {
26642685
name: z.string(),
26652686
value: z.string(),
26662687
},
2667-
callback: async ({name, value}) => ({
2688+
callback: async ({ name, value }) => ({
26682689
messages: [
26692690
{
26702691
role: "assistant",

src/types.ts

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -843,13 +843,13 @@ export const ToolSchema = z
843843
* If not set, a CallToolResult for this Tool MUST NOT contain a structuredContent field and MUST contain a content field.
844844
*/
845845
outputSchema: z.optional(
846-
z.object({
847-
type: z.literal("object"),
848-
properties: z.optional(z.object({}).passthrough()),
849-
required: z.optional(z.array(z.string())),
850-
})
846+
z.object({
847+
type: z.literal("object"),
848+
properties: z.optional(z.object({}).passthrough()),
849+
required: z.optional(z.array(z.string())),
850+
})
851851
.passthrough()
852-
),
852+
),
853853
/**
854854
* Optional additional tool information.
855855
*/
@@ -892,46 +892,21 @@ export const ContentListSchema = z.array(
892892
]),
893893
);
894894

895-
export const CallToolUnstructuredResultSchema = ResultSchema.extend({
895+
export const CallToolResultSchema = ResultSchema.extend({
896896
/**
897897
* A list of content objects that represent the result of the tool call.
898898
*
899899
* If the Tool does not define an outputSchema, this field MUST be present in the result.
900+
* For backwards compatibility, this field is always present, but it may be empty.
900901
*/
901-
content: ContentListSchema,
902-
903-
/**
904-
* Structured output must not be provided in an unstructured tool result.
905-
*/
906-
structuredContent: z.never().optional(),
907-
908-
/**
909-
* Whether the tool call ended in an error.
910-
*
911-
* If not set, this is assumed to be false (the call was successful).
912-
*/
913-
isError: z.optional(z.boolean()),
914-
});
902+
content: ContentListSchema.default([]),
915903

916-
export const CallToolStructuredResultSchema = ResultSchema.extend({
917904
/**
918905
* An object containing structured tool output.
919906
*
920907
* If the Tool defines an outputSchema, this field MUST be present in the result, and contain a JSON object that matches the schema.
921908
*/
922-
structuredContent: z.object({}).passthrough(),
923-
924-
/**
925-
* A list of content objects that represent the result of the tool call.
926-
*
927-
* If the Tool defines an outputSchema, this field MAY be present in the result.
928-
*
929-
* Tools may use this field to provide compatibility with older clients that
930-
* do not support structured content.
931-
*
932-
* Clients that support structured content should ignore this field.
933-
*/
934-
content: z.optional(ContentListSchema),
909+
structuredContent: z.object({}).passthrough().optional(),
935910

936911
/**
937912
* Whether the tool call ended in an error.
@@ -941,11 +916,6 @@ export const CallToolStructuredResultSchema = ResultSchema.extend({
941916
isError: z.optional(z.boolean()),
942917
});
943918

944-
export const CallToolResultSchema = z.union([
945-
CallToolUnstructuredResultSchema,
946-
CallToolStructuredResultSchema,
947-
]);
948-
949919
/**
950920
* CallToolResultSchema extended with backwards compatibility to protocol version 2024-10-07.
951921
*/
@@ -1397,8 +1367,6 @@ export type Tool = Infer<typeof ToolSchema>;
13971367
export type ListToolsRequest = Infer<typeof ListToolsRequestSchema>;
13981368
export type ListToolsResult = Infer<typeof ListToolsResultSchema>;
13991369
export type ContentList = Infer<typeof ContentListSchema>;
1400-
export type CallToolUnstructuredResult = Infer<typeof CallToolUnstructuredResultSchema>;
1401-
export type CallToolStructuredResult = Infer<typeof CallToolStructuredResultSchema>;
14021370
export type CallToolResult = Infer<typeof CallToolResultSchema>;
14031371
export type CompatibilityCallToolResult = Infer<typeof CompatibilityCallToolResultSchema>;
14041372
export type CallToolRequest = Infer<typeof CallToolRequestSchema>;

0 commit comments

Comments
 (0)