MCP in Claude Code: Connect Servers and Build Your Own, Step by Step
The Model Context Protocol (MCP) is an open standard that lets an AI assistant call tools in other systems — a task tracker, a database, your own API. In Claude Code you connect a server with one claude mcp add command, choose who gets it with a scope, and can build your own server in TypeScript in about twenty lines.


( Before you start )
What MCP is
MCP is a protocol between two sides. A server exposes tools — functions with a name, a description and an input schema. A client, Claude Code here, lists those tools and calls one when a task needs it. Write a server once and any MCP client can use it.
- Local (stdio) servers run as a process on your machine; Claude Code talks to them over standard input and output.
- Remote (HTTP) servers run elsewhere and are reached by URL — the way most hosted services offer MCP.
- Tools are what you will use most; servers can also offer resources and prompts.
( Connect a server, step by step )
Add a remote server
Hosted services publish an MCP URL. Add it with --transport http, a name of your choosing, and the URL:
claude mcp add --transport http notion https://mcp.notion.com/mcpIf the service needs you to sign in, run /mcp inside a Claude Code session and follow the authentication step there.
Add a local server
For a server that runs on your machine, the command goes after a double dash. Options such as --env come before the name; everything after -- is the command and its arguments:
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable -- npx -y airtable-mcp-serverChoose a scope
| Scope | Flag | Who gets it | Stored in |
|---|---|---|---|
| Local (default) | --scope local | You, in this project only | ~/.claude.json |
| Project | --scope project | Everyone who clones the repository | .mcp.json in the project root |
| User | --scope user | You, in every project | ~/.claude.json |
Project scope is the one to commit, so teammates get the same servers. Claude Code asks each person to approve project servers before using them, and claude mcp reset-project-choices clears those answers. A project file looks like this:
{
"mcpServers": {
"notion": {
"type": "http",
"url": "https://mcp.notion.com/mcp"
},
"docs": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./docs"]
}
}
}Never commit API keys in `.mcp.json`. Pass secrets with --env on your own machine, where they stay in your private configuration.
Check what is connected
claude mcp list
claude mcp remove airtableclaude mcp listprints every server with its health: connected, needs authentication, or failed to connect.- Inside a session,
/mcpshows each server’s status and tool count, signs you in, and switches servers on and off. claude mcp remove <name>deletes one.
Build your own server in TypeScript
The official TypeScript SDK makes a working server about twenty lines long. Since version 2 of the SDK, the server ships as its own package:
mkdir greeting-server && cd greeting-server
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server zodThen src/index.ts, the example from the SDK’s README:
import { McpServer } from '@modelcontextprotocol/server';
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
import * as z from 'zod/v4';
const server = new McpServer({ name: 'greeting-server', version: '1.0.0' });
server.registerTool(
'greet',
{
description: 'Greet someone by name',
inputSchema: z.object({ name: z.string() }),
},
async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
}),
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main();Every tool has a name, a description Claude reads to decide when to call it, an input schema, and a handler that returns content. Node 22.18 and later run TypeScript files directly, so you can register the file as it is (on an older Node, compile it with tsc first and point at the JavaScript):
claude mcp add --transport stdio greeting -- node "$(pwd)/src/index.ts"Start a new session, run /mcp to see the server connected, then ask Claude to greet someone. It asks your permission the first time it calls the tool.
( Going further )
Security checklist
- Only add servers you trust: a local server runs code on your machine, and every server sees what Claude sends it.
- Keep API keys out of
.mcp.json; pass them with--envinstead. - Prefer read-only tokens. A server that only reads issues should not be able to close them.
- Look at what each tool does in
/mcpbefore you approve it.
MCP FAQ
- Is MCP only for Claude?
- No. MCP is an open protocol, and the same server works with any client that supports it.
- What is the difference between local and project scope?
- Both apply to one project. Local stays private to you in
~/.claude.json; project is written to.mcp.jsonso it can be committed and shared. - Why does my server say it failed to connect?
- For a local server, run the command after
--by hand: if it crashes, or prints anything to standard output before the protocol starts, Claude Code cannot talk to it. For a remote server, check the URL and sign in with/mcp. - How do I share servers along with skills and hooks?
- Bundle them in a Claude Code plugin: a
.mcp.jsonat the plugin root is installed with everything else.
Reference: Claude Code docs — MCP and the MCP TypeScript SDK.