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:
- Codex
- Claude Code
- Cursor
- GitHub Copilot (including VS Code and Copilot coding agent scenarios)
The core idea is simple:
- Keep one canonical MCP manifest in your chezmoi source state.
- Generate each tool's native config format from that manifest.
- Let chezmoi manage symlinks/templates and machine-specific values.
Why this works
All four tools model MCP servers with the same conceptual fields:
- Server name
- Transport type (
stdiovs remote HTTP/SSE-like) - Command + args + env for local servers
- URL + headers/auth for remote servers
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.
What each tool expects today
Codex
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 Code
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
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.
GitHub Copilot / VS Code
There are two adjacent configuration worlds:
- VS Code MCP config:
mcp.json(workspace commonly at.vscode/mcp.json, plus user profile config) - Copilot coding agent MCP config: JSON with
mcpServersand explicittype(local,stdio,http,sse), and documented reuse from VS Code MCP configuration patterns
For a chezmoi setup, it is practical to generate:
-
.vscode/mcp.jsonfor local editor agent workflows -
.copilot/mcp-config.json(or equivalent copilot-target file in your model) for coding-agent workflows where needed
Common ground: a normalized MCP model
Use 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.
chezmoi layout that scales
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.
Templating pattern
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:
- Different filesystem roots on macOS vs Linux
- Company-only servers on work laptops
- Personal-only servers on home machines
Example gate in template:
{{- if eq .chezmoi.hostname "work-laptop" -}}
# render internal MCP server
{{- end -}}
Symlinks and private data
chezmoi source-state attributes are important for this problem:
-
symlink_to create symlink targets -
private_for sensitive files/permissions -
encrypted_+ age/gpg encryption for secret-bearing material
This is ideal for MCP because tokens and headers frequently differ by machine/account.
Recommended split:
- Keep server topology in a committed template/data file
- Keep secrets in encrypted/private files or external secret providers
- Render env var references into final tool configs
Mapping rules (the critical part)
Define clear transformation rules once:
-
transport: stdio- Codex: TOML command/args/env under
[mcp_servers.<name>] - Claude/Cursor/VSCode/Copilot: JSON object with command args env and tool-specific type field if required
- Codex: TOML command/args/env under
-
transport: http(orsse)- Codex:
url(+ auth/header fields) - JSON tools:
url,headers, and possiblytype(http/sse)
- Codex:
-
Optional per-tool fields
- Keep them in an
overridesmap in canonical YAML if absolutely necessary - Avoid polluting the base model with vendor-only keys unless needed
- Keep them in an
Suggested generation flow
- Edit canonical
servers.yaml - Run
chezmoi apply - Let templates produce:
-
~/.codex/config.tomlMCP block -
~/.claude.jsonor project.mcp.jsonprojection ~/.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.
Real-world caveats
- Copilot and Cursor MCP features are evolving quickly; treat adapters as projection layers, not permanent schemas.
- Claude has multiple config surfaces (
settings.json,~/.claude.json,.mcp.json), so be explicit about which one your team standardizes on. - Project-level files (
.vscode/mcp.json,.mcp.json,.codex/config.toml) are great for shared defaults; user-level files should hold personal secrets and machine specifics.
Bottom line
The durable strategy is not "pick one tool format."
It is:
- One canonical MCP model
- Many generated vendor configs
- chezmoi templates + machine facts + private/encrypted files to keep it safe and portable
That gives you consistency across Codex, Claude, Cursor, and Copilot without locking yourself to one vendor schema.
Sources
- chezmoi
- chezmoi templating guide
- chezmoi machine-to-machine differences
- chezmoi source state attributes
- OpenAI Codex MCP
- OpenAI Codex advanced config
- Anthropic Claude Code settings
- Anthropic Claude Code MCP
- Cursor MCP docs
- VS Code MCP docs
- GitHub Copilot MCP
- GitHub Copilot coding agent MCP
- skills-sync agent storage map
Top comments (0)