Configure MCP Servers Once: Claude Code, Cursor, Windsurf

By AppContext ·
mcpclaude-codecursorwindsurf

No AI coding tool reads another tool's MCP configuration. Claude Code, Cursor, and Windsurf each keep their own file in their own location, so adding one MCP server means editing three of them — four if you also run Claude Desktop. There are exactly two ways to configure a server once: keep a single source of truth and sync copies into every file, or run a local MCP hub — one endpoint that aggregates your servers, which each client connects to once and then never needs updating again.

This guide covers where each config file actually lives, the specific mechanisms that make the copies drift apart, and how to set up the one-endpoint approach on macOS.

Where each tool stores its MCP config

These are the paths as of August 2026, taken from each vendor's current documentation:

ToolConfig fileTop-level key
Claude Code — user scope~/.claude.jsonmcpServers
Claude Code — local scope (default)~/.claude.json, nested under the project's pathmcpServers
Claude Code — project scope.mcp.json in the project rootmcpServers
Cursor — global~/.cursor/mcp.jsonmcpServers
Cursor — project.cursor/mcp.jsonmcpServers
Windsurf (Cascade)~/.codeium/windsurf/mcp_config.jsonmcpServers
Claude Desktop (macOS)~/Library/Application Support/Claude/claude_desktop_config.jsonmcpServers

The shared mcpServers key is why copy-paste mostly works, and why people assume this problem is smaller than it is. Claude Code alone accounts for three of those rows: it supports three installation scopes — local (the default, private to you in one project), project (.mcp.json, committed to version control), and user (available across all your projects).

One navigation note: Windsurf's MCP documentation now redirects to Cognition's Devin docs domain, where the page covers Cascade alongside the Devin Desktop naming. The config path itself is unchanged.

Why the copies drift

Duplication isn't the actual problem. Duplication that silently diverges is. Four mechanisms do most of the damage:

1. Claude Code resolves duplicate names by precedence, and does not merge

When the same server name is defined at more than one scope, Claude Code connects once using the highest-precedence definition: local beats project, project beats user. Critically, the entire entry from the winning scope is used — fields are not merged across scopes.

So if you rotate an API key in your committed .mcp.json, but an older local-scoped entry with the same name still sits in ~/.claude.json, the local one wins and your agent keeps using the stale credential. Nothing warns you, because from Claude Code's perspective nothing is wrong. Run claude mcp list to see what actually resolved.

2. Remote-server key names differ between clients

For stdio servers every client takes command and args, so copy-paste is safe. Remote servers are where it breaks. Claude Code and Cursor use url (Claude Code pairs it with a type field), while Windsurf's documented example uses serverUrl. Paste a Cursor block into Windsurf and it may simply not connect.

3. Transport names are moving

Claude Code's docs now state plainly that the SSE transport is deprecated and to use HTTP servers where available. It also accepts streamable-http as an alias for http, so configurations copied straight from a server's own README work unmodified. A config file you wrote a year ago will still work, but it won't match what today's docs tell you to write — and the next person to copy from it inherits that.

4. Every client pays for every server, and their budgets differ

Because each client loads its own copy of the full list, each one also absorbs the full tool count. Windsurf's docs state that Cascade has a limit of 100 total tools available at any given time. Claude Code takes a different tack: it warns when a single MCP tool's output exceeds 10,000 tokens and caps output at 25,000 tokens by default, adjustable via MAX_MCP_OUTPUT_TOKENS. Adding one chatty server to all four files pushes on four different limits at once.

Option 1: one source of truth you sync into each file

The lowest-tech fix is to keep a canonical mcpServers block somewhere you control — a dotfiles repo, a shell script, a Makefile target — and write it into each client's file.

This is a legitimate answer, and it costs nothing to adopt. It has two honest limits. First, you own the sync forever, including the per-client key differences above; the moment anyone hand-edits one file, drift restarts. Second, it doesn't change the runtime picture at all — every client still spawns its own copy of every stdio server, so four clients running a filesystem server means four processes and four full tool lists.

Option 2: one endpoint every client points at

The other approach is to stop distributing the list. A personal MCP hub is itself an MCP server, but instead of exposing its own tools it connects to your upstream servers and re-exposes their tools behind a single endpoint. Each client is configured exactly once, with one entry, and never touched again. Adding, removing, or re-keying a server happens in the hub, and every connected tool sees the change.

Tools are namespaced by server on the way through — a filesystem server's read_file becomes filesystem:read_file — so two upstream servers that both define search don't collide. We go deeper on the mechanics in the MCP Hub guide, and on how this compares to the other native Mac approaches in managing MCP servers in one place on Mac.

Pointing Claude Code, Cursor, and Windsurf at one hub

Here's the concrete setup with AppContext, which runs a hub as a macOS menu bar app and serves its endpoint at http://localhost:7777/sse.

