Overview

Claude Code connects to MCP servers over HTTP (remote), stdio (local process), or WebSocket (JSON config only). This guide adds the GitHub MCP server and a local stdio server, picks the right scope, allows specific tools, and checks the connection. An MCP server is not a Claude Code skill; skills are covered in claude-code-skills.

Prerequisites

  • Claude Code installed and signed in; see set-up-claude-code.
  • For stdio servers distributed on npm, Node 22 or newer.
  • For GitHub, a personal access token with the narrowest scopes the task needs.

Steps

1. Prefer HTTP for remote servers

claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
  --header "Authorization: Bearer $GITHUB_PAT"

The SSE transport is deprecated; use --transport http wherever the server offers it. The old @modelcontextprotocol/server-github npm package is deprecated in favor of GitHub’s own server.

2. Add a local stdio server

Everything after -- is the server command.

claude mcp add --transport stdio --scope project fs -- \
  npx -y @modelcontextprotocol/server-filesystem /path/to/allowed/dir

3. Choose the scope

ScopeStored inShared
local (default)~/.claude.json, this project onlyNo
project.mcp.json at the repo rootYes, commit it
user~/.claude.json, all projectsNo

A committed .mcp.json can also be written by hand. Use ${VAR} or ${VAR:-default} for secrets in command, args, env, url, and headers; never write the literal token.

{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ${GITHUB_PAT}" }
    }
  }
}

Teammates must approve a project-scoped server the first time they run claude in the repo. claude mcp reset-project-choices clears those approvals.

4. Allow specific tools

Tools are named mcp__<server>__<tool>. Add read-only ones to permissions.allow in .claude/settings.json; everything else keeps prompting.

{ "permissions": { "allow": ["mcp__github__get_file_contents", "mcp__github__list_issues"] } }

Treat tool output as untrusted input; see mcp-security.

Verify it worked

claude mcp list          # configured servers
claude mcp get github    # scope, transport, URL

Inside a session, /mcp lists servers, tool counts, and OAuth state. Ask “List the last 5 open issues” and confirm a mcp__github__... call appears in the transcript.

Common errors

  • Server stays pending. A project-scoped server needs interactive approval; start claude in the repo and accept the prompt.
  • Empty token. ${GITHUB_PAT} expands from the shell that launched claude; export it first. Credential variables such as ANTHROPIC_API_KEY read as empty inside remote url and headers.
  • Prompted despite an allow rule. The name must match exactly; copy it from /mcp.
  • Server missing. .mcp.json must sit at the project root and be valid JSON; claude mcp get <name> shows what loaded.
  • Write tools are available. Narrow the token’s scopes at the provider; an allow list only skips prompts.

FAQ

Should I use SSE or HTTP for a remote MCP server in Claude Code?

Use --transport http; the SSE transport is deprecated.

Where does Claude Code store MCP server config?

local (the default) and user scopes live in ~/.claude.json, while project scope lives in .mcp.json at the repo root, which you commit to share with the team.

How do I keep an API token out of .mcp.json?

Write ${VAR} or ${VAR:-default} instead of the literal token; it expands from the shell that launched claude, so export the variable first.

Why does my project MCP server stay pending?

A project-scoped server needs interactive approval the first time each teammate runs claude in the repo. claude mcp reset-project-choices clears those approvals.

Does a permissions allow list stop Claude Code from using MCP write tools?

No; an allow list only skips prompts for the named mcp__<server>__<tool> tools. Narrow the token’s scopes at the provider to remove write access.