Node.js security releases (October 2026): update Node to 22.23.4, 24.22.1 or 26.12.1 before you use yokoten
yokoten
Docs Shipping an MCP server that works in every agent

The guide

Shipping an MCP server that works in every agent

Source: docs/guide.md · v0.1.2

An MCP server is one program that many agents start. Each agent reads the tool list a little differently. A schema that one agent accepts can make another drop the tool, with no message to the user.

yokoten mcp starts your server over stdio and reads its tool list. It reports each trap with a what, a why and a fix. Run it before a release, and in CI beside your tests.

yokoten mcp
yokoten mcp --json
yokoten mcp --command "node src/server.ts"

It reads .mcp.json, .vscode/mcp.json and mcp.json from the project root. It starts each stdio server, calls initialize, then tools/list. It stops each server when it is done. A server over HTTP is named and skipped: this check starts only stdio servers.

What it checks

Trap What the check looks for Fix
A schema Claude rejects A root anyOf, oneOf or allOf Put the branches under one property of a root object
A schema Gemini rejects A $ref or $defs, a list of types, or an array with no items Inline the schema, use one type, and add items
OpenAI strict mode A property that is not in required Add every property to required
A dropped property A property name outside [A-Za-z0-9_.-], or longer than 64 Rename it
A dropped tool A tool name longer than 64 Shorten it
A tool the client never shows 40 tools or more Merge tools, or keep 39 or fewer
A tool the client cannot gate A missing readOnlyHint, destructiveHint, idempotentHint or openWorldHint Set all four, each as true or false
An empty answer in Cursor A tool with outputSchema that returns only structuredContent Return a text content item too
A broken session A stdout line that is not JSON-RPC, is not UTF-8, or ends with CRLF Write logs to stderr, write UTF-8, and end each line with LF
A server that never starts on Windows A config command such as npx or bar.cmd Start it through cmd /c
A server that does not answer No reply to initialize or tools/list Run it by hand, and fix what stderr says

The check reports the tool count, the total size of the tool definitions, and the longest description. A large tool list costs every client context on every turn. Keep each tool small, and keep its description short.

The outputSchema rule

A tool may declare outputSchema. Clients that understand it read structuredContent. Other clients read only the text content. A result with just one of the two looks empty somewhere.

Return both:

{
  "structuredContent": { "reply": "ok" },
  "content": [{ "type": "text", "text": "ok" }]
}

yokoten mcp calls a tool only when it is safe to try: the tool sets readOnlyHint: true, declares an outputSchema, and requires no argument. Other tools are left alone. The check says how many it read.

Windows

Windows cannot start npx or a .cmd file the way a Unix shell can. A config entry that names one needs cmd:

{
  "mcpServers": {
    "demo": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "demo-mcp"]
    }
  }
}

The check warns about such an entry. A warning never fails the check: the same project may run on a machine that is not Windows.

stdout is for JSON-RPC only

The client reads stdout as a stream of JSON-RPC messages. One log line, one progress bar, or one carriage return breaks the session for every client.

  • Write logs to stderr.
  • Write one JSON-RPC message per line.
  • End each line with a line feed, not CRLF.
  • Write UTF-8 only. A Windows code page such as cp1252 corrupts a name.

In CI

Add the check after your tests:

yokoten mcp --json

It exits 1 when a tool breaks a rule. It exits 0 when the server is clean or the project has no MCP config. A Windows warning is reported and does not change the exit code.