Setting Up MCP Servers in Claude Code
Claude code mcp servers let you plug external tools, databases, and APIs directly into your terminal-based coding sessions, so Claude can query a database, open a browser, or read a ticket without you copy-pasting context by hand. The setup takes a few commands and one config file. This guide walks through installing your first server, understanding the config format, choosing between local and remote servers, and writing a small custom server when nothing off-the-shelf fits.
What an MCP server actually does
Model Context Protocol (MCP) is an open standard for connecting an AI agent to external capabilities. An MCP server exposes a set of tools (functions Claude can call), resources (files or data Claude can read), and sometimes prompts (reusable instruction templates). Claude Code acts as an MCP client: it starts or connects to servers, lists their tools, and lets the model call them mid-conversation just like it calls its built-in tools (Read, Bash, Edit, and so on).
The practical benefit is that you are not limited to what ships in the box. Want Claude to query your Postgres database, open a Jira ticket, drive a real browser, or hit an internal API? Someone has likely already written an MCP server for it, or you can write a thin one yourself in an afternoon.
Prerequisites
Before adding a server, confirm the basics:
- Claude Code is installed and you can run
claudefrom your terminal. - Node.js or Python is available if the server you want runs locally (most community servers are npm packages run via
npx). - You have any credentials the server needs (API keys, tokens) ready as environment variables, not hardcoded values.
Check your Claude Code version and confirm MCP support is active:
claude --version
claude mcp listAn empty list is normal on a fresh install. That is where you start.
Adding your first MCP server with the CLI
The fastest path is the claude mcp add command. Here is a local, stdio-based server (one that Claude Code starts as a subprocess and talks to over stdin/stdout):
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /Users/you/projectsBreak that down:
filesystemis the name you are giving this server inside Claude Code. You will reference it by this name later.- Everything after
--is the actual command Claude Code runs to start the server process. npx -ydownloads and runs the package without a permanent global install.- The trailing path is an argument the filesystem server itself expects (the directory it is allowed to expose).
Run claude mcp list again and you should see filesystem listed with its command. Start a new claude session in that project and ask it to list files in a directory outside your normal working tree. If the server connected correctly, Claude can now read that directory through the MCP tool rather than through its built-in file tools.
To remove a server:
claude mcp remove filesystemTo see full detail on one server, including which tools it exposes:
claude mcp get filesystemConfiguring servers in .mcp.json
The CLI is convenient for one-off additions, but for a team or a reproducible project setup, you want a config file checked into version control. Claude Code reads MCP server definitions from a .mcp.json file. A minimal one looks like this:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
}
}
}
}Each key under mcpServers is a server name. command and args describe how to launch it. env sets environment variables scoped to that server's process, which is where credentials belong instead of being baked into args.
If you already ran claude mcp add, the CLI wrote this file for you. Open it, read it, and treat it like any other config: review diffs carefully, especially anything a teammate adds that starts a new subprocess or points at a new remote URL.
For secrets, do not commit real values. Use a placeholder and load real credentials through your shell environment or a .env file that is gitignored:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}Claude Code expands ${VAR} references from your shell environment at launch time, so the actual connection string never touches the repo.
Local (stdio) vs remote (HTTP) servers
MCP servers come in two shapes, and picking the right one matters for both performance and security.
Local stdio servers run as a subprocess on your machine. Claude Code starts them, talks over stdin/stdout, and kills them when the session ends. Most filesystem, database, and git-related servers work this way. They are simple to set up and never leave your machine, but they need the runtime (Node, Python, etc.) installed locally and they only see what your local process can see.
Remote HTTP/SSE servers run somewhere else, a company's internal server, a SaaS vendor's hosted endpoint, and Claude Code connects to them over the network. Adding one looks like:
claude mcp add --transport http linear https://mcp.example.com/linearRemote servers are useful when the tool needs infrastructure you do not want to run locally (a full search index, a large dataset, a service that already has its own auth and rate limiting). The tradeoff is that you are trusting a third party with whatever context Claude sends it, so only add remote servers from vendors you actually trust.
Scoping: project, user, and local configs
Claude Code supports three scopes for MCP servers, and understanding the difference avoids a lot of confusion when a server "disappears" between projects.
- Local scope (default when you just run
claude mcp add): stored in a machine-specific config, applies only to you, on this machine, for this project. Good for personal experiments or servers with credentials you do not want to share. - Project scope: stored in
.mcp.jsonat the project root, checked into git, shared with everyone who clones the repo. Use--scope projectwhen adding:
claude mcp add --scope project filesystem -- npx -y @modelcontextprotocol/server-filesystem .- User scope: applies across every project you open on your machine, stored in your user config rather than a project directory. Use
--scope userfor servers you always want available regardless of which repo you are in, like a personal browser-automation server.
claude mcp add --scope user browser -- npx -y @modelcontextprotocol/server-puppeteerWhen you open a project, Claude Code merges user-scope and project-scope servers. If two servers share a name, project scope wins, which is the right default: a repo's checked-in config should be able to override a developer's personal setup for anything that touches shared infrastructure.
Popular MCP servers worth installing
A short list of servers that cover the most common needs, all runnable via npx the same way as the filesystem example above:
- A filesystem server for reading and writing files outside the current working directory.
- A git server for repository operations that go beyond what the built-in Bash tool covers cleanly, like structured diff or blame queries.
- A browser automation server (Puppeteer or Playwright based) for driving a real browser, filling forms, and taking screenshots.
- A database server (Postgres, SQLite) for letting Claude run read queries against your schema during debugging, without you pasting query results back manually.
- A search server that wraps a web search API, useful when you want Claude to check current documentation rather than relying on training data.
Install only what a given project actually needs. Every server you add is another subprocess Claude Code manages and another set of tools competing for the model's attention when it decides what to call, so a bloated server list can make tool selection noisier rather than more capable.
Authenticating remote MCP servers
Some remote servers use OAuth instead of a static API key. Claude Code handles this with a browser-based auth flow:
claude mcp add --transport http ticketing https://mcp.example.com/tickets
claude mcp auth ticketingThe auth command opens your default browser, walks you through the vendor's login and consent screen, and stores the resulting token locally, scoped to that server. You do not paste tokens into .mcp.json. If a token expires, re-run claude mcp auth <name> to refresh it.
For servers using a static API key instead of OAuth, put the key in an environment variable and reference it the same way shown earlier with ${VAR}, never as a literal string in a committed file.
Building a minimal custom MCP server
When no existing server covers what you need, writing one is not a large project. Here is a minimal Node.js MCP server that exposes a single tool for looking up order status from a fictional internal API:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "order-lookup",
version: "1.0.0"
});
server.tool(
"get_order_status",
{ orderId: z.string().describe("The order ID to look up") },
async ({ orderId }) => {
const response = await fetch(`https://internal-api.example.com/orders/${orderId}`, {
headers: { Authorization: `Bearer ${process.env.ORDERS_API_TOKEN}` }
});
const order = await response.json();
return {
content: [
{
type: "text",
text: `Order ${orderId} status: ${order.status}, last updated ${order.updatedAt}`
}
]
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);Save this as order-lookup-server.js, then register it:
claude mcp add order-lookup -- node /path/to/order-lookup-server.jsOnce connected, ask Claude something like "check the status of order 48213" and it will call get_order_status directly, no manual API call or copy-paste required. This pattern (one small server, one or two tools, a clear description on each) scales well: keep servers narrow and purpose-built rather than building one giant server that does everything.
Debugging MCP connection issues
When a server does not show up or fails silently, work through these in order:
- Run
claude mcp listand confirm the server is registered with the command you expect. - Run the underlying command by hand outside Claude Code (
npx -y @modelcontextprotocol/server-filesystem /path) and see if it errors immediately, before Claude Code even gets involved. - Check that any required environment variables are actually set in the shell Claude Code is running from, not just in a
.envfile that nothing is loading. - For remote servers, verify the URL is reachable with a plain HTTP request and that authentication has not expired (
claude mcp auth <name>again). - Start a fresh
claudesession after any config change. MCP servers are typically loaded at session start, so edits to.mcp.jsonwill not apply retroactively to a session already running.
If a server connects but its tools never get called, check the tool descriptions in the server's source. Claude decides whether to call a tool based on its name and description, so vague or generic descriptions make it easy for the model to skip the tool entirely, even when it is the right one for the task.
Security practices for MCP servers
Every MCP server you add can execute code or make network calls on your behalf, so treat the list the same way you would treat browser extensions or npm dependencies.
- Only add servers from sources you trust. Read the source of a community server before pointing it at a directory with sensitive files or a database with production credentials.
- Keep credentials in environment variables, never in
.mcp.jsonvalues that get committed. - Scope filesystem servers to the narrowest directory that actually needs exposing, not your entire home directory.
- Review project-scope
.mcp.jsonchanges in pull requests the same way you review dependency changes: a new server is a new piece of code with the same trust level as anything else running in your session. - Remove servers you are not actively using. An idle server is still a subprocess with access to whatever credentials it was given.
FAQ
What is the difference between an MCP server and a Claude Code built-in tool? Built-in tools (Read, Edit, Bash, and similar) ship with Claude Code and need no setup. MCP servers are external, either community-built or custom, and give Claude access to systems outside the local filesystem and shell, like a database, a ticketing system, or a remote API.
Do I need to restart Claude Code after editing .mcp.json? Yes. Start a new session after adding, removing, or editing a server entry. Servers are connected at session start, so changes made mid-session will not take effect until the next claude invocation.
Can I use the same MCP server across multiple projects? Yes, add it with --scope user instead of the default local scope. User-scope servers are available in every project you open on that machine, while project-scope servers live in that project's .mcp.json and only apply there.
Is it safe to add MCP servers from random GitHub repos? Only after reading the source. A malicious or careless MCP server can read files, make network requests, or exfiltrate whatever context Claude sends it. Treat an MCP server with the same scrutiny you would give a new production dependency, not a casual dev tool.
Why does Claude never call the tool from my custom server? Usually a weak tool description. Claude selects tools based on their name and description text, so a tool named do_thing with a one-word description is easy to miss. Write descriptions the way you would explain the tool to a new teammate: what it does, what input it needs, and when to use it.
Can an MCP server require authentication per user, not just per project? Yes, for HTTP-transport servers that support OAuth. Run claude mcp auth <name> and each user goes through their own login flow, so the same project config can serve a team without sharing a single shared credential.
AI CodingShip full-stack AI apps at conversation speed — specs, agents, deploys, all from the terminal.
Claude CodeGo from zero to confident with Claude Code, the terminal agent that reads, edits, runs, and verifies real code.