Claude Code MCP support connects Claude Code to external tools, databases and APIs through MCP servers, which speak the Model Context Protocol, an open source standard for AI-tool integrations (Claude Code docs: MCP). You add a server with claude mcp add, choose a scope that decides who gets it, and govern its tools with the same permission rules as Claude Code's built-in tools. Below is the setup, checked against the docs on October 3, 2026, and why most data work on this site still runs through plain scripts.
What is an MCP server in Claude Code?
A program that gives Claude Code tools beyond its built-in set, such as searching an issue tracker, querying a database or controlling a browser. It runs on your machine or as a hosted service (MCP quickstart). The docs' test for when to connect one: you keep copying data into chat from another tool (MCP reference). It also works the other way: claude mcp serve runs Claude Code itself as a stdio MCP server that another client, such as Claude Desktop, can connect to (Claude Code as an MCP server).
How do you add an MCP server?
Run claude mcp add in your terminal, not inside a claude session. These are the docs' own examples for a hosted server, a hosted server that takes a token, and a local process (installing MCP servers):
# Remote server over HTTP, the recommended transport for remote servers
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Remote server that takes a token in a header
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# Local stdio server: everything after -- is the command that starts it
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-serverWithout the --, Claude Code would read the server's own flags as its options. Put at least one other option between --env and the server name, or the CLI reads the name as one more KEY=value pair and rejects it (the -- separator). The SSE transport is deprecated; the docs say to use HTTP where available.
How do you know it connected?
The Added ... line only means the configuration was written. Run claude mcp list and look for ✔ Connected; ! Needs authentication wants a browser sign-in or a token, and ✘ Failed to connect shows the HTTP status or error code the server returned (server status). For an OAuth server, open /mcp in a session and choose Authenticate, or run claude mcp login <name> (sign in from the command line). Then ask Claude to use the server by name once: the tool call is labeled with the server's name, so you know the answer came from it (add and verify a server).
Which scope should a server use?
| Scope | Flag | Loads for | Stored in |
|---|---|---|---|
| Local (default) | --scope local | Only you, current project | ~/.claude.json, under that project's entry |
| Project | --scope project | Everyone who clones the project | .mcp.json in the project root |
| User | --scope user | Only you, all your projects | ~/.claude.json, top-level mcpServers key |
Local scope suits servers with credentials you keep out of version control; project scope is for a server the whole team should get, so you commit .mcp.json (installation scopes). When one server is defined in several places, Claude Code uses a single definition, in this order: local, project, user, plugin, claude.ai connector (precedence). Moving a server to another scope means claude mcp remove and adding it again (change server scope). Claude Code does not read paths such as ~/.claude/mcp.json, a common reason a hand-edited server never appears (troubleshooting).
How do permissions work for MCP tools?
Permission rules cover MCP tools like any other tool, and Claude Code enforces them, not the model (manage permissions). A rule names the server as you configured it, optionally followed by a tool: mcp__puppeteer matches every tool from the puppeteer server, mcp__puppeteer__puppeteer_navigate matches one (MCP rules). This block uses a pattern from the docs to auto-approve the github server's get_ tools:
{
"permissions": {
"allow": ["mcp__github__get_*"]
}
}Rules are checked deny, then ask, then allow, and the first match wins. An allow glob needs a literal mcp__<server>__ prefix, so "mcp__*" under allow is skipped with a warning, while under deny it blocks every MCP tool (tool name wildcards). A server author can go further: a tool marked anthropic/requiresUserInteraction prompts on every call, even in bypassPermissions mode and whatever the allow rules say (require approval).
What do the docs warn about third-party servers?
- Trust comes first. "Verify you trust each server before connecting it," the reference says: servers that fetch external content can expose you to prompt injection (find and build MCP servers).
- Anthropic does not audit them. The security page encourages writing your own servers or using ones from providers you trust; Anthropic reviews connectors for its Directory but does not security-audit or manage any MCP server (MCP security).
- A cloned repository needs your approval. In interactive sessions, servers from a project's
.mcp.jsonwait for you to approve them;claude -pruns, Agent SDK sessions and cloud sessions load them without asking. AdisabledMcpjsonServersentry blocks one in every mode (project scope). .mcp.jsonis not the full list. Other scopes, claude.ai connectors and plugins add servers a review of the repository never shows (MCP security).- Your Claude Code credentials stay out. In a remote server's
urlandheaders, variables such asANTHROPIC_API_KEYread as empty, so a project's.mcp.jsoncannot send them to a server it names (credential variables). - Least privilege. The docs' database example connects with a read-only user, so Claude's queries cannot modify data.
Why do I use scripts instead of MCP servers for API data?
Most of the data work on this site runs through plain scripts that call APIs directly: the Search Console API with a service account, Bing URL Submission, and a pay-as-you-go keyword data API. The keyword script has a cost gate: every paid command prints its estimate, spends nothing without an explicit flag, and stops above a limit:
def gate(estimate, args, what):
print(f'{what}: estimated cost ${estimate:.3f} (limit ${args.max_cost:.2f})')
if estimate > args.max_cost:
sys.exit('over the limit: raise --max-cost after the owner agrees')
if not args.yes:
sys.exit('estimate only. Add --yes to spend.')For a job like this, a script is simpler than a server:
- Nothing loads until it runs. Each connected server takes context space, because its tool names and server instructions load into every session (quickstart). A script is one command, run when the task needs it.
- The limit sits on the only code path. A server's tools take whatever arguments Claude sends, so a spend limit would have to be built into the server anyway. Here it is a few lines I can read.
- Bash rules already apply. In Manual mode, a command outside the built-in read-only set needs approval (permission system).
- No connection to keep alive. No browser sign-in, reconnects or server timeouts.
The gate is not a lock: an agent could pass a higher --max-cost. It shows the cost before anything is spent and turns an over-limit run into a stop that says to ask me. Extensions I did not write get the same idea in prompt form: third-party SEO skills run here under a rules block of mine, where no paid API call happens without my approval and my positioning rules win (how that block is set up). A rules block is still a prompt, which is why the limit itself lives in code.
When is an MCP server the better choice?
When the vendor hosts a server with OAuth: you sign in through the browser from /mcp instead of pasting a token, and Claude Code refreshes the token. When a team needs the same tools: a committed .mcp.json gives everyone the same servers. When the tool is a live session, like the quickstart's Playwright server, which gives Claude a browser to navigate, click and read. And when a call must always reach a person: requiresUserInteraction forces that, which a flag on my script cannot.
Where this fits
A server and a script both give an agent reach; what matters is where the check sits and whether it fails hard. How hard checks, soft rules and my approval of every commit fit together is in the guardrails I put around agents that work on this site.
Tags
Frequently asked questions
How do I add an MCP server to Claude Code?
Run claude mcp add in your terminal, not inside a session. For a hosted server: claude mcp add --transport http <name> <url>. For a local server: claude mcp add <name> -- <command>, where everything after -- is the command that starts it. The Added line only means the configuration was saved, so run claude mcp list and look for Connected.
Where does Claude Code store MCP servers?
Local and user scope servers live in ~/.claude.json: local ones under the entry for the current project, user ones under the top-level mcpServers key. Project scope servers live in .mcp.json at the project root. Claude Code does not read paths such as ~/.claude/mcp.json or ~/.claude/.mcp.json.
Why is my MCP server not showing up in Claude Code?
The usual causes: you added it at local scope from a different project, you edited a file Claude Code does not read, or an entry in .mcp.json is malformed and was skipped. A project server can also sit at Pending approval until you start claude interactively and approve it. Run claude mcp list from your shell to see each status and any parse warning.
Do MCP servers take up context in Claude Code?
Some. With tool search, which is on by default, only tool names and server instructions load at session start, and full tool definitions load when Claude needs them. Each connected server still takes space in every session, so removing servers you no longer use keeps it free. A server set to alwaysLoad loads all its tools upfront.