Step 1 — get your existing servers into the hub. Rather than retyping them, AppContext's Servers tab imports from Claude Code (~/.claude.json), Claude Desktop, and Cursor (~/.cursor/mcp.json), and it also discovers project-level .mcp.json files under your usual code directories. Windsurf isn't an import source today, so if a server exists only in mcp_config.json, add that one by hand.

Step 2 — point each client at the hub. One entry each, then you're done.

Claude Code, at user scope so it applies to every project:

claude mcp add --transport sse --scope user appcontext http://localhost:7777/sse

Claude Code labels SSE deprecated in favour of HTTP but still supports it, and AppContext serves SSE today — so this is the correct flag to use here rather than --transport http. Verify with claude mcp list.

Cursor, in ~/.cursor/mcp.json:

{
  "mcpServers": {
    "appcontext": {
      "url": "http://localhost:7777/sse"
    }
  }
}

Windsurf, in ~/.codeium/windsurf/mcp_config.json — note the different key:

{
  "mcpServers": {
    "appcontext": {
      "serverUrl": "http://localhost:7777/sse"
    }
  }
}

Step 3 — remove the now-duplicated entries. This is the step people skip, and skipping it gives you the worst of both worlds: every tool exposed twice, once directly and once namespaced through the hub. Delete the direct entries from each client after you've confirmed the hub route works.

What one choke point actually buys you

Collapsing four config files into one endpoint is a maintenance win on its own, but the more useful consequence is that every tool call from every client now passes through one place you control.

That's where per-tool authorization becomes practical. Blocking an individual tool — the destructive filesystem call, the repository-creating GitHub tool — applies to every connected client at once rather than needing to be re-done in each one, and the free tier covers up to three blocks in total across all your servers. Going beyond three, allowlist mode (where only explicitly permitted tools get through), and per-tool rate limiting are Pro features. Blocked calls return a POLICY_BLOCKED error to the agent rather than failing silently; the authorization guide covers how policies evaluate.

The same endpoint also carries AppContext's own visual-context tools, so an agent can see your iOS Simulator or browser while it works — that's the live view workflow, and it's a Pro feature.

Caveats worth knowing before you commit

A hub adds a component between your agents and your tools, and that's a real tradeoff. If the hub isn't running, none of your clients have MCP tools — versus per-client configs, where a broken config only breaks one tool. Restarting one app is a smaller surface than four config files, but it is a surface.

AppContext specifically is macOS-only today; there's no Windows or Linux build. It serves SSE rather than Streamable HTTP, which works with all three clients above but does mean using Claude Code's deprecated-but-supported flag. And it has no audit log or activity dashboard yet — you can block and rate-limit tool calls, but you can't currently review a history of what was called.

If you only use one AI coding tool, none of this is worth it: edit the one file and move on. The moment you're maintaining the same server list in two or more places, though, the copies will drift, and the question is only whether you'd rather own a sync script or a single endpoint.

AppContext is a free download for macOS, and the MCP Hub is part of the free tier.

Frequently asked questions

Can Claude Code, Cursor, and Windsurf share one MCP config file?

Not natively — each client reads only its own file, and there is no shared or standard location they all look at. You either sync the same mcpServers block into ~/.claude.json, ~/.cursor/mcp.json, and ~/.codeium/windsurf/mcp_config.json yourself, or point all three at a single local MCP hub endpoint so each one holds just one entry.

Where does Windsurf store its MCP server configuration?

Windsurf reads ~/.codeium/windsurf/mcp_config.json, using mcpServers as the top-level key. For remote servers its documented example uses a serverUrl field rather than the url field Cursor and Claude Code use, which is a common reason a config pasted from another client fails to connect.

Why does Claude Code ignore my updated MCP server settings?

Most likely a higher-precedence scope is shadowing the entry you edited. Claude Code resolves duplicate server names local > project > user and uses the winning entry whole, without merging fields from the others. Run claude mcp list to see which definition actually resolved, and remove the stale duplicate.

Does using an MCP hub reduce the number of tools my agent sees?

Not by itself — a hub re-exposes upstream tools behind one endpoint, so the count is broadly the same, just namespaced as server:tool. What it gives you is one place to turn tools off. That matters for Windsurf in particular, whose docs state Cascade has a limit of 100 total tools available at any given time.

Is an MCP hub free to use?

In AppContext, aggregating servers behind one endpoint, importing existing configs, and starting or stopping servers are all part of the free tier, as is blocking up to three tools in total across all your servers. Beyond three blocks, allowlist mode, per-tool rate limiting, and live view are Pro. AppContext is macOS-only today.

What happens to my AI tools if the hub isn't running?

They lose access to every server behind it, because each client now holds a single entry pointing at the hub rather than direct connections. That's the central tradeoff: one place to fix things, but also one thing that has to be up. Clients handle it the same way they handle any unreachable MCP server — the tools simply don't appear.

Give your AI coding agent eyes

AppContext streams live screenshots and logs from your iOS simulator and web app straight into Claude, Cursor, and Windsurf over MCP.

Get AppContext Free