Summary
instantly mcp registers all 171 tools successfully, but every tools/list request fails with:
Cannot read properties of undefined (reading '_zod')
As a result, no MCP client can enumerate any tools — the server is effectively unusable end-to-end, even though the stdio handshake and tool registration succeed.
Environment
instantly-cli@0.1.17 (latest)
- Node
v20.20.2, macOS
@modelcontextprotocol/sdk@1.29.0 (bundled)
zod@4.3.6 (bundled)
Repro
export INSTANTLY_API_KEY=...
(printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'; \
sleep 2) | instantly mcp
Observed:
Instantly MCP server started. Tools registered: 171
{"jsonrpc":"2.0","id":2,"error":{"code":-32603,"message":"Cannot read properties of undefined (reading '_zod')"}}
Root cause
I patched the vendored @modelcontextprotocol/sdk ListToolsRequestSchema handler to wrap each tool's serialization in a try/catch and log the failing name. One and only one of the 171 tools triggers the crash:
[BROKEN TOOL] enrichment_create: Cannot read properties of undefined (reading '_zod')
Looking at dist/index.js around the enrichmentCreateCommand definition (≈line 3188), its inputSchema is the only schema in the whole CLI that uses z.union([...]):
inputSchema: z72.object({
resource_id: z72.string().describe(...),
type: z72.enum(ENRICHMENT_TYPES).describe(...),
limit: z72.coerce.number().optional().describe(...),
filters: z72.union([ // <-- unique in the codebase
z72.string(),
z72.array(z72.record(z72.unknown()))
]).optional().describe(...),
custom_flow: z72.string().optional().describe(...)
}),
grep -c "z\.union\|z72\.union" across dist/index.js returns 1. That single z.union is the crash trigger — the SDK's toJsonSchemaCompat(..., { strictUnions: true, pipeStrategy: 'input' }) path (called from server/mcp.js ListToolsRequestSchema handler) dereferences ._zod on something undefined when walking the union branches in zod v4 Mini's compat layer.
Skipping enrichment_create via a try/catch patch returns the other 170 tools correctly and the MCP becomes fully functional.
Suggested fixes (pick one)
- Quick: replace the union with two separate optional fields, or accept a string and JSON-parse it in the handler (the handler already does
typeof input.filters === "string" ? JSON.parse(input.filters) : input.filters, so a plain z.string() plus validation at call time would work).
- Correct: bump
@modelcontextprotocol/sdk if a later version handles v4 unions + z.record(z.unknown()) inside arrays correctly, or drop strictUnions: true for the tools/list serialization.
Happy to PR the first option if useful.
Impact
Until fixed, any MCP client (Claude Desktop, Cursor, Gemini CLI) connecting to instantly mcp sees zero tools — the server is unusable without a manual patch to the vendored SDK.
Summary
instantly mcpregisters all 171 tools successfully, but everytools/listrequest fails with:As a result, no MCP client can enumerate any tools — the server is effectively unusable end-to-end, even though the stdio handshake and tool registration succeed.
Environment
instantly-cli@0.1.17(latest)v20.20.2, macOS@modelcontextprotocol/sdk@1.29.0(bundled)zod@4.3.6(bundled)Repro
Observed:
Root cause
I patched the vendored
@modelcontextprotocol/sdkListToolsRequestSchemahandler to wrap each tool's serialization in a try/catch and log the failing name. One and only one of the 171 tools triggers the crash:Looking at
dist/index.jsaround theenrichmentCreateCommanddefinition (≈line 3188), itsinputSchemais the only schema in the whole CLI that usesz.union([...]):grep -c "z\.union\|z72\.union"acrossdist/index.jsreturns1. That singlez.unionis the crash trigger — the SDK'stoJsonSchemaCompat(..., { strictUnions: true, pipeStrategy: 'input' })path (called fromserver/mcp.jsListToolsRequestSchemahandler) dereferences._zodon something undefined when walking the union branches in zod v4 Mini's compat layer.Skipping
enrichment_createvia a try/catch patch returns the other 170 tools correctly and the MCP becomes fully functional.Suggested fixes (pick one)
typeof input.filters === "string" ? JSON.parse(input.filters) : input.filters, so a plainz.string()plus validation at call time would work).@modelcontextprotocol/sdkif a later version handles v4 unions +z.record(z.unknown())inside arrays correctly, or dropstrictUnions: truefor the tools/list serialization.Happy to PR the first option if useful.
Impact
Until fixed, any MCP client (Claude Desktop, Cursor, Gemini CLI) connecting to
instantly mcpsees zero tools — the server is unusable without a manual patch to the vendored SDK.