One MCP Configuration for Codex, Claude, Cursor, and Copilot with chezmoi

Published: (March 7, 2026 at 04:11 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

When you use multiple coding agents on several machines, MCP configuration drift is inevitable—unless you make one file the source of truth.
The following guide shows a practical, reproducible setup for:

  • Codex
  • Claude Code
  • Cursor
  • GitHub Copilot (including VS Code and Copilot‑coding‑agent scenarios)

Core Idea

  1. Keep one canonical MCP manifest in your chezmoi source state.
  2. Generate each tool’s native config format from that manifest.
  3. Let chezmoi manage symlinks / templates and machine‑specific values.

All four tools model MCP servers with the same conceptual fields:

FieldMeaning
Server nameIdentifier used by the tool
Transport typestdio (local) vs. remote http/sse
Command + args + envFor local servers
URL + headers / authFor remote servers

What differs is file location and schema shape.
Instead of editing four formats manually, you maintain one normalized model and project it into each target file.

Tool‑Specific Storage Details

ToolWhere MCP livesFormatNotes
Codex~/.codex/config.toml (optional project overrides in .codex/config.toml)TOMLEntries under [mcp_servers.]
Claude~/.claude/settings.json, .claude/settings.json, .claude/settings.local.json (MCP config in ~/.claude.json for user/local scope and .mcp.json for project scope)JSONTreat .mcp.json as the repo‑shareable MCP surface; keep secrets outside the repo
Cursor~/.cursor/mcp.json (project: .cursor/mcp.json)JSONUses mcpServers array; supports command‑ and URL‑based MCP
VS CodeWorkspace: .vscode/mcp.json; User profile: mcp.jsonJSONFirst‑class MCP feature
Copilot coding agent~/.copilot/mcp-config.json (or equivalent)JSONSame schema as VS Code MCP, with explicit type (local, stdio, http, sse)

Canonical MCP Manifest

Create a single YAML file that describes all servers. Example:

# 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"

Tip: Store secrets (${GITHUB_TOKEN}) in encrypted/ private files (see Security below).

Directory Layout (chezmoi source state)

~/.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          ← canonical model (committed)
├─ 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
  • Files under .chezmoitemplates are reusable snippets.
  • Templates are recognized by the .tmpl suffix (or by living inside .chezmoitemplates).
  • Machine facts such as .chezmoi.os and .chezmoi.hostname are available inside templates.

Example Template Logic

{{- /* Render internal server only on work laptop */ -}}
{{- if eq .chezmoi.hostname "work-laptop" -}}
{
  "name": "internal",
  "type": "http",
  "url": "https://internal.example.com/mcp/",
  "headers": {
    "Authorization": "Bearer ${INTERNAL_TOKEN}"
  }
}
{{- end -}}

You can also vary filesystem roots, company‑only servers, etc., based on .chezmoi.os, .chezmoi.hostname, or any custom fact.

Source‑State Attributes (chezmoi)

PrefixPurpose
symlink_Create a symlink target
private_Mark file as private (restrict permissions)
encrypted_Encrypt with age/gpg (ideal for tokens, headers)

Recommended split

  • Committedservers.yaml (topology, non‑secret data)
  • Encrypted / private – per‑machine secrets (tokens, passwords)

Render env‑var references (${GITHUB_TOKEN}) into the final tool configs.

Transformation Rules (once, in templates)

Canonical fieldCodex (TOML)Claude / Cursor / VS Code / Copilot (JSON)
transport: stdiocommand, args, env under [mcp_servers.]command, args, env, type: "stdio"
transport: http (or sse)url, headers under [mcp_servers.]url, headers, type: "http" (or "sse")
Optional per‑tool keysAvoid unless absolutely requiredKeep in an overrides map inside servers.yaml if needed

Applying the Configuration

# From your chezmoi repo root
chezmoi apply

chezmoi will:

  • Render each template using the canonical servers.yaml (and any encrypted/private files).
  • Place the resulting files in the appropriate locations:
~/.codex/config.toml               ← MCP block
~/.claude.json   or   .mcp.json    ← projection
~/.cursor/mcp.json
.vscode/mcp.json
~/.copilot/mcp-config.json

Never edit the generated targets directly – always modify the source model or templates and re‑run chezmoi apply.

Security & Reproducibility

  • Strict reproducibility – generate all config files from templates; source‑only edits.
  • Secret handling – keep tokens in encrypted_ files or external secret managers; reference them via environment variables in the templates.
  • Version control – only the canonical model (servers.yaml) and template files are committed.
  • chezmoitemplating guide, machine facts, source‑state attributes
  • OpenAI Codex MCP – advanced config docs
  • Anthropic Claude Code MCP – settings overview
  • Cursor MCP – official docs page confirming first‑class MCP support
  • VS Code MCP – workspace (.vscode/mcp.json) and user config
  • GitHub Copilot MCP – coding‑agent configuration

TL;DR

  1. One canonical YAML model (servers.yaml).
  2. Templates for each tool’s native format.
  3. chezmoi manages rendering, symlinks, and machine‑specific overrides (private/encrypted).

Result: Consistent, drift‑free MCP configuration across Codex, Claude, Cursor, and Copilot without locking yourself into any single vendor schema.

# Copilot coding agent MCP

## skills-sync agent storage map
0 views
Back to Blog

Related posts

Read more »