Claude Code + MCP: The Practical Setup Guide (2026)

15–22 minutes
P1 claude code mcp

Every command here is real and current. Scoping, subagents, plan mode, CLAUDE.md, and what to do when a server refuses to connect.

Last updated: 19 August 2026  ·  Reading time: 10 min  ·  By: the geminy.ai editors

MCP (Model Context Protocol) lets an AI client call external tools — a database, an issue tracker, a browser — through one common interface. For the concept in full, plus a catalogue of servers, read our companion piece: What is an MCP server (and the best MCP servers in 2026). This guide covers the part nobody documents well: running MCP inside Claude Code day to day, at the command line.

Quick answer

The 60-second version. Add servers with claude mcp add. Remote servers take --transport http and a URL; local servers take a -- separator then the launch command. Three config scopes: local (default, private, this project), project (.mcp.json, committed, team-shared), and user (--scope user, every project on your machine). Check health with claude mcp list and /mcp. Add plan mode (Shift+Tab), a couple of subagents in .claude/agents/ and a short CLAUDE.md, and you have a setup that survives past the demo stage.

The three scopes, and which one you want

This is the decision that causes the most confusion, and worth getting right first — moving a server between scopes later means editing files by hand.

ScopeLoads inSharedStored in
Local (default)Current projectNo~/.claude.json
ProjectCurrent projectYes, via version control.mcp.json in project root
UserAll your projectsNo~/.claude.json

Local and user scope share a file, but a local server is filed under the current project’s path inside it, so it doesn’t leak elsewhere. MCP “local scope” is unrelated to .claude/settings.local.json.

The rule: if a teammate cloning the repo needs the server, use --scope project. If it’s a tool you reach for everywhere, use --scope user. Everything else stays local. When a name is defined twice, precedence runs local, project, user, plugin servers, then claude.ai connectors, and the winning source supplies the whole entry with no merging.

Project servers need approval: Claude Code prompts before using one it found in a committed .mcp.json. Reset your answers with claude mcp reset-project-choices. One caveat before automating anything — claude -p runs, SDK sessions and cloud sessions can’t show that prompt, so they load project servers without asking. To keep one out, add it to disabledMcpjsonServers.

Adding servers: the four commands you’ll use

A remote HTTP server

Most hosted MCP servers are HTTP now:

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

# With a static bearer token
claude mcp add --transport http secure-api https://api.example.com/mcp \
  --header "Authorization: Bearer your-token"

--transport, --header, --env and --scope have short forms -t, -H, -e, -s. If a server’s docs mention streamable-http, that’s the same transport — the JSON type field accepts it as an alias for http.

A remote SSE server

Some services still expose only SSE:

claude mcp add --transport sse asana https://mcp.asana.com/sse

A local stdio server

This is the one people get wrong. Everything after -- is passed to the server untouched:

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

Without the --, Claude Code parses the server’s flags (-y, --port) as its own and fails. A less obvious trap: --env accepts multiple KEY=value pairs, so a server name placed immediately after --env is read as another pair and rejected. Put another option between them, as above.

Straight from a JSON block

Docs written for Claude Desktop or Cursor hand you an mcpServers object rather than a command. Pass add-json the object inside the wrapper, not the wrapper:

claude mcp add-json example '{"command":"npx","args":["-y","@example/mcp-server"]}'

claude mcp add-from-claude-desktop brings a whole Desktop config across. Names may contain only letters, numbers, hyphens and underscores, so a server with a space in its name won’t import until you rename it.

Managing what you’ve added

claude mcp list          # every configured server, with health status
claude mcp get notion    # details and connection issues for one server
claude mcp remove notion # delete it
claude mcp login sentry  # run a server's OAuth flow from the shell
claude mcp logout sentry # clear stored credentials

claude mcp login saves opening a session just to authenticate; it needs v2.1.186 or later and takes --no-browser. In-session, /mcp remains the panel for auth, toggles and tool counts.

Which servers are worth wiring up

Resist installing everything. Each server is a failure point at startup and another set of tool descriptions competing for attention. A working setup is three to six.

Your code host or issue tracker. The pattern that pays for itself is “read the ticket, write the branch, open the PR”. Anthropic’s docs use the hosted GitHub endpoint with a token:

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

Worth knowing: claude mcp add writes config without validating credentials, so a bad token is accepted happily and only surfaces later as a failed connection. Anthropic’s guidance also suggests preferring the gh CLI where you can — a CLI driven through Bash is more context-efficient than a server exposing dozens of schemas.

A database, read-only. Use a read-only database user so nothing Claude runs can mutate data.

claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
  --dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"

A browser (Playwright) for visual verification, so Claude compares its output against a design rather than asserting it looks right. Observability turns “here’s a stack trace I pasted” into “read the last five occurrences”: claude mcp add --transport http sentry https://mcp.sentry.dev/mcp, then /mcp to sign in. What isn’t worth it: anything you’d touch once a month, or anything a shell command already does.

Keeping tool bloat under control

