How to Set Up MCP Servers in Claude Code — Complete Guide
Step-by-step guide to configuring MCP servers in Claude Code CLI. Learn project vs global config, the mcp add command, permissions, and troubleshooting.
Claude Code is Anthropic's terminal-based AI coding assistant. Unlike GUI editors with MCP support (Cursor, Windsurf, VS Code), Claude Code runs entirely in your terminal. You invoke it with the claude command, and it reads your codebase, edits files, runs commands, and manages git operations directly from the command line. It is one of the most powerful AI coding tools available, and its MCP integration is the most flexible of any client.
This guide walks through every aspect of setting up MCP servers in Claude Code: the two configuration methods, project vs global scope, environment variables, the permission model, a hands-on walkthrough with three real servers, and how to fix the issues that most commonly go wrong.
What Are MCP Servers?
MCP (Model Context Protocol) is an open standard created by Anthropic that lets AI models interact with external tools and services through a structured interface. An MCP server is a lightweight process that exposes a set of "tools" — functions the AI can call to perform actions like querying a database, managing GitHub repositories, running browser tests, or searching documentation.
When you connect an MCP server to Claude Code, the AI gains the ability to use those tools during your coding session. You ask it to "list all tables in my Supabase project" or "take a screenshot of the homepage," and Claude Code calls the appropriate MCP tool, gets the result, and uses it in its response. No tab switching, no copy-pasting.
Two Ways to Configure MCP Servers
Claude Code gives you two methods for adding MCP servers: a JSON config file and a CLI command. Both achieve the same result, but they suit different workflows.
Method 1: The .mcp.json Config File
Create a file called .mcp.json in your project root. This is the declarative approach — you define all your servers in one file, and Claude Code reads it on startup.
{
"mcpServers": {
"supabase-mcp": {
"command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase"],
"env": {
"SUPABASE_ACCESS_TOKEN": "sbp_your_token_here"
}
}
}
}
This file is project-specific. It sits alongside your package.json and other config files. You can commit it to version control (with placeholder values for secrets) so your entire team shares the same MCP setup.
Method 2: The claude mcp add Command
Claude Code also provides a CLI for managing MCP servers imperatively:
claude mcp add supabase-mcp \
--command npx \
--args "-y" "@supabase/mcp-server-supabase" \
--env SUPABASE_ACCESS_TOKEN=sbp_your_token_here
This is convenient for quick additions without opening a config file. The CLI writes the configuration to your settings, and the server is available immediately.
Both methods produce the same result. Use .mcp.json when you want a versioned, shareable config. Use claude mcp add when you want to set something up fast or are experimenting with a new server.
Project-Level vs User-Level Config
Claude Code supports two configuration scopes:
Project-level: .mcp.json
Place .mcp.json in the root of your project directory. Servers defined here are only available when Claude Code is running inside that project. This is the recommended approach because different projects have different needs — your Next.js app needs Supabase and Playwright, but your CLI tool does not.
my-project/
.mcp.json <-- project-level MCP config
package.json
src/
User-level: ~/.claude.json
Servers configured at the user level (via claude mcp add --global or by editing ~/.claude.json) are available in every project. Use this for servers you always want available, like a GitHub MCP server or a documentation search server.
# Add a server globally
claude mcp add github-mcp \
--command npx \
--args "-y" "@modelcontextprotocol/server-github" \
--env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_your_token_here \
--global
When both project-level and user-level configs exist, Claude Code merges them. Project-level servers take priority if there is a name conflict.
The .mcp.json Format in Detail
Here is a complete .mcp.json with three servers:
{
"mcpServers": {
"supabase-mcp": {
"command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase"],
"env": {
"SUPABASE_ACCESS_TOKEN": "sbp_your_token_here"
}
},
"github-mcp": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
},
"playwright-mcp": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
Field Reference
mcpServers: The top-level object. Each key is an arbitrary name you choose for the server.
command: The executable that starts the MCP server process. Common values:
"npx"— for npm-published servers (most common)"uvx"or"python"— for Python-based servers"node"— for running a local JavaScript file directly"docker"— for containerized servers
args: An array of command-line arguments. For npm servers, typically ["-y", "@package/name"]. The -y flag auto-confirms the npx install prompt. Some servers accept additional configuration arguments:
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
env: Environment variables passed to the server process. API keys and secrets go here. The server process receives these in its environment, keeping them off the command line.
The claude mcp CLI Commands
Claude Code provides several subcommands for managing MCP servers from the terminal:
Adding a stdio server
claude mcp add my-server \
--command npx \
--args "-y" "@some/mcp-server" \
--env API_KEY=your_key_here
Adding an HTTP/SSE server
For remote servers that communicate over HTTP:
claude mcp add remote-docs \
--url https://mcp.example.com/sse
Listing configured servers
claude mcp list
This shows all currently configured servers, their transport type, and their connection status. It is the fastest way to verify your setup is working.
Removing a server
claude mcp remove my-server
Scoping to project or global
Add --global to any command to operate on the user-level config instead of the project-level config:
claude mcp add github-mcp --command npx --args "-y" "@modelcontextprotocol/server-github" --global
claude mcp list --global
claude mcp remove github-mcp --global
Stdio vs HTTP/SSE Transport
MCP servers can communicate with Claude Code using two transport mechanisms:
Stdio (local servers)
Most MCP servers use stdio transport. Claude Code spawns the server as a child process and communicates through standard input/output. The server runs on your machine, starts and stops with your session, and has no network exposure.
{
"mcpServers": {
"playwright-mcp": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
Advantages: fast (no network latency), secure (no open ports), simple (no server infrastructure to manage).
HTTP/SSE (remote servers)
Some MCP servers are hosted remotely and communicate over HTTP, using Server-Sent Events for streaming. You configure these with a url field instead of command and args:
{
"mcpServers": {
"remote-server": {
"url": "https://mcp.example.com/sse"
}
}
}
Or via the CLI:
claude mcp add remote-server --url https://mcp.example.com/sse
Use remote servers when the service is managed by a third party or when you need to share a single server instance across a team. The trade-off is network latency and dependency on an external service being available.
Environment Variables and Secrets
Most MCP servers require API keys or tokens to authenticate with external services. There are several ways to handle these in Claude Code:
Inline in the config
The simplest approach — put the value directly in .mcp.json:
"env": {
"SUPABASE_ACCESS_TOKEN": "sbp_abc123def456"
}
This works for personal projects, but you should never commit real secrets to version control.
Placeholder values for shared configs
If you commit .mcp.json to git, use placeholder values and document what each developer needs to fill in:
"env": {
"SUPABASE_ACCESS_TOKEN": "YOUR_SUPABASE_ACCESS_TOKEN"
}
Using the CLI with environment variables
When using claude mcp add, you can reference existing shell environment variables:
export SUPABASE_ACCESS_TOKEN="sbp_abc123def456"
claude mcp add supabase-mcp \
--command npx \
--args "-y" "@supabase/mcp-server-supabase" \
--env SUPABASE_ACCESS_TOKEN=$SUPABASE_ACCESS_TOKEN
The .gitignore approach
If your .mcp.json contains only secrets and no shareable settings, add it to .gitignore:
# .gitignore
.mcp.json
Each developer maintains their own local copy with their own credentials.
The Permission Model
Claude Code has a built-in permission system for MCP tools. Unlike some clients that auto-allow everything, Claude Code asks you before each tool invocation the first time it encounters a new tool.
When Claude Code wants to use an MCP tool, you will see a prompt like:
Claude wants to use: supabase-mcp > list_tables
Allow this tool? (y/n/always)
Your options:
- y — allow this specific invocation
- n — deny this invocation
- always — allow this tool for the rest of the session without asking again
This means you maintain control over what MCP servers do during your coding session. If a server exposes a tool that drops database tables, Claude Code will ask before calling it. You can deny destructive operations while still allowing read-only queries.
This is a meaningful security advantage over clients that auto-allow all MCP tool calls without user confirmation.
Walkthrough: Setting Up 3 Servers From Scratch
Let's set up a real MCP environment for a fullstack web project. We will add Supabase for database operations, GitHub for repository management, and Playwright for browser testing.
Step 1: Gather your credentials
Before configuring anything, collect the tokens you need:
- Supabase: Go to supabase.com/dashboard/account/tokens and generate a personal access token.
- GitHub: Go to github.com/settings/tokens and create a personal access token with
reposcope. - Playwright: No token required — it runs locally.
Step 2: Create the .mcp.json file
In your project root, create .mcp.json:
{
"mcpServers": {
"supabase-mcp": {
"command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase"],
"env": {
"SUPABASE_ACCESS_TOKEN": "sbp_your_actual_token"
}
},
"github-mcp": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_actual_token"
}
},
"playwright-mcp": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
Step 3: Start Claude Code
Open your terminal in the project directory and start Claude Code:
claude
Claude Code automatically detects the .mcp.json file and starts the configured servers.
Step 4: Verify the servers are connected
Run the list command to confirm:
claude mcp list
You should see all three servers listed with their status. If any show as disconnected, check the troubleshooting section below.
Step 5: Test each server
Try a few prompts to verify each server is working:
- Supabase: "List all tables in my Supabase project"
- GitHub: "Show the open pull requests in this repository"
- Playwright: "Take a screenshot of http://localhost:3000"
When Claude Code tries to use each tool for the first time, it will ask for your permission. Approve them, and you should see real results from each service.
Verifying Your Setup
Beyond claude mcp list, here are ways to confirm everything is working:
Check tool availability
Ask Claude Code: "What MCP tools do you have available?" It will list all registered tools from all connected servers, grouped by server name. This confirms not just that the server connected, but that its tools are loaded and callable.
Run a health check
For each server, try a simple read-only operation:
Supabase: "List my Supabase projects"
GitHub: "What repositories do I have access to?"
Playwright: "Navigate to https://example.com and take a screenshot"
If any of these fail, the error message will usually point to the issue — an expired token, a missing dependency, or a crashed server process.
Troubleshooting
"Server failed to start"
This means Claude Code could not execute the command. Common causes:
npx not found: your PATH might not include the Node.js binary directory, especially if you installed Node via nvm.
# Find your npx path
which npx
# Use the absolute path in your config
{
"command": "/Users/you/.nvm/versions/node/v20.11.0/bin/npx",
"args": ["-y", "@supabase/mcp-server-supabase"]
}
Wrong package name: verify the npm package name is correct by searching on npmjs.com or running the command manually:
npx -y @supabase/mcp-server-supabase
If it fails here, you will see the actual error message that Claude Code cannot show you.
"Tool not available"
The server connected but its tools are not showing up. This usually means:
- The server crashed after starting. Check for error output in your terminal.
- The server requires additional configuration before exposing tools. Some servers need specific environment variables to be set before they register their tools.
- Claude Code needs to be restarted to pick up new tools from a server that was reconfigured.
Permission denied on tool usage
Claude Code's permission model means you might have denied a tool invocation earlier in the session. If you denied a tool you actually need, restart Claude Code — permission choices reset between sessions.
To avoid repeated prompts, use the "always" option when Claude Code asks about a tool you trust.
Environment variable issues
If a server starts but fails to authenticate with its external service:
- Check the variable name: it is case-sensitive.
SUPABASE_ACCESS_TOKENis not the same assupabase_access_token. - Copy the token fresh: trailing spaces or newlines from copy-pasting will cause silent authentication failures.
- Verify the token is valid: tokens expire. Log into the service dashboard and confirm your token is active.
- Check for quoting issues: in
.mcp.json, the value must be a JSON string with double quotes. No single quotes, no template literals.
JSON syntax errors in .mcp.json
The config file must be valid JSON. Common mistakes:
- Trailing comma after the last entry:
{"a": 1,}is invalid - Single quotes instead of double quotes:
{'a': 1}is invalid - Unquoted keys or values
Validate your file with:
python3 -c "import json; json.load(open('.mcp.json'))"
No output means valid JSON. An error message will point to the exact line and character position.
Server works in one project but not another
Check which config scope the server was added to. If you used claude mcp add without --global, the server only exists in the current project. Either add it globally or create a .mcp.json in the other project.
Managing MCP Across Multiple Projects
If you work on several projects with different MCP needs, here is a practical strategy:
Global servers for universal tools
Add servers you always want to the global config:
claude mcp add github-mcp --command npx --args "-y" "@modelcontextprotocol/server-github" --env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx --global
GitHub access is useful regardless of what project you are in.
Project-level servers for specific tools
Put database and project-specific servers in each project's .mcp.json:
{
"mcpServers": {
"supabase-mcp": {
"command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase"],
"env": {
"SUPABASE_ACCESS_TOKEN": "sbp_project_specific_token"
}
}
}
}
Keep a template
Maintain a template .mcp.json that you copy into new projects and customize:
{
"mcpServers": {
"supabase-mcp": {
"command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase"],
"env": {
"SUPABASE_ACCESS_TOKEN": "YOUR_SUPABASE_ACCESS_TOKEN"
}
},
"playwright-mcp": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
Watch your token budget
Each MCP server's tool definitions consume tokens from the context window. Running five servers simultaneously could use 40,000 or more tokens just for tool definitions, leaving less room for your code and conversation. Only enable the servers you actively need for the current task.
Generate Configs Instantly
Getting the config format right across different MCP clients is tedious. Claude Code uses .mcp.json, Cursor uses .cursor/mcp.json, Windsurf uses ~/.codeium/windsurf/mcp_config.json, and Claude Desktop has its own format entirely. Each has slightly different field names and conventions.
stackmcp.dev generates ready-to-use MCP configurations for Claude Code (and five other clients). Pick a pre-built stack tailored to your workflow — fullstack web, frontend developer, indie hacker — select Claude Code as your client, and get a .mcp.json file you can drop into your project. It lists all the environment variables you need to fill in and keeps the server count within a reasonable token budget.
No more piecing together config formats from scattered READMEs. Copy, paste, fill in your tokens, and start building.