Standardizing Cross-Client MCP Configurations
Eliminating configuration drift across Cursor, Windsurf, Claude Desktop, VS Code, and OpenAI Codex CLI with unified Single-Source-of-Truth (SSOT) schema synchronization.
Generate & Validate Multi-Client MCP Config
One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.
Standardizing Cross-Client MCP Configurations
As Model Context Protocol (MCP) adoption spreads across software engineering organizations, developers increasingly use diverse AI host environments: Cursor for rapid full-stack editing, Windsurf for multi-file cascading flows, Claude Desktop for high-level architectural planning, OpenAI Codex CLI for automated shell scripts, and VS Code for enterprise-governed workflows.
However, each client mandates its own configuration file format, file system path, and schema structure. While Claude Desktop and Cursor use JSON-based mcpServers keys, OpenAI Codex CLI uses TOML tables ([mcp_servers]), and Windsurf uses custom config directories.
This fragmentation causes severe configuration drift: team members run mismatched tool versions, leak plaintext API keys in ad-hoc configs, and struggle to replicate identical agent capabilities across different tools.
This guide provides a production blueprint for managing a Single Source of Truth (SSOT) configuration in YAML, with an automated transpiler and drift-detection CLI.
1. The Cross-Client Configuration Landscape
Each major MCP client runtime stores configuration in distinct OS locations and schema layouts:
graph TD
SSOT[Unified SSOT: .mcp-registry.yaml] --> CLI[mcp-sync Transpiler CLI]
CLI -->|Generate JSON| Cursor[.cursor/mcp.json]
CLI -->|Generate JSON| Claude[claude_desktop_config.json]
CLI -->|Generate JSON| Windsurf[~/.codeium/windsurf/mcp_config.json]
CLI -->|Generate TOML| Codex[~/.codex/config.toml]
CLI -->|Generate JSON| VSCode[.vscode/mcp.json]Path and Format Matrix
| Host Client | Operating System Paths | Format | Top-Level Key |
|---|---|---|---|
| Claude Desktop | macOS: ~/Library/Application Support/Claude/claude_desktop_config.json<br>Windows: %APPDATA%\Claude\claude_desktop_config.json | JSON | mcpServers |
| Cursor IDE | Workspace: .cursor/mcp.json<br>Global: ~/.cursor/mcp.json | JSON | mcpServers |
| Windsurf | ~/.codeium/windsurf/mcp_config.json | JSON | mcpServers |
| OpenAI Codex CLI | ~/.codex/config.toml or ./config.toml | TOML | [mcp_servers] |
| VS Code (MCP) | .vscode/mcp.json | JSON | servers |
2. Defining the Single Source of Truth (.mcp-registry.yaml)
Define all enterprise MCP servers in a central, declarative YAML manifest placed in your repository root or provisioned globally via dotfiles:
version: "1.0"
registry_name: "enterprise-engineering-mcp"
defaults:
env:
NODE_ENV: "production"
LOG_LEVEL: "info"
servers:
filesystem:
description: "Sandboxed workspace filesystem reader"
transport: "stdio"
command: "npx"
args:
- "-y"
- "@modelcontextprotocol/server-filesystem"
- "${WORKSPACE_ROOT}"
env:
FILE_ACCESS_TIER: "restricted"
clients: ["cursor", "windsurf", "claude_desktop", "vscode"]
enterprise-db:
description: "Read-only production PostgreSQL analytics pool"
transport: "sse"
url: "https://mcp-gateway.internal.enterprise.com/sse"
headers:
Authorization: "Bearer ${ENTERPRISE_MCP_TOKEN}"
X-Developer-Email: "${USER_EMAIL}"
clients: ["cursor", "windsurf", "codex", "claude_desktop"]
github-actions:
description: "CI/CD pipeline workflow auditor"
transport: "stdio"
command: "docker"
args:
- "run"
- "-i"
- "--rm"
- "-e"
- "GITHUB_TOKEN"
- "registry.enterprise.internal/ai/mcp-github:v1.2"
env:
GITHUB_TOKEN: "${GITHUB_PERSONAL_ACCESS_TOKEN}"
clients: ["codex", "cursor"]3. Automated Transpiler & Drift Detector (Node.js)
Below is an automated transpiler script (scripts/mcp-sync.mjs) that parses the SSOT YAML, interpolates environment variables safely, and generates exact configuration files for each client:
import fs from 'fs';
import path from 'path';
import os from 'os';
import yaml from 'js-yaml';
const WORKSPACE_DIR = process.cwd();
const REGISTRY_PATH = path.join(WORKSPACE_DIR, '.mcp-registry.yaml');
if (!fs.existsSync(REGISTRY_PATH)) {
console.error(`Error: Missing ${REGISTRY_PATH}`);
process.exit(1);
}
const rawConfig = fs.readFileSync(REGISTRY_PATH, 'utf8');
const parsed = yaml.load(rawConfig);
// Helper: Safely substitute environment variables
function interpolateEnv(str) {
if (typeof str !== 'string') return str;
return str.replace(/\$\{([^}]+)\}/g, (_, key) => {
if (key === 'WORKSPACE_ROOT') return WORKSPACE_DIR;
return process.env[key] || `\${${key}}`;
});
}
function processObjectEnv(obj) {
const result = {};
for (const [k, v] of Object.entries(obj || {})) {
result[k] = interpolateEnv(v);
}
return result;
}
// 1. Generate Standard JSON Client Format (Cursor / Claude / Windsurf)
function generateJsonConfig(targetClient) {
const mcpServers = {};
for (const [id, srv] of Object.entries(parsed.servers)) {
if (!srv.clients.includes(targetClient)) continue;
if (srv.transport === 'stdio') {
mcpServers[id] = {
command: srv.command,
args: srv.args.map(interpolateEnv),
env: processObjectEnv({ ...parsed.defaults.env, ...srv.env })
};
} else if (srv.transport === 'sse') {
mcpServers[id] = {
url: interpolateEnv(srv.url),
headers: processObjectEnv(srv.headers)
};
}
}
return JSON.stringify({ mcpServers }, null, 2);
}
// 2. Generate TOML Format (OpenAI Codex CLI)
function generateCodexToml() {
const lines = ['# Auto-generated by mcp-sync. DO NOT EDIT DIRECTLY.\n'];
for (const [id, srv] of Object.entries(parsed.servers)) {
if (!srv.clients.includes('codex')) continue;
const tomlId = id.replace(/-/g, '_');
lines.push(`[mcp_servers.${tomlId}]`);
if (srv.transport === 'stdio') {
lines.push(`command = "${srv.command}"`);
const argsStr = srv.args.map(a => `"${interpolateEnv(a)}"`).join(', ');
lines.push(`args = [${argsStr}]`);
const mergedEnv = { ...parsed.defaults.env, ...srv.env };
if (Object.keys(mergedEnv).length > 0) {
lines.push(`\n[mcp_servers.${tomlId}.env]`);
for (const [k, v] of Object.entries(mergedEnv)) {
lines.push(`${k} = "${interpolateEnv(v)}"`);
}
}
} else if (srv.transport === 'sse') {
lines.push(`url = "${interpolateEnv(srv.url)}"`);
if (srv.headers?.Authorization) {
lines.push(`bearer_token = "${interpolateEnv(srv.headers.Authorization).replace('Bearer ', '')}"`);
}
}
lines.push('');
}
return lines.join('\n');
}
// 3. Write Targets
const targets = [
{ client: 'cursor', path: path.join(WORKSPACE_DIR, '.cursor', 'mcp.json'), content: generateJsonConfig('cursor') },
{ client: 'windsurf', path: path.join(os.homedir(), '.codeium', 'windsurf', 'mcp_config.json'), content: generateJsonConfig('windsurf') },
{ client: 'codex', path: path.join(WORKSPACE_DIR, 'config.toml'), content: generateCodexToml() }
];
// OS-Specific Claude Desktop Path
const claudePath = process.platform === 'darwin'
? path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
: path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json');
targets.push({ client: 'claude_desktop', path: claudePath, content: generateJsonConfig('claude_desktop') });
for (const target of targets) {
try {
const dir = path.dirname(target.path);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(target.path, target.content, 'utf8');
console.log(`✓ Synchronized [${target.client}] config -> ${target.path}`);
} catch (err) {
console.warn(`! Skipped [${target.client}]: ${err.message}`);
}
}4. Generated Target Artifacts
Output: .cursor/mcp.json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/workspace/repo"
],
"env": {
"NODE_ENV": "production",
"LOG_LEVEL": "info",
"FILE_ACCESS_TIER": "restricted"
}
},
"enterprise-db": {
"url": "https://mcp-gateway.internal.enterprise.com/sse",
"headers": {
"Authorization": "Bearer eyJhbGci...",
"X-Developer-Email": "jane@enterprise.com"
}
}
}
}Output: config.toml (OpenAI Codex CLI)
# Auto-generated by mcp-sync. DO NOT EDIT DIRECTLY.
[mcp_servers.enterprise_db]
url = "https://mcp-gateway.internal.enterprise.com/sse"
bearer_token = "eyJhbGci..."
[mcp_servers.github_actions]
command = "docker"
args = ["run", "-i", "--rm", "-e", "GITHUB_TOKEN", "registry.enterprise.internal/ai/mcp-github:v1.2"]
[mcp_servers.github_actions.env]
NODE_ENV = "production"
LOG_LEVEL = "info"
GITHUB_TOKEN = "ghp_secure_token_991"5. CI/CD Drift Verification in GitHub Actions
To prevent developers from manually tampering with generated configurations, enforce a pull request lint check:
name: Verify MCP Configuration Sync
on: [push, pull_request]
jobs:
verify-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm install js-yaml
- name: Run MCP Transpiler
run: node scripts/mcp-sync.mjs
- name: Assert No Git Drift
run: |
git diff --exit-code .cursor/mcp.json config.toml || (echo "Error: MCP configuration drift detected. Run 'node scripts/mcp-sync.mjs' and commit changes." && exit 1)Related Configuration & Client Setup Guides
Build your full agent toolstack in the Visual Generator
Combine Standardizing Cross-Client MCP Configurations with databases, search APIs, and memory graphs in a single configuration file.
Standardizing Cross-Client MCP Configurations FAQ
What is the Standardizing Cross-Client MCP Configurations?
Eliminating configuration drift across Cursor, Windsurf, Claude Desktop, VS Code, and OpenAI Codex CLI with unified Single-Source-of-Truth (SSOT) schema synchronization.
How do I configure Standardizing Cross-Client MCP Configurations in Claude Desktop or Cursor?
You can copy the configuration JSON from our guide or launch the interactive MCP Codex Config Generator at https://mcp-codex.com/generator to export valid configs in 1 click.
Can I use Standardizing Cross-Client MCP Configurations with the OpenAI Codex CLI?
Yes, OpenAI Codex CLI supports Model Context Protocol. You can add it directly to ~/.codex/config.toml or pass arguments to codex mcp add.
Specializing in Model Context Protocol (MCP) integrations, autonomous AI agent orchestration, and distributed developer toolchains. Researches and benchmarks production MCP client-server architectures across OpenAI Codex, Claude, and Cursor.
Related Guides
Deploying Remote MCP Servers on Kubernetes at Scale
Production guide to deploying containerized remote Model Context Protocol (MCP) servers on Kubernetes with Helm, JSON-RPC queue-based HPA, and secure Ingress.
EnterpriseHardening MCP for SOC 2 and HIPAA Enterprise Workflows
Compliance architecture for Model Context Protocol (MCP): Client-side PII masking, immutable JSON-RPC audit logging, and zero-knowledge data pipelines for SOC 2 and HIPAA.
EnterpriseSandboxing MCP Server Execution: Containers to MicroVMs
Isolating Model Context Protocol (MCP) server execution to neutralize arbitrary code execution, filesystem escapes, and credential exfiltration using Docker rootless, gVisor, and Firecracker microVMs.