Skip to content

Claude Code and MCP: Connecting External Tools

MCP earns its place when the information lives somewhere the filesystem cannot reach. Here is how to connect it, and what you take on when you do.

Claude Code Guides: Claude Code and MCP. A central hub wired to three external systems.

What MCP is for

The Model Context Protocol is an open standard for connecting AI tools to external systems — databases, APIs, ticketing systems, error logs. An MCP server exposes capabilities; Claude Code calls them directly.

The practical value is narrow and real: it removes the copy-and-paste step. Instead of pulling an error from your monitoring dashboard, pasting it in, then pasting back the fix, Claude queries the monitoring system itself. Instead of describing your database schema, it reads it.

That also describes when not to bother. If the data is already in the repository, MCP adds nothing — Claude Code can already read files. MCP earns its place when the information lives somewhere the filesystem cannot reach.

The four transports

Transport Flag Use for
HTTP --transport http Remote services. The recommended default, with OAuth support.
Stdio --transport stdio A local process on your machine.
SSE --transport sse Legacy remote services. Deprecated — use HTTP where available.
WebSocket none Persistent bidirectional connections. Configured only through .mcp.json or claude mcp add-json.

In practice you will use HTTP for hosted services and stdio for anything running locally. If a server's documentation still tells you to use SSE, check whether it offers HTTP first.

Adding a server

A remote HTTP server:

claude mcp add --transport http stripe https://mcp.stripe.com

With a static auth header:

claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
  --header "Authorization: Bearer YOUR_GITHUB_PAT"

A local stdio server:

claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

The -- separator is required for stdio servers and is the single most common mistake here. Everything before it is Claude's options; everything after is the command to run. Omit it and your server command gets parsed as flags.

The rest of the surface:

claude mcp list                    # every server, with health status
claude mcp get <name>              # details for one
claude mcp remove <name>           # remove it
claude mcp login <name>            # OAuth
claude mcp logout <name>           # clear credentials
claude mcp add-json <name> '...'   # add from raw JSON config
claude mcp reset-project-choices   # re-run project approvals
claude mcp serve                   # run Claude Code itself as an MCP server

Inside a session, /mcp opens a panel where you can authenticate and toggle servers on and off.

Scopes, and which file each writes to

Three scopes, and choosing wrong is why a colleague cannot see the server you added.

Scope Available in Shared with the team Written to
Local (default) This project only No ~/.claude.json
Project This project only Yes — commit it .mcp.json at the project root
User All your projects No ~/.claude.json
claude mcp add --transport http shared-server --scope project https://example.com/mcp
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic

Note that local and user scope both land in ~/.claude.json — local under a per-project key, user at the top level. Neither is shareable. Only --scope project produces a committable file.

The recommendation for teams is unambiguous: one central team configures the servers and commits .mcp.json, so everyone gets them without wiring anything up. That is also a security benefit — one team reviews what is connected, rather than a long tail of individual setups nobody has audited.

Three MCP scopes compared. Local writes to ~/.claude.json, loads in this project, not shared. Project writes to .mcp.json at the repo root, loads in this project, and is shared — commit it. User writes to ~/.claude.json, loads in all your projects, not shared.
Only the highlighted row produces a file that travels with the repository.

The .mcp.json format

{
  "mcpServers": {
    "issues": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      },
      "timeout": 600000
    },
    "local-db": {
      "command": "/path/to/server",
      "args": ["--config", "${CLAUDE_PROJECT_DIR}/config.json"],
      "env": {
        "DB_URL": "${DATABASE_URL:-sqlite://default.db}"
      }
    }
  }
}

Two things make this file safe to commit.

Environment variable expansion. ${VAR} expands from the environment, and ${VAR:-default} falls back. It works in command, args, env, url, and headers — which is exactly the set you need to keep secrets out of the file. Commit the reference, never the token.

${CLAUDE_PROJECT_DIR} resolves to the project root, so paths do not depend on where anyone checked the repository out.

For authentication schemes that need a fresh value each time — Kerberos, short-lived tokens, internal SSO — use headersHelper instead of static headers. It points at a script that prints a JSON object of header key-value pairs to stdout, runs with a 10-second timeout, and is called fresh on every connection.

Authenticating remote servers

For an OAuth server, add it and then authenticate:

claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp login sentry

Or run /mcp in a session and follow the browser flow. On a headless machine, claude mcp login sentry --no-browser.

If you have your own client credentials, pass them rather than going through discovery:

