Set up MCP servers in Claude Code
PLClaude 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.jsonwith 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 -psmoke 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.
| Transport | How Claude Code reaches it | Use it for | Add it with |
|---|---|---|---|
http (streamable HTTP) | A URL, with OAuth or a header | Hosted services: GitHub, Sentry, Linear, Atlassian, Figma | claude mcp add --transport http <name> <url> |
stdio (the default) | Claude Code starts a local process | Databases, local tools, anything in Docker or npx | claude 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.
Add your first server and prove it works
Section titled “Add your first server and prove it works”Start with Context7: it needs no account, and one prompt shows whether it answered.
-
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-mcpClaude Code prints
Added stdio MCP server context7 ... to local config. Local scope is the default, so the entry is stored in~/.claude.jsonunder this project’s path and nobody else sees it. -
Confirm that it starts.
claude mcp listhealth-checks every server it is allowed to connect to;claude mcp get context7shows one:Terminal window claude mcp listclaude mcp get context7 -
Start
claudeand type/mcp. It shows each server’s status and tools./mcp reconnect context7retries a server without restarting the session. -
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.
Connect the servers most teams start with
Section titled “Connect the servers most teams start with”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:
export GITHUB_PAT=github_pat_... # in your shell profile, never in a file you commitclaude 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.
Issues, events, and traces from Sentry’s hosted server, with OAuth. This is the example in claude mcp add --help itself:
claude mcp add --transport http sentry https://mcp.sentry.dev/mcpThen /mcp → sentry → log in. If you use a token instead of OAuth, Sentry expects the header Authorization: Sentry-Bearer <token>, not Bearer. The stdio package @sentry/mcp-server targets self-hosted Sentry.
Both are hosted servers with OAuth:
claude mcp add --transport http linear https://mcp.linear.app/mcpclaude mcp add --transport http atlassian https://mcp.atlassian.com/v2/mcpAtlassian moved to /v2/mcp; the old /v1/sse endpoint stopped working after 30 June 2026. An Atlassian admin must allow the connection, and Jira Service Management tools need an API token. Details: Atlassian Rovo MCP.
Design context and Code Connect mappings from Figma’s hosted server. The official plugin bundles the server with Figma’s skills:
claude plugin install figma@claude-plugins-official# or the server alone:claude mcp add --transport http figma https://mcp.figma.com/mcpFigma limits Starter plans and View or Collab seats to up to 6 tool calls per month (Figma, checked September 2026), so give a Dev or Full seat to whoever runs design-to-code. See Figma and design system MCP.
DBHub (npm @bytebase/dbhub, 1.3.1 on 2026-09-26) is one stdio server for Postgres, MySQL, SQL Server, MariaDB, Oracle, and SQLite. Pin the version and read the DSN from the environment:
claude mcp add --scope project db -- \ npx -y @bytebase/dbhub@1.3.1 --transport stdio --dsn '${DATABASE_URL}'Point DATABASE_URL at a read-only database role on a local or staging copy. A tool that runs SQL runs it with whatever rights the role has, and a prompt injected through a table row or a ticket can ask for a write. More servers and guardrails: database MCP servers.
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:
| Scope | Flag | Stored in | Choose it when |
|---|---|---|---|
| Local (default) | --scope local | ~/.claude.json, under this project’s path | You are trying a server, or it uses your personal account in one repo |
| Project | --scope project | .mcp.json at the repository root, committed | Every teammate needs it in this repo, and credentials come from ${VAR} or OAuth |
| User | --scope user | ~/.claude.json, for all projects | It 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=falseloads everything upfront, andENABLE_TOOL_SEARCH=auto:Nswitches to search only when definitions pass N% of the context window. IfANTHROPIC_BASE_URLpoints at a proxy that is not a first-party Anthropic host, 2.1.283 turns tool search off unless you setENABLE_TOOL_SEARCH=true, which works only if the proxy forwardstool_referenceblocks. - One server can opt out of deferral, or in.
"alwaysLoad": truein a server’s entry loads its tools up front whateverENABLE_TOOL_SEARCHsays, at the price of context on every turn. Since v2.1.287 (both release channels on 2026-10-12),"alwaysLoad": falsekeeps 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 (
latestchannel 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 (latestonly; 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_TOKENSalways wins). Raise it for one session withMAX_MCP_OUTPUT_TOKENS=50000 claudewhen you need a whole log. Asking the server for less (a date range, aLIMIT) is usually better. - Idle servers are cheap but not free. Run
/contextto 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:
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.
When Claude Code MCP servers break
Section titled “When Claude Code MCP servers break”| Symptom | Likely cause | Recovery |
|---|---|---|
claude mcp list shows the remote server as Failed to connect with an ENOENT spawn error | It was added without --transport http, so it became a stdio server whose command is the URL | claude mcp remove <name>, then add it again with --transport http |
Project servers show Pending approval and never connect | Nobody approved .mcp.json in an interactive session, or someone declined | Start claude in the repo and approve; claude mcp reset-project-choices clears earlier decisions |
| “Connection closed” for a stdio server on native Windows | Windows cannot run npx directly | Wrap it: claude mcp add my-server -- cmd /c npx -y @some/package |
Server listed but no tools in /mcp | The command fails outside Claude Code: npx not on PATH, Docker stopped, or a ${VAR} unset in the shell that started claude | Run 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 app | Re-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 large | The default cap of about 25,000 tokens | Narrow the query first; otherwise set MAX_MCP_OUTPUT_TOKENS for that session |
| MCP tools stopped being found after you added an LLM gateway | Tool search is off behind a non-first-party ANTHROPIC_BASE_URL | Set 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 upgrade | It mishandles MCP 2026-07-28 negotiation | Set 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.287 | Claude Code now answers URL prompts from such servers, for example to sign in | Add "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 once | One 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 again | The 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 package | Slow first install | Pre-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.
Where to go next with MCP in Claude Code
Section titled “Where to go next with MCP in Claude Code”Did this guide help you?
One tap, no sign-in.
What will you do with it?
How did it read?
What got in the way? Pick any that apply
Your role?
Thanks. I read every answer. Michał Jaskólski
Did this guide help?
One tap each. Close whenever you like.
no sign-in