---
title: "在 CLI Agent 里挂 MCP server"
wiki: cli
category: "配置管理"
slug: configure-mcp-in-cli
url: https://learnagent.wiki/cli/cards/configure-mcp-in-cli
tags: ["MCP", "Claude Code", "claude mcp add", "配置", "集成"]
last_updated: 2026-04-22
reading_time: 19
---

> 在终端里跑 AI Agent，绕不开一个高频问题：**怎么让它访问外部工具？** 你想让 Claude Code 查 Sentry 错误、读 PostgreSQL 表、提 GitHub PR——这些事要么靠 shell 命令现凑（脆弱、上下文乱），要么走 [MCP（Model Context Protocol）](/mcp/cards/what-is-mcp) 把外部能力以"标准协议"的方式注册进来。后者就是这张卡要讲的事。

# 在 CLI Agent 里挂 MCP server

## 基础概念

在终端里跑 AI Agent，绕不开一个高频问题：**怎么让它访问外部工具？** 你想让 Claude Code 查 Sentry 错误、读 PostgreSQL 表、提 GitHub PR——这些事要么靠 shell 命令现凑（脆弱、上下文乱），要么走 [MCP（Model Context Protocol）](/mcp/cards/what-is-mcp) 把外部能力以"标准协议"的方式注册进来。后者就是这张卡要讲的事。

CLI Agent 接 MCP 和 Claude Desktop 接 MCP 的本质一致——都是 Host 启一个 Client、Client 连一个 Server——但 **CLI 端的配置入口完全不同**：

| 维度 | Claude Desktop | Claude Code（CLI） |
|------|---------------|-------------------|
| 配置方式 | 手动编辑 `claude_desktop_config.json` | `claude mcp add` 命令 + `.mcp.json` 文件 |
| 配置作用域 | 一份全局配置 | local / project / user 三级 |
| 团队协作 | 不支持（配置不进 Git） | `.mcp.json` 进 Git，团队 clone 即用 |
| 加新 Server 后是否要重启 | 必须重启 App | 改完进对话敲 `/mcp` 刷新即可 |
| 远程 Server 鉴权 | 手动填 Token | OAuth 2.0 浏览器流程 |
| 反向能力（Sampling 等） | 完整支持 | 当前不支持 Sampling |

> CLI 端的两种挂载方式不是对立的——`claude mcp add` 在底层就是写文件，写到哪个文件由 `--scope` 决定。**命令式适合个人快速试，配置式（特别是 project 作用域的 `.mcp.json`）适合团队共享和版本管理。**

### 核心要素

| 要素 | 说明 |
|------|------|
| **两种入口** | 命令式 `claude mcp add` / 配置式编辑 `.mcp.json` 或 `~/.claude.json` |
| **三种传输** | stdio（本地子进程，零网络）/ HTTP（远程，OAuth 友好）/ SSE（远程，已 deprecated） |
| **三级作用域** | local（默认，仅自己 + 当前项目）/ project（团队共享 `.mcp.json`）/ user（自己跨所有项目） |
| **状态查看** | 终端 `claude mcp list`；对话内 `/mcp` |
| **环境变量展开** | `.mcp.json` 支持 `${VAR}` 与 `${VAR:-default}` 占位符，避免把 secret 写进 Git |

### 从添加到调用的完整链路

```mermaid
sequenceDiagram
    participant U as 用户
    participant CLI as Claude Code 进程
    participant CFG as ~/.claude.json<br/>或 .mcp.json
    participant Cli as MCP Client
    participant Srv as MCP Server<br/>(stdio 或 HTTP)
    participant LLM as 模型

    U->>CLI: claude mcp add sentry --transport http https://...
    CLI->>CFG: 写入 mcpServers.sentry
    Note over CFG: 持久化到磁盘

    U->>CLI: 启动 claude
    CLI->>CFG: 读取所有 mcpServers
    loop 每个 Server
        CLI->>Cli: 创建 Client 实例
        Cli->>Srv: 启动 stdio 子进程 / 建 HTTP 连接
        Srv-->>Cli: tools/list 返回工具清单
    end

    U->>CLI: "看看 Sentry 最近 24h 的错误"
    CLI->>LLM: 把 tools 清单 + 用户消息发出去
    LLM-->>CLI: tool_use(sentry.list_errors, ...)
    CLI->>Cli: 转发调用
    Cli->>Srv: JSON-RPC tools/call
    Srv-->>Cli: 工具结果
    Cli-->>CLI: 结果
    CLI->>LLM: tool_result
    LLM-->>U: 自然语言回答
```

