-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Describe the bug
When a tool - either with or without an input schema - is registered onto the mcp server, it gets registered correctly with its input schema being a ZodObject ({type: 'object', shape: <accessor>}
), the server starts and the MCP inspector is able to connect to it.
When a list tools
request is sent from the mcp inspector, all toolDefinitions are generated, converting the existing tool inputSchema (Zod) into a jsonSchema. However, despite the shape and type of the zod input schema, the zodToJsonSchema
function always returns {type: "string", $schema: "http://json-schema.org/draft-07/schema#"}
. This turns into an error on the MCP inspector, being unable to list tools, thus unable to execute any of them.
To Reproduce
Steps to reproduce the behavior:
- Create an instance of McpServer:
server = new McpServer({...serverInfo}, {
capabilities,
instructions,
});
- Register a tool with an inputSchema:
server.registerTool(
name,
{
title: name,
description: description,
inputSchema: z.object({...schema}).shape,
},
handler,
);
- Start MCP inspector
- Connect to MCP server from inspector
- Try to list tools
- Get the error:
Uncaught (in promise) ZodError: [
{
"received": "string",
"code": "invalid_literal",
"expected": "object",
"path": [
"tools",
0,
"inputSchema",
"type"
],
"message": "Invalid literal value, expected \"object\""
}
]
Expected behavior
The input Schema of the tool should be converted into a valid, matching jsonSchema.
Additional Context
Debugging the application, I could see that the zodToJsonSchema
function calls the parseDef
function with the zod definition. When the jsonSchemaOrGetter
constant gets calculated through the selectParser
function, it passes def
, def.typeName
and refs
. The second argument is undefined. Then teh selectParser
function switches typeName
on all possible ZodFirstPartyTypeKind.<ZodType>
. However, ZodFirstPartyTypeKind is {}
, so the first one matches, which is the string matcher.
I have @modelcontextprotocol/[email protected]
dependency installed.