Skip to content

Claude Code connects to MCP (Model Context Protocol) servers registered with claude mcp add at one of three scopes: local, user, or project. Project-scoped servers live in a committed .mcp.json that expands ${VAR} references, so secrets stay out of git. Each server should pass a health check and a scripted tool-call test before its output is trusted.

This page is for the developer wiring Claude Code to the services they use every day, and for the tech lead who wants the same servers on every teammate’s machine. You ask Claude Code to fix the top Sentry error, and it says it cannot reach Sentry. You connect GitHub, and a week later nobody can tell whether the agent read the CI log or guessed. Connecting a server takes one command. Scoping what it may do, and proving that it actually ran, takes the rest of this page.

What you’ll walk away with from Claude Code MCP setup

Section titled “What you’ll walk away with from Claude Code MCP setup”
  • A first server (Context7) connected and proven live with claude mcp list, /mcp, and a prompt that forces a real tool call.
  • Copy-paste commands for the servers most teams start with: GitHub, Sentry, Linear, Atlassian, Figma, and a read-only database.
  • A scope decision (local, project, or user) and a committed .mcp.json with no secrets in it.
  • Permission rules that stop an MCP tool from writing without asking, and the settings that keep tool output from flooding the context.
  • A headless claude -p smoke test that fails when a required server did not start or was never called.

Before you start, finish Claude Code configuration. Every command here was checked on Claude Code 2.1.283 (the latest channel; claude --version) on 2026-09-26, except the passages that name a later version or 2026-10-12, which were re-checked against Claude Code 2.1.296 and Anthropic’s pages that day.

How does Claude Code connect to an MCP server?

Section titled “How does Claude Code connect to an MCP server?”

An MCP server gives Claude Code extra tools next to its built-in ones such as Read, Edit, and Bash. Each tool appears under the name mcp__<server>__<tool>, for example mcp__github__get_file_contents. You then ask for the outcome in plain language, and Claude Code decides which tool to call.

TransportHow Claude Code reaches itUse it forAdd it with
http (streamable HTTP)A URL, with OAuth or a headerHosted services: GitHub, Sentry, Linear, Atlassian, Figmaclaude mcp add --transport http <name> <url>
stdio (the default)Claude Code starts a local processDatabases, local tools, anything in Docker or npxclaude mcp add <name> -- <command> [args]

SSE is deprecated; use http for any hosted server that offers both. Claude Code negotiates the MCP 2026-07-28 protocol with direct HTTP servers by default (on all installs from v2.1.274) and, from v2.1.292, with local stdio servers too, and from v2.1.295 with claude.ai connectors on installs that fetch no feature flags (the v2.1.292 change and the v2.1.274 default are on both channels on 2026-10-17; the v2.1.295 change is on the latest channel only; MCP_PROTOCOL_NEGOTIATION=legacy opts out), which matters only when an older server misbehaves; see When Claude Code MCP servers break. The MCP overview explains the protocol itself.

Start with Context7: it needs no account, and one prompt shows whether it answered.

  1. Add the server in your terminal, from the project directory. Everything after -- is the command Claude Code runs:

    Terminal window
    claude mcp add context7 -- npx -y @upstash/context7-mcp

    Claude Code prints Added stdio MCP server context7 ... to local config. Local scope is the default, so the entry is stored in ~/.claude.json under this project’s path and nobody else sees it.

  2. Confirm that it starts. claude mcp list health-checks every server it is allowed to connect to; claude mcp get context7 shows one:

    Terminal window
    claude mcp list
    claude mcp get context7
  3. Start claude and type /mcp. It shows each server’s status and tools. /mcp reconnect context7 retries a server without restarting the session.

  4. Make Claude Code call a tool: paste the prompt below into the session, and check that the answer names a Context7 library ID and quotes a doc snippet.

The prompt demands the library ID and a quoted snippet on purpose. An answer without them came from the model’s training data, not from the server, and that is the failure you are ruling out.

Each tab gives the command and what to watch for. For hosted servers with OAuth, run /mcp in a session and pick the server to log in, or run claude mcp login <name> from the terminal (add --no-browser over SSH). URLs were checked against the vendors’ registry entries and READMEs in September 2026.

GitHub’s official remote server covers PRs, issues, and Actions logs. Claude Code sends a fine-grained personal access token as a header. Keep the token in your shell and put only the variable name in the config. The single quotes stop your shell from expanding it:

Terminal window
export GITHUB_PAT=github_pat_... # in your shell profile, never in a file you commit
claude mcp add --transport http --scope project github https://api.githubcopilot.com/mcp/ \
-H 'Authorization: Bearer ${GITHUB_PAT}'

The .mcp.json entry keeps the literal ${GITHUB_PAT}, and Claude Code expands it at startup. For triage-only work, point at https://api.githubcopilot.com/mcp/readonly, which exposes no write tools. gh in Bash covers much of the same ground with fewer tokens, so many teams run both. Toolsets and lockdown mode: GitHub MCP.

