Connect an MCP server to Windsurf
Windsurf's agent, Cascade, reads MCP servers from one JSON file — ~/.codeium/windsurf/mcp_config.json — with a plugin store and an MCPs panel that write to the same place. Remote servers take a URL, local
servers a launch command; every brand page here tells you which.
Where the config lives
Three routes to the same file: the MCPs icon in the Cascade panel's top-right menu, the MCP servers section of Windsurf's settings, or the plugin store for one-click installs of popular servers. Hand-editing works too:
Local (stdio) servers
{
"mcpServers": {
"example": {
"command": "npx",
"args": ["-y", "@vendor/mcp-server"],
"env": { "VENDOR_API_KEY": "${env:VENDOR_API_KEY}" }
}
}
}Python servers use uvx as the command. The ${env:…} form reads
the value from your environment at launch, so the secret never sits in the file — ${file:/path} does the same from a key file. After saving, refresh the
server list from the MCPs panel.
Remote (hosted) servers
Windsurf's remote config uses serverUrl where most clients use url:
{
"mcpServers": {
"linear": {
"serverUrl": "https://mcp.linear.app/mcp"
}
}
}Streamable HTTP and SSE are both supported, and OAuth sign-in kicks in automatically for
servers that require it — token-based servers take a headers object instead.
Servers you can add this way right now: fal.ai, Atlassian, Datadog, Buffer, Google Drive, Confluence.
The 100-tool budget
Cascade has a hard limit of 100 tools visible at once, summed across every enabled server. Big servers spend that budget fast — GitHub's alone ships dozens. When you cross the line, tools silently drop out. Treat servers like dependencies: enable what the project needs, toggle the rest off in the MCPs panel.
When it doesn't work
| Symptom | Usual cause | Fix |
|---|---|---|
| Server never appears | Invalid JSON | Check for a trailing comma, then hit refresh in the MCPs panel |
| Appears, fails to start | npx not on Windsurf's PATH | Use the absolute path from which npx |
| Starts, then exits | Missing API key | Set it in env — run the command in a terminal to see the real error |
| Remote server won't connect | Wrong field name | Remote needs serverUrl — a command-style block won't work |
| Tools randomly missing | Over the 100-tool limit | Disable unused servers or trim tools per server |
| Server blocked entirely | Team allowlist | Admins enforce allowlists — non-listed servers are blocked for members |
A word on trust
An MCP server runs with the credentials you give it, and Cascade acts on whatever it returns. Prefer official servers where they exist, and give community ones scoped, revocable keys. More in our MCP security guide.
Questions
Where is Windsurf's MCP config file?
~/.codeium/windsurf/mcp_config.json — the codeium in the path is the company's old name and still current on disk. The MCPs panel in Cascade and the plugin store both write to this same file.
Does Windsurf support remote MCP servers?
Yes — stdio, streamable HTTP and SSE, with OAuth sign-in supported on all of them. Remote servers use a serverUrl field (url also works) instead of a command.
Why did Cascade stop using some of my tools?
Cascade caps the tools it can see at 100 across every enabled server. Past that, tools get dropped — disable the servers a project doesn't need, or trim tools per server from the MCPs panel.
How do I keep secrets out of mcp_config.json?
Windsurf interpolates ${env:VAR_NAME} and ${file:/path/to/file} inside config values, so the file can reference a shell variable or a key file instead of containing the secret itself.
Can a team admin control which MCP servers we use?
Yes. Team admins can enforce an allowlist — when one is active, every non-allowlisted server is blocked for members — and can point the plugin store at a custom registry.