注意中间那段循环——**Server 进程是在 CLI 启动时一次性拉起的**。如果是 stdio Server，它就跟着 `claude` 进程的生命周期走，CLI 退出 Server 也跟着死；如果是 HTTP Server，断线时 Claude Code 会用指数退避重连最多 5 次，5 次失败后在 `/mcp` 里标 failed，需要手动 retry。stdio 进程崩了不会自动重启，要重新进会话。

## 基础用法

### 入口一：`claude mcp add` 命令式

最常用、最快的方式。一条命令搞定，比手动编辑 JSON 省心。语法：

```bash
# 基本形式（注意所有 flag 必须在 name 之前，stdio 启动命令在 -- 之后）
claude mcp add [options] <name> [-- <command> [args...]]
```

#### 挂一个 stdio Server（本地 PostgreSQL）

```bash
# 拉起一个本地 dbhub 进程，连只读 Postgres
claude mcp add db --transport stdio \
  --env LOG_LEVEL=info \
  -- npx -y @bytebase/dbhub --dsn "postgresql://readonly:pass@localhost:5432/analytics"

# 验证
claude mcp list
# 应该输出：db: npx -y @bytebase/dbhub --dsn ...
```

几个关键点：

- `--transport stdio` 是默认值，可省略，但显式写出来更清楚。
- `--env KEY=VAL` 把环境变量塞给子进程，可重复多次。
- `--` **是分隔符**，左边是 Claude Code 自己的 flag，右边是要 spawn 的命令本体。漏掉它，Claude 会把 `npx` 当成 `claude mcp add` 的参数，报奇怪的错。
- Server 名字（这里是 `db`）是你自己起的别名，后面 `claude mcp get db` / `claude mcp remove db` 都用这个名字。

#### 挂一个远程 HTTP Server（Sentry，带 OAuth）

```bash
# 远程 server 一行命令，不需要写 token
claude mcp add sentry --transport http https://mcp.sentry.dev/mcp

# 进对话授权
claude
# 在对话里输入：
# /mcp
# 选 sentry → Authenticate → 浏览器弹 OAuth 页 → 授权完成
```

`--transport http` 是当前推荐的远程协议；`--transport sse` 还能用但**官方已标 deprecated**，新接入直接选 http。

如果远程 Server 不走 OAuth，要手填 header：

```bash
claude mcp add my-internal-api --transport http https://api.internal.com/mcp \
  --header "Authorization: Bearer $INTERNAL_TOKEN" \
  --header "X-Tenant: acme"
```

#### 三种作用域怎么选

```bash
# 默认：local（只在当前项目可见，写到 ~/.claude.json 的 projects.<当前路径>.mcpServers）
claude mcp add stripe --transport http https://mcp.stripe.com

# project：写到项目根目录的 .mcp.json，进 Git，团队共享
claude mcp add paypal --scope project --transport http https://mcp.paypal.com/mcp

# user：写到 ~/.claude.json 的 user 段，自己所有项目都生效
claude mcp add github --scope user --transport http https://api.githubcopilot.com/mcp/
```

优先级 **local > project > user**，同名 Server 高优先级覆盖低优先级。

#### 管理命令一览

