← All guides

Claude Code MCP Server Setup: A Practical Guide (2026)

How to add MCP servers to Claude Code — local stdio servers, remote HTTP servers, and the debugging workflow when things don't work.

🇰🇷 한국어로 보기 →

Claude Code MCP Server Setup: A Practical Guide (2026)

MCP (Model Context Protocol) lets Claude Code talk to external tools and data sources through a standardized interface. Instead of Claude having to search the web or read files manually, an MCP server can expose tools that Claude calls directly — fetching Slack threads, querying databases, running browser automation, or reading from any API.

This guide covers the practical setup: where the config lives, how to add servers, the differences between local and remote servers, and how to debug when tools don't appear.

Where the MCP config lives

Claude Code reads MCP server configuration from two places:

User-level (applies to all projects):

~/.claude/claude_desktop_config.json

Project-level (checked into your repo):

.claude/mcp.json    # or claude_desktop_config.json

Project-level takes precedence for the servers defined there. Both files are merged — you can have global servers (GitHub, Slack) and project-specific servers (a database connection, a local test runner) active simultaneously. Both MCP config files and hook definitions live inside the same .claude/ directory — see the Claude Code settings.json reference for the full schema.

Config format

Both files use the same JSON structure:

{
  "mcpServers": {
    "server-name": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/server.js"],
      "env": {
        "API_KEY": "your-key-here"
      }
    }
  }
}

The key fields:

Adding a local stdio server

Most community MCP servers are npm packages that run as local processes. The pattern:

{
  "mcpServers": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
    },
    "github": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
      }
    },
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
    }
  }
}

After editing the config, restart Claude Code. New servers take effect on next launch.

Adding a remote SSE server

For servers that run as HTTP endpoints (e.g., a deployed MCP server your team runs):

{
  "mcpServers": {
    "company-data": {
      "type": "sse",
      "url": "https://mcp.yourcompany.com/sse",
      "headers": {
        "Authorization": "Bearer your-token"
      }
    }
  }
}

SSE servers don't require a local process. Claude Code connects to the URL and maintains a server-sent events connection for the duration of the session.

Verifying servers loaded correctly

In a Claude Code session, run:

/mcp

This shows all configured MCP servers, their connection status, and the tools they expose. A healthy output looks like:

MCP Servers:
  ✓ filesystem — connected (3 tools: read_file, write_file, list_directory)
  ✓ github — connected (8 tools: get_file_contents, create_issue, ...)
  ✗ postgres — failed to connect (exit code 1)

If a server shows failed to connect, that's the signal to debug.

Debugging a server that won't connect

Step 1: Run the server command manually.

Take the exact command from your config and run it in your terminal:

npx -y @modelcontextprotocol/server-postgres "postgresql://localhost/mydb"

If it exits immediately with an error, you'll see the real error message. Common causes:

Step 2: Check environment variable injection.

Env vars in the MCP config are injected into the server process, but they aren't available in your shell. If the server needs GITHUB_PERSONAL_ACCESS_TOKEN, it must be in the config's "env" block, not just in your .zshrc:

"env": {
  "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_actual_token"
}

Step 3: Check MCP logs.

Claude Code writes server stderr to logs. On macOS:

# For Claude Desktop app
cat ~/Library/Logs/Claude/mcp-server-{server-name}.log

# For Claude Code CLI
cat ~/.claude/logs/mcp-{server-name}.log

The logs show the exact error the server process emitted before exiting.

Step 4: Verify the server version is compatible.

MCP is a living protocol. Some community servers target an older SDK version and haven't been updated. Check the package's GitHub issues for "Claude Code compatibility" before spending time debugging an incompatibility.

Writing your own MCP server

If you need to expose internal data or tools that don't have a community server, the SDK makes this straightforward:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "my-internal-tools", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "get_customer",
      description: "Fetch customer record by ID from internal CRM",
      inputSchema: {
        type: "object",
        properties: {
          customer_id: { type: "string", description: "Customer ID" },
        },
        required: ["customer_id"],
      },
    },
  ],
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "get_customer") {
    const { customer_id } = request.params.arguments as { customer_id: string };
    const customer = await fetchFromCRM(customer_id);
    return {
      content: [{ type: "text", text: JSON.stringify(customer, null, 2) }],
    };
  }
  throw new Error(`Unknown tool: ${request.params.name}`);
});

