TL;DR: Claude Code MCP setup is one command: claude mcp add --transport http <name> <url> for a remote server, or claude mcp add <name> -- <command> for a local one. Scope decides who sees it: local, project, or user. Run /mcp inside a session to confirm the connection and to sign in.
Most of what goes wrong here is not the protocol. It is a url field with no type next to it, a server added at the wrong scope, or a bearer token quietly blocking the OAuth flow you expected. This page walks the current CLI surface, verified against Anthropic's own documentation on August 27, 2026, then covers what only bites after the first server works.
A note on sources first: Anthropic moved these docs. The Claude Code pages that lived at docs.claude.com/en/docs/claude-code/... now redirect to code.claude.com/docs/en/mcp; the general platform docs go to platform.claude.com.
What is MCP, in one paragraph?
The Model Context Protocol is an open standard for connecting AI applications to external systems. The specification describes it as a way to share contextual information with language models, expose tools and capabilities to AI systems, and build composable integrations, using JSON-RPC 2.0 messages between three roles: hosts (the LLM application), clients (connectors inside the host), and servers (the services providing capability). The protocol's own intro page puts it more bluntly: MCP is "like a USB-C port for AI applications."
Architecturally it splits into two layers: the data layer is the JSON-RPC exchange protocol, and the transport layer is how those messages physically move. That split matters when you configure Claude Code, because almost every decision you make is a transport decision.
Servers expose three primitives: tools (functions the model executes), resources (context data) and prompts (reusable templates). Clients can expose elicitation, where a server asks the user for input mid-task. As of revision 2026-07-28, the current one, sampling and logging are deprecated for new implementations.
What does Claude Code actually do with an MCP server?
It gains tools it can call during a turn, resources it can read, and prompts you can run as slash commands. Anthropic's heuristic for when to bother: connect a server "when you find yourself copying data into chat from another tool, like an issue tracker or a monitoring dashboard."
From Anthropic's own examples: implement a feature described in a JIRA issue and open the PR, query Postgres for the users who touched it, pull the Figma design the email template should match. In each case the alternative is you, pasting.
Before connecting anything, read the warning on that same page: "Verify you trust each server before connecting it." Servers that fetch external content can expose you to prompt injection. An MCP server is not a sandboxed plugin, it is a set of callable functions handed to a model already editing your files.
How do you add an MCP server to Claude Code?
Four ways, one per transport. The syntax differs enough that copying the wrong one is the usual first failure.
Remote HTTP. The recommended option for anything cloud-hosted:
# Basic syntax
claude mcp add --transport http <name> <url>
# Real example
claude mcp add --transport http notion https://mcp.notion.com/mcp
With a static token instead of OAuth:
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
Remote SSE. Anthropic marks this transport deprecated and says to use HTTP where available. Some services still expose only an SSE endpoint:
claude mcp add --transport sse asana https://mcp.asana.com/sse
Local stdio. A process on your machine, talking over stdin and stdout:
# Basic syntax
claude mcp add [options] <name> -- <command> [args...]
# Real example
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-server
Remote WebSocket. Not available through --transport, which does not accept ws. Configure it with JSON:
claude mcp add-json events-server \
'{"type":"ws","url":"wss://mcp.example.com/socket","headers":{"Authorization":"Bearer YOUR_TOKEN"}}'
Two syntax traps live in that block. First, the double dash: everything after -- is passed to the server untouched, which is how Claude Code knows -y belongs to npx and not to itself. Second, quieter: --env accepts multiple KEY=value pairs, so a server name placed directly after --env is read as another pair and rejected. Put another option between them, as the Airtable example does.
Which transport should you choose?
If the vendor gives you a URL, you are on HTTP or SSE and the vendor decides which. If they give you an npx or uvx command, you are on stdio. Most of the time that is the whole decision.
| Transport | Add with | Runs where | Auth |
|---|---|---|---|
| HTTP (streamable) | --transport http | Vendor's infrastructure | OAuth, or --header |
| SSE | --transport sse | Vendor's infrastructure | OAuth, or --header |
| stdio | -- <command> | Your machine | Environment variables via --env |
| WebSocket | add-json with "type":"ws" | Vendor's infrastructure | Headers only, no OAuth |
One naming detail that trips up copy-paste: in JSON config, type accepts streamable-http as an alias for http. The specification uses the longer name, so a block lifted from a server's README works unmodified.
The related failure is worth memorising, because the error used to be misleading. A JSON entry with a url but no type is a configuration error: Claude Code reads a typeless entry as stdio, skips it, and names the missing type field in the warning. Before v2.1.202 the same mistake surfaced as command: expected string, received undefined, which sent people looking in the wrong place.
What do local, project and user scope actually change?
Scope is where most of the real confusion lives, partly because "local" here does not mean what "local settings" means elsewhere.
| 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 |
Local scope is the default and private to you, stored under that project's path inside ~/.claude.json. Anthropic flags the naming collision explicitly: MCP local scope writes to ~/.claude.json in your home directory, while general local settings use .claude/settings.local.json in the project.
Project scope is the collaborative one. Claude Code writes this file:
{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}
Commit that and everyone on the repo gets the same servers. Claude Code prompts for approval in interactive sessions before using anything from .mcp.json, and claude mcp reset-project-choices clears those answers.
The exception matters for automation. In claude -p runs, Agent SDK sessions and cloud sessions, Claude Code cannot show that prompt, so it loads project-scoped servers without asking. To exclude one anyway, disabledMcpjsonServers blocks it in every permission mode, and --strict-mcp-config limits the session to servers passed via --mcp-config.
User scope makes a server available across every project on your machine:
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
When the same server appears in more than one place, Claude Code connects once, using the highest-precedence definition whole rather than merging fields. The order is local, project, user, plugin-provided servers, then claude.ai connectors. The three scopes match duplicates by name; plugins and connectors match by endpoint.
Because .mcp.json is committed, keep secrets out of it. Claude Code expands environment variables in command, args, env, url and headers, using ${VAR} and ${VAR:-default}:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}
If a referenced variable is unset with no default, the config still loads: Claude Code warns in claude mcp list and uses the literal ${VAR} text, producing a connection failure that looks like an auth problem and is not.
How does authentication work?
Claude Code marks a remote server as needing authentication when it answers 401 Unauthorized or 403 Forbidden. The browser flow starts inside the session:
/mcp
Pick the server, sign in, approve. Tokens are stored and refreshed automatically, and an already-signed-in server that returns 401 gets one silent refresh-and-retry before Claude Code flags it.
Since v2.1.186 you can do the same without opening a session:
claude mcp login sentry
claude mcp logout sentry
Over SSH, where there is no local browser, add --no-browser and paste the redirect URL back at the prompt. Connect with ssh -t, since the paste step needs an interactive terminal:
claude mcp login sentry --no-browser
Two details save real time. If a server requires a redirect URI registered in advance, pin the port instead of letting Claude Code pick one at random:
claude mcp add --transport http \
--callback-port 8080 \
my-server https://mcp.example.com/mcp
And if you set headers.Authorization yourself and the server rejects it, Claude Code reports a failed connection rather than falling back to OAuth. Deliberate, and genuinely confusing the first time. Remove the header if you meant to use the browser flow.
In non-interactive mode there is no /mcp panel, so Claude Code cannot run OAuth for you. As of v2.1.196, with tool search on, it tells Claude the server's tools are unavailable until you authorise it, so Claude names the server rather than acting as though it were never configured.
How do you confirm a server is really connected?
claude mcp add printing Added ... only means the config was written. The health check is separate:
# List all configured servers, with a health status per server
claude mcp list
# Details for one server
claude mcp get notion
# Remove it
claude mcp remove notion
claude mcp list shows ✔ Connected, ! Needs authentication, or ✘ Failed to connect. A failure means Claude Code could not reach that server, not that the list command broke. A fourth status, ⏸ Pending approval, reports a configuration decision rather than a connection attempt: a project-scoped server from .mcp.json you have not approved yet, fixed by running claude interactively.
Inside a session, /mcp shows the panel with a tool count per server, and flags servers that advertise a tools capability but expose none. You can toggle one off there without deleting it.
When none of that explains it, turn on the relevant debug categories:
claude --debug='mcp,startup'
The filter binds only in the = form. A space-separated one enables debug mode without filtering, burying the MCP lines in noise.
What breaks once you have a lot of servers?
Three things, in roughly this order.
Context. Tool search is on by default and keeps this manageable: only tool names and server instructions load at session start, with full definitions deferred until Claude needs them. Anthropic states there is no fixed per-server tool cap and that the practical limit is your context window budget. To change that:
# Load tools upfront until definitions reach 5% of the context window, then defer
ENABLE_TOOL_SEARCH=auto:5 claude
# Disable deferral entirely
ENABLE_TOOL_SEARCH=false claude
Writing a server rather than consuming one? Claude Code truncates tool descriptions and server instructions at 2KB each, so put the critical detail first.
Output size. Claude Code warns when any MCP tool output exceeds 10,000 tokens, and the default maximum is 25,000. For a server that returns genuinely large payloads:
export MAX_MCP_OUTPUT_TOKENS=50000
claude
Permissions. MCP rules use the server name as configured, optionally followed by a tool name:
{
"permissions": {
"allow": [
"mcp__puppeteer__puppeteer_navigate",
"mcp__github__get_*"
],
"deny": ["mcp__*"]
}
}
mcp__puppeteer matches every tool from that server, and so does mcp__puppeteer__*. Allow rules accept globs only after a literal mcp__<server>__ prefix, so the server segment must name one you actually configured; an unanchored allow glob such as mcp__* is skipped with a warning and approves nothing. Deny rules are looser, and "mcp__*" in a deny list removes every MCP tool from Claude's context.
How do you call a server directly instead of hoping Claude picks it?
Two mechanisms, and they are not the same thing.
Servers exposing prompts get slash commands, in the form /mcp__servername__promptname. Type / to see them alongside your own. Arguments go space-separated after the command:
/mcp__github__list_prs
/mcp__github__pr_review 456
/mcp__jira__create_issue "Bug in login flow" high
Servers exposing resources get @ mentions, in the form @server:protocol://resource/path. They appear in the same autocomplete as your files and are fetched as attachments:
Can you analyze @github:issue://123 and suggest a fix?
Compare @postgres:schema://users with @docs:file://database/user-model
The difference is worth internalising: a tool call is Claude deciding, a slash command is you deciding. When a workflow has to be reproducible, drive it from the slash command rather than leaving the choice to the model, the same way you would pin a prompt template instead of retyping it. For the multi-client version of this problem, see MCP prompt management in Cursor and Claude Desktop.
Connecting the Prompt Architects MCP server
This is the vendor section, so treat it as one. If you came here to wire up Sentry or Postgres, everything above was the part you needed.
We run an MCP server at https://mcp.prompt-architects.com/mcp. It exposes four prompt operations: improve (rewrite for clarity and structure), refine (asks one to three clarifying questions first), shorten (compress while preserving intent), and enhance (add role framing and depth). Each is callable by the model on its own and as a slash command.
# OAuth: opens a browser tab to sign in
claude mcp add --transport http pa https://mcp.prompt-architects.com/mcp
For headless or CI use, generate a pa_live_… personal access token from Settings → MCP in your dashboard and pass it directly:
claude mcp add --transport http pa \
https://mcp.prompt-architects.com/mcp \
--header "Authorization: Bearer pa_live_<your-token>"
Then confirm and use it:
/mcp
/mcp__pa__improve
/mcp__pa__refine
/mcp__pa__shorten
/mcp__pa__enhance
The OAuth side is standard rather than bespoke, which is why it works in six different clients. Check it yourself, no account needed:
curl -s https://mcp.prompt-architects.com/.well-known/oauth-protected-resource
curl -s https://mcp.prompt-architects.com/.well-known/oauth-authorization-server
The second advertises S256 as the supported code challenge method and a dynamic client registration endpoint, which is what lets Claude Code register itself instead of you creating an OAuth app by hand. An unauthenticated call to the endpoint returns 401 with a WWW-Authenticate header pointing back at the resource metadata, which is exactly the discovery path described above.
The same endpoint is documented for Claude Desktop, Claude.ai, Cursor, Codex and Codex CLI. For the JSON-driven clients the block is the ordinary one:
{
"mcpServers": {
"pa": {
"url": "https://mcp.prompt-architects.com/mcp"
}
}
}
On plans, plainly. Checked against the live pricing page on August 27, 2026: the comparison table has no MCP row, and neither it nor the MCP integration page states a tier requirement for connecting. What is metered is enhancements, not the connection. Our FAQ publishes 5 prompt enhancements per day, forever on Free; pricing publishes 200 architected prompts a month on Pro at $4.99/month and unlimited on Advanced at $9.99/month, both at the time of writing under a launch promotion. An MCP call spends the same quota a click in the web app would, so a free account gets five improve calls a day whichever client made them.
That number is ours, from our own database, not third-party research. MCP adoption across the whole customer base is 4.8%; among the top 5% by engagement it is 60.6%, the single strongest predictor of a high-value account in the dataset. Claude Code accounts for roughly 89% of all MCP events we see. Correlation, obviously: people who wire a tool into their terminal were already the committed ones. The gap is still wide enough that we treat connecting MCP as the activation milestone that matters.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.
Create An AccountClaude Code as an MCP server, in the other direction
Less well known: Claude Code can be the server. claude mcp serve starts it as a stdio MCP server other applications connect to.
claude mcp serve
It prints nothing on start. A stdio server communicates over stdin and stdout, so a silent, blocked terminal is what success looks like. To use it from Claude Desktop:
{
"mcpServers": {
"claude-code": {
"type": "stdio",
"command": "claude",
"args": ["mcp", "serve"],
"env": {}
}
}
}
If claude is not on your PATH, use the absolute path from which claude, or you get spawn claude ENOENT. Note Anthropic's caveat: this exposes Claude Code's tools to your client, which is then responsible for confirming individual tool calls.
The five failures worth recognising
Most Claude Code MCP problems are one of these, and none look like what they are.
- A
urlwith notype. Claude Code reads it as stdio and skips the server. Add"type": "http","sse"or"ws". - A bearer header where you wanted OAuth. If the server rejects your header, Claude Code reports a failed connection instead of starting the browser flow. Remove the header.
- A server name with an illegal character. Names may contain only letters, numbers, hyphens and underscores. This is why
claude mcp add-from-claude-desktopskips some imported servers, reporting each one it rejects. - Missing
--on a stdio server. Without it, Claude Code tries to parse the server's own flags as its own options. - Right server, wrong scope. A local-scoped server added in one repository will not appear in another, by design. If a teammate cannot see it, it was never in
.mcp.json.
For symptoms that survive all five: MCP not working, 15 fixes and why isn't my MCP server showing up.
MCP gets the data in front of the model. How you frame it once it arrives is still yours to get right, and Claude in particular responds well to explicitly delimited context: see using XML tags in Claude prompts.
Sources. Claude Code MCP, permissions and CLI reference pages at code.claude.com/docs/en/mcp, and MCP specification revision 2026-07-28 plus the architecture overview at modelcontextprotocol.io. All accessed August 27, 2026. This surface moves fast enough that any tutorial, including this one, is worth re-checking against that reference page in six months.