#9: MCP Servers in Claude Code 🔌
Today we'll look at connecting MCP servers to Claude Code, so Claude can reach tools and data that live outside our project.
The Model Context Protocol (MCP) is an open standard for hooking AI tools up to outside services. Once a server is connected, its tools show up next to the built-in ones, and Claude can call them as part of its normal work.
Let's take a look.
Adding a Server
Remote servers over HTTP are the recommended option. One command does it:
claude mcp add --transport http notion https://mcp.notion.com/mcp
# With a bearer token
claude mcp add --transport http hal-api https://api.example.com/mcp \
--header "Authorization: Bearer $HAL_TOKEN"Local servers run as a process on our machine over stdio. Everything after the -- is the command that starts the server:
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-serverThat -- matters. Without it, Claude Code would try to read the server's own flags, like -y, as its options. The order of --env matters too: if the server name comes right after it, the CLI reads the name as another KEY=value pair, so we keep another option like --transport in between.
The older SSE transport is deprecated. Newer versions of Claude Code try HTTP first and fall back to SSE on their own.
Picking a Scope
Every server is added at one of three scopes:
- local (the default): this project only, private to us, stored in
~/.claude.json - project: this project, shared with the team through a
.mcp.jsonfile at the root - user: every project on our machine, also stored in
~/.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/anthropicIf the same server name is defined at more than one scope, local wins over project, and project wins over user. Entries aren't merged, the whole winning definition is used.
Sharing With .mcp.json
Project-scoped servers land in .mcp.json, which we check into git so everyone gets the same tools:
{
"mcpServers": {
"marvin-db": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@example/db-server"],
"env": { "DB_URL": "${MARVIN_DB_URL}" }
},
"data-api": {
"type": "http",
"url": "${DATA_API_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${DATA_API_KEY}" }
}
}
}${VAR} expands an environment variable, and ${VAR:-default} falls back to a default when it isn't set. Expansion works in command, args, env, url, and headers, so secrets stay out of the repo.
For safety, Claude Code asks before using servers from a project's .mcp.json in interactive sessions. claude mcp reset-project-choices resets those approvals.
Managing Servers
A few commands cover the day-to-day:
claude mcp list # every server, with health status
claude mcp get notion # details for one server
claude mcp remove notionInside a session, /mcp shows each server's status. It's also where we sign in to servers that use OAuth: pick the server, follow the browser flow, and Claude Code stores and refreshes the tokens for us. From the shell, claude mcp login <name> does the same thing.
We can also toggle a server off in /mcp without deleting its config.
Prompts and Resources
Servers can offer more than tools. Their prompts show up as slash commands, and their resources can be @-mentioned like files:
/mcp__github__pr_review 456
Can you analyze @github:issue://123 and suggest a fix?Typing @ lists resources from every connected server right alongside our files. Neat!
More info about MCP in Claude Code can be found at the Claude Code docs.