Slack’s official server needs a pre-registered OAuth client, so install it as the slack@claude-plugins-official plugin (/plugin in a session) rather than with a bare claude mcp add line. Browse the rest with /plugin, and compare servers on essential MCP servers before you add more than three.

Not every integration needs a server. An MCP server earns its place when the agent needs live data or actions in another system: an open Sentry issue, a Jira ticket, a database row. When the job is a procedure the agent should follow, such as your release checklist or how to write a migration, a skill is lighter: it costs almost no context until it is used and needs no process or token. Many vendors ship both in one plugin, as Figma does above. See Agent Skills for the other half of that decision.

Should a server be local, project, or user scope?

Section titled “Should a server be local, project, or user scope?”

Pick the scope by who needs the server and whose credentials it uses:

ScopeFlagStored inChoose it when
Local (default)--scope local~/.claude.json, under this project’s pathYou are trying a server, or it uses your personal account in one repo
Project--scope project.mcp.json at the repository root, committedEvery teammate needs it in this repo, and credentials come from ${VAR} or OAuth
User--scope user~/.claude.json, for all projectsIt is a personal tool you want everywhere, such as Context7

A committed .mcp.json looks like this. It holds only URLs, commands, and variable names:

{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": { "Authorization": "Bearer ${GITHUB_PAT}" }
},
"sentry": { "type": "http", "url": "https://mcp.sentry.dev/mcp" },
"context7": { "type": "stdio", "command": "npx", "args": ["-y", "@upstash/context7-mcp@4.1.1"] }
}
}

The stdio entry pins a version (@upstash/context7-mcp 4.1.1 on npm, 26 September 2026): every teammate runs this command, so a floating npx package is a supply-chain risk. ${VAR} and ${VAR:-default} expand in command, args, env, url, and headers. Use a default only for non-secret values such as a staging base URL. Document the variables each server needs in CLAUDE.md or the README.

Project servers do not start until each person approves them. claude mcp list shows them as Pending approval, and the first interactive claude session in the repository asks. That prompt is a safeguard: a .mcp.json from an untrusted branch can launch any command on your machine. To pre-approve named servers, list them in enabledMcpjsonServers in your settings; avoid enableAllProjectMcpServers: true outside repositories you control.

Control what each MCP server may do and what it costs

Section titled “Control what each MCP server may do and what it costs”

Every server puts its tools in reach of the model, and a write tool acts with its token’s full rights. Permission rules decide what happens next: an allow rule lets a tool run without asking, and a deny rule blocks it in every permission mode, auto mode included. Allow the read-only servers and deny the irreversible tools. Put team rules in .claude/settings.json:

{
"permissions": {
"allow": ["mcp__context7", "mcp__sentry"],
"deny": ["mcp__github__merge_pull_request", "mcp__github__delete_file"]
}
}

mcp__context7 matches every tool on that server; mcp__github__merge_pull_request matches one tool. Read the real tool names from /mcp before you write a rule, because a misspelled name matches nothing.

Tool definitions and tool output both use context:

  • Tool search is on by default. Claude Code loads MCP tool definitions on demand instead of all at once. ENABLE_TOOL_SEARCH=false loads everything upfront, and ENABLE_TOOL_SEARCH=auto:N switches to search only when definitions pass N% of the context window. If ANTHROPIC_BASE_URL points at a proxy that is not a first-party Anthropic host, 2.1.283 turns tool search off unless you set ENABLE_TOOL_SEARCH=true, which works only if the proxy forwards tool_reference blocks.
  • One server can opt out of deferral, or in. "alwaysLoad": true in a server’s entry loads its tools up front whatever ENABLE_TOOL_SEARCH says, at the price of context on every turn. Since v2.1.287 (both release channels on 2026-10-12), "alwaysLoad": false keeps all of that server’s tools behind tool search, including tools its author marked to load up front (Claude Code MCP documentation, checked 2026-10-12).
  • Descriptions are cut. Claude Code truncates each tool description and each server’s instructions that it sends up front: the default limit rose from 2,048 to 4,096 characters in v2.1.296 (latest channel only on 2026-10-12), although Anthropic’s MCP page still said 2,048 on 2026-10-12. A description that the model loads through tool search is cut at 16,384 characters from v2.1.295 (latest only; it was 2,048). CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH (v2.1.280 or later) sets the limit for every server. If you write a server, put the critical detail first.
  • Large results are capped. A single MCP result is limited to about 25,000 tokens by default (the fallback in 2.1.283; a value set by Anthropic’s server can replace it, but MAX_MCP_OUTPUT_TOKENS always wins). Raise it for one session with MAX_MCP_OUTPUT_TOKENS=50000 claude when you need a whole log. Asking the server for less (a date range, a LIMIT) is usually better.
  • Idle servers are cheap but not free. Run /context to see what MCP tools cost in the current session, and /mcp disable <server> to switch one off for this project. Reducing MCP token cost covers the wider trade-off.

