使用谷歌 Gemini 2.5 Pro 的 MCP
通过完整代码进行深度剖析. 包含代码, 架构和实际使用案例的分步指南.
随着 GPT-4, Claude, Gemini 和 Llama3 等大型语言模型(LLM)的发展, 我们需要标准化的方法将它们与工具, API 和系统连接起来. 然而, 这些模型是基于预训练数据孤立运行的, 无法内置访问实时数据, 数据库, 外部 API 或本地文件的权限.
在本文中, 我将在深入探讨实现之前, 详细讨论MCP的概念:
1. 什么是MCP?
MCP是 Anthropic 开发的一种标准化开放协议, 可使AI模型与外部数据源和工具无缝交互, 是AI集成的通用连接器.
将 MCP 视为 “AI集成的 USB-C”, 它为AI模型连接不同设备和数据源提供了一种通用方式.
MCP 如何工作?
MCP 采用客户端-服务器架构, 其中包括:
- 客户(如AI应用程序或 LLM)连接到
- 服务器(MCP 工具提供商)将工具, API或数据源暴露给客户.
这就实现了 LLM 模型与外部 API 之间的动态和结构化交互.
MCP 的优势:
- 标准化集成: 将 LLM 连接到任何外部系统, 减少定制工作.
- 灵活性: LLM 可以按需使用多种工具和服务.
- 安全性: 支持安全的API交互, 无需硬编码凭据.
- 简化开发: 轻松构建和公开自定义 MCP 服务器.
- 维护更轻松: 不再有重复的集成逻辑.
MCP将API转换为模型友好工具, 具有自动发现, 可预测模式和结构化交互功能.
MCP 服务器示例
- 文件系统: 访问本地文件和目录.
- 网络搜索: 运行实时网络搜索.
- 数据库: 查询 SQL 或 NoSQL 数据库
- 客户关系管理: 连接到客户关系管理系统, 如 Salesforce.
- 版本控制: 访问 Git 等版本控制系统
何时使用MCP?
当出现以下情况时, 应使用MCP:
- 我们正在构建代理系统
- 我们希望工具模块化, 可重用, 可发现
- 我们希望使用多个外部资源
- 我们希望扩展到多个工具或工具链.
架构
以下项目集成了多个组件, 使用Gemini + MCP 实现自然语言航班搜索:
组件交互
1. 用户到客户端
- 用户提供自然语言查询(例如, “查找明天从广州飞往北京的航班”).
客户端脚本(
client.py
)处理输入内容
2. 客户端到 MCP 服务器
- 客户端启动 MCP 服务器进程 (
mcp-flight-search
) - 建立 stdio 通信通道
- 检索可用工具及其说明
3. 客户端到GeminiAPI
- 发送用户查询
- 为函数调用提供工具说明
- 接收带有提取参数的结构化函数调用
4. 客户端到 MCP 工具
- 从 Gemini 获取函数调用参数
- 使用参数调用相应的 MCP 工具
- 处理响应处理
5. MCP 服务器到 SerpAPI
- MCP 服务器向 SerpAPI 提出请求
- 查询谷歌航班数据
- 处理和格式化航班信息
实施
让我们深入了解使用Gemini AI构建此管道的关键实施步骤.
前提条件
-
安装Python 3.8+
-
通过 API 密钥访问谷歌 Gemini生成式AI
-
有效的 SerpAPI key (用于获取实时飞行数据)
步骤 1: 设置虚拟环境
安装依赖项
#Setup virtual env
python -n venv venv
#Activate venv
source venv/bin/activate
#Install dependancies
pip install google-genai mcp
google-genai
: 用于与谷歌生成式AI模型(如Gemini)交互的官方 Python 库.mcp
: 用于与 MCP服务器交互的 Python SDK. 该 SDK 可提供与外部工具或服务通信的功能.
设置环境变量
export GEMINI_API_KEY="your-google-api-key"
export SERP_API_KEY="your-serpapi-key"
步骤 2: 安装 MCP 服务器 - mcp-flight-search
为使 Gemini 能够与现实世界的 API 交互, 我们将使用兼容 MCP 的服务器.
在本文中, 我将使用mcp-flight-search--一个使用FastMCP构建的轻量级 MCP 服务器, 它提供了一个使用 SerpAPI 搜索实时飞行数据的工具.
在我发布到 PyPi 的地方安装 MCP 服务器软件包 pypi.org/project/mcp…
# Install from PyPI
pip install mcp-flight-search
让我们验证 MCP 服务器包是否安装成功:
第3步: 了解MCP工具包
导入库, 用于初始化 Gemini 和 MCP SDK 并为异步执行做好准备.
from google import genai
以上是从 google-generativeai
库导入genai
模块. 它提供了对Google 强大的 LLMs(如 Gemini 1.5 和 2.0, 2.5 模型)的访问, 并包含使用自然语言与模型交互的客户端方法.
from google.genai import types
以上模块可访问 Gemini API 使用的类型定义和配置结构. 例如
-
工具: 定义模型可调用的工具(函数).
-
GenerateContentConfig
: 允许我们配置模型的响应方式(如温度, 工具支持等).
from mcp import ClientSession, StdioServerParameters
以上类来自 mcp-sdk-python库, 是与 MCP 服务器交互的基本要素:
-
ClientSession: 管理客户端/应用程序与 MCP 服务器之间的通信会话.
-
StdioServerParameters: stdio 允许服务器不依赖语言, 并可轻松嵌入到不同的环境中.
from mcp.client.stdio import stdio_client
导入stdio_client
, 这是一个异步上下文管理器, 用于通过标准 I/O 与 MCP 服务器建立连接. 它确保服务器正确启动, 客户端准备好发送/接收结构化请求.
from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
以上 4 个关键导入共同构成了我们如何将Gemini 的 LLM 交互与通过 MCP 工具暴露的现实世界 API连接起来的支柱.
第 4 步: 初始化Gemini客户端
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
GenAI.Client()
是与谷歌生成模型(如Gemini 2.5 Pro, Gemini 2 Flash)交互的主要接口.
GenAI 客户端初始化后, 该客户端对象可以:
- 向Gemini模型发送提示
- 传递工具定义(函数调用)
- 接收结构化响应和函数调用对象
步骤 5: 配置 MCP 工具服务器
下面的代码块设置了与 MCP 服务器启动和通信所需的参数, 该服务器提供工具(在我们的例子中是航班搜索功能).
server_params = StdioServerParameters(
command="mcp-flight-search",
args=["--connection_type", "stdio"],
env={"SERP_API_KEY": os.getenv("SERP_API_KEY")},
)
-
mcp-flight-search
- 这是运行本地 MCP 服务器的 CLI 入口点, 在我们的例子中也可以是实现 MCP 协议的 Python 模块. -
stdio
- 这将告诉服务器使用**标准输入/输出(stdio)**作为其通信渠道. Stdio 简单, 与语言无关, 非常适合在本地或子进程中运行工具服务器. -
SERP_API_KEY
- 将环境变量(SERP_API_KEY
)传递给运行工具的子进程. 在我们的例子中, 工具需要它来验证SERPAPI
, 以获取实时飞行数据.
一旦定义了
server_params
, 我们就可以使用它来使用stdio_client
异步上下文管理器启动服务器.
Python 3.11.11 (main, Dec 3 2024, 17:20:40) [Clang 16.0.0 (clang-1600.0.26.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> from google import genai
>>> from google.genai import types
>>> from mcp import ClientSession, StdioServerParameters
>>> from mcp.client.stdio import stdio_client
>>>
>>> client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
>>>
>>> server_params = StdioServerParameters(
... command="mcp-flight-search",
... args=["--connection_type", "stdio"],
... env={"SERP_API_KEY": os.getenv("SERP_API_KEY")},
... )
>>> server_params
StdioServerParameters(command='mcp-flight-search', args=['--connection_type', 'stdio'], env={'SERP_API_KEY':'XXXXXXXXX'}, cwd=None, encoding='utf-8', encoding_error_handler='strict')
>>>
Gemini 客户端处理语言理解, 提示生成和函数调用.
MCP 工具服务器(飞行搜索)通过 SerpAPI 监听工具调用并实时执行.
第 6 步: 连接到 MCP 服务器并列出工具
以下代码块执行三个重要步骤:
- 启动与 MCP 服务器的连接,
- 为结构化工具通信初始化会话, 以及
- 为Gemini动态发现和格式化可用工具.
async def run():
# Remove debug prints
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
prompt = f"Find Flights from Atlanta to Las Vegas 2025-05-05"
await session.initialize()
# Remove debug prints
mcp_tools = await session.list_tools()
# Remove debug prints
tools = [
types.Tool(
function_declarations=[
{
"name": tool.name,
"description": tool.description,
"parameters": {
k: v
for k, v in tool.inputSchema.items()
if k not in ["additionalProperties", "$schema"]
},
}
]
)
for tool in mcp_tools.tools
]
# Remove debug prints
response = client.models.generate_content(
model="gemini-2.5-pro-exp-03-25",
contents=prompt,
config=types.GenerateContentConfig(
temperature=0,
tools=tools,
),
)
让我们逐行分析, 以了解 MCP 客户端与服务器之间的通信是如何在 Gemini LLM 框架下进行的
stdio_client
是一个异步上下文管理器, 负责处理以下事务:
- 将 MCP 服务器作为子进程启动
- 管理消息交换的输入/输出流
读和写对象是异步流:
- 读:从服务器读取响应或工具注册
- 写:向服务器发送请求或工具调用
prompt = f"Find Flights from Atlanta to Las Vegas 2025-05-05"
上面的提示是我们将发送给 Gemini 模型的自然语言查询, Gemini 随后会将其转化为结构化的工具调用.
await session.initialize()
session.initialize()
会触发客户端与服务器之间的初始MCP握手.
服务器注册其可用工具(在我们的例子中:航班搜索工具).
- 服务器注册其可用工具(本例中为航班搜索工具).
- 会话现在可以列出, 调用和执行工具.
mcp_tools = await session.list_tools()
以上请求服务器提供的所有工具(函数)列表.
- 在
mcp_tools.tools
中的每个工具都包含 - 名称
- 描述
- 输入模式(即它接受什么参数, 以 JSON 模式格式表示)
mcp_tools.tools
使 MCP 服务器自我描述, 因此 LLM 可以自动理解如何调用每个工具.
tools = [
types.Tool(
function_declarations=[
{
"name": tool.name,
"description": tool.description,
"parameters": {
k: v
for k, v in tool.inputSchema.items()
if k not in ["additionalProperties", "$schema"]
},
}
]
)
for tool in mcp_tools.tools
]
以上步骤将 MCP 工具定义转换为 Gemini 函数声明 格式.
现在我们的 MCP 服务器已经运行, 会话也已初始化, 可以从 MCP 服务器发现工具供 Gemini 使用
第 6 步:Gemini - 解释提示并建议函数调用
response = client.models.generate_content(
model="gemini-2.5-pro-exp-03-25",
contents=prompt,
config=types.GenerateContentConfig(
temperature=0,
tools=tools,
),
)
最后, 用户的提示会连同从 MCP 服务器发现的可用工具列表一起发送到 Gemini 模型.
如果 Gemini 识别出提示与function_mode
相匹配, 它就会返回一个function_call
对象, 其中包括工具名称和自动填充的参数.
result = await session.call_tool(
function_call.name, arguments=dict(function_call.args)
)
第 7 步 : Gemini LLM 最终响应
如果 Gemini 确定提示与函数一致(基于名称, 描述或参数), 则会返回一个结构化的 function_call
对象, 例如:
{
"function_call": {
"name": "search_flights",
"args": {
"source": "ATL",
"destination": "LAS",
"date": "2025-05-05"
}
}
}
Gemini LLM 从一个被动的文本模型过渡到一个主动的决策者, 它能:
- 解释自然输入
- 选择合适的工具
- 自动填写函数参数
- 我们没有编写任何解析逻辑.
- Gemini LLM 模型通过解释用户的自然语言来填写所有字段.
- 函数调用是结构化的, 可随时执行.
最终演示: Gemini 2.5 Pro与 MCP
下面的调试日志清楚地显示了 Gemini, Model Context Protocol 如何共同解释用户意图, 匹配工具并返回实时数据.
与 Gemini LLM 一起使用MCP的最佳实践
1. 工具设计
- 明确的工具名称: 使用简短, 有意义的名称(如 search_flights, get_weather).
- 充分描述每个工具: 提供简单明了的描述--模型以此来决定何时以及如何调用工具.
- 使用强类型: 明确定义输入参数(如字符串, 枚举, 数字), 以帮助模型准确填写.
2. 模型交互
- 更少的工具意味着更高的准确性: 避免模型超载--只使用相关工具.
- 动态工具加载: 根据用户的查询或对话上下文加载工具.
- 明确提示模型: 设定模型的角色, 并解释如何以及何时使用工具.
3. 服务器设置
- 使用 stdio以简化操作: 使用 connection_type stdio 启动 MCP 服务器, 便于本地开发.
- 安全传递环境变量: 使用环境变量安全地向工具服务器发送
SERP_API_KEY
等密钥.
4. 请求处理
- 首先初始化会话: 在列出或调用工具之前, 始终运行
session.initialize()
. - 动态列出工具: 使用
session.list_tools()
, 以保持客户端的灵活性和工具无关性.
5. 错误处理与安全
- 返回有用的错误: 确保工具服务器在出现故障时提供有意义的信息.
- 安全的API: 切勿在日志或错误信息中泄露 API 密钥等秘密.
GitHub 存储库:
你可以在我的 GitHub 上访问本教程中使用的所有代码: mcp-gemini-search
限制
截至本文撰写之时(2025 年 3 月), 在使用 Gemini LLM 的MCP和函数调用时存在一些限制:
- 部分支持 OpenAPI
- Python 支持的参数类型有限.
- 自动函数调用仅是 Python SDK 的一项功能.
总结一下
在本文中, 我们探讨了如何使用MCP和谷歌Gemini LLM来构建一个实时的, 工具增强型AI助手. 通过逐步演练, 我们看到了如何做到这一点:
- Gemini可以处理自然语言提示,
- MCP 公开了结构化的自描述工具,
- MCP + 功能调用实现了由实时数据驱动的无缝功能执行.
通过将我们的AI应用程序与外部工具(在本演示中如mcp-flight-search)和使用 MCP 的 LLMs - Gemini 2.0 Flash 或 Gemini 2.5 Pro 实验整合在一起, 我们的系统发展成为智能的, 行动驱动的代理, 能够进行动态决策, 函数调用并提供结构化结果, 而无需硬编码逻辑.
好吧, 今天的内容就分享到这里啦!
一家之言, 欢迎拍砖!
Happy Coding! Stay GOLDEN!