MCP Servers (How To)
June 4, 2026 ยท View on GitHub
MCP server configuration follows the same layered-data pattern as Brew.
Source files:
home/.chezmoidata/mcps/*.yaml(canonical overlays, merged lexically)- schema:
schemas/mcp-servers.schema.json
Shared prep partial (single source of the filtering + $data.* resolution; see
CONTEXT.md and ADR-0001):
home/.chezmoitemplates/mcp-eligible-servers.tmplโ emits the eligible server set per target as JSON
Render targets (each consumes the prep partial via includeTemplate ... | fromJson, then maps to its own schema):
- Cursor via
home/dot_cursor/mcp.json.tmpl - OpenCode via
home/dot_config/opencode/modify_opencode.json(partialhome/.chezmoitemplates/opencode-mcp.jsonc.tmpl) - pi via
home/dot_pi/agent/mcp.json.tmpl - Zed (Unix) via
home/dot_config/zed/modify_settings.json(partialhome/.chezmoitemplates/zed-context-servers.tmpl) - Zed (Windows) via
home/AppData/Roaming/Zed/modify_settings.json(same partial) - Claude Code via
home/modify_dot_claude.json - Claude Desktop (Windows) via
home/AppData/Roaming/Claude/modify_claude_desktop_config.json - mcpproxy via
home/private_dot_mcpproxy/modify_mcp_config.json
Data shape
Each overlay contributes to:
mcp:
serversById:
<server-id>:
enabled: true
local: ... # or remote: ...
serversById is a map keyed by server id. This enables clean layered overrides across multiple YAML files.
Quick start
Add a remote server
mcp:
serversById:
context7:
enabled: true
remote:
url: "https://mcp.context7.com/mcp"
Add a local server
mcp:
serversById:
obsidian:
enabled: true
local:
command: "mise"
args:
- "x"
- "node@22"
- "--"
- "npx"
- "-y"
- "@mauricio.wolff/mcp-obsidian@0.8.2"
- "$data.obsidianVaultPath"
env: {}
Common tasks
Disable a server
mcp:
serversById:
atlassian:
enabled: false
Enable a server for one client only
Targets are opt-in: a server renders to a target only when it explicitly sets
targets.<name>.enabled: true. Unlisted targets get nothing, so to scope a server to a
single client list only that client:
mcp:
serversById:
mcp-atlassian:
enabled: true
targets:
cursor:
enabled: true
Show a server only on certain machines
Use conditions against global chezmoi data (for example from home/.chezmoi.toml.tmpl):
conditions:
private: false
Interpolate data values in args
Use $data.<key> in local.args; template rendering replaces tokens inline.
Field reference
Per-server fields under mcp.serversById.<id>:
enabled(required)conditions(optional)targets(optional, opt-in). Each target defaults tofalse; a server renders to a target only when that target setsenabled: true. Unlisted targets render nothing.targets.<name>.enabledfornamein:cursor,opencode,pi,zed,claudeCode,claudeDesktop,mcpproxy(optional, defaultfalse)- exactly one of
localorremote
local fields:
command(required)args(required)env(optional)
remote fields:
url(required)transport(optional)headers(optional)
Validation
- Render each target with
chezmoi cat <target-path>(orchezmoi execute-template) and confirm valid JSON with the expected servers and resolved$data.*args. - After changing the shared prep partial, confirm render output is byte-identical for the
targets you can render on the current OS (
chezmoi catbefore/after). - Run
pre-commit run --all-files(on Windows run via WSL in this repo).
See .agents/skills/update-mcp-servers/SKILL.md for the full validation workflow.