Lukas WolfsteinerIf you use multiple coding agents across multiple machines, MCP configuration drift is unavoidable...
If you use multiple coding agents across multiple machines, MCP configuration drift is unavoidable unless you make one file the source of truth.
This guide shows a practical setup for:
The core idea is simple:
All four tools model MCP servers with the same conceptual fields:
stdio vs remote HTTP/SSE-like)What differs is file location and schema shape.
So instead of manually editing four formats, you maintain one normalized model and project it into each target file.
Codex stores MCP inside config.toml, typically at ~/.codex/config.toml, with optional project overrides in .codex/config.toml for trusted projects.
MCP entries are under [mcp_servers.<name>] and support both local command servers and remote URL servers.
Claude settings are split across ~/.claude/settings.json, .claude/settings.json, and .claude/settings.local.json, but MCP server configuration is associated with ~/.claude.json for user/local scope and .mcp.json for project scope.
In practice, you can treat .mcp.json as the repository-shareable MCP surface and keep secrets/user-only material outside repo.
Cursor uses JSON with mcpServers and supports command- and URL-based MCP installations.
The official docs page confirms MCP as a first-class feature and transport diversity; path specifics (~/.cursor/mcp.json, .cursor/mcp.json) are consistent with the validated storage map you linked.
There are two adjacent configuration worlds:
mcp.json (workspace commonly at .vscode/mcp.json, plus user profile config)mcpServers and explicit type (local, stdio, http, sse), and documented reuse from VS Code MCP configuration patternsFor a chezmoi setup, it is practical to generate:
.vscode/mcp.json for local editor agent workflows.copilot/mcp-config.json (or equivalent copilot-target file in your model) for coding-agent workflows where neededUse one canonical data file, for example in chezmoi source state:
dot_config/mcp/servers.yaml
servers:
github:
transport: http
url: "https://api.githubcopilot.com/mcp/"
headers:
Authorization: "Bearer ${GITHUB_TOKEN}"
filesystem:
transport: stdio
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/lukas"]
env:
NODE_NO_WARNINGS: "1"
Then render adapters per tool.
A practical structure:
~/.local/share/chezmoi/
.chezmoitemplates/
mcp/
codex-config.toml.tmpl
claude-mcp.json.tmpl
cursor-mcp.json.tmpl
vscode-mcp.json.tmpl
copilot-mcp-config.json.tmpl
dot_config/
mcp/
servers.yaml
dot_codex/
config.toml.tmpl
dot_claude/
mcp_servers.json.tmpl
dot_cursor/
mcp.json.tmpl
dot_vscode/
mcp.json.tmpl
dot_copilot/
mcp-config.json.tmpl
Use .chezmoitemplates for reusable snippets and avoid duplicating mapping logic.
chezmoi treats files as templates when they have .tmpl suffix (or live under .chezmoitemplates), and exposes machine facts like .chezmoi.os and .chezmoi.hostname.
That lets you do things like:
Example gate in template:
{{- if eq .chezmoi.hostname "work-laptop" -}}
# render internal MCP server
{{- end -}}
chezmoi source-state attributes are important for this problem:
symlink_ to create symlink targetsprivate_ for sensitive files/permissionsencrypted_ + age/gpg encryption for secret-bearing materialThis is ideal for MCP because tokens and headers frequently differ by machine/account.
Recommended split:
Define clear transformation rules once:
transport: stdio
[mcp_servers.<name>]
transport: http (or sse)
url (+ auth/header fields)url, headers, and possibly type (http/sse)Optional per-tool fields
overrides map in canonical YAML if absolutely necessaryservers.yaml
chezmoi apply
~/.codex/config.toml MCP block~/.claude.json or project .mcp.json projection~/.cursor/mcp.json.vscode/mcp.json~/.copilot/mcp-config.json (if used in your setup)If you want strict reproducibility, generate all from templates only and never edit generated targets directly.
settings.json, ~/.claude.json, .mcp.json), so be explicit about which one your team standardizes on..vscode/mcp.json, .mcp.json, .codex/config.toml) are great for shared defaults; user-level files should hold personal secrets and machine specifics.The durable strategy is not "pick one tool format."
It is:
That gives you consistency across Codex, Claude, Cursor, and Copilot without locking yourself to one vendor schema.