随着像GPT-4、Claude、Gemini和Llama3这样的大语言模型不断发展,我们需要有标准化的方式将它们与各种工具、应用程序编程接口(API)以及系统连接起来。然而,这些模型基于预训练数据独立运行,没有内置对实时数据、数据库、外部API或本地文件的访问功能。
在本文中,在深入探讨实现方法之前,我们将进一步讨论模型上下文协议(MCP)的概念:
1. 什么是模型上下文协议(MCP)?
模型上下文协议(MCP)是由Anthropic公司开发的一种标准化、开放的协议,它使人工智能模型能够与外部数据源和工具无缝交互,充当人工智能集成的通用连接器。
可以把MCP想象成“人工智能集成的USB-C接口”,它为人工智能模型提供了一种通用的方式来连接不同的设备和数据源。
MCP是如何工作的?
MCP遵循客户端-服务器架构,其中:
这使得大语言模型(LLM)与外部API之间能够进行动态且结构化的交互。
MCP的优势:
MCP将API转变为对模型友好的工具,具备自动发现、可预测的模式以及结构化的交互功能。
MCP服务器的示例:
何时使用模型上下文协议(MCP)?
在以下情况下使用MCP:
架构
以下项目集成了多个组件,以使用Gemini和MCP实现自然语言航班搜索功能。
组件交互
1. 用户与客户端的交互
2. 客户端与MCP服务器的交互
3. 客户端与Gemini API的交互
4. 客户端与MCP工具的交互
5. 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
设置环境变量
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服务器软件包是否已成功安装。
步骤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`是一个异步上下文管理器,它负责处理以下事项:
`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和模型上下文协议(MCP)是如何协同工作,以解读用户意图、匹配工具并返回实时数据的。
使用模型上下文协议(MCP)与Gemini大语言模型的最佳实践
1. 工具设计
2. 模型交互
3. 服务器设置
4. 请求处理
5. 错误处理与安全性
结论
在本文中,我们探讨了如何利用模型上下文协议(MCP)和谷歌的Gemini大语言模型来构建一个实时的、工具增强型的人工智能助手。通过逐步的讲解,我们了解到了以下内容:
1. Gemini模型如何处理自然语言提示;
2. MCP如何暴露结构化、具备自我描述功能的工具;
3. MCP与函数调用如何借助实时数据实现无缝的函数执行。
通过使用MCP将我们的人工智能应用程序与外部工具(在本次演示中为mcp-flight-search)以及大语言模型(如Gemini 2.0 Flash或处于实验阶段的Gemini 2.5 Pro)集成在一起,我们的系统演变成了一个智能的、以行动为导向的智能体,能够进行动态决策、函数调用,并在无需硬编码逻辑的情况下提供结构化的结果。