There is no shared schema for a server entry. Every client invented its own field set on top of the same two ideas, a command to launch or a URL to call. This is what each one documents, read on 2026-09-08.
| Field | Claude Desktop | Claude Code | Cursor | VS Code | Windsurf | Cline |
|---|---|---|---|---|---|---|
command | yes | yes | yes, required for stdio | yes | yes | yes |
args | yes | yes | yes | yes | yes | yes |
env | yes | yes, or --env | yes | yes | yes | yes |
type | not documented | yes, http / streamable-http / ws | required | yes | documented as stdio, HTTP and SSE | yes, and the default is the trap |
url | not applicable | yes | yes | yes | serverUrl or url | yes |
headers | not applicable | yes, or --header | yes | yes | yes | yes |
envFile | no | no | yes, stdio only | no | no | no |
timeout | no | yes, milliseconds, per server | no | no | no | set in MCP settings |
disabled | no | toggled, stored in ~/.claude.json | no | stored outside mcp.json | toggled per tool | yes, in the entry |
autoApprove | no | no | no | no | no | yes, an array of tool names |
inputs | no | no | no | yes, top-level, with ${input:id} | no | no |
sandboxEnabled | no | no | no | yes, macOS and Linux | no | no |
| Client | Syntax | Fields it expands in |
|---|---|---|
| Claude Code | ${VAR} and ${VAR:-default} | command, args, env, url, headers |
| Cursor | ${env:NAME}, ${userHome}, ${workspaceFolder} | command, args, env, url, headers |
| Windsurf | ${env:VAR} and ${file:/path/to/file} | command, args, env, serverUrl, url, headers |
| VS Code | ${input:id} against a top-level inputs array | server configuration values |
| Claude Desktop | none documented | literal values in env |
Windsurf's ${env:VAR} resolves to an empty string when the variable is unset, and its
${file:...} is left as-is when the file cannot be read. Both are worth knowing before
you debug an authentication failure: the config did what it was told and told you nothing.
type, omitted. Cline falls back to the legacy SSE transport. Claude
Code reads an entry with a url and no type as a stdio server, skips it, and
reports that the entry has a url but no type. Cursor's field table marks it required outright.
command, bare. Cursor's documentation is precise about this: the
command must be available on your system path or contain its full path. The path a desktop client has
is not the path your shell has.
envFile, on a remote server. Cursor supports it for stdio servers only.
An HTTP or SSE server does not read it, and the fix is interpolation from the shell environment
instead.
The top-level key. Not a field, but the same class of failure. VS Code expects
servers; the other five expect mcpServers. Table at
MCP config file locations.
// Claude Desktop, Cursor, Windsurf, Cline, Claude Code
{ "mcpServers": { "invoice": {
"type": "stdio",
"command": "/opt/homebrew/bin/node",
"args": ["/Users/you/mcp-servers/servers/invoice/dist/index.js"]
} } }
// VS Code
{ "servers": { "invoice": {
"command": "/opt/homebrew/bin/node",
"args": ["/Users/you/mcp-servers/servers/invoice/dist/index.js"]
} } }
type: "stdio" is harmless in the clients that do not require it and required in Cursor,
so writing it always is one less thing to remember.
Claude Desktop from modelcontextprotocol.io/docs/develop/connect-local-servers, Claude Code from docs.claude.com/en/docs/claude-code/mcp, Cursor from cursor.com/docs/context/mcp, VS Code from code.visualstudio.com/docs/copilot/customization/mcp-servers, Windsurf from docs.devin.ai/desktop/cascade/mcp, Cline from docs.cline.bot/mcp/mcp-overview. All read 2026-09-08. A blank cell means the vendor does not document the field, not that it is known to be unsupported.
The 30 MCP servers published from this repository ship a per-client config block for each of these,
generated from one table so a field cannot drift on one page and not the others; the source rows are in
billing/src/setup.js.
No. The specification standardises the wire protocol, not the client's server list. The shared shape is a map of server names to objects with command and args or url, and everything past that is per vendor.
Only by symlinking, and only among the five that use mcpServers with the same field names. VS Code's servers key rules it out, and any entry using a client-specific variable syntax stops being portable the moment it is expanded.
The confirmation prompt before a tool call, per tool name, in Cline. Read-only tools are reasonable candidates. Anything that writes a file, sends a request or spends money is worth leaving off it, because seeing the call before it happens is the point of the prompt.
None of them hold a secret safely as a literal. VS Code's inputs array and every client's variable interpolation exist so the value stays outside a file that gets committed. Cursor's envFile is the same idea for stdio servers.
All MCP servers and prices · All guides · Buy the bundle $39