Magic Tools
Developer ToolsBy CooconAugust 3, 2026330 views5 min read

MCP Config Generator: How to Write a Correct mcp.json for Claude Code, Cursor & VS Code

Most MCP setup failures are not the server's fault. They are mistakes in the config file — a trailing comma, a comment left in strict JSON, a command line crammed into the wrong field, or a root key that one client accepts and another silently ignores. This guide explains how MCP config files actually work across the major clients, shows you the exact file each one reads, and covers the errors that trip everyone up.

What Is an MCP Config File?

MCP (Model Context Protocol) servers are configured through JSON files. Each client — Claude Code, Claude Desktop, Cursor, VS Code — reads a different file, and they do not all agree on the structure. The two things that vary are:

  1. Where the file lives
  2. The root key (mcpServers vs servers)

Get either one wrong and the client silently ignores your server, or throws a confusing parse error that says nothing about the real problem.

Where Is the mcp.json File Located for Each Client?

Client Config file Root key
Claude Code .mcp.json at the project root (plus user-level config) mcpServers
Claude Desktop claude_desktop_config.json in its app-support folder mcpServers
Cursor .cursor/mcp.json mcpServers
VS Code .vscode/mcp.json servers

The filename and location matter as much as the JSON itself. Save a Claude Code config where VS Code expects it and VS Code will never see it.

How to Add an MCP Server to Claude Code

Two ways, and a good MCP config generator gives you both:

  1. Save an .mcp.json at your project root with the server under the mcpServers key. Checked into the repo, it works for everyone on the team.
  2. Run claude mcp add from the terminal to register the server without creating a file.

For team projects the checked-in file is the better choice — it version-controls the setup. For personal experiments the CLI command is faster.

stdio vs HTTP: Two Transport Shapes

stdio servers are local processes the client launches directly (command + args). They suit tools that need local access — files, databases, your machine's capabilities.

HTTP servers are remote endpoints connected by URL. The modern Streamable HTTP transport has replaced the deprecated SSE transport; if you see "transport": "sse" in an old config, that is a migration signal.

The #1 Mistake: Arguments in the Wrong Field

The most common error in stdio configs is writing the whole command line into command:

{ "command": "npx -y @modelcontextprotocol/server-filesystem" }

Clients execute command directly, without going through a shell. There is no file called npx -y @modelcontextprotocol/server-filesystem, so this fails. The executable goes in command, and every argument becomes its own string in args:

{
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem"]
}

This is the single most common stdio configuration mistake, and a proper validator checks for it specifically.

Other Common mcp.json Errors

  • Trailing commas after the last item in an object or array — legal in JavaScript, illegal in strict JSON
  • // comments — legal in JavaScript, illegal in strict JSON
  • Misspelled root keys — mcpservers (wrong case) or mcpServer (wrong pluralization) instead of mcpServers
  • args that isn't an array — some tools accept a single string; the schema wants an array
  • Outdated transport — sse instead of streamable-http

Client error messages rarely tell you which of these you hit. That is why a validator that names the exact mistake and the fix beats staring at a generic parse error.

Don't Commit API Keys

MCP configs routinely carry tokens, and the files are easy to commit by accident. Claude Code supports ${VAR} environment-variable expansion inside .mcp.json values, so you can commit the config and keep secrets in the environment:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" }
    }
  }
}

For other clients, keep secret-bearing configs out of version control or inject values at deploy time.

Generate and Validate, Don't Hand-Write

Config syntax is unforgiving and the details differ per client. Use the MCP Config Generator to produce a correct mcp.json for Claude Code, Claude Desktop, Cursor, or VS Code — it picks the right file path and root key for your client, and for Claude Code it also prints ready-to-run claude mcp add commands. Paste an existing config into its validator and it reports each problem with the fix, not a generic parse error.

Everything runs locally in your browser, which matters because mcp.json files routinely carry API keys and tokens.

FAQ

Where is the mcp.json file located for each client? Claude Code reads .mcp.json at the project root, Claude Desktop reads claude_desktop_config.json in its app-support folder, Cursor reads .cursor/mcp.json, and VS Code reads .vscode/mcp.json.

Why does my mcp.json fail to parse? Almost always a trailing comma after the last item, or a // comment — both legal in JavaScript, neither legal in strict JSON. A validator points at the exact line.

What's the difference between stdio and HTTP transport? stdio servers are local processes launched by the client (command + args), for local resources. HTTP servers are remote endpoints connected by URL; Streamable HTTP has replaced the deprecated SSE transport.

Why must arguments go in args, not command? Clients execute command without a shell. "command": "npx -y server" looks for a file literally named npx -y server and fails. Executable in command, each argument as its own string in args.

How do I avoid committing API keys inside .mcp.json? Claude Code supports ${VAR} expansion, so commit the config and keep secrets in the environment. For other clients, keep secret-bearing configs out of version control or inject at deploy time.

Is my config uploaded anywhere? No. Both the generator and the validator are pure client-side JavaScript — your config, including any tokens in it, never leaves the browser.

Related Articles

Blocking rm -rf in Claude Code: A Deny Rule Stopped 14 Deletes in Two Weeks, 7 Other Spellings Still Get Through, and a Hook That Closes the Gap

To keep Claude Code from deleting things by accident, I added a deny rule, Bash(rm -rf *), to my global settings. Across my sessions from October 7 to 21 it blocked 14 deletes. After each denial the model picked a new directory name 8 times and dropped the delete 6 times. It never tried another spelling. Then I replayed 22 delete commands verbatim against Claude Code 2.1.285 through a stub. rm -fr, rm -r -f, rm -Rf and rm -r deleted the directory in manual, auto and bypass mode alike. /bin/rm, find -delete and bash -c deleted it in manual and bypass mode. In auto mode, rm -fr inside the working directory skips the classifier because it 'would be allowed in acceptEdits mode'. A second, built-in dangerous-rm check fires on targets like $D/*, even in bypass mode, but loses track of a variable assignment when a heredoc comes earlier in the same command. The post ends with a PreToolUse hook that blocks every recursive spelling in all three modes and tells the model what to do instead.

claude-codehooks+5
pitfallsOct 21, 20268 min
407

The Self-Reinforcing Flywheel Is Harder Than It Looks: 40 Days of an LLM Auto-Tuning Loop

We ran an 'LLM proposes, code decides' auto-tuning loop on a daily WeChat newsletter for 40 days: 18 versions, 8 rollbacks. Three of those rollbacks overturned decisions a human had made, and one version whose knobs were identical to its parent still got rolled back. Using our real numbers, telling apart a 20% difference needs about 25,000 reads per version. At 60 reads a day, that is more than 400 days. This postmortem covers five reasons the flywheel never turned, and what actually moved the numbers.

wechatpostmortem+4
pitfallsOct 21, 20268 min
268

Dev Breakfast · 2026-10-21

Today's headline: A single "bonsoir, Elliot" makes the model leak its .env: a backdoor for under $50. Plus 4 more: DeepSeek open-sources its inference engine: V4.1 Flash only, and KV cache still missing; TorchTPU goes open source: PyTorch models can run directly on TPU; and more.

daily-intelOct 21, 20268 min
606

Dev Breakfast · 2026-10-20

Today's headline: Should You Merge AI Code You Don't Understand: Settle the Abstraction Layer Yourself First. Plus 4 more: tmux as a Remote Control: Multi-Session Claude Code and send-keys; headroom Goes Open Source: 95% Token Savings on JSON, Only 20% for Coding Agents; and more.

daily-intelOct 20, 20265 min
551

Published by Magic Tools