---
title: "How to run Claude Code with an MCP server"
slug: "run-claude-code-with-mcp"
category: "howto"
tags: ["howto", "claude-code", "mcp", "ai-agents", "tutorial", "tools"]
status: "stable"
last_updated: 2026-08-14
summary: "Install Claude Code, configure an MCP server in .mcp.json using the GitHub server as the example, restrict permissions, and verify the connection with /mcp."
related: ["[[ai-agents/claude-code]]", "[[ai-agents/mcp-servers]]", "[[ai-agents/multi-agent]]", "[[tooling/claude-code-workflow]]", "[[howto/set-up-claude-code]]", "[[tooling/github]]", "[[ai-agents/prompt-injection-defense]]"]
---

## 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 [[ai-agents/mcp-servers]].

## Prerequisites

- Claude Code installed and authenticated. If not, follow [[howto/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:read` scope 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.

```bash
npm install -g @anthropic-ai/claude-code
claude --version
```

Authenticate 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.

```bash
touch .mcp.json
```

### 3. Add the GitHub MCP server

The GitHub MCP server (`@modelcontextprotocol/server-github`) exposes tools to read issues, pull requests, file contents, and repository metadata.

```json
{
  "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:

```json
{
  "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 [[ai-agents/mcp-servers]] for the full permissions model and [[ai-agents/prompt-injection-defense]] for why you should keep write tools behind prompts.

### 5. Verify with `/mcp`

Start a Claude Code session in the repository:

```bash
claude
```

Then 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

```bash
# 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 username
```

## Common errors

- **`/mcp` shows 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.json` that you have not personally approved yet stays pending until you run `claude` interactively in the repo and accept the workspace trust dialog; a fresh clone never auto-approves its own `.mcp.json`. Run `claude`, approve the prompt, then re-check `/mcp`.
- **`/mcp` shows server as disconnected**. The `npx` command failed to install the package. Run `npx -y @modelcontextprotocol/server-github` manually to see the error. Common causes: network proxy, wrong Node version.
- **`GITHUB_PERSONAL_ACCESS_TOKEN` is empty**. The `${GITHUB_PAT}` substitution only works if the variable is exported in the shell running `claude`. Add `export GITHUB_PAT=...` to your shell profile.
- **Tool calls prompt for confirmation despite being in `allow`**. The tool name in `allow` must match exactly, including the `mcp__<server>__` prefix. Use `/mcp` to confirm the exact names.
- **`.mcp.json` is not read**. Claude Code looks for `.mcp.json` in the working directory where `claude` was 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 `allow` list. Defense-in-depth: least privilege at both layers.

## Related

- [[ai-agents/claude-code]]
- [[ai-agents/mcp-servers]]
- [[ai-agents/multi-agent]]
- [[tooling/claude-code-workflow]]
- [[howto/set-up-claude-code]]
- [[tooling/github]]
- [[ai-agents/prompt-injection-defense]]
