跳转到内容

MCP 协议集成

Gemini CLI — MCP 协议集成

学习目标

  • 理解 Gemini CLI 的 MCP 服务器配置格式和工具发现机制
  • 掌握 MCP 工具的前缀命名空间和通配符策略规则
  • 分析 MCP OAuth 认证自动化流程

前置知识

本章涉及 MCP 协议的通用原理,建议先阅读:

下文假设你已理解 MCP 的传输层和客户端/服务器架构,直接聚焦 Gemini CLI 的具体集成实现。


项目实践

MCP 服务器配置

用户在 ~/.gemini/settings.json 或项目级配置中声明 MCP 服务器:

{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "..." }
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"]
}
}
}

支持的传输类型

  • stdio:通过子进程启动 MCP 服务器,标准输入输出通信(最常见)
  • SSE:通过 Server-Sent Events 连接到远程服务器
  • HTTP:HTTP 端点连接
  • TCP:TCP socket 连接

工具发现与注册

McpClientManager 负责管理所有 MCP 服务器的连接和工具发现:

McpClientManager.connectToServer(serverConfig):
1. 根据传输类型创建 MCP Client(stdio/SSE/HTTP/TCP)
2. 建立连接,获取服务器能力
3. 调用 tools/list 获取工具列表
4. 为每个工具创建 DiscoveredMCPTool 实例
5. 注册到 ToolRegistry

工具命名约定:MCP 工具注册时使用前缀命名空间

mcp_{serverName}_{toolName}

例如 github 服务器的 list_pull_requests 工具注册为 mcp_githubfox_list_pull_requests(实际前缀为 mcp_ + 服务器名 + _ + 工具名)。

这使得:

  • 不同服务器的同名工具不会冲突
  • 工具名称可追溯来源服务器
  • 策略引擎可针对特定服务器制定规则

MCP 工具的执行流程

LLM: functionCall("mcp_github_list_prs", { state: "open" })
ToolRegistry: 识别为 MCP 工具(DISCOVERED_TOOL_PREFIX)
DiscoveredMCPTool.execute():
├── 通过 McpClientManager 找到对应服务器
├── 发送 tools/call 请求
├── 接收 tools/call 响应
└── 返回格式化结果

进度追踪:长时间运行的 MCP 操作通过 CoreEvent.McpProgress 事件向 Scheduler 推送进度更新,实时更新 UI 显示。

MCP OAuth 认证自动化

Gemini CLI 为 MCP 服务器提供自动 OAuth 处理packages/core/src/mcp/):

认证类型说明
google-credentials使用 Google 账户自动认证(内置 Google Auth Provider)
oauth标准 OAuth 2.0 流程,支持自定义 client_id/scopes
无认证不需要认证的服务器

OAuth Token 存储oauth-token-storage.ts):

  • Token 持久化到本地安全存储
  • 自动检测 token 过期并刷新
  • 支持多服务器独立 Token 管理

MCP 资源访问

除了工具调用,Gemini CLI 还提供两个专用 MCP 资源工具:

  • list-mcp-resources:列出 MCP 服务器提供的资源
  • read-mcp-resource:读取指定 MCP 资源的内容

这使得 MCP 服务器不仅可以提供工具,还可以提供上下文资源(如文档、配置文件等)。

MCP 通配符策略规则

Policy Engine 支持 MCP 工具的通配符授权

{
"rules": [
{ "name": "mcp_github_*", "action": "allow" },
{ "name": "mcp_*", "action": "ask_user" }
]
}

通配符匹配逻辑policy-engine.ts):

模式含义
*允许所有工具
mcp_*允许所有 MCP 工具
mcp_{serverName}_*允许指定 MCP 服务器的所有工具

实现细节

matchesWildcard(pattern, toolName, serverName):
if pattern == "*": return true
if pattern == "mcp_*": return serverName !== undefined
if pattern startsWith "mcp_" and endsWith "_*":
expectedServerName = pattern.slice("mcp_".length, -2)
return serverName == expectedServerName
&& toolName.startsWith("mcp_" + expectedServerName + "_")

这使得管理员可以对 MCP 工具进行批量授权,而无需逐工具配置。


问题与规避

MCP 服务器启动失败

问题:MCP 服务器的 stdio 子进程可能因依赖缺失或配置错误而无法启动。

对策McpClient 在连接失败时记录详细错误信息(stderr 输出),并通过 ToolRegistry 将工具标记为不可用。用户可在启动日志中看到具体的连接错误。

MCP 工具调用的超时

问题:MCP 服务器的工具调用可能挂起,阻塞整个 Agent 循环。

对策

  • 每个 MCP 服务器配置支持 timeout 字段
  • McpClient 在超时后终止子进程并返回错误
  • Scheduler 的 signal 机制支持用户主动取消

MCP 工具参数验证

问题:MCP 服务器返回的工具 schema 可能不完整或不正确。

对策DiscoveredMCPToolbuild() 阶段使用 Zod schema 验证参数。如果 MCP 服务器未提供 schema,工具仍可调用,但参数验证较弱。


设计取舍

前缀命名空间 vs 独立工具注册

方案优势代价
前缀命名空间实现简单、可追溯来源、支持通配符策略工具名称较长,用户需记住前缀
独立注册工具名称简洁无法追溯来源,不同服务器同名工具可能冲突

Gemini CLI 的选择:前缀命名空间,因为 MCP 工具数量可能很多,且需要支持通配符策略规则。


参考来源