在 Gemini CLI 中使用 MCP 服务器
本文档提供了在 Gemini CLI 中配置和使用模型上下文协议(MCP)服务器的指南。
什么是 MCP 服务器?
MCP 服务器是一个应用程序,通过模型上下文协议向 Gemini CLI 公开工具和资源,允许它与外部系统和数据源交互。MCP 服务器充当 Gemini 模型与您的本地环境或其他服务(如 API)之间的桥梁。
MCP 服务器使 Gemini CLI 能够:
- 发现工具: 通过标准化模式定义列出可用工具、它们的描述和参数。
- 执行工具: 使用定义的参数调用特定工具并接收结构化响应。
- 访问资源: 从特定资源读取数据(尽管 Gemini CLI 主要专注于工具执行)。
使用 MCP 服务器,您可以扩展 Gemini CLI 的功能,执行超出其内置功能的操作,例如与数据库、API、自定义脚本或专门工作流进行交互。
核心集成架构
Gemini CLI 通过内置在核心包(packages/core/src/tools/
)中的复杂发现和执行系统与 MCP 服务器集成:
发现层(mcp-client.ts
)
发现过程由 discoverMcpTools()
协调,它:
- 遍历配置的服务器,从您的
settings.json
mcpServers
配置中 - 建立连接,使用适当的传输机制(Stdio、SSE 或 Streamable HTTP)
- 从每个服务器获取工具定义,使用 MCP 协议
- 清理和验证工具模式,确保与 Gemini API 兼容
- 在全局工具注册表中注册工具,并进行冲突解决
执行层(mcp-tool.ts
)
每个发现的 MCP 工具都包装在 DiscoveredMCPTool
实例中,该实例:
- 处理确认逻辑,基于服务器信任设置和用户偏好
- 管理工具执行,通过使用适当参数调用 MCP 服务器
- 处理响应,用于 LLM 上下文和用户显示
- 维护连接状态并处理超时
传输机制
Gemini CLI 支持三种 MCP 传输类型:
- Stdio 传输: 生成子进程并通过 stdin/stdout 通信
- SSE 传输: 连接到服务器发送事件端点
- Streamable HTTP 传输: 使用 HTTP 流进行通信
如何设置您的 MCP 服务器
Gemini CLI 使用 settings.json
文件中的 mcpServers
配置来定位和连接到 MCP 服务器。此配置支持使用不同传输机制的多个服务器。
在 settings.json 中配置 MCP 服务器
您可以在 ~/.gemini/settings.json
文件的全局级别配置 MCP 服务器,或者在项目的根目录中创建或打开 .gemini/settings.json
文件。在文件中,添加 mcpServers
配置块。
配置结构
将 mcpServers
对象添加到您的 settings.json
文件中:
{ ...file contains other config objects
"mcpServers": {
"serverName": {
"command": "path/to/server",
"args": ["--arg1", "value1"],
"env": {
"API_KEY": "$MY_API_TOKEN"
},
"cwd": "./server-directory",
"timeout": 30000,
"trust": false
}
}
}
配置属性
每个服务器配置支持以下属性:
必需(以下之一)
command
(字符串):Stdio 传输的可执行文件路径url
(字符串):SSE 端点 URL(例如,"http://localhost:8080/sse"
)httpUrl
(字符串):HTTP 流端点 URL
可选
args
(字符串[]):Stdio 传输的命令行参数headers
(对象):使用url
或httpUrl
时的自定义 HTTP 头env
(对象):服务器进程的环境变量。值可以使用$VAR_NAME
或${VAR_NAME}
语法引用环境变量cwd
(字符串):Stdio 传输的工作目录timeout
(数字):请求超时时间,以毫秒为单位(默认:600,000ms = 10 分钟)trust
(布尔值):当为true
时,绕过此服务器的所有工具调用确认(默认:false
)includeTools
(字符串[]):要从此 MCP 服务器包含的工具名称列表。指定时,只有此处列出的工具才可从此服务器获得(白名单行为)。如果未指定,默认启用服务器的所有工具。excludeTools
(字符串[]):要从此 MCP 服务器排除的工具名称列表。此处列出的工具将不可用于模型,即使它们由服务器公开。注意:excludeTools
优先于includeTools
- 如果工具在两个列表中,它将被排除。
远程 MCP 服务器的 OAuth 支持
Gemini CLI 支持使用 SSE 或 HTTP 传输的远程 MCP 服务器的 OAuth 2.0 身份验证。这使得能够安全访问需要身份验证的 MCP 服务器。
自动 OAuth 发现
对于支持 OAuth 发现的服务器,您可以省略 OAuth 配置并让 CLI 自动发现它:
{
"mcpServers": {
"discoveredServer": {
"url": "https://api.example.com/sse"
}
}
}
CLI 将自动:
- 检测服务器何时需要 OAuth 身份验证(401 响应)
- 从服务器元数据发现 OAuth 端点
- 如果支持,执行动态客户端注册
- 处理 OAuth 流和令牌管理
身份验证流程
连接到启用 OAuth 的服务器时:
- 初始连接尝试失败,返回 401 未授权
- OAuth 发现找到授权和令牌端点
- 浏览器打开进行用户身份验证(需要本地浏览器访问)
- 授权代码被交换为访问令牌
- 令牌被安全存储供将来使用
- 连接重试使用有效令牌成功
浏览器重定向要求
重要: OAuth 身份验证要求您的本地机器能够:
- 打开网络浏览器进行身份验证
- 在
http://localhost:7777/oauth/callback
接收重定向
此功能在以下情况下不起作用:
- 没有浏览器访问的无头环境
- 没有 X11 转发的远程 SSH 会话
- 没有浏览器支持的容器化环境
管理 OAuth 身份验证
使用 /mcp auth
命令管理 OAuth 身份验证:
# 列出需要身份验证的服务器
/mcp auth
# 与特定服务器进行身份验证
/mcp auth serverName
# 如果令牌过期,重新身份验证
/mcp auth serverName
OAuth 配置属性
enabled
(布尔值):为此服务器启用 OAuthclientId
(字符串):OAuth 客户端标识符(使用动态注册时可选)clientSecret
(字符串):OAuth 客户端密钥(对于公共客户端可选)authorizationUrl
(字符串):OAuth 授权端点(如果省略则自动发现)tokenUrl
(字符串):OAuth 令牌端点(如果省略则自动发现)scopes
(字符串[]):必需的 OAuth 范围redirectUri
(字符串):自定义重定向 URI(默认为http://localhost:7777/oauth/callback
)tokenParamName
(字符串):SSE URL 中令牌的查询参数名称
令牌管理
OAuth 令牌自动:
- 安全存储在
~/.gemini/mcp-oauth-tokens.json
中 - 在过期时刷新(如果可用刷新令牌)
- 在每次连接尝试前验证
- 在无效或过期时清理
身份验证提供程序类型
您可以使用 authProviderType
属性指定身份验证提供程序类型:
authProviderType
(字符串):指定身份验证提供程序。可以是以下之一:dynamic_discovery
(默认):CLI 将自动从服务器发现 OAuth 配置。google_credentials
:CLI 将使用 Google 应用程序默认凭据(ADC)与服务器进行身份验证。使用此提供程序时,您必须指定所需的范围。
{
"mcpServers": {
"googleCloudServer": {
"httpUrl": "https://my-gcp-service.run.app/mcp",
"authProviderType": "google_credentials",
"oauth": {
"scopes": ["https://www.googleapis.com/auth/userinfo.email"]
}
}
}
}
示例配置
Python MCP 服务器(Stdio)
{
"mcpServers": {
"pythonTools": {
"command": "python",
"args": ["-m", "my_mcp_server", "--port", "8080"],
"cwd": "./mcp-servers/python",
"env": {
"DATABASE_URL": "$DB_CONNECTION_STRING",
"API_KEY": "${EXTERNAL_API_KEY}"
},
"timeout": 15000
}
}
}
Node.js MCP 服务器(Stdio)
{
"mcpServers": {
"nodeServer": {
"command": "node",
"args": ["dist/server.js", "--verbose"],
"cwd": "./mcp-servers/node",
"trust": true
}
}
}
基于 Docker 的 MCP 服务器
{
"mcpServers": {
"dockerizedServer": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"API_KEY",
"-v",
"${PWD}:/workspace",
"my-mcp-server:latest"
],
"env": {
"API_KEY": "$EXTERNAL_SERVICE_TOKEN"
}
}
}
}
基于 HTTP 的 MCP 服务器
{
"mcpServers": {
"httpServer": {
"httpUrl": "http://localhost:3000/mcp",
"timeout": 5000
}
}
}
带有自定义头的基于 HTTP 的 MCP 服务器
{
"mcpServers": {
"httpServerWithAuth": {
"httpUrl": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer your-api-token",
"X-Custom-Header": "custom-value",
"Content-Type": "application/json"
},
"timeout": 5000
}
}
}
带有工具过滤的 MCP 服务器
{
"mcpServers": {
"filteredServer": {
"command": "python",
"args": ["-m", "my_mcp_server"],
"includeTools": ["safe_tool", "file_reader", "data_processor"],
// "excludeTools": ["dangerous_tool", "file_deleter"],
"timeout": 30000
}
}
}
发现过程深入分析
当 Gemini CLI 启动时,它通过以下详细过程执行 MCP 服务器发现:
1. 服务器迭代和连接
对于 mcpServers
中的每个配置服务器:
- 状态跟踪开始: 服务器状态设置为
CONNECTING
- 传输选择: 基于配置属性:
httpUrl
→StreamableHTTPClientTransport
url
→SSEClientTransport
command
→StdioClientTransport
- 建立连接: MCP 客户端尝试使用配置的超时连接
- 错误处理: 连接失败被记录,服务器状态设置为
DISCONNECTED
2. 工具发现
成功连接后:
- 工具列表: 客户端调用 MCP 服务器的工具列表端点
- 模式验证: 验证每个工具的函数声明
- 工具过滤: 基于
includeTools
和excludeTools
配置过滤工具 - 名称清理: 清理工具名称以满足 Gemini API 要求:
- 无效字符(非字母数字、下划线、点、连字符)被替换为下划线
- 超过 63 个字符的名称被截断并进行中间替换(
___
)
3. 冲突解决
当多个服务器公开具有相同名称的工具时:
- 首次注册获胜: 第一个注册工具名称的服务器获得无前缀名称
- 自动前缀: 后续服务器获得前缀名称:
serverName__toolName
- 注册表跟踪: 工具注册表维护服务器名称与其工具之间的映射
4. 模式处理
工具参数模式经过清理以兼容 Gemini API:
$schema
属性被移除- **
additionalProperties
**被剥离 - **带有
default
的anyOf
**移除其默认值(Vertex AI 兼容性) - 递归处理应用于嵌套模式
5. 连接管理
发现后:
- 持久连接: 成功注册工具的服务器维持其连接
- 清理: 不提供可用工具的服务器连接被关闭
- 状态更新: 最终服务器状态设置为
CONNECTED
或DISCONNECTED
工具执行流程
当 Gemini 模型决定使用 MCP 工具时,发生以下执行流程:
1. 工具调用
模型生成带有以下内容的 FunctionCall
:
- 工具名称: 注册名称(可能带前缀)
- 参数: 匹配工具参数模式的 JSON 对象
2. 确认过程
每个 DiscoveredMCPTool
实现复杂的确认逻辑:
基于信任的绕过
if (this.trust) {
return false; // 不需要确认
}
动态允许列表
系统维护内部允许列表:
- 服务器级别:
serverName
→ 此服务器的所有工具都被信任 - 工具级别:
serverName.toolName
→ 此特定工具被信任
用户选择处理
需要确认时,用户可以选择:
- 仅此次继续: 仅此次执行
- 始终允许此工具: 添加到工具级别允许列表
- 始终允许此服务器: 添加到服务器级别允许列表
- 取消: 中止执行
3. 执行
确认后(或信任绕过):
参数准备: 根据工具模式验证参数
MCP 调用: 底层
CallableTool
使用以下内容调用服务器:typescriptconst functionCalls = [ { name: this.serverToolName, // 原始服务器工具名称 args: params, }, ];
响应处理: 结果格式化用于 LLM 上下文和用户显示
4. 响应处理
执行结果包含:
llmContent
: 语言模型上下文的原始响应部分returnDisplay
: 用户显示的格式化输出(通常是 markdown 代码块中的 JSON)
如何与您的 MCP 服务器交互
使用 /mcp
命令
/mcp
命令提供有关您的 MCP 服务器设置的全面信息:
/mcp
这显示:
- 服务器列表: 所有配置的 MCP 服务器
- 连接状态:
CONNECTED
、CONNECTING
或DISCONNECTED
- 服务器详细信息: 配置摘要(排除敏感数据)
- 可用工具: 每个服务器的工具列表及描述
- 发现状态: 整体发现过程状态
示例 /mcp
输出
MCP Servers Status:
📡 pythonTools (CONNECTED)
Command: python -m my_mcp_server --port 8080
Working Directory: ./mcp-servers/python
Timeout: 15000ms
Tools: calculate_sum, file_analyzer, data_processor
🔌 nodeServer (DISCONNECTED)
Command: node dist/server.js --verbose
Error: Connection refused
🐳 dockerizedServer (CONNECTED)
Command: docker run -i --rm -e API_KEY my-mcp-server:latest
Tools: docker__deploy, docker__status
Discovery State: COMPLETED
工具使用
一旦发现,MCP 工具就像内置工具一样可供 Gemini 模型使用。模型将自动:
- 选择适当的工具,基于您的请求
- 显示确认对话框(除非服务器被信任)
- 使用适当参数执行工具
- 以用户友好格式显示结果
状态监控和故障排除
连接状态
MCP 集成跟踪几种状态:
服务器状态(MCPServerStatus
)
DISCONNECTED
: 服务器未连接或有错误CONNECTING
: 连接尝试进行中CONNECTED
: 服务器已连接且就绪
发现状态(MCPDiscoveryState
)
NOT_STARTED
: 发现尚未开始IN_PROGRESS
: 当前正在发现服务器COMPLETED
: 发现完成(有或没有错误)
常见问题和解决方案
服务器无法连接
症状: 服务器显示 DISCONNECTED
状态
故障排除:
- 检查配置: 验证
command
、args
和cwd
是否正确 - 手动测试: 直接运行服务器命令以确保它工作
- 检查依赖项: 确保安装了所有必需的包
- 查看日志: 在 CLI 输出中查找错误消息
- 验证权限: 确保 CLI 可以执行服务器命令
未发现工具
症状: 服务器连接但没有可用工具
故障排除:
- 验证工具注册: 确保您的服务器实际注册工具
- 检查 MCP 协议: 确认您的服务器正确实现 MCP 工具列表
- 查看服务器日志: 检查 stderr 输出中的服务器端错误
- 测试工具列表: 手动测试您服务器的工具发现端点
工具无法执行
症状: 工具被发现但在执行期间失败
故障排除:
- 参数验证: 确保您的工具接受预期参数
- 模式兼容性: 验证您的输入模式是有效的 JSON 模式
- 错误处理: 检查您的工具是否抛出未处理的异常
- 超时问题: 考虑增加
timeout
设置
沙盒兼容性
症状: 启用沙盒时 MCP 服务器失败
解决方案:
- 基于 Docker 的服务器: 使用包含所有依赖项的 Docker 容器
- 路径可访问性: 确保服务器可执行文件在沙盒中可用
- 网络访问: 配置沙盒以允许必要的网络连接
- 环境变量: 验证所需的环境变量已传递
调试技巧
- 启用调试模式: 使用
--debug
运行 CLI 以获得详细输出 - 检查 stderr: 捕获并记录 MCP 服务器 stderr(过滤 INFO 消息)
- 测试隔离: 在集成之前独立测试您的 MCP 服务器
- 增量设置: 在添加复杂功能之前从简单工具开始
- 频繁使用
/mcp
: 在开发期间监控服务器状态
重要注意事项
安全考虑
- 信任设置:
trust
选项绕过所有确认对话框。谨慎使用,仅用于您完全控制的服务器 - 访问令牌: 配置包含 API 密钥或令牌的环境变量时要注意安全
- 沙盒兼容性: 使用沙盒时,确保 MCP 服务器在沙盒环境中可用
- 私人数据: 使用范围广泛的个人访问令牌可能导致仓库间的信息泄露
性能和资源管理
- 连接持久性: CLI 维护与成功注册工具的服务器的持久连接
- 自动清理: 不提供工具的服务器连接被自动关闭
- 超时管理: 根据服务器的响应特性配置适当的超时
- 资源监控: MCP 服务器作为单独的进程运行并消耗系统资源
模式兼容性
- 属性剥离: 系统自动移除某些模式属性(
$schema
、additionalProperties
)以兼容 Gemini API - 名称清理: 工具名称自动清理以满足 API 要求
- 冲突解决: 服务器间的工具名称冲突通过自动前缀解决
这种全面的集成使 MCP 服务器成为扩展 Gemini CLI 功能的强大方式,同时保持安全性、可靠性和易用性。
MCP 提示作为斜杠命令
除了工具之外,MCP 服务器还可以公开预定义的提示,这些提示可以作为 Gemini CLI 中的斜杠命令执行。这允许您为常见或复杂的查询创建快捷方式,可以通过名称轻松调用。
在服务器上定义提示
以下是定义提示的 stdio MCP 服务器的小示例:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({
name: 'prompt-server',
version: '1.0.0',
});
server.registerPrompt(
'poem-writer',
{
title: 'Poem Writer',
description: 'Write a nice haiku',
argsSchema: { title: z.string(), mood: z.string().optional() },
},
({ title, mood }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Write a haiku${mood ? ` with the mood ${mood}` : ''} called ${title}. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables `,
},
},
],
}),
);
const transport = new StdioServerTransport();
await server.connect(transport);
这可以在 settings.json
的 mcpServers
下包含:
"nodeServer": {
"command": "node",
"args": ["filename.ts"],
}
调用提示
一旦发现提示,您可以使用其名称作为斜杠命令调用它。CLI 将自动处理解析参数。
/poem-writer --title="Gemini CLI" --mood="reverent"
或者,使用位置参数:
/poem-writer "Gemini CLI" reverent
当您运行此命令时,Gemini CLI 使用提供的参数在 MCP 服务器上执行 prompts/get
方法。服务器负责将参数替换到提示模板中并返回最终提示文本。然后 CLI 将此提示发送给模型执行。这提供了一种方便的方式来自动化和共享常见工作流。