豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 93640d3

Browse files
fix: reject plain JSON Schema objects passed as inputSchema (#1596)
Co-authored-by: Matt <77928207+mattzcarey@users.noreply.github.com>
1 parent 4cbcec0 commit 93640d3

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

src/server/mcp.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,9 +1024,10 @@ export class McpServer {
10241024
annotations = rest.shift() as ToolAnnotations;
10251025
}
10261026
} else if (typeof firstArg === 'object' && firstArg !== null) {
1027-
// Not a ZodRawShapeCompat, so must be annotations in this position
1028-
// Case: tool(name, annotations, cb)
1029-
// Or: tool(name, description, annotations, cb)
1027+
// ToolAnnotations values are primitives. Nested objects indicate a misplaced schema
1028+
if (Object.values(firstArg).some(v => typeof v === 'object' && v !== null)) {
1029+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
1030+
}
10301031
annotations = rest.shift() as ToolAnnotations;
10311032
}
10321033
}
@@ -1386,7 +1387,7 @@ function isZodRawShapeCompat(obj: unknown): obj is ZodRawShapeCompat {
13861387

13871388
/**
13881389
* Converts a provided Zod schema to a Zod object if it is a ZodRawShapeCompat,
1389-
* otherwise returns the schema as is.
1390+
* otherwise returns the schema as is. Throws if the value is not a valid Zod schema.
13901391
*/
13911392
function getZodSchemaObject(schema: ZodRawShapeCompat | AnySchema | undefined): AnySchema | undefined {
13921393
if (!schema) {
@@ -1397,6 +1398,10 @@ function getZodSchemaObject(schema: ZodRawShapeCompat | AnySchema | undefined):
13971398
return objectFromShape(schema);
13981399
}
13991400

1401+
if (!isZodSchemaInstance(schema as object)) {
1402+
throw new Error('inputSchema must be a Zod schema or raw shape, received an unrecognized object');
1403+
}
1404+
14001405
return schema;
14011406
}
14021407

test/server/mcp.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,37 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
20502050
// Clean up spies
20512051
warnSpy.mockRestore();
20522052
});
2053+
2054+
test('should reject plain JSON Schema objects passed as inputSchema', () => {
2055+
const mcpServer = new McpServer({
2056+
name: 'test server',
2057+
version: '1.0'
2058+
});
2059+
2060+
const jsonSchema = {
2061+
type: 'object',
2062+
properties: {
2063+
directory_id: {
2064+
type: 'string',
2065+
format: 'uuid',
2066+
description: 'The UUID of the directory'
2067+
}
2068+
},
2069+
required: ['directory_id']
2070+
} as any;
2071+
2072+
const cb = async ({ directory_id }: any) => ({
2073+
content: [{ type: 'text' as const, text: `Got: ${directory_id}` }]
2074+
});
2075+
2076+
expect(() => {
2077+
mcpServer.tool('test', 'A tool', jsonSchema, cb);
2078+
}).toThrow(/unrecognized object/);
2079+
2080+
expect(() => {
2081+
mcpServer.registerTool('test', { description: 'A tool', inputSchema: jsonSchema }, cb);
2082+
}).toThrow(/unrecognized object/);
2083+
});
20532084
});
20542085

20552086
describe('resource()', () => {

0 commit comments

Comments
 (0)