```bash
claude mcp list             # 列所有 Server
claude mcp get sentry       # 看某个 Server 详情（含 OAuth 状态）
claude mcp remove sentry    # 删除
claude mcp reset-project-choices  # 重置 .mcp.json 的批准状态
claude mcp serve            # 把 Claude Code 自己当 Server，供别的 Host 调
claude mcp add-from-claude-desktop  # 从 Desktop 一键导入（仅 macOS / WSL）
```

### 入口二：直接编辑配置文件

当你需要团队共享、或者要写复杂的 env 变量展开时，编辑文件比命令式更直观。

#### 团队共享的 `.mcp.json`（项目根目录）

```json
{
  "mcpServers": {
    "sentry": {
      "type": "http",
      "url": "https://mcp.sentry.dev/mcp"
    },
    "internal-api": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    },
    "db-readonly": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@bytebase/dbhub",
        "--dsn",
        "${DATABASE_URL}"
      ],
      "env": {
        "LOG_LEVEL": "info"
      }
    }
  }
}
```

这个文件**可以、也应该提交到 Git**，团队成员 clone 仓库后第一次启 Claude Code 会弹确认框（防止恶意仓库塞 Server 进来），同意后就跟自己配的没区别。

环境变量展开规则：

- `${VAR}` —— 取环境变量 `VAR` 的值，未设置则**解析失败**，整个 `.mcp.json` 都加载不了。
- `${VAR:-default}` —— `VAR` 没设置时回退到 `default`。
- 可以出现的字段：`command`、`args` 中的每一项、`env` 的 value、`url`、`headers` 的 value。

写完团队 Wiki 里告诉每个人：`export API_KEY=xxx`、`export DATABASE_URL=xxx`，剩下的事 Claude Code 替大家管。**绝对不要把 token 直接写进 `.mcp.json`**，否则进 Git 历史就洗不掉。

#### 个人作用域的 `~/.claude.json`

local 和 user 作用域都落在 `~/.claude.json`，结构大致是：

```json
{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    }
  },
  "projects": {
    "/Users/me/work/project-a": {
      "mcpServers": {
        "stripe": {
          "type": "http",
          "url": "https://mcp.stripe.com"
        }
      }
    }
  }
}
```

顶层 `mcpServers` 是 **user 作用域**（所有项目可见）；`projects.<绝对路径>.mcpServers` 是 **local 作用域**（仅那个目录可见）。一般不建议手改这个文件——用 `claude mcp add --scope user/local` 让 Claude Code 自己写更稳。

#### 进阶：`claude mcp add-json` 一次塞一坨配置

复杂 server 可以直接传 JSON：

```bash
claude mcp add-json weather '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer abc"}}'
```

适合脚本批量初始化场景。

### 验证：进对话敲 `/mcp`

```text
$ claude
> /mcp

✔ sentry        connected   2 tools, OAuth authorized
✔ db-readonly   connected   8 tools
○ internal-api  pending     reconnecting (attempt 2/5)
✗ legacy-sse    failed      Connection refused. [r]etry [d]isable

> 看看 Sentry 最近 24h 错误最多的 endpoint
[调用工具：sentry.list_errors，参数：{ "lookback": "24h" }]
最近 24 小时报错最多的是 /api/checkout，共 1287 次……
```

绿色勾 = 已连上、工具就绪；圆圈 = 重连中；红叉 = 5 次都失败、需手动 retry。

## 同类工具对比

