广告

深入探索:Google Gemini 2.5 Pro MCP模型协议及代码实现

2025年04月07日 由 alex 发表 4837 0

随着像GPT-4、Claude、Gemini和Llama3这样的大语言模型不断发展,我们需要有标准化的方式将它们与各种工具、应用程序编程接口(API)以及系统连接起来。然而,这些模型基于预训练数据独立运行,没有内置对实时数据、数据库、外部API或本地文件的访问功能。


在本文中,在深入探讨实现方法之前,我们将进一步讨论模型上下文协议(MCP)的概念:


1. 什么是模型上下文协议(MCP)?

模型上下文协议(MCP)是由Anthropic公司开发的一种标准化、开放的协议,它使人工智能模型能够与外部数据源和工具无缝交互,充当人工智能集成的通用连接器。


可以把MCP想象成“人工智能集成的USB-C接口”,它为人工智能模型提供了一种通用的方式来连接不同的设备和数据源。


MCP是如何工作的?

MCP遵循客户端-服务器架构,其中:

  • 客户端(如人工智能应用程序或大语言模型)进行连接;
  • 服务器(MCP工具提供商)向客户端公开工具、API或数据源。


这使得大语言模型(LLM)与外部API之间能够进行动态且结构化的交互。


MCP的优势:

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


MCP将API转变为对模型友好的工具,具备自动发现、可预测的模式以及结构化的交互功能。


MCP服务器的示例:

  • 文件系统:访问本地文件和目录。
  • 网络搜索:进行实时网络搜索。
  • 数据库:查询SQL或NoSQL数据库。
  • 客户关系管理系统(CRM):连接到如Salesforce这样的CRM系统。
  • 版本控制:访问如Git这样的版本控制系统。


何时使用模型上下文协议(MCP)?

在以下情况下使用MCP:

  • 我们正在构建智能代理系统;
  • 我们希望工具具有模块化、可复用性和可发现性;
  • 我们希望使用多个外部数据源;
  • 我们希望扩展到多个工具或工具链。


架构

以下项目集成了多个组件,以使用Gemini和MCP实现自然语言航班搜索功能。 


1


组件交互


1. 用户与客户端的交互

  • 用户提供自然语言查询内容(例如:“查找明天从亚特兰大飞往拉斯维加斯的航班”)
  • 客户端脚本(`client.py`)处理输入内容


2. 客户端与MCP服务器的交互

  • 客户端启动MCP服务器进程(`mcp-flight-search`)
  • 建立标准输入输出(stdio)通信通道
  • 检索可用的工具及其描述信息


3. 客户端与Gemini API的交互

  • 发送用户的查询内容
  • 提供用于函数调用的工具描述信息
  • 接收带有提取参数的结构化函数调用


4. 客户端与MCP工具的交互

  • 从Gemini获取函数调用参数
  • 使用参数调用相应的MCP工具
  • 处理响应内容


5. MCP服务器与SerpAPI的交互

  • MCP服务器向SerpAPI发出请求
  • 查询谷歌航班数据
  • 处理并格式化航班信息


实现过程

让我们通过分解关键实现步骤,深入了解如何使用Gemini AI构建这个流程。


先决条件

1. 已安装Python 3.8及以上版本

2. 通过API密钥获得谷歌Gemini生成式人工智能的访问权限

3. 有效的SerpAPI密钥(用于获取实时航班数据)


步骤1:设置虚拟环境

安装依赖项 


