Overview
Model Context Protocol (MCP) servers extend Claude Code with external tool access, read databases, call APIs, or browse files outside the project directory. This guide installs Claude Code, wires the GitHub MCP server as a concrete example, limits permissions to read-only, and confirms the server is reachable with /mcp. The full MCP server reference lives in mcp-servers.
Prerequisites
- Claude Code installed and authenticated. If not, follow set-up-claude-code first.
- Node 22 on the path. MCP servers are most commonly Node packages.
- A GitHub personal access token (PAT) with at least
repo:readscope for the GitHub server example. Generate one at GitHub > Settings > Developer Settings > Personal Access Tokens. - The repository you are working in, open in a terminal.
Steps
1. Install Claude Code
If already installed, skip to step 2.
npm install -g @anthropic-ai/claude-code
claude --versionAuthenticate on first run. claude opens the login flow; complete it in the browser.
2. Locate or create .mcp.json
MCP server configuration lives in .mcp.json at the repository root (project scope, meant to be committed and shared with the team) or in ~/.claude.json (user scope, personal). .claude/settings.json is a separate file for permissions and hooks; Claude Code does not read mcpServers from it.
touch .mcp.json3. Add the GitHub MCP server
The GitHub MCP server (@modelcontextprotocol/server-github) exposes tools to read issues, pull requests, file contents, and repository metadata.
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PAT}"
}
}
}
}The ${GITHUB_PAT} syntax reads from the environment. Store the token in .env or export it in your shell profile; never hardcode it. Add .env to .gitignore. .mcp.json itself is meant to be committed; a teammate who pulls it sees the server as “Pending approval” until they run claude and accept it. You can also register the server without hand-editing JSON: claude mcp add --env GITHUB_PERSONAL_ACCESS_TOKEN=${GITHUB_PAT} --transport stdio github --scope project -- npx -y @modelcontextprotocol/server-github.
4. Restrict permissions
By default Claude Code prompts for confirmation on every tool call. Add an allow list under permissions in .claude/settings.json to restrict what the GitHub server may do to read-only operations:
{
"permissions": {
"allow": [
"mcp__github__get_file_contents",
"mcp__github__list_issues",
"mcp__github__list_pull_requests",
"mcp__github__get_commit",
"mcp__github__search_code"
]
}
}Listing tools explicitly in allow skips the confirmation prompt for those tools only. Any tool not in the list still prompts. See mcp-servers for the full permissions model and prompt-injection-defense for why you should keep write tools behind prompts.
5. Verify with /mcp
Start a Claude Code session in the repository:
claudeThen run the /mcp command inside the session:
/mcp
Claude Code lists all connected MCP servers and their status. A healthy connection shows:
github: connected (14 tools available)
If the server shows “disconnected” or an error, check the troubleshooting section below.
6. Test a tool call
Ask Claude Code to use the server:
List the last 5 open issues in this repository.
Claude Code calls mcp__github__list_issues and prints the result. Confirm the tool call appears in the transcript.
Verify it worked
# 1. /mcp shows the server as connected.
# Run inside a claude session: /mcp
# 2. The MCP config file is valid JSON.
node -e "JSON.parse(require('fs').readFileSync('.mcp.json','utf8'))"
# No output means valid JSON.
# 3. The PAT has the right scope.
curl -sH "Authorization: Bearer $GITHUB_PAT" https://api.github.com/user | jq .login
# Your GitHub usernameCommon errors
/mcpshows the server as “Pending approval” instead of connected. This is the step most likely to trip up a first run. A project-scoped server from.mcp.jsonthat you have not personally approved yet stays pending until you runclaudeinteractively in the repo and accept the workspace trust dialog; a fresh clone never auto-approves its own.mcp.json. Runclaude, approve the prompt, then re-check/mcp./mcpshows server as disconnected. Thenpxcommand failed to install the package. Runnpx -y @modelcontextprotocol/server-githubmanually to see the error. Common causes: network proxy, wrong Node version.GITHUB_PERSONAL_ACCESS_TOKENis empty. The${GITHUB_PAT}substitution only works if the variable is exported in the shell runningclaude. Addexport GITHUB_PAT=...to your shell profile.- Tool calls prompt for confirmation despite being in
allow. The tool name inallowmust match exactly, including themcp__<server>__prefix. Use/mcpto confirm the exact names. .mcp.jsonis not read. Claude Code looks for.mcp.jsonin the working directory whereclaudewas invoked. Start Claude Code from the repo root, and confirm the server shows as connected (not “Pending approval”) with/mcp.- Write tools are available when they should not be. Remove write tools from the PAT scopes at the GitHub level, not just from the
allowlist. Defense-in-depth: least privilege at both layers.