---
title: "Shipping an MCP server that works in every agent"
description: "「Shipping an MCP server that works in every agent」：yokoten 使用指南的一章。"
canonical: https://yokoten.app/zh-tw/docs/guide/shipping-an-mcp-server-that-works-in-every-agent
lang: en
source: https://github.com/yokoten-labs/yokoten/blob/v0.1.2/docs/guide.md
ref: "v0.1.2"
---

> For AI agents: the documentation index is at https://yokoten.app/llms.txt. To set up yokoten in a project, follow https://yokoten.app/agents.md.

> 這一頁還沒有繁體中文版，下面是英文原文。

# Shipping an MCP server that works in every agent

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.

```sh
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:

```json
{
  "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`:

```json
{
  "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:

```sh
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.

---

上一章: [Install and commands](https://yokoten.app/zh-tw/docs/guide/install-and-commands.md)
下一章: [The core rules](https://yokoten.app/zh-tw/docs/guide/the-core-rules.md)
