AI Agent 教程

第11章:MCP —— Agent 世界的"USB 接口"

一句话:理解 MCP 协议,让你的 Agent 能连接任何外部工具和服务,就像 USB-C 让所有设备都能互联互通。

本章目标

前置知识


11.1 MCP 是什么?

先说个故事

假设你买了一部新手机,想给它充电。你翻遍抽屉,找到了 5 根不同的充电线 —— Micro USB、Lightning、USB-C、某个不知名品牌的专属接口...

这就是 AI 工具集成在 MCP 出现之前的状况。

每个 AI 平台都有自己的工具接口规范。你想让 AI 连 GitHub?写一套代码。想连数据库?再写一套。想连 Slack?又一套。每个工具供应商也得为每个 AI 平台分别做适配。

MCP(Model Context Protocol,模型上下文协议) 就是 AI 世界的 USB-C。

一个标准,统一所有

MCP 是 Anthropic 在 2024 年底发明的一个开放标准协议。它定义了 AI Agent 和外部工具之间的通信方式。简单说:

MCP 之前(混乱的世界):

  Claude ──专用接口──→ GitHub
  Claude ──专用接口──→ Slack
  Claude ──专用接口──→ 数据库
  GPT    ──专用接口──→ GitHub
  GPT    ──专用接口──→ Slack
  GPT    ──专用接口──→ 数据库
  Gemini ──专用接口──→ GitHub
  ...(排列组合,爆炸!)

MCP 之后(统一的世界):

  Claude ──┐                ┌──→ GitHub MCP Server
  GPT    ──┤── MCP 协议 ──├──→ Slack MCP Server
  Gemini ──┘                └──→ 数据库 MCP Server

谁在用 MCP?

MCP 虽然是 Anthropic 发明的,但现在已经成为行业标准:

这意味着什么?你现在学会用 MCP 连接工具,这些工具以后在任何 AI 平台上都能用。学一次,到处用。

MCP 的本质

用大白话说,MCP 就是一个"翻译协议":

  1. Agent 想用某个外部工具(比如查 GitHub Issue)
  2. Agent 按照 MCP 格式发出请求:"嘿,帮我列出最近的 Issue"
  3. MCP Server(GitHub)收到请求,翻译成 GitHub API 调用
  4. 拿到结果后,再按 MCP 格式返回给 Agent
  5. Agent 拿到结果,继续干活

Agent 不需要知道 GitHub API 怎么调,就像你用 USB-C 充电不需要知道电路板怎么设计一样。


11.2 MCP 的三种连接方式

MCP 支持三种不同的"连线方式",适用于不同场景。我们一个一个来看。

方式一:stdio(标准输入输出)—— 最常用

什么是 stdio?

stdio 就是"标准输入输出"的缩写。说人话就是:Agent 在你的电脑上启动一个小程序(MCP Server),然后通过"管道"和它对话。

工作原理:

你的 Agent 程序
    │
    │  启动子进程
    ▼
MCP Server 进程(比如 GitHub MCP Server)
    │
    │  Agent 通过 stdin 发送 JSON 请求
    │  MCP Server 通过 stdout 返回 JSON 结果
    ▼
来回对话,直到任务完成

生活比喻: 两个人坐在同一个房间里传纸条。速度快,不需要网络,但两个人必须在同一台机器上。

代码示例:

import { query } from "@anthropic-ai/claude-agent-sdk";

