Dates are simple. Config files are simple. Two config files that do almost the same thing but silently diverge on one critical behavior — that’s where you lose an afternoon.
Claude Code has two places you can define MCP servers. One of them doesn’t actually work the way you’d expect. There’s no error, no warning, no indication that anything is wrong. The server starts, the API calls fail, and you start debugging the wrong thing.
Here’s the three-attempt debugging journey that led to the fix — and the two rules that would have saved the trip.
The Problem
Claude Code supports MCP (Model Context Protocol) servers — external tools that extend what Claude can do. You configure them with a command, arguments, and environment variables (typically API keys). The config looks identical whether you put it in settings.json or .mcp.json. But the behavior isn’t identical at all.
settings.json silently ignores env blocks for MCP servers. The process spawns. It runs. But it never receives the environment variables you defined. Every API call that depends on those secrets fails — and the error comes from the downstream service, not from Claude Code. You’ll see auth errors, 401s, or cryptic API failures that point you toward the MCP server itself, not the config.
The Debugging Journey
Attempt 1 — settings.json (env silently ignored)
The natural place to put MCP config. It’s where Claude Code settings live. It even has an mcpServers key. So you add your server:
// ~/.claude/settings.json
{
"mcpServers": {
"stitch": {
"command": "npx",
"args": ["@_davideast/stitch-mcp", "proxy"],
"env": {
"STITCH_API_KEY": "your-key-here"
}
}
}
}
Server starts. Every API call fails. No indication that STITCH_API_KEY was never passed to the process.
Attempt 2 — .mcp.json in the wrong location
You learn that .mcp.json is the right file for MCP servers. You create it — but in ~/.claude/.mcp.json, next to settings.json. Seems logical.
// ~/.claude/.mcp.json — WRONG PLACE for project-scoped servers
{
"mcpServers": {
"stitch": {
"type": "stdio",
"command": "npx",
"args": ["@_davideast/stitch-mcp", "proxy"],
"env": {
"STITCH_API_KEY": "your-key-here"
}
}
}
}
Claude Code doesn’t see it. No “new server found” prompt. No error. Nothing.
Attempt 3 — .mcp.json at the project root (works)
Move the file to the root of your project — the directory where you launch Claude Code:
// /path/to/your/project/.mcp.json — RIGHT PLACE
{
"mcpServers": {
"stitch": {
"type": "stdio",
"command": "npx",
"args": ["@_davideast/stitch-mcp", "proxy"],
"env": {
"STITCH_API_KEY": "your-key-here"
}
}
}
}
Next session start: “New MCP server found in .mcp.json: stitch” — the confirmation prompt that means it’s actually working.
The Rules
Two things to know. That’s it.
1. MCP env vars only work in .mcp.json, not settings.json. The settings.json file is for Claude Code preferences and permissions. MCP server definitions belong in .mcp.json. Both files accept an mcpServers key — only one of them passes env vars to the spawned process.
2. Project-scoped .mcp.json must be at the repo root. The directory where you launch Claude Code. Not in a subdirectory, not in ~/.claude/ (that’s for user-scoped servers that apply everywhere). Claude Code scans the working directory root on startup. If the file isn’t there, it’s invisible.
The Confirmation Signal
When Claude Code finds a new MCP server, it shows:
New MCP server found in .mcp.json: {name}
If you don’t see this prompt on startup after adding a new server, the file isn’t being read. Check the location.
Bonus: Cached Failure State
One more gotcha. If an MCP server fails to connect on first attempt, Claude Code may cache that failure. Subsequent /mcp reconnect attempts can fail instantly without re-spawning the process — even after you’ve fixed the underlying issue.
The fix: rename the server key in .mcp.json (e.g., stitch to google-stitch). Claude Code treats it as a new server and makes a fresh connection attempt. Restart the session after renaming.
Pro Tips
- Use the full path to
npxif you’re on nvm (e.g.,/Users/you/.nvm/versions/node/v24.14.0/bin/npx). Claude Code’s shell may not inherit your nvm setup. - Use variable expansion to keep secrets out of config:
"STITCH_API_KEY": "${STITCH_API_KEY}"references your shell environment. - Test the MCP server manually first — run the command with the env var exported and confirm it works. Then narrow the problem to config placement.
- Two valid
.mcp.jsonscopes exist: user-scoped (~/.claude/.mcp.json) applies to all projects, project-scoped (.mcp.jsonat repo root) applies to that project only.