| 维度 | Claude Code | Cursor | VS Code（Copilot Chat） | Claude Desktop |
|------|-------------|--------|------------------------|----------------|
| 配置入口 | `claude mcp add` 命令 + `.mcp.json` | Settings UI 或 `.cursor/mcp.json` | Settings UI 或 `.vscode/mcp.json` | 手动编辑 `claude_desktop_config.json` |
| 配置文件根字段 | `mcpServers` | `mcpServers` | **`servers`**（注意，不是 mcpServers） | `mcpServers` |
| 项目级共享文件 | `.mcp.json`（仓库根） | `.cursor/mcp.json`（仓库根） | `.vscode/mcp.json`（仓库根） | 不支持 |
| 全局/用户作用域 | `~/.claude.json` + `--scope user` | `~/.cursor/mcp.json` | 用户 profile 设置 | 唯一一份全局配置 |
| 三级作用域 | ✅ local / project / user | ⚠️ 项目 + 全局两级 | ⚠️ 工作区 + 用户两级 | ❌ 全局一份 |
| 传输支持 | stdio / HTTP / SSE | stdio / HTTP | stdio / HTTP / SSE | stdio / HTTP |
| OAuth 流程 | `/mcp` 内置一键授权 | 内置授权 | `inputs` + 手填或 OAuth | 手动配 token |
| 环境变量占位符 | `${VAR}` `${VAR:-default}` | `${env:VAR}` | `${env:VAR}` `${input:NAME}` | 不支持占位符（要写实值） |
| 管理命令 | `claude mcp list/get/remove` | UI 操作 | UI 操作 | 改 JSON + 重启 |
| 加 Server 后需重启 | ❌ `/mcp` 刷新即可 | ❌ 自动检测 | ❌ 自动检测 | ✅ 必须重启 App |

核心区别一句话：

- **Claude Code**：命令式入口最完善，三级作用域 + 团队共享 `.mcp.json` 是它的招牌，纯命令行重度用户首选。
- **Cursor / VS Code**：作为 IDE 的 MCP 接入，UI 配置友好，但只有"项目 + 全局"两级，且 VS Code 用 `servers` 字段跟其他三家不一致，迁移配置时容易踩坑。
- **Claude Desktop**：MCP 支持最全（含 Sampling、Elicitation），但配置必须手动改 JSON、改完必须重启，团队共享几乎没法做。

## 常见误区

| 误区 | 准确理解 |
|------|----------|
| 以为 `.mcp.json` 是 Claude Desktop 的配置 | Desktop 的配置叫 `claude_desktop_config.json`，路径在 `~/Library/Application Support/Claude/`。**`.mcp.json` 是 Claude Code 在项目根目录创建的团队共享文件，两者文件名都不一样。** |
| 以为远程 MCP 必须 HTTP / 必须公网域名 | 远程 transport 有 HTTP（推荐）和 SSE（已 deprecated）两种，`localhost` 上的进程也能用 HTTP 暴露。**stdio 才是"本地默认"，HTTP 不等于必须公网。** |
| 以为 `claude mcp add` 不可逆 | 完全可逆。`claude mcp remove <name>` 删掉，或者直接编辑 `~/.claude.json` / `.mcp.json` 把那段去掉就行。`claude mcp reset-project-choices` 还能重置项目批准状态。 |
| 以为加完 Server 必须重启 `claude` | 不用。在对话里敲 `/mcp` 就会重新读配置、重连 Server。**只有第一次添加全新 Server 时，建议起一次新会话确保 tool 列表注入**。 |
| 以为 `--env` 和 `.mcp.json` 里的 `env` 等价 | 作用域不同。`--env` 跟着命令走，写到 local 作用域只对自己生效；`.mcp.json` 里的 `env` 是 project 作用域、团队共享。秘密信息**永远用环境变量占位符** `${API_KEY}`，不要把实值写进 `.mcp.json`。 |
| 以为 stdio Server 的 `command` 可以直接写 `npx`（在 Windows 上） | Windows native（非 WSL）不能直接 spawn `npx`，必须套 `cmd /c`：`-- cmd /c npx -y @some/package`。漏了会报 "Connection closed"。 |
| 以为 `.mcp.json` 进 Git 会泄露 secret | 只要严格使用 `${API_KEY}` 占位符，仓库里没有真值，每个团队成员在自己机器 `export API_KEY=xxx` 即可。**会泄露的从来不是 `.mcp.json` 本身，而是把实值硬编码进去的人。** |

## 优劣势分析

### 命令式 `claude mcp add`

