
Claude Code SDK #8:MCP 集成全解——三种接入方式 × 工具命名规范 × Tool Search 懒加载,把 Agent 能力边界推到任意外部服务
MCP 是 Claude Code SDK 把 Agent 能力边界从「内置 11 工具」扩展到任意外部服务的核心机制。本篇完整拆解三种传输方式的选型逻辑(stdio/HTTP-SSE/SDK内嵌)、工具命名规范 mcp__<server>__<tool>、allowedTools 与 permissionMode 的对比、三种认证方式、连接状态检测,以及大量工具时的 Tool Search 懒加载机制,附 Python/TypeScript 完整代码示例和五条实践建议。
리서치 브리프
一个 Agent,内置 11 种工具——Read、Write、Bash、WebSearch……已经够强了。但如果你需要查 GitHub Issues、查 Postgres 数据库、操控浏览器?
不需要自己写工具执行器。Claude Code SDK 支持 MCP(Model Context Protocol),一个开放标准,让你用几行配置接入数百个现成服务。1
本篇拆解 SDK 的 MCP 集成机制:三种传输方式的选型逻辑、容易踩坑的工具命名规范、权限控制与
permissionMode 的对比,以及大量工具时必须理解的 Tool Search 懒加载机制。为什么 MCP 不是"可选插件"
内置工具覆盖了文件系统和 shell,但 Agent 真正要自主处理业务时,外部服务调用几乎是刚需:查数据库、提 PR、发通知、操控 UI。
如果用 Client SDK 手写这些工具,你需要实现完整的工具循环——拦截
tool_use 块、调用外部 API、把结果塞回 tool_result。MCP 把这套胶水代码变成了一个标准接口:你只需要配置服务器地址,SDK 自动处理工具发现和执行。2目前 MCP 服务目录里已有数十个官方维护的服务器,涵盖 GitHub、Postgres、Slack、Filesystem 等主流场景,直接
npx 启动即用。工具命名规范:最容易忽略的细节
MCP 工具在 SDK 里遵循固定命名格式:
mcp__<服务器名>__<工具名>比如,你把服务器命名为
github,它提供了 list_issues 工具,那这个工具在 allowedTools 里的写法就是 mcp__github__list_issues。这个命名规则直接决定了权限配置能否生效。如果服务器名拼错一个字符,Claude 能看到工具但调用时权限不通过——这是很多人初次接入 MCP 时卡住的地方。
支持通配符:
mcp__github__* 表示开放该服务器的全部工具,不需要逐一列举。三种传输方式
MCP 服务器通过三种方式与你的 Agent 通信,选哪种取决于服务器的部署形式。3

判断依据很简单:
- 文档给你的是命令行命令(比如
npx @modelcontextprotocol/server-github)→ 用 stdio - 文档给你的是URL→ 用 HTTP 或 SSE
- 你想直接在代码里定义工具函数→ 用 SDK 内嵌服务器
stdio:本地子进程
最常见的形式,MCP 服务器作为本地进程运行,通过 stdin/stdout 通信:
# Python
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="列出 anthropics/claude-code 最近 3 个 Issues",
options=ClaudeAgentOptions(
mcp_servers={
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]}
}
},
allowed_tools=["mcp__github__list_issues"]
)
):
...// TypeScript
for await (const message of query({
prompt: "列出最近 3 个 Issues",
options: {
mcpServers: {
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN }
}
},
allowedTools: ["mcp__github__list_issues"]
}
})) { ... }HTTP / SSE:云端服务
适合云托管的 MCP 服务和远程 API:
options=ClaudeAgentOptions(
mcp_servers={
"remote-api": {
"type": "sse", # 或 "http" 用于 Streamable HTTP
"url": "https://api.example.com/mcp/sse",
"headers": {
"Authorization": f"Bearer {os.environ['API_TOKEN']}"
}
}
},
allowed_tools=["mcp__remote-api__*"]
)注意:JSON 配置文件(
.mcp.json)里可以用 "streamable-http" 作为 "http" 的别名,但代码里只接受 "http"。混淆这两者会导致连接静默失败。SDK 内嵌服务器(Python 专属)
用
@tool 装饰器直接在 Python 代码里定义工具,不需要启动额外进程——开发调试时非常实用:from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("query_db", "按自然语言查询数据库", {"question": str})
async def query_db(args):
sql = translate_to_sql(args["question"])
result = await db.execute(sql)
return {"content": [{"type": "text", "text": str(result)}]}
my_server = create_sdk_mcp_server(
name="db-tools",
tools=[query_db]
)
options = ClaudeAgentOptions(
mcp_servers={"db": my_server},
allowed_tools=["mcp__db__query_db"]
)Python SDK 里
create_sdk_mcp_server() 返回 McpSdkServerConfig(type="sdk"),直接传给 mcp_servers 即可。权限控制:为什么不应该依赖 permissionMode