How do you verify MCP-backed work without reading every line?

Section titled “How do you verify MCP-backed work without reading every line?”

A server changes what the agent knows, not how you check the result. Verify three things in order.

1. The server is up. claude mcp list reports each server as connected, failed, or needing auth. Run it after onboarding a teammate and after every Claude Code upgrade.

2. The tool was called. In headless mode, --output-format stream-json prints one JSON event per line. The first event ("subtype":"init") lists every MCP server with its status, and each tool call appears as a tool_use block in an assistant message. This script fails unless Context7 connected and was actually called. Run it from the repository root, on your machine or in a CI job that runs only trusted code:

Terminal window
claude -p "Use the context7 MCP server to resolve the library ID for React. Reply with the ID only." \
--mcp-config .mcp.json --strict-mcp-config \
--allowedTools "mcp__context7" \
--output-format stream-json --verbose > mcp-smoke.jsonl
jq -e 'select(.type=="system" and .subtype=="init")
| .mcp_servers[] | select(.name=="context7" and .status=="connected")' mcp-smoke.jsonl >/dev/null \
|| { echo "context7 did not connect"; exit 1; }
jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' mcp-smoke.jsonl \
| grep -q '^mcp__context7__' && echo "context7 OK" || { echo "context7 NOT CALLED"; exit 1; }

--strict-mcp-config loads only the servers from --mcp-config, so the result does not depend on anyone’s personal config. Every server in that file starts, though, so in CI point it at a dedicated mcp-smoke.json that holds only the servers under test; the full .mcp.json would also start GitHub with an unset ${GITHUB_PAT} and Sentry without an OAuth login. --allowedTools pre-approves the one server, because nobody is there to answer a permission prompt. stream-json with -p requires --verbose. Never run this against a pull request from an untrusted fork with secrets in the environment: a .mcp.json from that branch runs its own commands. The agent threat model and securing MCP servers cover that case.

3. The change is correct. Docs from Context7 or a stack trace from Sentry do not make the code right. The gate is still your tests, type checker, and linter, plus a failing test written before the fix. Ask for that explicitly:

The reviewer, usually the developer who opened the PR and then the tech lead who owns .mcp.json, signs off on evidence: the Sentry issue ID, the test that failed and now passes, and a green suite in CI. That review does not require reading the diff line by line.

SymptomLikely causeRecovery
claude mcp list shows the remote server as Failed to connect with an ENOENT spawn errorIt was added without --transport http, so it became a stdio server whose command is the URLclaude mcp remove <name>, then add it again with --transport http
Project servers show Pending approval and never connectNobody approved .mcp.json in an interactive session, or someone declinedStart claude in the repo and approve; claude mcp reset-project-choices clears earlier decisions
“Connection closed” for a stdio server on native WindowsWindows cannot run npx directlyWrap it: claude mcp add my-server -- cmd /c npx -y @some/package
Server listed but no tools in /mcpThe command fails outside Claude Code: npx not on PATH, Docker stopped, or a ${VAR} unset in the shell that started claudeRun the exact command in a terminal; export the variables, then /mcp reconnect <name>
OAuth fails with “does not support dynamic client registration”The server needs a pre-registered OAuth appRe-add with --client-id <id> --client-secret (you are prompted for the secret) and --callback-port if the redirect URI is fixed
Output is cut off or rejected as too largeThe default cap of about 25,000 tokensNarrow the query first; otherwise set MAX_MCP_OUTPUT_TOKENS for that session
MCP tools stopped being found after you added an LLM gatewayTool search is off behind a non-first-party ANTHROPIC_BASE_URLSet ENABLE_TOOL_SEARCH=true if the gateway forwards tool_reference blocks; otherwise keep the server count low
An older self-hosted HTTP server fails after an upgradeIt mishandles MCP 2026-07-28 negotiationSet MCP_PROTOCOL_NEGOTIATION=legacy while the server is updated; see MCP 2026-07-28
A server on the 2025-11-25 protocol stopped connecting after v2.1.287Claude Code now answers URL prompts from such servers, for example to sign inAdd "bareElicitationCapability": true to that server’s MCP config entry, as the 2.1.287 changelog entry says
Several servers failed or need sign-in at onceOne restart or one sign-in per server is slow/mcp reconnect all retries every server that failed or needs authentication; it needs v2.1.284 or later in the interactive terminal, and older versions print MCP server "all" not found
A tool call stops with a prompt to sign in againThe server asked for more OAuth scope during the call (v2.1.288, both release channels on 2026-10-17)Accept the re-authenticate prompt, or re-authenticate the server in /mcp
First start times out while npx downloads a packageSlow first installPre-fetch once in a terminal, or raise MCP_TIMEOUT (milliseconds)

MCP connection issues covers transport-level debugging that applies to every client, and claude --debug "mcp" logs the connection attempts.

Did this guide help you?

One tap, no sign-in.

not at all a lot