| 优势 | 劣势 |
|------|------|
| 一行搞定，不用记 JSON 字段名（`type` / `command` / `args` 顺序）| 配置复杂时（多 env、多 header）命令越写越长，可读性下降 |
| `--scope` 一个 flag 切换三级作用域，零成本试错 | 不适合团队共享 —— 命令式的 local 配置只在你机器上 |
| 自带校验，写错 transport 类型会立即报错 | 无法表达 `${VAR:-default}` 这种环境变量回退 |
| `claude mcp add-from-claude-desktop` 一键迁移已有配置 | Windows 下 stdio 命令需要套 `cmd /c`，命令式写起来更绕 |

### 配置式（直接编辑 `.mcp.json` / `~/.claude.json`）

| 优势 | 劣势 |
|------|------|
| `.mcp.json` 进 Git，团队 clone 即获得统一工具栈 | 改完没有自动校验，JSON 写错（多逗号、漏引号）整份配置加载失败 |
| 支持 `${VAR}` / `${VAR:-default}` 环境变量展开，secret 不进 Git | 必须教会团队成员设置对应 env，新人冷启动有学习成本 |
| 复杂 server 一次性写清楚，比拼接命令直观 | 项目作用域首次使用要弹批准框（虽然这是好的安全设计） |
| 可写注释、可用 IDE schema 校验、可 review diff | 手改 `~/.claude.json` 容易破坏 Claude Code 自身管理的字段，建议只用 `claude mcp add --scope user/local` |

**实战配比**：个人快速试用走命令式（local 作用域），团队稳定用的工具走 `.mcp.json`（project 作用域 + 占位符），自己跨项目通用的工具走命令式（`--scope user`）。

## 思考题

<details>
<summary>初级：团队 5 人协作开发一个 Web 项目，需要让大家的 Claude Code 都能访问公司内部的 Sentry。配置应该走 local / project / user 哪个作用域？为什么？</summary>

**参考答案：**

走 **project 作用域**，写进项目根目录的 `.mcp.json`，提交到 Git。

理由：

1. **统一性**：5 人都需要这个 Server，写一份大家共享，避免每个人各配各的、各踩各的坑。
2. **变更可追踪**：以后 Server URL 换了、加了新工具，改 `.mcp.json` 走 PR review，所有人下次 pull 自动更新。
3. **安全**：Sentry token 用 `${SENTRY_TOKEN}` 占位符，每个人在自己 `.zshrc` 里 `export SENTRY_TOKEN=xxx`，仓库里没有秘密。

具体配置：

```json
{
  "mcpServers": {
    "sentry": {
      "type": "http",
      "url": "https://mcp.sentry.dev/mcp",
      "headers": {
        "Authorization": "Bearer ${SENTRY_TOKEN}"
      }
    }
  }
}
```

如果是个人偏好的工具（比如自己喜欢的笔记 MCP），用 user 作用域 (`--scope user`)；如果是含个人测试 token 的临时实验，用 local 作用域避免误提交。

</details>

<details>
<summary>中级：你写好了一个本地 Python MCP Server (server.py)，需要传一个 OPENAI_API_KEY 给它。同时希望团队其他人也能用，但不想把 API key 进 Git。完整的 .mcp.json 应该长什么样？</summary>

**参考答案：**

```json
{
  "mcpServers": {
    "my-python-server": {
      "type": "stdio",
      "command": "python",
      "args": [
        "${PROJECT_ROOT:-.}/scripts/server.py",
        "--mode",
        "production"
      ],
      "env": {
        "OPENAI_API_KEY": "${OPENAI_API_KEY}",
        "LOG_LEVEL": "${LOG_LEVEL:-info}"
      }
    }
  }
}
```

关键点：

1. `command` 用 `python`，不写绝对路径，让每个人系统 PATH 里的 Python 都能跑。
2. `args` 里用 `${PROJECT_ROOT:-.}` 兜底当前目录，避免脚本路径硬编码。
3. `env.OPENAI_API_KEY` 用占位符——`.mcp.json` 里只有 `${OPENAI_API_KEY}` 这串字面量，**没有真值**。
4. `LOG_LEVEL` 给个默认值 `info`，团队成员不用必须设置。