// stdio 方式连接文件系统 MCP Server
for await (const message of query({
  prompt: "列出 /Users/me/projects 目录下的所有文件",
  options: {
    mcpServers: {
      // "filesystem" 是你给这个 MCP Server 起的名字
      filesystem: {
        command: "npx",  // 用 npx 来运行
        args: [
          "-y",  // 自动确认安装
          "@modelcontextprotocol/server-filesystem",  // MCP Server 的 npm 包名
          "/Users/me/projects"  // 允许访问的目录
        ]
      }
    },
    // 允许 Agent 使用这个 MCP Server 的所有工具
    allowedTools: ["mcp__filesystem__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

stdio 配置的三个关键字段:

字段 含义 示例
command 用什么命令启动 MCP Server "npx""node""python"
args 命令的参数 ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
env 传给 MCP Server 的环境变量 { GITHUB_TOKEN: "xxx" }

什么时候用 stdio?

方式二:HTTP/SSE(网络通信)—— 远程服务

什么是 HTTP/SSE?

HTTP 你肯定知道,就是浏览器上网用的协议。SSE(Server-Sent Events)是一种服务器向客户端推送消息的技术。合在一起:

生活比喻: 打电话给远方的人。比传纸条慢一点,但可以跨越距离。

代码示例:

import { query } from "@anthropic-ai/claude-agent-sdk";

// HTTP 方式连接远程 MCP Server
for await (const message of query({
  prompt: "查一下 Claude Code 的文档中关于 Hooks 的说明",
  options: {
    mcpServers: {
      "claude-code-docs": {
        type: "http",  // 指定连接类型为 HTTP
        url: "https://code.claude.com/docs/mcp"  // 远程 MCP Server 的地址
      }
    },
    allowedTools: ["mcp__claude-code-docs__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

HTTP/SSE 配置的关键字段:

字段 含义 示例
type 连接类型,必须是 "http" "http"
url 远程 MCP Server 的 URL "https://example.com/mcp"
headers HTTP 请求头(用来传认证信息等) { "Authorization": "Bearer xxx" }

什么时候用 HTTP/SSE?

带认证的 HTTP 示例:

mcpServers: {
  "my-api": {
    type: "http",
    url: "https://api.example.com/mcp",
    headers: {
      "Authorization": "Bearer " + process.env.API_TOKEN
    }
  }
}

方式三:SDK 内置(代码内定义)—— 上一章学过的

这是什么?

就是上一章学的 createSdkMcpServer()。你直接在代码里定义工具,不需要启动额外的进程或连接远程服务。

import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// 用代码创建一个 MCP Server
const myTools = createSdkMcpServer({
  tools: [
    tool(
      "get_weather",
      "查询城市天气",
      { city: z.string().describe("城市名称") },
      async ({ city }) => ({
        content: [{ type: "text", text: `${city}今天晴,25度` }]
      })
    )
  ]
});

for await (const message of query({
  prompt: "今天北京天气怎么样?",
  options: {
    mcpServers: {
      weather: myTools  // 直接传入代码创建的 MCP Server
    },
    allowedTools: ["mcp__weather__*"]
  }
})) {
  // 处理消息
}

什么时候用 SDK 内置?

三种方式对比总结

特性 stdio HTTP/SSE SDK 内置
MCP Server 在哪 本地进程 远程服务器 代码里
需要网络吗 不需要 需要 不需要
启动方式 自动启动子进程 连接已运行的服务 直接在内存中
适合场景 用现成的 MCP Server 云端/共享服务 自定义工具
配置复杂度
生活比喻 同屋传纸条 打电话 自言自语

11.3 连接现成的 MCP Server

MCP 生态已经非常丰富了。社区有成百上千个现成的 MCP Server,拿来就能用。这里列出最常用的几个:

官方维护的 MCP Server

MCP Server 做什么的 npm 包名
GitHub 管理 GitHub Issues、PR、仓库 @modelcontextprotocol/server-github
文件系统 安全地读写本地文件 @modelcontextprotocol/server-filesystem
PostgreSQL 查询 PostgreSQL 数据库 @modelcontextprotocol/server-postgres
SQLite 查询 SQLite 数据库 @modelcontextprotocol/server-sqlite
Brave Search 用 Brave 搜索引擎搜网页 @modelcontextprotocol/server-brave-search
Puppeteer 浏览器自动化(爬虫、截图) @modelcontextprotocol/server-puppeteer
Memory 持久化记忆存储 @modelcontextprotocol/server-memory
Google Maps 地图和地理位置查询 @modelcontextprotocol/server-google-maps

社区热门 MCP Server

MCP Server 做什么的
Slack MCP 发消息、管理 Slack 频道
Notion MCP 读写 Notion 文档
Linear MCP 管理 Linear 项目和 Issue
Sentry MCP 查看错误日志和监控报告
Docker MCP 管理 Docker 容器

怎么找更多 MCP Server?

  1. 官方仓库https://github.com/modelcontextprotocol/servers
  2. MCP Hub:社区维护的 MCP Server 目录
  3. npm 搜索:在 npm 上搜索 mcp-server 关键词

小贴士:MCP 生态发展非常快,几乎每天都有新的 MCP Server 发布。你想让 AI 连什么服务,先搜搜有没有现成的 MCP Server,大概率有人已经做好了。


11.4 实战:用 GitHub MCP Server 管理项目

这是本章最重要的实战环节。我们来做一个能管理 GitHub 项目的 Agent。

第一步:准备 GitHub Token

GitHub MCP Server 需要一个 Personal Access Token(个人访问令牌)来访问你的 GitHub 账号。

获取步骤:

  1. 打开 https://github.com/settings/tokens
  2. 点击 "Generate new token (classic)"
  3. 勾选需要的权限(至少需要 repo 权限)
  4. 生成后复制 Token

设置环境变量:

# macOS / Linux
export GITHUB_TOKEN="ghp_你的Token放这里"

# 或者写入 .env 文件
echo 'GITHUB_TOKEN=ghp_你的Token放这里' >> .env

第二步:创建项目

mkdir github-agent && cd github-agent
npm init -y
npm install @anthropic-ai/claude-agent-sdk dotenv

第三步:编写代码

创建 github-agent.ts

import { query } from "@anthropic-ai/claude-agent-sdk";
import "dotenv/config";

// 确保 GITHUB_TOKEN 已设置
if (!process.env.GITHUB_TOKEN) {
  console.error("请先设置 GITHUB_TOKEN 环境变量!");
  console.error("export GITHUB_TOKEN=ghp_你的Token");
  process.exit(1);
}

async function main() {
  console.log("正在启动 GitHub Agent...\n");

  for await (const message of query({
    prompt: "列出 anthropics/claude-code 仓库最近的 3 个 Issue,告诉我每个 Issue 的标题和状态",
    options: {
      mcpServers: {
        // 配置 GitHub MCP Server(stdio 方式)
        github: {
          command: "npx",
          args: ["-y", "@modelcontextprotocol/server-github"],
          env: {
            GITHUB_TOKEN: process.env.GITHUB_TOKEN!
          }
        }
      },
      // 允许使用 GitHub MCP Server 的指定工具
      allowedTools: [
        "mcp__github__list_issues",
        "mcp__github__get_issue"
      ]
    }
  })) {
    // 处理不同类型的消息
    switch (message.type) {
      case "assistant":
        // Agent 的回复(可能包含思考过程和工具调用)
        if (typeof message.content === "string") {
          console.log("Agent:", message.content);
        } else if (Array.isArray(message.content)) {
          for (const block of message.content) {
            if (block.type === "text") {
              console.log("Agent:", block.text);
            } else if (block.type === "tool_use") {
              console.log(`\n[调用工具] ${block.name}`);
              console.log(`[参数] ${JSON.stringify(block.input, null, 2)}\n`);
            }
          }
        }
        break;

      case "result":
        if (message.subtype === "success") {
          console.log("\n--- 任务完成 ---");
          console.log(message.result);
        } else {
          console.error("\n--- 任务失败 ---");
          console.error(message.error);
        }
        break;
    }
  }
}

main().catch(console.error);

第四步:运行

npx tsx github-agent.ts

你会看到类似这样的输出:

正在启动 GitHub Agent...

[调用工具] mcp__github__list_issues
[参数] {
  "owner": "anthropics",
  "repo": "claude-code",
  "state": "open",
  "per_page": 3
}

Agent: 以下是 anthropics/claude-code 仓库最近的 3 个 Issue:

1. **#1234 - 支持自定义快捷键** (open)
   状态:打开中

2. **#1233 - Windows 上的路径解析问题** (open)
   状态:打开中

3. **#1232 - 建议添加暗色主题** (open)
   状态:打开中

--- 任务完成 ---

第五步:进阶 —— 让 Agent 干更多事

让我们扩展这个 Agent,让它能创建 Issue 和回复评论:

import { query } from "@anthropic-ai/claude-agent-sdk";
import "dotenv/config";

async function githubAgent(task: string) {
  for await (const message of query({
    prompt: task,
    options: {
      mcpServers: {
        github: {
          command: "npx",
          args: ["-y", "@modelcontextprotocol/server-github"],
          env: {
            GITHUB_TOKEN: process.env.GITHUB_TOKEN!
          }
        }
      },
      // 用通配符允许所有 GitHub 工具
      allowedTools: ["mcp__github__*"],
      // 给 Agent 一些行为指导
      systemPrompt: `你是一个 GitHub 项目管理助手。请注意:
        1. 操作前先确认用户意图
        2. 创建 Issue 时使用清晰的标题和描述
        3. 回复评论时保持专业和友善
        4. 列出信息时使用格式化的表格或列表`
    }
  })) {
    if (message.type === "result" && message.subtype === "success") {
      console.log(message.result);
    }
  }
}

// 示例:列出 Issue
await githubAgent("列出我的仓库 myname/myproject 中所有打开的 Issue");

// 示例:创建 Issue
await githubAgent(`
  在 myname/myproject 仓库创建一个新 Issue:
  标题:添加用户登录功能
  描述:需要实现基本的用户名密码登录,包括注册、登录、登出功能。
  标签:enhancement
`);

// 示例:回复评论
await githubAgent("在 myname/myproject 的 Issue #42 上回复:'这个问题已经修复了,请更新到最新版本试试。'");

11.5 实战:用文件系统 MCP Server

文件系统 MCP Server 允许 Agent 安全地访问你指定的目录。注意关键词:安全地

为什么不直接用内置的 Read/Write 工具?

内置工具可以读写任何文件,权力太大了。文件系统 MCP Server 可以限制 Agent 只能访问你指定的目录,更安全。

基本用法

import { query } from "@anthropic-ai/claude-agent-sdk";

async function fileAgent(task: string) {
  for await (const message of query({
    prompt: task,
    options: {
      mcpServers: {
        filesystem: {
          command: "npx",
          args: [
            "-y",
            "@modelcontextprotocol/server-filesystem",
            // 只允许访问这个目录(安全限制)
            "/Users/me/projects/my-app"
          ]
        }
      },
      allowedTools: ["mcp__filesystem__*"]
    }
  })) {
    if (message.type === "result" && message.subtype === "success") {
      console.log(message.result);
    }
  }
}

// 让 Agent 分析项目结构
await fileAgent("分析这个项目的目录结构,告诉我它是什么类型的项目");

// 让 Agent 整理文件
await fileAgent("找出所有的 .log 文件,告诉我它们的大小和最后修改时间");

// 让 Agent 创建文件
await fileAgent("在项目根目录创建一个 .gitignore 文件,包含常见的 Node.js 忽略规则");

指定多个目录

你可以在 args 中传多个路径,允许 Agent 访问多个目录:

filesystem: {
  command: "npx",
  args: [
    "-y",
    "@modelcontextprotocol/server-filesystem",
    "/Users/me/projects/frontend",  // 前端项目
    "/Users/me/projects/backend",   // 后端项目
    "/Users/me/documents"           // 文档目录
  ]
}

Agent 只能在这些目录里操作,其他目录一律访问不了。这就是"最小权限原则"的体现。


11.6 同时连接多个 MCP Server

真正强大的 Agent 通常需要连接多个工具。MCP 天然支持同时连接多个 Server。

完整示例:GitHub + 文件系统 + 数据库

import { query } from "@anthropic-ai/claude-agent-sdk";

async function superAgent(task: string) {
  for await (const message of query({
    prompt: task,
    options: {
      mcpServers: {
        // 工具1:GitHub 项目管理
        github: {
          command: "npx",
          args: ["-y", "@modelcontextprotocol/server-github"],
          env: {
            GITHUB_TOKEN: process.env.GITHUB_TOKEN!
          }
        },

        // 工具2:文件系统操作
        filesystem: {
          command: "npx",
          args: [
            "-y",
            "@modelcontextprotocol/server-filesystem",
            "/Users/me/projects"
          ]
        },

        // 工具3:SQLite 数据库查询
        database: {
          command: "npx",
          args: [
            "-y",
            "@modelcontextprotocol/server-sqlite",
            "--db-path",
            "/Users/me/data/app.db"
          ]
        }
      },

      // 精确控制每个 Server 的工具权限
      allowedTools: [
        "mcp__github__list_issues",      // GitHub:只允许列出 Issue
        "mcp__github__get_issue",        // GitHub:只允许查看 Issue 详情
        "mcp__filesystem__*",            // 文件系统:允许所有操作
        "mcp__database__query"           // 数据库:只允许查询,不允许修改
      ]
    }
  })) {
    if (message.type === "result" && message.subtype === "success") {
      console.log(message.result);
    }
  }
}

// 一个任务里用到多个工具
await superAgent(`
  帮我做以下事情:
  1. 查看 GitHub 上 myname/myproject 仓库最近的 5 个 Issue
  2. 从本地数据库中查询最近一周的用户反馈
  3. 综合以上信息,在本地文件系统中生成一份周报(保存为 weekly-report.md)
`);

不同 Server 的工具如何共存?

每个 MCP Server 的工具都有唯一的名称,格式是 mcp__<服务器名>__<工具名>。所以即使两个 Server 都有叫 query 的工具,它们也不会冲突:

mcp__github__query     → GitHub 的查询工具
mcp__database__query   → 数据库的查询工具

Agent 会根据上下文自动选择正确的工具。你让它"查数据库",它就用 mcp__database__query;你让它"查 GitHub",它就用 mcp__github__query


11.7 MCP 工具命名规则

这部分很重要,理解了命名规则,你就知道怎么精确控制 Agent 能用哪些工具。

命名格式

mcp__<服务器名>__<工具名>

其中:
  <服务器名> = 你在 mcpServers 配置中给 Server 起的 key 名
  <工具名>   = MCP Server 提供的工具的名称

示例:

mcpServers: {
  github: { ... },      // 服务器名 = "github"
  mydb: { ... },        // 服务器名 = "mydb"
  "my-files": { ... }   // 服务器名 = "my-files"
}

// 对应的工具名:
// mcp__github__list_issues
// mcp__github__create_issue
// mcp__github__get_issue
// mcp__mydb__query
// mcp__mydb__execute
// mcp__my-files__read_file
// mcp__my-files__write_file

通配符

当你不想一个一个列出所有工具时,用通配符 *

allowedTools: [
  "mcp__github__*",           // 允许 github 服务器的所有工具
  "mcp__database__query",     // 只允许 database 服务器的 query 工具
  "mcp__slack__send_message"  // 只允许 slack 服务器的 send_message 工具
]

建议:

工具搜索(Tool Search)—— 当工具太多时

如果你连了好多 MCP Server,每个 Server 又有几十个工具,工具描述加起来可能会占用很多上下文空间。这时候可以开启"工具搜索"功能:

Agent 不再一次性加载所有工具描述,而是根据需要按需搜索合适的工具。

配置方法:

for await (const message of query({
  prompt: "帮我查一下最近的 GitHub Issue",
  options: {
    mcpServers: { /* 你的 MCP Servers */ },
    allowedTools: ["mcp__github__*", "mcp__slack__*", "mcp__notion__*"],
    env: {
      // 配置工具搜索
      ENABLE_TOOL_SEARCH: "auto"  // 默认值:当工具描述超过上下文 10% 时自动开启
    }
  }
})) {
  // ...
}

ENABLE_TOOL_SEARCH 的可选值:

行为
"auto" 当 MCP 工具描述超过上下文的 10% 时自动开启(默认)
"auto:5" 自定义阈值,5% 时开启
"true" 始终开启工具搜索
"false" 禁用,所有工具描述一次性全部加载

什么时候需要工具搜索?

大多数情况下,用默认的 "auto" 就够了,SDK 会自动帮你决定。


11.8 用配置文件管理 MCP Server

除了在代码里配置,你还可以用 .mcp.json 配置文件来管理 MCP Server。

创建 .mcp.json

在你的项目根目录创建 .mcp.json 文件:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"]
    },
    "database": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "--db-path", "./data/app.db"]
    }
  }
}

使用配置文件

SDK 会自动加载项目根目录下的 .mcp.json,你的代码可以更简洁:

import { query } from "@anthropic-ai/claude-agent-sdk";

// 不需要在代码里配置 mcpServers 了,SDK 会自动从 .mcp.json 加载
for await (const message of query({
  prompt: "列出 GitHub Issue 并生成报告",
  options: {
    allowedTools: ["mcp__github__*", "mcp__filesystem__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

配置文件 vs 代码配置

方式 优点 缺点
.mcp.json 文件 可以团队共享、版本管理;代码更简洁 不够灵活,不能动态配置
代码里配置 灵活,可以根据条件动态选择 代码冗长

建议: 固定不变的 MCP Server 用 .mcp.json,需要动态配置的用代码。


11.9 MCP vs 自定义工具 vs Skills

学到这里,你可能有点困惑:MCP、自定义工具(createSdkMcpServer)、Skills,这三个东西有什么区别?什么时候用什么?

三者的本质区别

┌─────────────────────────────────────────────────────┐
│                   Agent 的完整能力                     │
│                                                       │
│  ┌──────────────┐  ┌──────────────┐  ┌─────────────┐ │
│  │   MCP Server  │  │  自定义工具   │  │   Skills    │ │
│  │  (外部工具)   │  │  (内部工具)   │  │  (知识)     │ │
│  │              │  │              │  │             │ │
│  │ 标准化接口    │  │ 代码内定义    │  │ Markdown    │ │
│  │ 可复用       │  │ 应用专属      │  │ 文档        │ │
│  │ 社区生态      │  │ 灵活定制      │  │ 教程        │ │
│  └──────────────┘  └──────────────┘  └─────────────┘ │
│                                                       │
│  提供"能力"(能做什么)          提供"知识"(怎么做)  │
└─────────────────────────────────────────────────────┘

详细对比

维度 MCP Server 自定义工具 Skills
是什么 标准化的外部工具接口 代码里直接定义的工具 教 Agent 怎么做事的知识文档
定义方式 独立进程 / 远程服务 createSdkMcpServer() + tool() .claude/skills/ 目录下的 Markdown 文件
解决什么问题 连接外部服务和工具 实现应用特有的功能 教 Agent 遵循特定流程和规范
可复用性 高(任何 AI 都能用) 低(只在你的应用里用) 中(可以跨项目复用)
社区生态 丰富(成百上千个) 无(你自己写的) 可以分享给团队
类比 USB 设备(即插即用) 焊在主板上的芯片 说明书/操作手册

什么时候用什么?

用 MCP Server 的场景:

用自定义工具的场景:

用 Skills 的场景:

它们可以一起用!

这三者不是互斥的,而是互补的。一个强大的 Agent 通常会同时使用三种方式:

import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// 自定义工具:查询公司内部数据
const internalTools = createSdkMcpServer({
  tools: [
    tool(
      "query_internal_api",
      "查询公司内部用户数据",
      { userId: z.string() },
      async ({ userId }) => {
        const data = await fetch(`https://internal.api/users/${userId}`);
        return { content: [{ type: "text", text: JSON.stringify(await data.json()) }] };
      }
    )
  ]
});

for await (const message of query({
  prompt: "分析用户 U12345 的问题,在 GitHub 上创建对应的 Issue",
  options: {
    mcpServers: {
      // MCP Server:连接 GitHub
      github: {
        command: "npx",
        args: ["-y", "@modelcontextprotocol/server-github"],
        env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN! }
      },
      // 自定义工具:查询内部数据
      internal: internalTools
    },
    allowedTools: [
      "mcp__github__*",
      "mcp__internal__*"
    ],
    // Skills 通过 settingSources 自动加载 .claude/skills/ 目录下的文件
    settingSources: ["project"]
  }
})) {
  // 处理消息
}

在这个例子中:

  1. MCP Server(GitHub) 提供了操作 GitHub 的能力
  2. 自定义工具 提供了查询公司内部数据的能力
  3. Skills(通过 settingSources 加载)告诉 Agent 创建 Issue 时应该遵循什么规范

11.10 常见问题和调试技巧

问题1:MCP Server 启动失败

症状: 报错 "Failed to start MCP server" 或类似错误。

排查步骤:

# 1. 先手动运行 MCP Server,看看能不能正常启动
npx -y @modelcontextprotocol/server-github

# 2. 检查 Node.js 版本(需要 18+)
node -v

# 3. 检查 npx 是否可用
npx --version

# 4. 如果是权限问题,尝试清缓存
npm cache clean --force

问题2:工具调用没反应

症状: Agent 说"我没有合适的工具来完成这个任务"。

排查:

// 检查 allowedTools 是否正确
// 错误写法(少了前缀):
allowedTools: ["list_issues"]

// 正确写法:
allowedTools: ["mcp__github__list_issues"]

// 或者用通配符:
allowedTools: ["mcp__github__*"]

问题3:认证失败

症状: 报错 "401 Unauthorized" 或 "403 Forbidden"。

排查:

// 确保环境变量正确传递
mcpServers: {
  github: {
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-github"],
    env: {
      // 确保这个值不是 undefined
      GITHUB_TOKEN: process.env.GITHUB_TOKEN!
    }
  }
}

// 调试:打印看看环境变量有没有值
console.log("Token:", process.env.GITHUB_TOKEN ? "已设置" : "未设置!");

问题4:工具太多,Agent 选错工具

解决方案:

// 方案1:缩小 allowedTools 范围
allowedTools: [
  "mcp__github__list_issues",  // 只给它需要的工具
  "mcp__github__get_issue"
]

// 方案2:在 systemPrompt 中给出指导
systemPrompt: "当用户让你查看 Issue 时,使用 mcp__github__list_issues 工具"

// 方案3:开启工具搜索
env: { ENABLE_TOOL_SEARCH: "true" }

动手练习

练习1:GitHub Issue 管理 Agent

目标: 做一个能管理 GitHub Issue 的 Agent。

要求:

  1. 连接 GitHub MCP Server
  2. 能列出指定仓库的 Issue
  3. 能根据关键词搜索 Issue
  4. 能创建新 Issue
  5. 输出格式化的 Issue 列表

提示代码框架:

import { query } from "@anthropic-ai/claude-agent-sdk";

async function issueManager(command: string) {
  for await (const message of query({
    prompt: command,
    options: {
      mcpServers: {
        github: {
          command: "npx",
          args: ["-y", "@modelcontextprotocol/server-github"],
          env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN! }
        }
      },
      allowedTools: ["mcp__github__*"],
      systemPrompt: `你是一个 GitHub Issue 管理助手。
        - 列出 Issue 时使用表格格式
        - 创建 Issue 时使用 Conventional Commits 风格的标题
        - 每次操作后给出简短的确认信息`
    }
  })) {
    if (message.type === "result" && message.subtype === "success") {
      console.log(message.result);
    }
  }
}

// 你的测试代码:
await issueManager("列出 owner/repo 仓库中标签为 bug 的所有 Issue");

练习2:文件整理 Agent

目标: 做一个能帮你整理文件的 Agent。

要求:

  1. 连接文件系统 MCP Server
  2. 指定一个目录,让 Agent 分析其中的文件
  3. 按文件类型分类统计(多少个 .ts 文件、多少个 .json 文件等)
  4. 找出超过 1MB 的大文件
  5. 生成一份整理报告

提示:

练习3:多功能 Agent

目标: 同时连接 3 个 MCP Server,做一个全能 Agent。

要求:

  1. 连接 GitHub MCP Server(管理代码)
  2. 连接文件系统 MCP Server(读写文件)
  3. 连接 SQLite MCP Server(查询数据)
  4. 让 Agent 完成一个跨工具的任务:
    • 从数据库查出最近的错误日志
    • 在本地文件系统生成错误报告
    • 在 GitHub 上创建对应的 Issue

提示:


本章小结

恭喜你读完了这一章!让我们回顾一下关键知识点:

  1. MCP 是什么:Model Context Protocol,AI 世界的 USB-C 标准。它让 Agent 能用统一的方式连接任何外部工具和服务。

  2. 三种连接方式

    • stdio:本地进程通信,最常用,用 command + args 配置
    • HTTP/SSE:远程服务器通信,用 type: "http" + url 配置
    • SDK 内置:代码内直接定义,用 createSdkMcpServer() 创建
  3. 丰富的生态:GitHub、文件系统、数据库、搜索引擎...成百上千个现成的 MCP Server 等你使用。

  4. 工具命名规则mcp__<服务器名>__<工具名>,支持 * 通配符。

  5. 工具搜索:当工具太多时,用 ENABLE_TOOL_SEARCH 让 Agent 按需加载工具。

  6. 配置方式:代码配置和 .mcp.json 文件配置两种方式。

  7. 三者关系:MCP 提供标准化外部工具接口,自定义工具提供应用内部能力,Skills 提供操作知识和规范。三者互补,不是竞争关系。


下一章预告

下一章我们要学 第12章:Hooks —— 在 Agent 干活的每个节点插一脚

你有没有想过这些问题:

Hooks 就是干这个的。它让你在 Agent 工作流程的每个关键节点都能插入自己的逻辑,就像流水线上的"质检站"。

下一章见!

← 上一章10. 自定义工具