The Navigator · 11 min mission
MCP: Connecting Claude to Everything
Wire Claude into your tools, data, and services through MCP servers.
On this page
- What the Model Context Protocol is
- Adding a server: claude mcp add and transports
- Scopes: who sees the server, and where
- The .mcp.json file
- Tool search: how dozens of servers stay cheap
- A few servers worth connecting first
- OAuth, pinned scopes, and custom auth
- Resources and prompts: the other two capabilities
- Worked example: Codex as an MCP server
Claude Code is excellent at the things it can reach: your files, your shell, your git history. But the moment a task lives somewhere else — a Sentry error, a Jira ticket, a row in your production Postgres, a Figma frame — the loop breaks. You go copy the data into chat by hand, paste Claude's answer back into the other tool, and play courier between two systems all afternoon.
The Model Context Protocol (MCP) exists to delete that courier job. Connect a server once and Claude reads from and acts on the external system directly, in the same session, with no copy-paste in between.
What the Model Context Protocol is
MCP is an open-source standard for connecting AI applications to external systems — data sources, tools, and workflows. It was introduced by Anthropic and is now supported across a wide range of clients (Claude, ChatGPT, VS Code, Cursor, and more) and an ecosystem of servers, so a server you write once works everywhere.
The official analogy is the cleanest mental model you will get: MCP is a USB-C port for AI applications. Before USB-C, every device needed its own proprietary cable. Before MCP, every AI tool needed a bespoke, hand-rolled integration for every system it touched — an N×M explosion of one-off connectors. MCP replaces that with one standard plug. Build a server that speaks MCP, and any MCP client can use it.
A server can expose three kinds of capability. Tools are actions Claude can take (query a database, open a pull request). Resources are data Claude can read, referenced with @ mentions like files. Prompts are pre-built workflows the server publishes as slash commands. In Claude Code you will lean hardest on tools, but the other two are why MCP is a protocol and not just a plugin API. And because it is an open standard rather than a Claude-only API, the same server that powers Sentry or GitHub here also works in other MCP clients — connecting one means joining an ecosystem, which is exactly why the trust model later in this guide matters.
Adding a server: claude mcp add and transports
You connect a server with one command: claude mcp add. It takes a name you choose and the server's URL (for remote servers) or command (for local ones). The remaining choice is the transport — how Claude Code talks to the server. You pick it with --transport, and it changes nothing about how the tools feel once connected, only where the server lives and how messages travel.
stdio runs the server as a local process on your machine over standard input/output — right for tools that need direct system access or run a local script, as in claude mcp add --transport stdio db -- npx -y @bytebase/dbhub --dsn "postgresql://...". The syntax has one sharp edge: a -- separates Claude's own flags from the command that launches the server, so everything after -- is passed to the server untouched. Forget the -- and Claude Code tries to parse the server's flags as its own.
HTTP is the recommended transport for remote servers and the most widely supported for cloud services. It supports OAuth, custom headers, and automatic reconnection if the connection drops mid-session. In a .mcp.json config the type is written http, and streamable-http is accepted as an alias so configs copied from a server's own docs work unchanged. SSE (Server-Sent Events) is an older remote transport that is now deprecated — the official docs say to use HTTP instead wherever it is available.
Many cloud servers need authentication, so you either pass a token as a header when you add them, or connect first and complete an OAuth login from inside Claude Code with /mcp — which also shows each server's live status and tool count.
| Transport | Where the server runs | Use it for | Status |
|---|---|---|---|
stdio | Local process on your machine | Local scripts, tools needing direct system access | Current |
http | Remote, over HTTP(S) | Cloud services — the recommended remote option | Current |
sse | Remote, over Server-Sent Events | Legacy servers not yet migrated | Deprecated — prefer HTTP |
Scopes: who sees the server, and where
Every server you add is stored at one of three scopes. The scope decides which projects the server loads in and whether your teammates get it too. This is the single most common thing people get wrong, because the default is intentionally private.
Local is the default. The server loads only in the current project and stays private to you — Claude Code records it in ~/.claude.json under that project's path, so it does not appear in your other projects. Reach for local scope for experiments and for any server holding credentials you do not want in version control.
Project scope writes the server into a .mcp.json file at your project root, designed to be committed to git. This is how you share a server with your whole team: everyone who checks out the repo gets the same tools. Use it for the servers your project genuinely depends on.
User scope stores the server in ~/.claude.json and makes it available across all your projects while staying private to your account. This is the home for personal utilities you want everywhere — a scratch database client, a docs server — without committing them to any single repo.
When the same server name is defined at more than one scope, Claude Code uses exactly one definition by precedence: local beats project beats user (and both are beaten by nothing else among the three). Fields are not merged across scopes — the winning entry is used whole.
| Scope | Loads in | Shared with team | Stored in |
|---|---|---|---|
| Local *(default)* | Current project only | No | ~/.claude.json |
| Project | Current project only | Yes, via version control | .mcp.json in project root |
| User | All your projects | No | ~/.claude.json |
The .mcp.json file
Project scope produces a single artifact worth understanding directly, because it is the one you commit and your team reads: .mcp.json at the repo root. It is a plain JSON file with an mcpServers object mapping each server name to its config — type and url for remote servers, or command, args, and env for stdio ones.
Its best feature is environment-variable expansion. You can write ${VAR} to pull a value from the environment, or ${VAR:-default} to fall back to a default when the variable is unset. This is what makes a committed config safe: the shape of the server is shared in git, but the secret stays in each developer's environment.
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}Expansion works in command, args, env, url, and headers. One guardrail to know: if a required variable has no value and no default, Claude Code refuses to parse the file rather than connecting with a blank secret.
Tool search: how dozens of servers stay cheap
Here is the problem that nearly killed MCP-at-scale: every tool a server exposes used to cost context tokens just by existing. Connect five busy servers and their tool definitions could eat your context window before you typed a word. People rationed their servers to stay lean.
Tool search solves this, and it is on by default. Instead of loading every tool definition upfront, Claude Code defers them — only tool names and short server instructions load at session start, and Claude pulls in a tool's full schema through a search step when a task actually needs it. The practical effect: adding more servers has minimal impact on your context, so you can connect everything you might use and let Claude find the right tool on demand. There is no fixed per-server tool cap; your context budget is the only ceiling.
Two escape hatches are worth knowing. If a handful of tools should always be visible without a search step — because Claude needs them every turn — set "alwaysLoad": true on that server in its config; its tools then load upfront regardless of tool search. And if you want different loading behavior globally, the ENABLE_TOOL_SEARCH environment variable controls it: auto loads schemas upfront only while they fit a context threshold, and false turns deferral off entirely. One caveat from the docs: tool search needs a model that supports tool references, and Haiku models do not — so a Haiku session loads tools the old way.
Managing servers once they are connected
List and inspect
claude mcp listshows every configured server and its state — project servers awaiting your approval appear as⏸ Pending approval.claude mcp get <name>prints a single server's full configuration, including its transport and whether OAuth credentials are set.Check live status with /mcp
Inside a session,
/mcpis your control panel: it shows each connected server, its tool count, and lets you complete OAuth logins or clear authentication for servers that use it.Remove and reset
claude mcp remove <name>deletes the server from its scope. Pair it withclaude mcp reset-project-choiceswhen you want to re-trigger the approval prompts for project-scoped servers in.mcp.json.
A few servers worth connecting first
You do not need a wall of servers — you need the two or three that touch your daily loop, managed with the commands above. The official docs use these as worked examples, which makes them a sane starting set.
A GitHub server (added over HTTP with a personal access token as a header) lets Claude review PRs, open issues, and read repo state without you leaving the terminal. A Sentry server turns "what's breaking in production?" into a direct query against your real error data. A Postgres server — for instance the stdio @bytebase/dbhub with a read-only connection string — lets Claude answer questions about your actual schema and rows instead of guessing. Browse the reviewed connectors in the Anthropic directory for more, and remember that any remote server listed there installs with the same claude mcp add you already know.
The instinct to build toward is small and deliberate: connect the systems you would otherwise copy-paste from, keep secrets in environment variables, scope team-critical servers to .mcp.json, and let tool search keep the whole thing cheap.
OAuth, pinned scopes, and custom auth
For most remote servers the OAuth dance is invisible: you add the server, run /mcp, finish the browser login, and tokens are stored and refreshed for you. But three official knobs matter the moment a security team or a stricter server gets involved [V].
Some servers require a specific redirect URI registered in advance, and by default Claude Code picks a random callback port — which will never match. Pin it with --callback-port so the callback lands at http://localhost:PORT/callback exactly as registered: claude mcp add --transport http --callback-port 8080 my-server https://mcp.example.com/mcp. You can use it alone (with dynamic client registration) or alongside --client-id and --client-secret when the server hands you pre-configured credentials [V]. The secret is stored in your system keychain, never in the config, and these flags apply only to HTTP and SSE transports — they do nothing for stdio servers [V].
When an upstream server advertises more OAuth scopes than your org wants to grant, pin the request with oauth.scopes in the server's .mcp.json entry. The value is a single space-separated string (the RFC 6749 scope format), and it takes precedence over both authServerMetadataUrl and whatever the server discovers at /.well-known [V]:
{
"mcpServers": {
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": { "scopes": "channels:read chat:write search:read" }
}
}
}If a tool later returns a 403 insufficient_scope, Claude Code re-authenticates with the same pin — so widen oauth.scopes deliberately rather than letting the server quietly request everything [V]. And for servers that don't speak OAuth at all — Kerberos, short-lived tokens, internal SSO — use headersHelper instead of a static Authorization header. Claude Code runs the command at connection time, expects a JSON object of string key/value pairs on stdout (10-second timeout), and merges the result into the request headers, re-running it fresh on every reconnect with CLAUDE_CODE_MCP_SERVER_NAME and CLAUDE_CODE_MCP_SERVER_URL set so one script can serve many servers [V].
Resources and prompts: the other two capabilities
Tools get all the attention, but a server can also expose resources and prompts, and both surface as first-class affordances in the session [V].
A resource is data you pull in with an @ mention, the same way you reference a file. Type @ and resources from every connected server appear in the autocomplete alongside your files; reference a specific one with @server:protocol://resource/path [V]. So Can you analyze @github:issue://123 and suggest a fix? attaches that issue's contents directly, and you can mix several in one prompt — Compare @postgres:schema://users with @docs:file://database/user-model — with Claude Code fetching each and including it as an attachment [V].
A prompt is a pre-built workflow the server publishes as a slash command. Type / and MCP prompts appear in the format /mcp__servername__promptname [V]. Run one with no arguments — /mcp__github__list_prs — or pass space-separated arguments after it: /mcp__github__pr_review 456, or /mcp__jira__create_issue "Bug in login flow" high. Server and prompt names are normalized (spaces become underscores), the prompts are discovered dynamically from whatever is connected, and the result is injected straight into the conversation [V].
Worked example: Codex as an MCP server
MCP runs both directions — Claude Code is also an MCP client of other agents. The sharpest use of this is wiring OpenAI Codex in as a server so Claude can hand a self-contained sub-task to a second model and read back the result, without you shuttling between two terminals.
Codex ships an MCP server mode. Add it as a stdio server and Claude Code launches codex mcp-server as a child process [V]:
claude mcp add codex -- codex mcp-serverRemember the --: everything after it is the command Claude runs untouched, so Claude Code does not try to parse mcp-server as one of its own flags. Once connected, the server exposes two tools [V]. codex runs a fresh Codex session — it takes a prompt plus optional config like approval policy, sandbox mode, model override, and working directory. codex-reply continues an existing session, and this is the part worth understanding: Codex is stateful. The first codex call returns a threadId in structuredContent.threadId of the tools/call response, and you pass that same threadId back into codex-reply to keep the conversation going with full context — so Claude can open a thread, read the answer, then ask a follow-up against the same session rather than starting cold [V].
One operational gotcha: the very first run often shells out to npx to fetch the Codex binary, and on a slow network that download can outrun Claude Code's default MCP startup timeout. Raise it with MCP_TIMEOUT for that launch — MCP_TIMEOUT=60000 claude gives the server 60 seconds to come up [V]. If you want session IDs surfaced even more explicitly, the community codex-mcp server (by LanceVCS) wraps codex exec --json, parses the thread.started event, and returns the session ID inline — a drop-in alternative when you are orchestrating Codex as a controllable subprocess [V].
Knowledge check
You add a database server that your whole team should get when they clone the repo, and the connection string contains a password you must not commit. What is the right setup?
Reach the end and this star joins your charted sky.