This quietly determines whether a setup stays usable. Since the Claude 4.5 generation, tool search is on by default: MCP tool schemas are deferred rather than loaded upfront, and Claude searches for the ones a task needs. Nothing changes from your side, but the context saving is real past two or three servers.

Two levers. If a handful of tools are needed every turn, exempt that server with "alwaysLoad": true on its .mcp.json entry — sparingly, since each upfront tool costs context. ENABLE_TOOL_SEARCH=false claude disables deferral entirely, mostly useful for debugging.

The other cost is output size. Claude Code warns when one tool call returns over 10,000 tokens and truncates at 25,000 by default. If a data server routinely hits that, raise it with MAX_MCP_OUTPUT_TOKENS=50000 claude rather than letting results vanish.

Plan mode: the habit with the best return

Of everything here, Claude Code plan mode is the cheapest change with the biggest effect. It tells Claude to research and propose without acting: it reads files and runs exploratory commands, then writes a plan, but your source stays untouched until you approve.

Three ways in — press Shift+Tab until the status bar shows ⏸ plan mode on; prefix a prompt with /plan; or start with claude --permission-mode plan. The recommended workflow is four phases: explore, plan, implement, commit. Ctrl+G opens the plan in your editor first — editing three lines of a plan is far cheaper than correcting the resulting diff.

To make it the default for every session:

{
  "permissions": {
    "defaultMode": "plan"
  }
}

Plan mode does add overhead, and the docs are honest about it. If you could describe the diff in one sentence — a typo, a log line, a rename — skip it. It earns its keep when a change spans files, when you’re unsure of the approach, or when the code is unfamiliar.

Subagents: isolated context, scoped tools

Claude Code subagents are separate agents with their own context window, tool allowlist and, optionally, their own MCP servers. Context is the binding constraint and investigation fills it — a subagent that reads forty files and reports back three paragraphs leaves your main conversation clean for implementation.

A subagent is a markdown file with YAML frontmatter. Project ones live in .claude/agents/; personal ones in ~/.claude/agents/ follow you everywhere.

---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
---

You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.

Only name and description are required; tools inherits everything and model defaults to inherit. Useful extras: disallowedTools, permissionMode, maxTurns, skills, memory, isolation: worktree. Since v2.1.198 the /agents command no longer opens a creation wizard — write the file, or ask Claude to.

The field tying this back to MCP is mcpServers, which scopes a server to one subagent, inline or by reference:

---
name: browser-tester
description: Tests features in a real browser using Playwright
mcpServers:
  # Inline definition: scoped to this subagent only
  - playwright:
      type: stdio
      command: npx
      args: ["-y", "@playwright/mcp@latest"]
  # Reference by name: reuses an already-configured server
  - github
---

Use the Playwright tools to navigate, screenshot, and interact with pages.

This is the cleanest answer to tool bloat: define a server inline here rather than in .mcp.json and the subagent gets the tools while your main conversation never sees the descriptions. Inline servers connect when the subagent starts and disconnect when it finishes. One pattern is worth adopting deliberately — after Claude implements something, have a fresh subagent review the diff against the plan, since a reviewer that never saw the reasoning judges the result on its own terms.

CLAUDE.md conventions that actually help

CLAUDE.md loads into context at the start of every session. That single fact should govern how you write it: everything in there is rent you pay on every conversation.

Run /init to generate a starter file, then prune. Target under 200 lines. The test Anthropic suggests for each line: would removing this cause Claude to make mistakes? If not, cut it. Include bash commands Claude can’t guess, style rules that differ from language defaults, testing instructions, PR etiquette and non-obvious gotchas. Exclude anything derivable from the code. Be concrete: “use 2-space indentation” beats “format code properly”.

Files live at ./CLAUDE.md or ./.claude/CLAUDE.md (team, committed), ~/.claude/CLAUDE.md (personal, all projects) and ./CLAUDE.local.md (personal, gitignored); Claude Code walks up the tree and concatenates what it finds. Verify with /context — if a file isn’t in the Memory files list, no rewording will help. When it grows, split rather than extend: a rule in .claude/rules/ with paths: frontmatter loads only when Claude touches matching files:

---
paths:
  - "src/api/**/*.ts"
---

# API Development Rules

- All API endpoints must include input validation
- Use the standard error response format

If your repo already has an AGENTS.md, don’t duplicate it — Claude Code reads CLAUDE.md only, so create one whose first line is @AGENTS.md. Two things CLAUDE.md is not. It isn’t enforcement — it’s context, so for anything that must happen every time, use a hook. And it isn’t the place for occasional workflows; those belong in skills. Worth knowing in 2026: custom slash commands have been merged into skills, so .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both give you /deploy. Existing command files keep working; new work belongs in skills/. This hook runs Prettier after every edit, in .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
        ]
      }
    ]
  }
}

Run /hooks to see what’s registered. Matchers can target MCP tools too, via the mcp__<server>__<tool> naming convention.

When a server won’t connect

