通过 Google Gemini 2.5 Pro 实现 MCP

214 阅读10分钟

使用谷歌 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 的优势:

  1. 标准化集成: 将 LLM 连接到任何外部系统, 减少定制工作.
  2. 灵活性: LLM 可以按需使用多种工具和服务.
  3. 安全性: 支持安全的API交互, 无需硬编码凭据.
  4. 简化开发: 轻松构建和公开自定义 MCP 服务器.
  5. 维护更轻松: 不再有重复的集成逻辑.

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构建此管道的关键实施步骤.

前提条件

  1. 安装Python 3.8+

  2. 通过 API 密钥访问谷歌 Gemini生成式AI

  3. 有效的 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工具包

导入库, 用于初始化 GeminiMCP 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 服务器并列出工具

以下代码块执行三个重要步骤:

  1. 启动与 MCP 服务器的连接,
  2. 为结构化工具通信初始化会话, 以及
  3. 为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和函数调用时存在一些限制:

  1. 部分支持 OpenAPI
  2. Python 支持的参数类型有限.
  3. 自动函数调用仅是 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!