---
title: "Claude Code: MCP Integration"
slug: "claude-code-mcp"
category: "ai-agents"
tags: ["claude-code", "mcp", "tools", "integrations", "ai-agents", "settings"]
status: "stable"
last_updated: 2026-05-29
summary: "Connect MCP servers to Claude Code via settings.json, scope tools per repo, pass secrets through env, and prefer MCP tools over Bash for durable integrations."
related: ["[[ai-agents/claude-code]]", "[[ai-agents/mcp-servers]]", "[[ai-agents/claude-code-permissions]]", "[[ai-agents/claude-code-hooks]]", "[[tooling/claude-code-workflow]]", "[[tooling/github]]", "[[howto/set-up-claude-code]]"]
---

## Overview

Claude Code connects to MCP servers declared in `settings.json`. Once connected, the server's tools appear alongside built-in tools and Claude can call them in any turn. The pattern rule is: prefer MCP tools over `Bash` when the integration will be used across sessions. A one-off `gh` invocation is fine; recurring GitHub operations belong in the GitHub MCP server. Use the GitHub-maintained `github/github-mcp-server`, not the archived `@modelcontextprotocol/server-github` npm package. See [[ai-agents/mcp-servers]] for designing servers; this page covers the Claude Code client configuration.

## Declare MCP servers in settings.json

Each server gets an entry under `mcpServers`. The key is the server's logical name; the value describes how to launch or connect to it.

```json
{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}
```

GitHub maintains `github/github-mcp-server`. Run it from the published Docker image (shown above), from the prebuilt Go binary, or point Claude Code at GitHub's hosted remote server (`https://api.githubcopilot.com/mcp/`) over Streamable HTTP. The old `@modelcontextprotocol/server-github` npm package has been archived to `modelcontextprotocol/servers-archived` and receives no security fixes; do not use it.

Place project-specific servers in `.claude/settings.json`. Place personal or cross-project servers in `~/.claude/settings.json`. Both files are read; project settings merge on top.

## Pass secrets through environment variables, never inline

The `env` block in the server config accepts `${VAR}` substitutions resolved from the shell environment. Never write a token or connection string as a literal value in `settings.json`.

Reasons: `settings.json` is often committed to version control. Literals leak in diffs, logs, and PR reviews. Environment variables stay in `.env` (gitignored) or in the CI secrets store.

```json
"env": {
  "GITHUB_TOKEN": "${GITHUB_TOKEN}",
  "DATABASE_URL": "${DATABASE_URL}"
}
```

Claude Code reads the current shell environment when launching servers. Set the variables in your shell profile or a gitignored `.env.local` file sourced at session start.

## Restrict tool exposure with allowedTools

By default, Claude Code exposes every tool a server advertises. Use `allowedTools` to restrict access to the tools the project actually needs.

```json
{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
        "ghcr.io/github/github-mcp-server"
      ],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" },
      "allowedTools": [
        "mcp__github__list_issues",
        "mcp__github__create_pull_request",
        "mcp__github__pull_request_read",
        "mcp__github__merge_pull_request"
      ]
    }
  }
}
```

Restricting to read-only tools for a project that should not create issues prevents accidents during exploratory sessions. Allowlists also document the project's intended integration surface.

## Scope servers to specific repositories

Use project-level `.claude/settings.json` rather than user-level `~/.claude/settings.json` when the server is specific to one repo. A Postgres server pointed at the dev database for project A should not appear in project B's sessions.

For shared servers (GitHub, Notion), declare them at the user level but restrict `allowedTools` per project. The user-level declaration provides the auth; the project-level restriction limits the blast radius.

## Prefer MCP tools over Bash for durable integrations

The tradeoff is:

- `Bash` with `gh pr create`: works, no setup, breaks on quoting edge cases, not logged by MCP, not consistent across sessions.
- `mcp__github__create_pull_request`: typed inputs, no quoting issues, MCP-level logging, consistent schema across sessions.

Use `Bash` for one-off commands the agent will not repeat. Use MCP tools for operations that recur: reading PRs, posting comments, querying a database, writing to a project management tool.

The practical test: if you have written the same `Bash` command in three different briefs, write an MCP server for it or enable the official one.

## Confirm server connectivity before relying on it in a brief

MCP servers can fail to start (missing binary, bad token, network error). A brief that assumes GitHub MCP is live will silently fall back to Bash or fail mid-session.

Add a preflight step to briefs that depend on MCP:

```
Phase 0: Verify MCP connectivity.
Run: list available tools and confirm mcp__github__list_issues is present.
If not present, stop and report the error.
```

This catches misconfiguration before the expensive phases run.

## Related

- [[ai-agents/claude-code]]
- [[ai-agents/mcp-servers]]
- [[ai-agents/claude-code-permissions]]
- [[ai-agents/claude-code-hooks]]
- [[tooling/claude-code-workflow]]
- [[tooling/github]]
- [[howto/set-up-claude-code]]