#Setup virtual env
python -n venv venv 
#Activate venv
source venv/bin/activate
#Install dependancies
pip install google-genai mcp


  • google-genai:用于与谷歌生成式人工智能模型(如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搜索实时航班数据的工具。


安装我发布到Python包索引(PyPi)上的MCP服务器软件包,地址为https://pypi.org/project/mcp-flight-search/ 。 


# Install from PyPI
pip install mcp-flight-search


让我们验证一下MCP服务器软件包是否已成功安装。


2


步骤3:了解MCP工具包

导入可同时初始化Gemini和MCP软件开发工具包(SDK)并为异步执行做准备的库。 


from google import genai


上述代码从`google-generativeai`库中导入了`genai`模块。它提供了对谷歌强大的大语言模型(LLM)的访问权限,比如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`(标准输入输出服务器参数):标准输入输出使得服务器能够做到与语言无关,并且易于嵌入到不同的环境中。 


from mcp.client.stdio import stdio_client


这导入了`stdio_client`,它是一个异步上下文管理器,用于通过标准输入输出与MCP服务器建立连接。它确保服务器能够正确启动,并且客户端已准备好发送/接收结构化的请求。 


from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


上述4个关键的导入内容共同构成了我们将Gemini大语言模型的交互与通过MCP工具所暴露的现实世界应用程序编程接口(API)连接起来的基础架构。


步骤4:初始化Gemini客户端 


client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))"GEMINI_API_KEY"))


`genai.Client()`是用于与谷歌生成式模型(如Gemini 2.5 Pro、Gemini 2 Flash)进行交互的主要接口。


一旦GenAI客户端初始化完成,这个客户端对象就可以:

- 向Gemini模型发送提示信息

- 传递工具定义(进行函数调用)

- 接收结构化响应和函数调用对象


步骤5:配置MCP工具服务器

下面的代码块设置了启动与MCP服务器进行通信所需的参数,该服务器会暴露工具(在我们的例子中是航班搜索功能)。 


server_params = StdioServerParameters(
    command="mcp-flight-search","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)作为其通信通道。标准输入输出简单易用、与语言无关,非常适合在本地或子进程中运行工具服务器。


`SERP_API_KEY`——这会将一个环境变量(`SERP_API_KEY`)传递给运行该工具的子进程。在我们的例子中,该工具需要这个环境变量来向SerpAPI进行身份验证,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服务器;
  • 管理用于消息交换的输入/输出流。


`read`和`write`对象是异步流:

  •  `read`:从服务器读取响应或工具注册信息;
  •  `write`:向服务器发送请求或工具调用指令。 


 prompt = f"Find Flights from Atlanta to Las Vegas 2025-05-05"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()await session.list_tools()


上述操作请求获取服务器所暴露的所有工具(函数)的列表。


`mcp_tools.tools` 中的每个工具都包含:

1. 一个名称

2. 一段描述

3. 一个输入模式(即以JSON模式格式表示它所接受的参数)


`mcp_tools.tools` 使MCP服务器具备自我描述的能力,这样大语言模型(LLM)就能自动理解如何调用每个工具。 


tools = [
    types.Tool(
        function_declarations=[
            {
                "name": tool.name,"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","gemini-2.5-pro-exp-03-25",
    contents=prompt,
    config=types.GenerateContentConfig(
        temperature=0,
        tools=tools,
    ),
)


最后,用户的提示信息会连同从MCP服务器发现的可用工具列表一起发送给Gemini模型。


如果Gemini识别出该提示信息与某个函数的模式匹配,它就会返回一个函数调用对象,其中包括工具名称以及自动填充的参数。 


result = await session.call_tool(
    function_call.name, arguments=dict(function_call.args)
)


步骤7:Gemini大语言模型的最终响应

如果Gemini判断提示信息与某个函数(根据名称、描述或参数)相符,它会返回一个结构化的函数调用对象,如下所示: 


{
  "function_call": {"function_call": {
    "name": "search_flights",
    "args": {
      "source": "ATL",
      "destination": "LAS",
      "date": "2025-05-05"
    }
  }
}


Gemini大语言模型从一个被动的文本模型转变为一个主动的决策制定者,它能够:

  • 解读自然语言输入
  •  选择合适的工具
  • 自动填充函数的参数
  • 我们无需编写任何解析逻辑。
  • Gemini大语言模型通过解读用户的自然语言填充了所有字段。
  • 函数调用是结构化的,且已准备好执行。


以下调试日志准确展示了Gemini和模型上下文协议(MCP)是如何协同工作,以解读用户意图、匹配工具并返回实时数据的。

 


使用模型上下文协议(MCP)与Gemini大语言模型的最佳实践

1. 工具设计

  • 清晰的工具名称:使用简短且有意义的名称(例如,search_flights(搜索航班)、get_weather(获取天气))。
  • 详细描述每个工具:提供简单、清晰的描述——模型会依据这些描述来决定何时以及如何调用该工具。
  • 使用强类型:明确地定义输入参数(例如,字符串、枚举、数字),以帮助模型准确地填充参数。


2. 模型交互

  • 工具越少,准确性越高:避免让模型负担过重——只保留相关的工具即可。
  • 动态工具加载:根据用户的查询或对话上下文来加载工具。
  • 清晰地提示模型:设定模型的角色,并解释如何以及何时使用这些工具。
  • 清晰地提示模型:设定模型的角色,并解释如何以及何时使用这些工具。


3. 服务器设置

  • 为简便起见使用标准输入输出(stdio):使用“connection_type stdio(连接类型为标准输入输出)”启动MCP服务器,以便于本地开发。
  • 安全传递环境变量:使用“env”将诸如SERP_API_KEY(搜索引擎结果页面应用程序编程接口密钥)等密钥安全地发送到工具服务器。


4. 请求处理

  • 先初始化会话:在列出或调用工具之前,务必运行session.initialize()(会话初始化)。
  • 动态列出工具:使用session.list_tools()(会话列出工具),以保持客户端的灵活性且与工具无关。


5. 错误处理与安全性

  • 返回有用的错误信息:确保当出现故障时,工具服务器能够返回有意义的消息。
  • 保障应用程序编程接口(API)的安全:绝不要在日志或错误消息中暴露像API密钥这样的机密信息。 


结论

在本文中,我们探讨了如何利用模型上下文协议(MCP)和谷歌的Gemini大语言模型来构建一个实时的、工具增强型的人工智能助手。通过逐步的讲解,我们了解到了以下内容:

1. Gemini模型如何处理自然语言提示;

2. MCP如何暴露结构化、具备自我描述功能的工具;

3. MCP与函数调用如何借助实时数据实现无缝的函数执行。


通过使用MCP将我们的人工智能应用程序与外部工具(在本次演示中为mcp-flight-search)以及大语言模型(如Gemini 2.0 Flash或处于实验阶段的Gemini 2.5 Pro)集成在一起,我们的系统演变成了一个智能的、以行动为导向的智能体,能够进行动态决策、函数调用,并在无需硬编码逻辑的情况下提供结构化的结果。 



文章来源:https://medium.com/google-cloud/model-context-protocol-mcp-with-google-gemini-llm-a-deep-dive-full-code-ea16e3fac9a3
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
PilotAILabs
30000~60000/年 深圳市
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
Maluuba
20000~40000/月
写评论取消
回复取消