const transport = new StdioServerTransport();
await server.connect(transport);

Then add it to your config:

{
  "mcpServers": {
    "internal-crm": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/your/server.js"],
      "env": {
        "CRM_API_KEY": "your-key"
      }
    }
  }
}

Security: what to keep in mind

MCP servers run with your permissions. A stdio server runs as your local user and can read any file you can. Only add servers you trust.

Don't commit secrets to the project config. If .claude/mcp.json is checked in, use environment variable references rather than hardcoding tokens. Some teams use a .claude/mcp.local.json (gitignored) pattern for local overrides.

Remote SSE servers see your requests. Claude sends tool call arguments to the server, which means the server can log anything Claude sends. For sensitive internal data, a locally-running server is safer than a remote one. You can also use Claude Code hooks to log or block specific MCP tool calls at the Claude Code level as an extra layer of control.

Practical server recommendations for Claude Code workflows

Use case Server Install
Read/write local files @modelcontextprotocol/server-filesystem npx -y @modelcontextprotocol/server-filesystem /path
GitHub repos, issues, PRs @modelcontextprotocol/server-github Needs GITHUB_PERSONAL_ACCESS_TOKEN
Postgres queries @modelcontextprotocol/server-postgres Pass connection string as arg
Fetch web pages @modelcontextprotocol/server-fetch No config needed
Browser automation @playwright/mcp Requires Playwright install
Slack threads Community Slack MCP Needs workspace token

The MCP registry at modelcontextprotocol.io maintains the canonical list of official and community servers. For curated picks across the most common developer workflows, see best MCP servers for Claude Code in 2026.


For more Claude Code configuration patterns — including 40 slash command templates and 300 production-tested prompts — see the Claude Code Power Prompts collection.

Drafted with Claude Code. MCP configuration behavior tested against Claude Code CLI 1.x. The MCP protocol and server list evolve frequently — check the official registry for the latest server packages.

Frequently Asked Questions

Where should I put my MCP server configuration — user-level or project-level?

Use ~/.claude/claude_desktop_config.json for servers you want available in every project (GitHub, Slack, filesystem access to your home directory). Use .claude/mcp.json for project-specific servers like a database connection or a custom internal tool. Both files are merged — servers from both locations are active simultaneously.

Why does my MCP server show "failed to connect" in /mcp?

The most common causes are: a misspelled npm package name, a missing environment variable not included in the config's "env" block, a malformed connection string, or a version incompatibility between the server and the MCP protocol. Run the exact command from your config manually in your terminal to see the actual error message before debugging further.

Do I need to restart Claude Code every time I change the MCP config?

Yes. MCP server configuration is read at startup. After editing claude_desktop_config.json or .claude/mcp.json, restart your Claude Code session. Changes will not take effect in an already-running session.

Is it safe to check .claude/mcp.json into git?

It is safe to commit the structure and server definitions, but never commit the actual secrets. Use the "env" block for API tokens and reference them as environment variables that team members set locally, or use .claude/mcp.local.json (gitignored) for personal credentials on top of the shared project config.

Can I build an MCP server in Python instead of TypeScript?

Yes. The MCP SDK has official Python support (pip install mcp). The TypeScript SDK is more commonly used in examples because most community servers are Node.js packages, but Python MCP servers work identically — implement the ListTools and CallTool request handlers, connect via stdio transport, and add the server to your config the same way.


Take It Further

Claude Code Power Prompts 300 — 300 battle-tested prompts for Claude Code, organized by use case. Copy, paste, ship.

40 slash command templates. Token-optimized variants. JSONL file for direct import. Tested in production sessions.

→ Get Claude Code Power Prompts 300 — $29

30-day money-back guarantee. Instant download.

AI Disclosure: Drafted with Claude Code. MCP protocol behavior verified against the Claude Code 1.x changelog as of 2026-04-26.

Tools and references