{"record":{"id":"6c7054131cd3fcb1","repo":"payloadcms/payload","slug":"error-initializing-mcp-handler-string-error","errorCode":null,"errorMessage":"Error initializing MCP handler: ${String(error)}","messagePattern":"Error initializing MCP handler: (.+?)","errorType":"http","errorClass":"APIError","httpStatus":500,"severity":"error","filePath":"packages/plugin-mcp/src/mcp/buildMcpServer.ts","lineNumber":243,"sourceCode":"                input: toolInput,\n                req,\n                serverContext: ctx,\n              })\n              return finalizeToolResponse({\n                input: toolInput,\n                overrideResponse: tool.overrideResponse,\n                response,\n                toolName: item.mcpName,\n              })\n            },\n          )\n          logger.info(`✅ Tool: ${item.mcpName} Registered.`)\n          break\n        }\n      }\n    }\n  } catch (error) {\n    throw new APIError(`Error initializing MCP handler: ${String(error)}`, 500)\n  }\n\n  return server\n}\n\nconst withSlugInput = ({\n  name,\n  input,\n}: {\n  input?: ToolInputSchema\n  name: 'collectionSlug' | 'globalSlug'\n}): ToolInputSchema => {\n  const description = name === 'collectionSlug' ? 'The collection slug' : 'The global slug'\n  const slugSchema = z.string().describe(description)\n\n  if (!input) {\n    return z.object({ [name]: slugSchema })\n  }","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/plugin-mcp/src/mcp/buildMcpServer.ts#L225-L261","documentation":"Thrown by the MCP plugin's server builder when anything inside the tool/resource registration loop throws — a malformed Zod input schema that fails `toStandardSchema`, a duplicate `mcpName`, or a rejection from the underlying `server.registerTool`/`server.registerResource` call. The whole build is wrapped in one try/catch that re-throws the original cause as a 500 APIError, so the root error is preserved in the message suffix.","triggerScenarios":"Registering an MCP tool whose `input` Zod schema uses a construct `toStandardSchema` cannot convert; registering two tools/resources with the same `mcpName`; an incompatible `@modelcontextprotocol/sdk` version where `registerTool`'s signature changed; a builtin resource whose URI template is invalid.","commonSituations":"Custom MCP tool authored with an unsupported Zod type (e.g. `z.any()`, `z.transform`); name collision between builtin collections tool and a user-supplied tool; major SDK upgrade of `@modelcontextprotocol/sdk` without bumping the plugin; passing a non-Zod schema object as `input`.","solutions":["Read the `String(error)` suffix — it carries the original cause verbatim and pinpoints the failing item","Validate each tool's `input` Zod schema in isolation before registering it with the plugin","Ensure every tool/resource `mcpName` is unique across builtin + custom items","Pin `@modelcontextprotocol/sdk` to the exact version the installed plugin-mcp release expects"],"exampleFix":"// before: schema with an unsupported construct\nconst input = z.object({ id: z.any() })\n// after: use a concrete primitive\nconst input = z.object({ id: z.string() })","handlingStrategy":"try-catch","validationCode":"// Validate each tool's Zod schema parses a sample input before registering\nimport type { ZodTypeAny } from 'zod'\nfunction assertSchemaOk(name: string, schema: ZodTypeAny | undefined, sample: unknown) {\n  if (!schema) return\n  const r = schema.safeParse(sample)\n  if (!r.success) throw new Error(`tool ${name} schema rejects sample: ${r.error.message}`)\n}","typeGuard":"import { APIError } from 'payload'\nfunction isMcpInitError(e: unknown): e is APIError {\n  return e instanceof APIError && typeof (e as any).statusCode === 'number'\n    && /^Error initializing MCP handler:/.test((e as APIError).message)\n}","tryCatchPattern":"try {\n  const server = await buildMcpServer(config)\n} catch (e) {\n  if (e instanceof APIError && /^Error initializing MCP handler:/.test(e.message)) {\n    // e.message suffix is the original cause — log it and surface to operator\n    const cause = e.message.replace('Error initializing MCP handler: ', '')\n    logger.error('MCP build failed: ' + cause)\n  }\n  throw e\n}","preventionTips":["Author tool input schemas with concrete Zod primitives; avoid z.any()/z.unknown() at the top level","Namespace every custom tool's mcpName to avoid collisions with builtin tools","Pin @modelcontextprotocol/sdk to the version the plugin release was built against","Add a startup self-test that registers all tools against a throwaway MCP server before the real one boots"],"tags":["mcp","zod","initialization","configuration","server-startup"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}