Skip to content

Commit 6068664

Browse files
committed
fix(server): accept omitted prompt arguments
1 parent 5fc42e9 commit 6068664

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@modelcontextprotocol/server': patch
3+
---
4+
5+
fix(server): accept omitted prompt arguments when the schema only has optional fields

packages/server/src/server/mcp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ function createPromptHandler(
13391339
const typedCallback = callback as (args: unknown, ctx: ServerContext) => GetPromptResult | Promise<GetPromptResult>;
13401340

13411341
return async (args, ctx) => {
1342-
const parseResult = await validateStandardSchema(argsSchema, args);
1342+
const parseResult = await validateStandardSchema(argsSchema, args ?? {});
13431343
if (!parseResult.success) {
13441344
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`);
13451345
}

packages/server/test/server/mcp.compat.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,56 @@ describe('registerTool/registerPrompt accept raw Zod shape (auto-wrapped)', () =
119119

120120
await server.close();
121121
});
122+
123+
it('omitted prompt arguments validate as an empty object', async () => {
124+
const server = new McpServer({ name: 't', version: '1.0.0' });
125+
126+
let received: { topic?: string } | undefined;
127+
server.registerPrompt('draft', { argsSchema: z.object({ topic: z.string().optional() }) }, async args => {
128+
received = args;
129+
return {
130+
messages: [
131+
{
132+
role: 'user' as const,
133+
content: { type: 'text' as const, text: args.topic ?? 'default' }
134+
}
135+
]
136+
};
137+
});
138+
139+
const [client, srv] = InMemoryTransport.createLinkedPair();
140+
await server.connect(srv);
141+
await client.start();
142+
143+
const responses: JSONRPCMessage[] = [];
144+
client.onmessage = m => responses.push(m);
145+
146+
await client.send({
147+
jsonrpc: '2.0',
148+
id: 1,
149+
method: 'initialize',
150+
params: {
151+
protocolVersion: LATEST_PROTOCOL_VERSION,
152+
capabilities: {},
153+
clientInfo: { name: 'c', version: '1.0.0' }
154+
}
155+
} as JSONRPCMessage);
156+
await client.send({ jsonrpc: '2.0', method: 'notifications/initialized' } as JSONRPCMessage);
157+
await client.send({
158+
jsonrpc: '2.0',
159+
id: 2,
160+
method: 'prompts/get',
161+
params: { name: 'draft' }
162+
} as JSONRPCMessage);
163+
164+
await vi.waitFor(() => expect(responses.some(r => 'id' in r && r.id === 2)).toBe(true));
165+
166+
expect(received).toEqual({});
167+
const result = responses.find(r => 'id' in r && r.id === 2) as { result?: { messages: Array<{ content: { text: string } }> } };
168+
expect(result.result?.messages[0]?.content.text).toBe('default');
169+
170+
await server.close();
171+
});
122172
});
123173

124174
describe('InferRawShape', () => {

0 commit comments

Comments
 (0)