Work through this in order; it resolves the large majority of cases.

  1. Read the status, not the confirmation. claude mcp add prints Added ... once config is written, which proves nothing. claude mcp list shows health: ✔ Connected, ! Needs authentication, ✘ Failed to connect, or ⏸ Pending approval.
  2. Get the detail. claude mcp get <name> shows an Issue: line with the status code and any text the server returned; a 401 means credentials, not configuration. Credential-like text is redacted, so it’s safe to paste into a bug report.
  3. Check for stray whitespace. The most common self-inflicted failure. Pasted tokens often carry a trailing newline; Claude Code warns (Leading or trailing whitespace in: headers.Authorization) but does not trim it.
  4. Check the name. workspace, claude-in-chrome, computer-use, Claude Preview and Claude Browser are reserved for built-in servers and skipped at load time.
  5. Check unexpanded variables. .mcp.json supports ${VAR} and ${VAR:-default} in command, args, env, url and headers. An unset variable with no default doesn’t block loading — Claude Code warns and passes the literal text through, so give shared configs a fallback.
  6. Give slow servers time. MCP_TIMEOUT=10000 claude sets a ten-second startup timeout, usually enough for a local server that fetches a package on first run.
  7. Confirm your CLI version. Several behaviours above are version-gated. [Insert live content] current stable Claude Code version at publish date — run /status to see yours, and /doctor for a checkup that can fix configuration issues.

If an HTTP or SSE server drops mid-session, Claude Code reconnects with exponential backoff — five attempts, starting at one second. Stdio servers are not reconnected automatically, so a crashed one needs a manual retry from /mcp.

What a good setup looks like after a month

Three or four servers, most project-scoped and committed. A CLAUDE.md under 200 lines you’ve pruned twice. Two or three subagents — a reviewer, an investigator, maybe a browser tester with Playwright scoped to it alone. A formatting hook. Plan mode as the default. The setups that fall over installed fifteen servers in week one.

Frequently asked questions

What is the difference between local, project, and user scope in Claude Code MCP?

Local is the default: the server loads only in the project where you added it and stays private, stored under that project’s path in ~/.claude.json. Project scope writes to .mcp.json in your project root, which you commit so the team gets the same servers. User scope also lives in ~/.claude.json but loads in every project on your machine.

Where does Claude Code store MCP configuration?

Two places: .mcp.json at your project root for project scope, and ~/.claude.json for local and user scope — local nested under the project’s path, user at the top level. When a name appears in several scopes, precedence runs local, project, user, plugin servers, then claude.ai connectors, and the winning definition is used whole rather than merged.

How do I add an MCP server when the instructions were written for Claude Desktop?

A URL means a remote server: claude mcp add --transport http <name> <url>, or --transport sse for an SSE endpoint. A launch command such as npx -y @example/mcp-server means stdio: put it after a -- separator. An mcpServers JSON block goes to claude mcp add-json — pass the object inside the wrapper, not the wrapper. For a whole config, use claude mcp add-from-claude-desktop.

Why won’t my MCP server connect in Claude Code?

Start with claude mcp list, because claude mcp add confirms only that config was written. Then claude mcp get <name> for the Issue: line with the status code. Common causes: an expired token (a 401), trailing whitespace on a pasted token, an unapproved project server showing as pending, an unexpanded ${VAR}, a startup timeout, or a reserved server name such as workspace.

Do MCP servers slow Claude Code down or use up context?

Much less than they used to. Tool search is on by default on current models: MCP tool schemas are deferred rather than loaded upfront, so only tools actually used enter context. You can force a server’s tools to load at startup with "alwaysLoad": true, sparingly. The bigger cost is output — Claude Code warns above 10,000 tokens from one call and truncates at 25,000 by default, raisable with MAX_MCP_OUTPUT_TOKENS.

What is Claude Code plan mode and when should I use it?

Plan mode tells Claude to research and propose changes without making them: it reads files and runs exploratory commands, writes a plan, and leaves your source untouched until you approve. Enter it with Shift+Tab until the status bar shows plan mode on, prefix a prompt with /plan, or start with claude --permission-mode plan. Use it for multi-file or unfamiliar changes; skip it when you could describe the diff in one sentence.

How are Claude Code subagents different from just asking Claude to do the work?

A subagent runs in its own context window with its own tool allowlist and, optionally, its own MCP servers. That isolation is the point: research reads many files, and in the main conversation every read consumes context you need for implementation. Define them as markdown files with YAML frontmatter in .claude/agents/ or ~/.claude/agents/; only name and description are required.

Should I document MCP tools in CLAUDE.md?

Generally no. CLAUDE.md loads at the start of every session, so anything in it is a permanent cost, and servers already advertise their own tool descriptions. Keep it for what Claude cannot infer: build commands, testing instructions, style rules that differ from defaults, repository etiquette. Anything longer belongs in a skill under .claude/skills/ or a path-scoped rule in .claude/rules/.

Sources

On this page

Leave a Reply

About geminy.ai

An independent, free-to-read comparison site for generative AI platforms. We review and compare the major tools and point readers to them. We do not host, resell or broker AI models.

No affiliate links. No sponsored placements. No paid rankings.

Corrections and enquiries: bestmarketingtools.ai@gmail.com

Discover more from Geminy AI — Independent AI Platform Comparisons

Subscribe now to keep reading and get access to the full archive.

Continue reading