团队 README 里同步写一段："使用前请 `export OPENAI_API_KEY=sk-...`"。新人冷启动一次后，后续完全无感。

如果想再稳一点，加一个 `.env.example` 列出所有需要 export 的变量，让团队成员对照设置。

</details>

<details>
<summary>进阶：在 Windows native（非 WSL）上挂一个 npx 启动的 stdio Server，会遇到什么问题？为什么 macOS / Linux 没事？</summary>

**参考答案：**

会遇到 **"Connection closed"** 错误，Server 一启动就死。原因是 Windows native 的进程模型不能直接 spawn `npx`——`npx` 在 Windows 上其实是 `npx.cmd` 这种批处理脚本，必须通过 `cmd.exe` 解释器才能执行。

错的写法：

```bash
claude mcp add my-server --transport stdio -- npx -y @some/package
# Claude Code 内部会执行 spawn("npx", ["-y", "@some/package"])
# Windows: ENOENT，没法直接 spawn .cmd 文件
```

正确写法：套一层 `cmd /c`：

```bash
claude mcp add my-server --transport stdio -- cmd /c npx -y @some/package
# 内部变成 spawn("cmd", ["/c", "npx", "-y", "@some/package"])
# 由 cmd.exe 解释 npx.cmd，工作正常
```

或者写到 `.mcp.json` 里：

```json
{
  "mcpServers": {
    "my-server": {
      "type": "stdio",
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@some/package"]
    }
  }
}
```

macOS / Linux 没事是因为这些系统上 `npx` 是真正的可执行脚本（带 shebang `#!/usr/bin/env node`），可以被 `execve` 直接加载，不需要 shell 中转。

附带一个延伸坑：Windows 上配置 `env` 变量时，如果 npm 没全局安装、出现 `${APPDATA}` 路径错误，需要在 `env` 里手动设置 `APPDATA` 的展开值（比如 `"APPDATA": "C:\\Users\\you\\AppData\\Roaming\\"`）。这是 Claude Desktop 时代就有的老问题，Claude Code 在 native Windows 上沿用了同样的行为。

如果你不想踩这一类坑，**最稳的方案是直接用 WSL2 跑 Claude Code**——WSL 内的环境是 Linux，所有 stdio Server 配置和 Mac 完全一致，团队的 `.mcp.json` 也可以无缝复用。

</details>

## 参考资料

1. Claude Code 官方 MCP 接入文档：<https://code.claude.com/docs/en/mcp>（查询日期 2026-04-22）
2. MCP 官方 - 连接本地 Server：<https://modelcontextprotocol.io/docs/develop/connect-local-servers>（查询日期 2026-04-22）
3. MCP 官方 - 连接远程 Server：<https://modelcontextprotocol.io/docs/develop/connect-remote-servers>（查询日期 2026-04-22）
4. MCP 协议规范最新版（2025-06-18）：<https://modelcontextprotocol.io/specification/latest>
5. Claude Code GitHub 仓库（issues / release notes）：<https://github.com/anthropics/claude-code>
6. VS Code MCP 配置参考（注意根字段是 `servers`）：<https://code.visualstudio.com/docs/copilot/reference/mcp-configuration>（查询日期 2026-04-22）
7. Cursor MCP 配置说明：<https://docs.cursor.com/context/model-context-protocol>（查询日期 2026-04-22）
8. 站内互链 - MCP 是什么：[/mcp/cards/what-is-mcp](/mcp/cards/what-is-mcp)
9. 站内互链 - MCP 架构：[/mcp/cards/mcp-architecture](/mcp/cards/mcp-architecture)
10. 站内互链 - 在 Claude Code 中配置 MCP（聚焦 Claude Code 单工具）：[/mcp/cards/claude-code-setup](/mcp/cards/claude-code-setup)

---
*Source: https://learnagent.wiki/cli/cards/configure-mcp-in-cli*
*Markdown mirror of https://learnagent.wiki, served as text/markdown for LLM ingestion.*