Registering it with a client
Connect koyu-mcp to your agent's client. It takes one line, or a few lines of JSON. No environment variables, no credentials.
Before you start
- Node 22 or later, and
npx. The server itself has no runtime dependencies. - Your
.murofiles under git.write_layerreplaces files wholesale and has no undo. Rollback is git's job. - Commit before you let an agent write.
Two launch commands
Whatever the client, this is the only thing koyu asks you to specify.
From npm.
npx -p @kensnzk/koyu koyu-mcp
From a clone, using a development build. Run npm install && npm run build first. dist/mcp.js has no runtime dependencies, so node can launch it directly.
node /path/to/koyu/dist/mcp.js
Transport is stdio; no environment variables, no authentication, no network access. Those four facts and the launch command are all a client needs to be told.
Claude Code (CLI)
One line.
claude mcp add koyu -- npx -p @kensnzk/koyu koyu-mcp
claude mcp add koyu -- node /path/to/koyu/dist/mcp.js # development build
claude mcp list lists the registered servers with their connection status. During a session, /mcp shows all 12 tools.
Sharing it through the repository (project scope)
Commit a .mcp.json at the root of the repository and everyone who clones gets the same registration. For a project that keeps its .muro files in the repository, make this the default.
{
"mcpServers": {
"koyu": {
"command": "npx",
"args": ["-p", "@kensnzk/koyu", "koyu-mcp"]
}
}
}
A server that comes from .mcp.json needs approval the first time. Until you approve it, it does not connect and shows as pending in the listing.
Claude Desktop
Settings → Developer → Edit config opens claude_desktop_config.json. Write the same mcpServers shape as above and restart the app.
| OS | Location |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
The desktop app does not always inherit your shell's PATH. Writing npx or node as an absolute path (whatever which node / where node prints) is the reliable choice.
Any other MCP client
Most read the same mcpServers JSON shape. Follow that client's conventions for the key name and the file location.
What koyu requires is only:
- stdio transport (not HTTP, not SSE)
- one of the two launch commands above
- no environment variables
- no authentication
The server reads line-delimited JSON from stdin and writes line-delimited JSON to stdout. When stdin closes, it exits 0. The full surface is on The protocol.
Pass the entry as an absolute path
When a tool's file argument is relative, it resolves against the server process's working directory — and which directory the client starts the server in is up to the client. An absolute path is the reliable choice.
Get it wrong and you get this. Here the working directory was /tmp.
line 0: Cannot read file: /private/tmp/examples/two-rooms.muro
Checking it without a client
When a registration looks doubtful, skip the agent and push JSON-RPC into stdio directly. Run this at the root of the repository.
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"doors","arguments":{"file":"examples/two-rooms.muro","from":"/L1/a","to":"/out"}}}' \
| npx tsx src/mcp.ts
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"koyu","version":"0.16.0"},"instructions":"Server for koyu, a space-first architectural description. Grasp the building with model_summary, read the original layers with layers, and edit with write_layer. check is the gatekeeper of the build and returns errors tagged layer:line — it guarantees structural consistency only. validate delivers the architectural verdicts, which are a separate and unfrozen surface. doors/light/site/spaces are different questions put to the same description. Form (plan_svg) is generated, never written."}}
{"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\n \"doors\": 2,\n \"path\": [\n \"/L1/a\",\n \"/L1/b\",\n \"/out\"\n ]\n}"}]}}
To check an installed package instead, swap the last line for npx -p @kensnzk/koyu koyu-mcp and make the file path absolute.
Send {"jsonrpc":"2.0","id":3,"method":"tools/list"} the same way and all 12 tools come back with name, description and inputSchema.
See also
- koyu-mcp — statelessness, the standard loop, the 12 tools
- The protocol — what
initializeannounces, how errors come back - Writing — write_layer / new_uids — the blast radius of a write
- The koyu command — the same derivations by hand