Claude Code MCP Config: .mcp.json, Scopes und Vorrang
Local, Project oder User Scope: wo Claude Code MCP-Server speichert, welche Definition gewinnt und wie du .mcp.json mit ${VAR} sicher ins Repo legst.
- Server mit persönlichen Credentials im Local Scope, nicht in .mcp.json
- Jedes Remote-Entry mit url hat auch ein type, sonst liest Claude Code es als stdio
- Secrets nur als ${VAR}, Defaults per ${VAR:-default} für Pfade und Base-URLs
- Keine Claude-Code- oder Cloud-Credentials wie ANTHROPIC_API_KEY im Header referenzieren
- Gleicher Servername nicht in mehreren Scopes mit verschiedenen Endpoints
- Unerwünschte Projekt-Server über disabledMcpjsonServers blocken
- Headless-Läufe mit --strict-mcp-config und --mcp-config fahren
Grafik: Vibecoding Pro · Grundlage: die Quellen unten
Du hast einen MCP-Server mit claude mcp add eingerichtet, er läuft, und dann klont ein Kollege das Repo und sieht nichts davon. Oder umgekehrt: Ein Server, den du gar nicht mehr willst, taucht in jedem Projekt wieder auf. In beiden Fällen lohnt der Blick auf den Scope. Claude Code kennt drei Orte für MCP-Konfiguration, und die Regeln, welcher davon gewinnt, sind strenger, als die meisten annehmen. Grundlage hier ist die offizielle MCP-Doku von Claude Code.
Drei Scopes, zwei Dateien
Jedes claude mcp add und claude mcp add-json schreibt in den Local Scope, solange du nicht --scope project oder --scope user mitgibst.
- Local (Default): lädt nur im aktuellen Projekt, bleibt privat. Gespeichert in
~/.claude.jsonunter dem Pfad des Projekts. Richtig für experimentelle Server und alles mit persönlichen Credentials. - Project: lädt nur im aktuellen Projekt, wird aber über
.mcp.jsonim Repo-Root geteilt. Claude Code legt die Datei bei Bedarf selbst an. Die Datei gehört ins Version Control. - User: lädt in allen deinen Projekten, bleibt privat, liegt ebenfalls in
~/.claude.json. Gedacht für persönliche Utilities, die du überall brauchst.
Wichtig für das Debugging: Local und User teilen sich dieselbe Datei. Ein cat ~/.claude.json zeigt dir beide, nur an unterschiedlichen Stellen.
Vorrang: ganzer Eintrag statt Merge
Steht derselbe Server an mehreren Stellen, verbindet sich Claude Code genau einmal, und zwar mit der Definition aus der Quelle mit dem höchsten Rang:
- Local
- Project
- User
- Plugin-Server
- claude.ai Connectors
Der Trade-off, über den man stolpert: Es wird nicht gemerged. Überschreibst du im Local Scope einen Projekt-Server, um nur einen Header zu ändern, gilt dein kompletter lokaler Eintrag. Alles, was das Team später in .mcp.json ändert, siehst du nicht mehr.
Zwischen den drei Scopes matcht Claude Code per Name. Plugins und Connectors werden dagegen per Endpoint verglichen: Zeigen sie auf dieselbe URL oder denselben Command wie ein Server weiter oben, gelten sie als Duplikat. Groß-/Kleinschreibung von Scheme und Host, ein Default-Port wie :443 oder ein Slash am Ende machen keinen Unterschied, ein anderer Pfad oder Query-String schon. Ein Server, den deine Organisation über managedMcpServers bereitstellt, steht über allem (ab v2.1.259).
Gleicher Name in mehreren Scopes mit unterschiedlichen Endpoints erzeugt eine Warnung in claude mcp list und /mcp. Weil OAuth-Logins pro Endpoint gespeichert werden, musst du dich sonst in jedem Projekt separat anmelden. Aufräumen mit claude mcp remove <name> --scope <scope>.
.mcp.json teilbar machen mit ${VAR}
Damit .mcp.json ins Repo darf, gehören Secrets und maschinenspezifische Pfade nicht hinein. Claude Code expandiert Variablen in command, args, env, url und headers:
{
"mcpServers": {
"api": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${API_KEY}" }
}
}
}
Drei Details, die in der Praxis Zeit kosten:
- Fehlender Wert ohne Default: Der Server lädt trotzdem, mit dem unexpandierten
${VAR}-Text.claude mcp listwarnt und nennt die Variable. - Leerer String zählt als gesetzt:
API_BASE_URL=""ergibt die URL/mcp, nicht den Default. Variable unsetten statt leeren. - Credential-Variablen bleiben leer: In
urlundheadersvon Remote-Servern liest Claude Code eigene und Cloud-Credentials wieANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,AWS_BEARER_TOKEN_BEDROCK,HTTPS_PROXYoderNPM_TOKENimmer als leer, auch ein:-defaultwird ignoriert. Das verhindert, dass ein fremdes.mcp.jsondeine Keys an einen Server schickt. Der Server antwortet dann meist mit401. Brauchst du so einen Wert, kopierst du ihn in eine eigene Variable.
Außerdem: Ein Entry mit url, aber ohne type, wird als stdio-Server gelesen und übersprungen. streamable-http wird als Alias für http akzeptiert. Versteckte Whitespace-Zeichen, etwa ein Newline hinter einem eingefügten Token, meldet Claude Code als Warnung, trimmt sie aber nicht.
Approval, Trust und Headless
Projekt-Server aus .mcp.json brauchen in interaktiven Sessions eine Freigabe. Bis dahin zeigt claude mcp list sie als ⏸ Pending approval. Zurücksetzen lässt sich das mit claude mcp reset-project-choices. Ein geklontes Repo kann sich nicht selbst freigeben: enableAllProjectMcpServers oder enabledMcpjsonServers in der eingecheckten .claude/settings.json werden ignoriert, solange der Ordner nicht als vertrauenswürdig bestätigt ist. Freigaben aus ~/.claude/settings.json, Managed Settings und --settings gelten dagegen auch dort.
Die Kehrseite: Bei claude -p, im Agent SDK und in Cloud-Sessions außerhalb eines Projekts gibt es keinen Prompt, Projekt-Server werden ohne Rückfrage geladen. Gleiches gilt für bypassPermissions mit skipDangerousModePermissionPrompt. Wenn dein CI-Job fremde Branches auscheckt, ist das relevant. Dein Werkzeugkasten:
disabledMcpjsonServersblockt einen Server in jedem Permission Mode.--setting-sources(bzw.settingSourcesim SDK) schließt Projekt-Settings ganz aus.--strict-mcp-confignutzt nur die Server aus--mcp-config. Dass dabei nicht mehr auf Approval für ungeladene Projekt-Server gewartet wird, gilt erst ab v2.1.246.
Wie du Tool-Aufrufe zusätzlich einschränkst, steht in settings.json Permissions. Für Server mit Datenbankzugriff lohnt der Blick auf MCP-Server Guardrails.
Was das für deinen Workflow bedeutet
Behandle .mcp.json wie Code: nur Server, die das ganze Repo braucht, keine Secrets, nur ${VAR}-Referenzen, jeder Remote-Eintrag mit explizitem type. Persönliches gehört in Local oder User. Lokale Overrides eines Projekt-Servers sind eine Falle, weil sie den Team-Eintrag komplett verdecken. Und für Headless-Läufe definierst du die erlaubten Server explizit, statt dich auf einen Approval-Prompt zu verlassen, der dort nie erscheint. Wer Bash-Zugriff zusätzlich einhegen will, findet das in Claude Code Sandbox.
Die Scope-Regeln sind schnell erklärt, die Wechselwirkung mit Settings, Trust und CI ist es nicht. Du willst wissen, ob deine .mcp.json, deine Freigaben und dein CI-Setup zusammenpassen? Fordere ein Agent-Setup-Review an.
Häufige Fragen
Welche MCP Scopes gibt es in Claude Code?
Es gibt drei: Local (Default, nur das aktuelle Projekt, privat, in ~/.claude.json), Project (nur das aktuelle Projekt, per .mcp.json im Repo geteilt) und User (alle deine Projekte, privat, ebenfalls in ~/.claude.json).
Welche Definition gewinnt, wenn ein MCP-Server in mehreren Scopes steht?
Claude Code verbindet sich nur einmal und nimmt den kompletten Eintrag aus der Quelle mit dem höchsten Vorrang: Local vor Project vor User, danach Plugin-Server und claude.ai Connectors. Felder werden nicht über Scopes hinweg gemerged.
Fragt Claude Code bei Servern aus .mcp.json immer nach Freigabe?
Nur in interaktiven Sessions. Bei claude -p, im Agent SDK und in Cloud-Sessions außerhalb eines Projekts lädt Claude Code Projekt-Server ohne Rückfrage. Wer einen Server sicher draußen halten will, nutzt disabledMcpjsonServers oder --strict-mcp-config.
Warum kommt mein Bearer-Token aus ${ANTHROPIC_AUTH_TOKEN} nicht beim MCP-Server an?
In url und headers von Remote-Servern liest Claude Code Credential-Variablen wie ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN oder NPM_TOKEN absichtlich als leer. Kopiere den Wert in eine eigene Variable und referenziere diese.