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 and has the most flexible MCP integration of any client. It supports two config methods (JSON file and CLI), project-scoped and global servers, a granular permission model, and both stdio and HTTP transports. This guide covers everything you need to get MCP servers running in Claude Code.
TL;DR: Create a
.mcp.jsonfile in your project root with your server definitions, or useclaude mcp addfrom the terminal. Claude Code merges project-level and global configs automatically and asks permission before each tool invocation.
graph TD
A[Get API tokens] --> B[Create .mcp.json or run claude mcp add]
B --> C[Start Claude Code]
C --> D{Servers connected?}
D -->|Yes| E[Approve tool permissions]
D -->|No| F[Check troubleshooting below]
E --> G[Ready to use]
Two Ways to Configure MCP Servers
Claude Code gives you two methods for adding MCP servers: a JSON config file and a CLI command.
Method 1: The .mcp.json Config File
Create a file called .mcp.json in your project root. 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. You can commit it to version control (with placeholder values for secrets) so your team shares the same MCP setup.
Method 2: The claude mcp add Command
claude mcp add supabase-mcp \
--command npx \
--args "-y" "@supabase/mcp-server-supabase" \
--env SUPABASE_ACCESS_TOKEN=sbp_your_token_here
Use .mcp.json for versioned, shareable configs. Use claude mcp add for quick experiments. Both produce identical results.
Project-Level vs User-Level Config
Project-level: .mcp.json
Place .mcp.json in your project root. Servers defined here are only available inside that project.
my-project/
.mcp.json <-- project-level MCP config
package.json
src/
User-level: ~/.claude.json
Servers configured globally (via claude mcp add --global) are available in every project. Good for universally useful servers like GitHub MCP.
claude mcp add github-mcp \
--command npx \
--args "-y" "@modelcontextprotocol/server-github" \
--env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_your_token_here \
--global
When both exist, Claude Code merges them. Project-level takes priority on name conflicts.
Complete .mcp.json Example
Three servers covering a typical fullstack web workflow:
Supabase MCP | npm | Tools: 25 | ~12,875 tokens
GitHub MCP | npm | Tools: 20 | ~10,300 tokens
Playwright MCP | npm | Tools: 20 | ~10,300 tokens
{
"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: Top-level object. Each key is the server name you choose.command: The executable ("npx","uvx","node","docker").args: Command-line arguments. For npm servers:["-y", "@package/name"].env: Environment variables passed to the server process. API keys go here.
The claude mcp CLI Commands
# Add a stdio server
claude mcp add my-server --command npx --args "-y" "@some/mcp-server" --env API_KEY=your_key
# Add an HTTP/SSE server
claude mcp add remote-docs --url https://mcp.example.com/sse
# List configured servers
claude mcp list
# Remove a server
claude mcp remove my-server
# Global scope (add --global to any command)
claude mcp add github-mcp --command npx --args "-y" "@modelcontextprotocol/server-github" --global
Stdio vs HTTP/SSE Transport
Stdio (local): Claude Code spawns the server as a child process. Fast, secure, no network exposure.
{
"mcpServers": {
"playwright-mcp": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
HTTP/SSE (remote): For hosted MCP servers. Uses url instead of command/args.
{
"mcpServers": {
"remote-server": {
"url": "https://mcp.example.com/sse"
}
}
}
Environment Variables and Secrets
- Inline in config: Put the value directly in
.mcp.json. Fine for personal projects, never commit real secrets. - Placeholder values: Commit with
"YOUR_SUPABASE_ACCESS_TOKEN"and document what each dev needs. - CLI with shell vars:
claude mcp add supabase-mcp --env SUPABASE_ACCESS_TOKEN=$SUPABASE_ACCESS_TOKEN .gitignoreapproach: Add.mcp.jsonto.gitignoreif it contains only secrets.
The Permission Model
Claude Code asks before each tool invocation:
Claude wants to use: supabase-mcp > list_tables
Allow this tool? (y/n/always)
- y -- allow this invocation
- n -- deny this invocation
- always -- allow for the rest of the session
This is a meaningful security advantage over clients that auto-allow all MCP tool calls. If a server exposes a destructive tool, you can deny it while allowing read-only queries. For more on MCP security, see how to secure your MCP server setup.
Walkthrough: Setting Up 3 Servers From Scratch
Step 1: Gather credentials
- Supabase: supabase.com/dashboard/account/tokens
- GitHub: github.com/settings/tokens (needs
reposcope) - Playwright: No token required
Step 2: Create .mcp.json
Use the complete example from the section above. Replace placeholder tokens with your real values.
Step 3: Start Claude Code
claude
Claude Code detects .mcp.json automatically and starts the servers.
Step 4: Verify
claude mcp list
All three servers should show as connected.
Step 5: Test
- "List all tables in my Supabase project"
- "Show the open pull requests in this repository"
- "Take a screenshot of http://localhost:3000"
Approve tool permissions when prompted. For deep dives on each server, see the individual guides: Supabase MCP, GitHub MCP, Playwright MCP.
Troubleshooting
"Server failed to start"
npx not found: Your PATH might not include Node.js, especially with nvm. Use the absolute path:
{
"command": "/Users/you/.nvm/versions/node/v20.11.0/bin/npx",
"args": ["-y", "@supabase/mcp-server-supabase"]
}
Wrong package name: Test manually: npx -y @supabase/mcp-server-supabase
"Tool not available"
- Server crashed after starting -- check terminal output
- Server needs additional env vars before exposing tools
- Restart Claude Code to pick up reconfigured servers
Environment variable issues
- Variable names are case-sensitive (
SUPABASE_ACCESS_TOKEN!=supabase_access_token) - Copy tokens fresh -- trailing spaces cause silent auth failures
- Verify the token is still valid in the service dashboard
JSON syntax errors in .mcp.json
Validate with:
python3 -c "import json; json.load(open('.mcp.json'))"
Common mistakes: trailing commas, single quotes, unquoted keys. For a comprehensive list of fixes, see how to fix MCP server connection errors.
Managing MCP Across Multiple Projects
- Global servers for universal tools: GitHub MCP is useful regardless of project. Add it with
--global. - Project-level for specific tools: Database and project-specific servers go in each project's
.mcp.json. - Watch your token budget: Each server's tool definitions consume context tokens. Five servers could use 40,000+ tokens. Only enable what you actively need. See how to cut MCP token costs for strategies.
The same servers work across Cursor, Continue.dev, and Windsurf -- only the config format changes. Browse pre-built stacks to find the right server combination for your workflow.