claude mcp add --transport http \
  --client-id your-client-id --client-secret --callback-port 8080 \
  my-server https://mcp.example.com/mcp

--client-secret with no value prompts with masked input. For scripting, set MCP_CLIENT_SECRET in the environment instead — which is the right pattern, because a secret on a command line ends up in your shell history.

How MCP tools appear

MCP tools are namespaced:

mcp__<server-name>__<tool-name>

mcp__github__create_issue
mcp__notion__query_database

You need this format any time you write a permission rule, a subagent tools list, or an --allowedTools argument. Getting the double underscores wrong is a quiet failure — the rule simply never matches.

Servers bundled in a plugin carry a longer name:

mcp__plugin_<plugin-name>_<server-name>__<tool-name>

Reading the status output

claude mcp list reports a state per server, and most of them mean something specific:

Status Meaning
✔ Connected Working
! Needs authentication Run claude mcp login <name> or /mcp
⏸ Pending approval A project .mcp.json server you have not trusted yet
⊘ Disabled for this project Toggled off in /mcp
✘ Failed to connect With a detail explaining why
cached 2h ago Tools came from the discovery cache, not a live connection

That last one matters when you are debugging: a cached entry can look healthy while the server is down.

The risk you are taking on

This section is the reason to read the article rather than skim the commands.

Verify you trust a server before connecting it. A server that fetches external content can expose you to prompt injection — content it returns is text Claude reads, and text Claude reads can attempt to instruct it. That is a genuine attack surface, not a theoretical one.

Practical rules:

  • Prefer read-only where the work is read-only. A database server pointed at a read-only user cannot be talked into a write.
  • Scope credentials narrowly. A personal access token with full repository access does more damage than one scoped to issues.
  • Review project servers before accepting the trust dialogue. That prompt is doing real work; a .mcp.json arriving in a pull request is a capability grant arriving in a pull request.

Non-interactive runs cannot show an approval dialogue, so claude -p and Agent SDK sessions need project servers pre-approved in settings, or --strict-mcp-config to use only what --mcp-config supplies. If you are running Claude Code in CI, that distinction is the one to get right.

Limits that bite in practice

Limit Default Override
Tool output warning 10,000 tokens
Tool output cap 25,000 tokens MAX_MCP_OUTPUT_TOKENS
Long calls move to background 2 minutes CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS
Idle timeout 5 min HTTP, 30 min stdio CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT
Reconnect attempts 5, exponential backoff

The output cap is the one that surprises people. A query returning a large result set gets truncated at 25,000 tokens, and the truncation is not always obvious in the response. If you are querying a database, put the LIMIT in the query rather than relying on the cap to do it for you.

Which servers are actually worth adding

An honest filter, because it is easy to accumulate servers that never get used and cost context on every session.

Add a server when the data lives outside your repository and you reference it often. Error tracking, issue tracking, a database schema you query while building, analytics you check while optimising.

Do not add one for data already in the repository. Claude Code reads files. An MCP server that reads your code is a slower version of a tool it already has.

Do not add one you will use twice. A one-off query is faster to run yourself and paste.

Two concrete examples worth the setup for most web projects:

# GitHub — issues and pull requests without leaving the terminal
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
  --header "Authorization: Bearer YOUR_GITHUB_PAT"

# A read-only database connection for schema questions
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
  --dsn "postgresql://readonly:pass@host:5432/db"

Note the readonly user in the second. That is the pattern: connect with the least privilege that makes the tool useful.

Where to go next

MCP extends what Claude Code can reach. Skills package what it does with that reach, subagents isolate the work and restrict the tools, and plugins ship all three to a team in one install. For enforcing rules around MCP calls, see hooks. New to the tool entirely? Start with getting started in the terminal.

For where a connected toolchain fits in real work, the complete website workflow covers the full build, the prompt library covers directing it, and a production CLAUDE.md covers the context every session starts from.

Sources and further reading

More Claude Code guides

Free download

The CLAUDE.md Starter Kit, free

Four working CLAUDE.md files you can drop into a project today, plus the one-page checklist for what belongs in one and how to tell whether yours is actually working.

  • CLAUDE.md for a static marketing site
  • CLAUDE.md for a web application, with security and migration rules
  • CLAUDE.md for a Shopify theme, including the gotchas that cost hours
  • CLAUDE.md for a shared package in a monorepo
  • A one-page checklist, and how to test the file is actually working

The download appears here as soon as you submit. I will also email you when there is a new guide worth reading. No fixed schedule, no selling your address, unsubscribe from any email. See the privacy policy.