By Kodelyth · · 7 min read
ECC ships a Model Context Protocol server that exposes the entire toolkit — every agent, skill, command, and rule, plus the local memory store — to any MCP-compatible client. That is useful only if the server is actually wired into the IDE you use, and wiring MCP by hand means finding the right config file, guessing the right JSON key, and not corrupting whatever is already in there.
kodelythecc --target <ide> does that wiring for six IDEs. This post is about
which file each one gets, the one that isn't JSON, and the careful part that
keeps the merge from eating your config.
What the server is
One process, stdio JSON-RPC, no network:
kodelythecc mcp[kodelyth-mcp] ready · 2.29.0 · 16 tools · 6 prompts · 389 resourcesThe 16 tools are the useful surface. route_intent suggests the right
specialist for a message; list_agents / get_agent (and the skill, command,
rule, bundle equivalents) fetch catalog entries on demand; recall_memory and
capture_memory read and write the local BM25 store. The server adds no model
calls of its own — it surfaces context, and your IDE's model decides what to do
with it. Local reads and local memory only; no telemetry.
One command wires the targeted IDE
Install and target an IDE in one step:
npm i -g kodelyth-ecc
kodelythecc --target cursorThe post-install step does two things. First it always registers the server in
Claude Code (~/.claude.json) and Claude Desktop — those are the baseline. Then,
if your --target is a non-Claude IDE whose config ECC can safely merge, it
wires the server there too:
━ ECC MCP server registration ─────────────────
✓ added: /Users/you/.claude.json
✓ added: /Users/you/.cursor/mcp.json
· Restart your AI tool to pick up the serverThe six auto-wired targets are claude-code, cursor, windsurf,
gemini-cli, codex, and kiro. Opt out of all of it with
--no-mcp-register.
Which file each IDE gets
The server definition is identical across clients; only the file location and format differ.
| Target | Config file | Format |
|---|---|---|
claude-code | ~/.claude.json | JSON |
cursor | <project>/.cursor/mcp.json | JSON |
windsurf | ~/.codeium/windsurf/mcp_config.json | JSON |
gemini-cli | ~/.gemini/settings.json | JSON |
kiro | <project>/.kiro/settings/mcp.json | JSON |
codex | ~/.codex/config.toml | TOML |
The five JSON targets all use the same { mcpServers: { ... } } shape as Claude
Code — Kiro included, because it is MCP-native — so one hardened merge handles
all of them. The entry written is deliberately minimal:
{
"mcpServers": {
"kodelyth-ecc": { "command": "kodelythecc", "args": ["mcp"], "env": {} }
}
}Codex is the odd one out. It stores MCP servers in TOML as [mcp_servers.<name>]
tables, so ECC writes that instead — without pulling in a TOML parser, and only
when the table is absent, because appending a table is order-independent in TOML
and never clobbers existing servers:
[mcp_servers."kodelyth-ecc"]
command = "kodelythecc"
args = ["mcp"]The merge refuses to clobber
This is the part worth dwelling on, because an installer that edits your config files has one job above all others: do no harm. Reading a config file has three outcomes, not two, and collapsing them is how data gets destroyed.
An earlier version returned null for every read failure and the caller did
readJson(file) || {}. So a config that merely failed to parse — one trailing
comma from a hand-edit, a half-written file — was treated as empty, and the merge
wrote it back containing only ECC's own entry. Measured on a realistic config:
366 bytes in, 140 bytes out, with every other MCP server and every setting
gone. Silently, during an install nobody thought was risky.
The reader now distinguishes absent from unreadable:
if (cfg.state === 'unreadable') {
throw new Error(
`refusing to modify ${file}: it exists but could not be parsed. ` +
`Fix or move the file, then re-run. Nothing was written.`
);
}Absent is safe to treat as empty and create. Unreadable is not — it is refused,
with nothing written. The write itself is atomic (temp file, then rename) and
preserves the file's existing permissions, and the whole thing is idempotent: run
it twice and the second run reports unchanged.
What it unlocks
Once wired, the IDE's model can reach the whole ECC catalog and your memory
without you attaching anything by hand. A single route_intent call turns "my
build is red" into the right build-resolver; a recall_memory call surfaces how
you fixed the same class of bug three weeks ago in another repo — and because the
memory store is keyed by git remote, that
recall works even if you've since moved the repo. The 389 resources mean every
agent and skill is addressable as kodelyth://agents/<name> for clients that
render resources.
What still needs a human
Two honest gaps. Cline and Roo Code store their MCP settings inside VS Code's
globalStorage, a path that is editor-version-specific and fragile to guess, so
ECC does not write it for you — those stay a manual paste of the same server
entry. And RTK, ECC's separate shell-output compression layer, wires into a
different set of targets than MCP does; it has no mapping for Kiro or Aider,
so on those two you get the MCP server and memory but not RTK's input savings.
Neither gap is hidden. The installer only claims the targets it can wire safely, and stays quiet on the ones it can't — which is the right behaviour for a tool that edits files you care about.
Auto-registration shipped across the ECC 2.2x line. The per-IDE config writer, including the tri-state reader and the TOML special case, is dependency-free Node in scripts/mcp/register-self.js. See MCP Server for the full tool list and External MCP Servers for the inverse — ECC consuming Stripe, GitHub, or Postgres.
npm i -g kodelyth-ecc && kodelythecc --target cursor