Skip to content

Commit 316906a

Browse files
fix: Support updating output schema (#1048)
Co-authored-by: Konstantin Konstantinov <konstantin@mach5technology.com>
1 parent a57303c commit 316906a

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

src/server/mcp.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,95 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
480480
expect(notifications).toHaveLength(0);
481481
});
482482

483+
/***
484+
* Test: Updating Tool with outputSchema
485+
*/
486+
test('should update tool with outputSchema', async () => {
487+
const mcpServer = new McpServer({
488+
name: 'test server',
489+
version: '1.0'
490+
});
491+
const notifications: Notification[] = [];
492+
const client = new Client({
493+
name: 'test client',
494+
version: '1.0'
495+
});
496+
client.fallbackNotificationHandler = async notification => {
497+
notifications.push(notification);
498+
};
499+
500+
// Register initial tool
501+
const tool = mcpServer.registerTool(
502+
'test',
503+
{
504+
outputSchema: {
505+
result: z.number()
506+
}
507+
},
508+
async () => ({
509+
content: [{ type: 'text', text: '' }],
510+
structuredContent: {
511+
result: 42
512+
}
513+
})
514+
);
515+
516+
// Update the tool with a different outputSchema
517+
tool.update({
518+
outputSchema: {
519+
result: z.number(),
520+
sum: z.number()
521+
},
522+
callback: async () => ({
523+
content: [{ type: 'text', text: '' }],
524+
structuredContent: {
525+
result: 42,
526+
sum: 100
527+
}
528+
})
529+
});
530+
531+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
532+
533+
await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]);
534+
535+
// Verify the outputSchema was updated
536+
const listResult = await client.request(
537+
{
538+
method: 'tools/list'
539+
},
540+
ListToolsResultSchema
541+
);
542+
543+
expect(listResult.tools[0].outputSchema).toMatchObject({
544+
type: 'object',
545+
properties: {
546+
result: { type: 'number' },
547+
sum: { type: 'number' }
548+
}
549+
});
550+
551+
// Call the tool to verify it works with the updated outputSchema
552+
const callResult = await client.request(
553+
{
554+
method: 'tools/call',
555+
params: {
556+
name: 'test',
557+
arguments: {}
558+
}
559+
},
560+
CallToolResultSchema
561+
);
562+
563+
expect(callResult.structuredContent).toEqual({
564+
result: 42,
565+
sum: 100
566+
});
567+
568+
// Update happened before transport was connected, so no notifications should be expected
569+
expect(notifications).toHaveLength(0);
570+
});
571+
483572
/***
484573
* Test: Tool List Changed Notifications
485574
*/

src/server/mcp.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ export class McpServer {
906906
if (typeof updates.title !== 'undefined') registeredTool.title = updates.title;
907907
if (typeof updates.description !== 'undefined') registeredTool.description = updates.description;
908908
if (typeof updates.paramsSchema !== 'undefined') registeredTool.inputSchema = objectFromShape(updates.paramsSchema);
909+
if (typeof updates.outputSchema !== 'undefined') registeredTool.outputSchema = objectFromShape(updates.outputSchema);
909910
if (typeof updates.callback !== 'undefined') registeredTool.handler = updates.callback;
910911
if (typeof updates.annotations !== 'undefined') registeredTool.annotations = updates.annotations;
911912
if (typeof updates._meta !== 'undefined') registeredTool._meta = updates._meta;

0 commit comments

Comments
 (0)