Claude Code MCP setup
In Claude Code you add an MCP server from the command line, not by hand-editing a config file. Run `claude mcp add --transport http <name> <url>` for a remote HTTP server, or `claude mcp add <name> -- <command> [args...]` for a local stdio server (everything after the `--` is the launch command). Pick where it is stored with `--scope local` (default, this project only), `--scope project` (shared via a checked-in `.mcp.json` using the `mcpServers` key), or `--scope user` (all your projects). Because a server's tool descriptions and outputs flow straight into the model's context, vet any third-party server before you add it.
The claude mcp add command (and where config is stored)
Claude Code is CLI-first: you register servers with `claude mcp add`, and Claude Code writes the configuration for you. For a remote server, HTTP is the recommended transport: `claude mcp add --transport http <name> <url>`. For a local server that runs as a subprocess, use the stdio form: `claude mcp add <name> -- <command> [args...]`. The double dash `--` matters: it separates Claude Code's own flags (like `--transport`, `--env`, `--scope`) from the command and arguments that actually launch the server, which are passed through untouched.
Where the entry is saved depends on the `--scope` flag. Local scope (the default) and user scope are stored in `~/.claude.json` in your home directory; local-scoped servers are nested under your project's path so they stay private to that project, while user-scoped servers load across all your projects. Project scope is different: it writes a `.mcp.json` file at your repository root, designed to be committed so your whole team gets the same servers. (Note: MCP "local scope" in `~/.claude.json` is not the same as general local settings in `.claude/settings.local.json`.)
Pass secrets with `--env KEY=value` rather than embedding them in arguments, and authenticate remote OAuth servers afterward with the `/mcp` command inside a session (or `claude mcp login <name>` from the shell).
Choosing a scope: local, project, or user
Local scope is the default and loads only in the project where you added it, kept private to you in `~/.claude.json`. Use it for personal or experimental servers, or anything with credentials you do not want in version control. Add it explicitly with `claude mcp add --transport http <name> --scope local <url>`.
Project scope stores the server in a `.mcp.json` file at the project root so it can be checked into version control and shared with everyone on the team: `claude mcp add --transport http <name> --scope project <url>`. For security, Claude Code prompts each user for approval before it will use project-scoped servers from a `.mcp.json` it has not seen — a safeguard worth keeping in mind when you pull a repo that ships its own MCP servers.
User scope makes a server available across all of your projects (also stored in `~/.claude.json`) and suits personal utility servers you reuse everywhere: `claude mcp add --transport http <name> --scope user <url>`. When the same server name is defined at more than one scope, Claude Code uses one definition by precedence — local, then project, then user — without merging fields across scopes.
Minimal examples (CLI and .mcp.json)
A remote HTTP server: `claude mcp add --transport http <name> <url>` — for example `claude mcp add --transport http notion https://mcp.notion.com/mcp`. To pass a token, add `--header "Authorization: Bearer <token>"`. A local stdio server: `claude mcp add --env API_KEY=<key> --transport stdio <name> -- npx -y <some-mcp-server>` — the part after `--` is the exact command Claude Code runs. (Place a flag like `--transport stdio` between `--env` and the server name; if the name comes directly after `--env`, the CLI reads it as another KEY=value pair and rejects it.)
When you use `--scope project`, the resulting `.mcp.json` at your repo root uses a top-level `mcpServers` object keyed by server name. A minimal file with one stdio server and one remote server looks like: { "mcpServers": { "my-local-tool": { "command": "<command>", "args": [], "env": {} }, "my-remote-tool": { "type": "http", "url": "<url>" } } }. The `type` field accepts `http` (or its spec alias `streamable-http`), `sse` (deprecated), `stdio`, and `ws`. You can edit this file directly, or generate it with `claude mcp add-json <name> '<json>'`.
Claude Code expands environment variables inside `.mcp.json` — `${VAR}` and `${VAR:-default}` work in `command`, `args`, `env`, `url`, and `headers` — so teams can share one config while keeping machine-specific paths and secrets like API keys out of the committed file.
Managing and verifying servers
Once added, manage servers with `claude mcp list` (lists every configured server and its status), `claude mcp get <name>` (shows one server's details, including whether OAuth credentials are configured), and `claude mcp remove <name>`. Inside a Claude Code session, the `/mcp` panel shows connection status, the tool count per server, and is where you complete OAuth logins for remote servers.
Project-scoped servers awaiting your approval appear as `Pending approval` in `claude mcp list` until you review them interactively. If you ever need to re-review the project servers you previously accepted, `claude mcp reset-project-choices` clears those approval decisions.
Vet the server before you add it
Adding an MCP server grants it real reach into your session. The server's tool descriptions are read into the model's context as authoritative text, and the outputs its tools return are read back as data the model may act on. A malicious or compromised server can abuse either channel to steer the agent — this is tool poisoning and tool-output prompt injection — without the text ever appearing in your terminal. Claude Code's own docs warn that servers which fetch external content can expose you to prompt-injection risk.
The risk is additive across every server you load. A server that can read private data, one that can fetch untrusted content, and one that can send data out can together form the lethal trifecta — the combination under which a single injection becomes real data exfiltration — even if each looked harmless alone. Project-scoped `.mcp.json` is shared through version control, so a server one teammate adds runs for everyone who approves it, which is exactly why the approval prompt exists.
Practical defenses: add servers only from sources you trust, pass credentials through `--env` (or `${VAR}` references in `.mcp.json`) rather than hardcoding them, prefer servers that mark destructive operations with annotations, and audit any unfamiliar server before adding it. Servers can also silently change their tool definitions after you approve them (a rug pull), so re-checking on updates — not just on day one — is part of staying safe.
How CheckMCP handles it
Before you run `claude mcp add` on a third-party server, CheckMCP tells you whether it is safe to wire into your agent. Paste the server's URL at checkmcp.dev — or run `uvx checkmcp <url>` from the open-source CLI (MIT, stdlib-only) — and CheckMCP probes the live endpoint and returns an explainable, vendor-neutral MCP Score 0-100 (grade A-F) across seven weighted pillars led by security (weight 20), which runs an OWASP MCP Top 10 pass for tool poisoning, hardcoded secrets, command injection and the lethal trifecta. Hard caps surface the worst configurations immediately: a secret found in a tool schema caps the grade at D, and a failed MCP handshake caps it at F. Opt-in behavioral evals exercise read-only tools with canary inputs to catch prompt-injection and data-exfiltration in tool responses. For servers you depend on in a shared `.mcp.json`, the GitHub Action (`uses: H129hj/checkmcp@v1`) can gate CI on a score regression or rug-pull, and drift monitoring re-checks on every change; an in-band Gateway (passive or active mode) can block tool-poisoning and drift before they reach your agent. CheckMCP audits the server; you keep your Claude Code config clean.