allowedTools 精确授权而非宽泛的权限模式 4| 方式 | 对 MCP 的实际效果 | 问题 |
|---|---|---|
acceptEdits | 不会自动放通 MCP 工具 | 只作用于文件编辑和 Bash 命令 |
bypassPermissions | 会放通 MCP 工具 | 同时跳过所有其他安全检查,范围太大 |
allowedTools 通配符 | 精准放通目标服务器 | ✅ 推荐方式 |
正确做法是用
allowedTools 配合通配符:allowed_tools=["mcp__github__*"] # 只开放 github 服务器
allowed_tools=["mcp__db__query"] # 只开放 db 服务器的 query 工具Claude 不会无限制地调用工具——它在
system init 消息里看到所有可用工具,但只有 allowedTools 里列出的才能不经审批直接调用。认证:三种方式
环境变量(stdio)
给 stdio 服务器注入密钥的标准方式。在
.mcp.json 里可以用 ${VAR_NAME} 语法引用运行时环境变量:{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}HTTP Header(HTTP/SSE)
远程服务通过
headers 字段传认证信息:mcp_servers={
"secure-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {"Authorization": f"Bearer {token}"}
}
}OAuth2
SDK 不自动处理 OAuth 流程,但支持在 OAuth 完成后把 access token 塞进 header:
access_token = await complete_oauth_flow()
mcp_servers={
"oauth-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {"Authorization": f"Bearer {access_token}"}
}
}OAuth 流程本身由你的应用负责,SDK 只处理 token 之后的通信。
连接状态检测与错误处理
async for message in query(prompt="...", options=options):
# 检查连接状态
if hasattr(message, 'subtype') and message.subtype == "init":
servers = message.data.get("mcp_servers", [])
failed = [s for s in servers if s.get("status") != "connected"]
if failed:
print(f"连接失败: {failed}")
break
if hasattr(message, 'result'):
print(message.result)TypeScript 侧写法一致:
if (message.type === "system" && message.subtype === "init") {
const failed = message.mcp_servers.filter(s => s.status !== "connected");
if (failed.length > 0) console.warn("Failed:", failed);
}ClaudeSDKClient 还提供了两个动态方法:get_mcp_status():随时获取所有服务器的连接状态reconnect_mcp_server(name):对失败的服务器触发重连toggle_mcp_server(name, enabled):在会话中动态启停某个服务器
常见失败原因:环境变量未设置(stdio 最常见)、npm 包未安装、远程 URL 不可达、网络防火墙拦截。
콘텐츠 카드를 불러오는 중…
Tool Search:上百工具时的上下文管理
接入多个 MCP 服务器后,工具数量可能迅速膨胀。50 个工具定义大约占 10-20k tokens 上下文,工具选择准确率也会在超过 30-50 个工具时明显下降。6
SDK 默认开启 Tool Search:不把所有工具定义一次性塞进上下文,而是按需检索。工作流程是:
- Agent 遇到需要外部能力的任务
- 向工具目录发起语义搜索
- 加载最相关的 3-5 个工具定义
- 这些工具在后续轮次中保持可用
这比每次加载所有定义多一个「搜索」round-trip,但对大型工具集来说,减小的上下文开销通常值得。
可以通过环境变量精细控制行为:
ClaudeAgentOptions(
mcp_servers={ ... },
env={
# auto:5 = 工具定义超过上下文窗口 5% 时启动懒加载
"ENABLE_TOOL_SEARCH": "auto:5"
}
)ENABLE_TOOL_SEARCH 值 | 效果 |
|---|---|
| 未设置(默认) | 开启,在 Vertex AI 和非官方代理上回退为全量加载 |
true | 强制开启(即使在 Vertex AI) |
auto | 超过上下文 10% 时自动开启 |
auto:N | 超过 N% 时开启 |
false | 关闭,全量加载所有工具定义 |
工具少于 10 个时,全量加载通常更快;超过 30 个时建议评估是否启用懒加载。
工具描述质量直接影响搜索召回。
search_slack_messages 比 query_slack 匹配范围更广,描述写"按关键词、频道或日期搜索 Slack 消息"比"查询 Slack"精确得多。发现可用工具
不知道一个 MCP 服务器提供哪些工具?从
system init 消息里读:async for message in query(prompt="...", options=options):
if hasattr(message, 'subtype') and message.subtype == "init":
mcp_info = message.data.get("mcp_servers", [])
for server in mcp_info:
print(f"服务器: {server['name']}")
for tool in server.get('tools', []):
print(f" - {tool['name']}: {tool.get('description', '')}")ClaudeSDKClient 还可以在会话中随时调用 get_mcp_status() 获取每个服务器的工具列表和连接状态。实践建议
1. 工具权限最小化
不要用
mcp__*__* 通配符一次放通所有 MCP 工具。对每个服务器单独配置通配符(mcp__github__*),或精确到工具名(mcp__db__query),便于审计和限制意外调用。2. 总是检查 init 消息
MCP 连接失败是静默的——Claude 只是无法调用这些工具。在生产代码里,总应该在
init 消息里检查连接状态,而不是等到任务失败时才发现服务器没接上。3. 分离只读和写操作
通过
allowedTools 的精细配置,可以让 Agent 只拥有读权限的工具(比如 mcp__db__query),而不开放写操作(mcp__db__execute)。这和上一篇子 Agent 里工具最小化的原则一致。4. 调试时用 stdin 打印 mcp_servers
接入新服务器时,先把
print(message.data.get("mcp_servers")) 加进去,确认服务器已连接、工具列表符合预期,再开始测试实际功能。5. 超过 30 个工具时评估 Tool Search
工具多了之后,先用
ENABLE_TOOL_SEARCH=auto 跑一下,观察是否自动触发。如果工具定义较重,适当降低阈值(auto:5)。下期 #9:自定义工具(Custom Tools)——用
@tool 装饰器在 SDK 内嵌入你自己的工具函数,以及如何用 in-process MCP 服务器在代码里定义完整工具集。文档入口:https://docs.anthropic.com/en/docs/agent-sdk/custom-tools
이 콘텐츠를 둘러싼 관점이나 맥락을 계속 보강해 보세요.