从零开始,亲手开发你的第一个AI大模型(二)MCP实战

484 阅读11分钟

本文较长,建议点赞收藏。更多AI大模型开发学习视频籽料, 都在这>>Github<<

📖说明

本篇文章是:从零开始,亲手开发你的第一个AI大模型! 的第二篇。主要介绍了什么是MCP!文章不仅仅停留于理论。还通过一个小Demo,带你亲手实践如何使用MCP。

在 GPT-4、Claude、Gemini 和 Llama3 等大型语言模型(LLM)不断演进的今天,我们迫切需要一种标准化方式,将它们与外部工具、API 和系统进行连接。 但问题是:这些模型都是“闭环”的 —— 它们只能处理预训练数据,无法直接访问实时数据、数据库、API 或本地文件系统。

今天我们要介绍的主角 —— Model Context Protocol(MCP) 就可以帮助我们解决上述的问题。

image.png

什么是 Model Context Protocol

随着大语言模型(LLM)的能力越来越强,它们已经不只是“聊天机器人”,而正在演变成具备实际执行力的智能体(Agent)。

但 LLM 有个“致命限制”:它们是封闭系统,无法直接访问外部世界的数据、接口和工具。

这就像你拥有一位博学多才的助手,但他关在屋子里,既看不到新闻,也摸不到文件,手脚都被绑住了。

MCP 就是打开这扇门的钥匙

Model Context Protocol(MCP) 是一种由 Anthropic 推出的通用协议,它让大语言模型可以:

  • 查询实时数据;
  • 访问数据库;
  • 操作本地文件;
  • 甚至调用 CRM、Git 等业务系统。

你可以把 MCP 理解为 “AI 工具的插头和插座” —— 不管是 Gemini、Claude 还是 GPT,只要符合 MCP 协议,就能通过统一方式接入这些“外部世界的工具”。

MCP = LLM 的万能转接头 🧩 LLM ⟶ MCP ⟶ 外部工具/API/数据库

它为 AI 系统打通了“感知-思考-执行”的完整闭环,是 Agent 系统落地的关键基建。

✦ ✧ ✦

MCP 的工作原理:就像“遥控指挥 + 实时执行”

MCP 采用的是一个 “客户端 - 服务端”架构,角色分工非常清晰:

角色作用
客户端一般是 AI 模型(如 Gemini、GPT-4 等)或模型应用
服务端MCP 工具提供方,用来暴露功能,比如“搜索航班”工具、“查询数据库”等

举个例子:

假设你给 Gemini 发一句话:

“查一下明天从北京到上海的高铁票”

系统执行过程大致如下:

  1. Gemini 接收到自然语言;
  2. 它通过 MCP 协议得知有一个叫 search_trains 的工具;
  3. 它根据 prompt 自动生成结构化函数调用(如 source: 北京,destination: 上海);
  4. 这个调用通过 MCP 协议传给 MCP Server;
  5. MCP Server 实际调用第三方 API(比如 12306 数据接口);
  6. 返回结果后,反馈给 Gemini;
  7. Gemini 再用自然语言将结果表达给用户。

整个过程像是一场模型和工具之间的“协同舞蹈”,由 MCP 串联而成。

✦ ✧ ✦

MCP 工具的应用示例

以下是 MCP 可支持的一些典型工具类型,覆盖了日常应用、商业系统、开发运维等多个场景:

工具类型示例功能说明
📁 本地文件系统file_browser读取、列出本地文件夹内容
🔍 实时搜索工具web_search基于 Bing、Google 进行网页搜索
📊 数据查询工具sql_query_tool连接 PostgreSQL/MySQL 数据库进行 SQL 查询
🧾 CRM 工具salesforce_tool调用 Salesforce 接口,查询客户或订单信息
🛠 开发工具集成git_tool查询 Git 仓库中的提交记录或差异
📦 产品信息查询ecommerce_tool搜索电商平台商品详情,如亚马逊

实际例子:

  • 企业可以使用 MCP + LLM 实现“智能客服”,自动调用数据库查订单;
  • AI 编程助手可通过 MCP 工具调用 Git 工具查找代码变更;
  • 财务助手通过 MCP 查询 Excel 文件或 ERP 系统发票信息;
  • 只要你能把功能封装成 MCP 工具,LLM 就能学会使用它。

MCP 的典型使用场景

✅ 构建 Agent 系统(具备感知、记忆、执行能力的 AI)

MCP 是 AI Agent 的“胳膊和腿”,是连接语言和行动之间的桥梁。

✅ 搭建多工具工作流

需要串联多个工具完成任务时(如:搜索 → 总结 → 存储),MCP 可以让每个环节模块化、可重用。

✅ 自然语言 + 实时外部数据结合

任何“用嘴控制工具”的场景 —— 比如语音助手、智能问答、企业数据 Copilot,都离不开 MCP。

✅ 企业内部系统集成

无论你用的是 Oracle、SAP、Salesforce、还是自研系统,都可以包装成 MCP 工具暴露出去。只要遵循协议,模型就能自动发现并调用。

✦ ✧ ✦

实战教程:基于 Gemini + MCP 构建实时航班查询系统

image.png

🧰 准备工作

  • Python ≥ 3.8
  • 拥有 Google Gemini API Key
  • 拥有 SerpAPI Key(用于实时航班数据)

Google Gemini API Key

Google Gemini 是 Google 推出的系列大型语言模型(LLM),通过 Google AI Studio 提供 API 接口。

✅ 步骤如下:

这是 Google AI Studio 的入口页面,国内建议使用科学上网访问。

  • 登录你的 Google 账号;
  • 点击右上角头像,选择 “Get API Key” 或进入控制台:aistudio.google.com/app/apikey
  • 同意服务条款,生成 API Key;

SerpAPI Key

SerpAPI 是一个第三方 API 服务,可以将 Google、Bing、YouTube 等搜索结果结构化返回,非常适合 LLM 使用。

✅ 步骤如下:

  • 打开官网:serpapi.com/
  • 点击右上角「Sign Up」注册一个账号(支持 Google 登录);
  • 登录后进入控制台:serpapi.com/dashboard
  • 在页面上找到你的 API Key,复制即可;

Step 1:创建虚拟环境

python -m venv venv
source venv/bin/activate
pip install google-genai mcp
  • google-genai:与 Google 的生成式 AI 模型(如 Gemini)交互的官方 Python 库;
  • 用于与 MCP(Model Context Protocol,模型上下文协议)服务器交互的 Python SDK,该 SDK 提供了与外部工具或服务通信的相关功能;

设置环境变量:

export GEMINI_API_KEY="你的 Gemini API 密钥"
export SERP_API_KEY="你的 SerpAPI 密钥"

Step 2:安装 MCP 服务器(mcp-flight-search)

pip install mcp-flight-search

为了让 Gemini 能够与真实世界的 API 交互,我们需要使用一个符合 MCP 协议的服务器。

在本文中,我们将使用名为 mcp-flight-search 的服务器 —— 这是一个基于 FastMCP 构建的轻量级 MCP Server,它通过 SerpAPI 暴露了一个可以实时搜索航班数据的工具。

你可以通过以下链接在 PyPI 上安装该 MCP 服务器包:👉 https://pypi.org/project/mcp-flight-search/

如果你的 MCP 服务器包安装成功,你将会看到下面的内容。

image.png

Step 3:导入关键库

导入用于初始化 Gemini 和 MCP SDK 的库,并为异步执行做好准备。

from google import genai

上面这行代码导入的是 google-generativeai 库中的 genai 模块, 它使我们可以访问 Google 强大的语言模型,例如 Gemini 1.5、2.0 和 2.5,并提供了与模型进行自然语言交互的客户端方法。

from google.genai import types

这行代码提供了 Gemini API 中使用的类型定义和配置结构。 例如:

  • Tool:定义模型可以调用的工具(函数);
  • GenerateContentConfig:用于配置模型的响应方式,如温度、是否启用函数调用等。
from mcp import ClientSession, StdioServerParameters

这行代码来自 mcp-sdk-python 库,是与 MCP 服务器交互所必需的组件:

  • ClientSession:用于管理客户端(或应用)与 MCP 服务端之间的通信会话;
  • StdioServerParameters:指定通过标准输入输出(stdio)方式与 MCP 服务端交互,语言无关,易于集成。
from mcp.client.stdio import stdio_client

这行代码导入了 stdio_client,它是一个异步上下文管理器, 用于通过标准输入输出(stdin/stdout)建立与 MCP Server 的连接,确保服务器正确启动,客户端可以结构化地发送和接收请求。

完整导入模块

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

Step 4:初始化 Gemini 客户端

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

genai.Client() 是与 Google 生成式模型(例如 Gemini 2.5 Pro、Gemini 2 Flash)交互的主要接口。

一旦初始化了 GenAI 客户端,该客户端对象就可以执行以下操作:

  • 向 Gemini 模型发送提示语(prompt);
  • 传递工具定义(用于函数调用);

接收结构化的响应结果和函数调用对象。

Step 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 服务器的命令行入口,也可以是一个实现了 MCP 协议的 Python 模块(在我们的例子中即如此)。

stdio —— 指定服务器使用标准输入/输出(stdio)作为通信通道。Stdio 简单、语言无关,非常适合在本地或子进程中运行工具服务器。

SERP_API_KEY —— 通过环境变量将 SERP_API_KEY 传递给运行该工具的子进程。在我们的案例中,这个工具需要使用该密钥来验证并访问 SerpAPI,以获取实时航班数据。

一旦定义了 server_params,我们就可以使用 stdio_client 异步上下文管理器来启动 MCP 服务器。

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 实时执行这些操作。

Step 6:连接 MCP 服务 & 工具注册

以下这段代码执行了三个重要的步骤:

  1. 建立与 MCP 服务器的连接;
  2. 初始化一个用于结构化工具通信的会话;
  3. 动态发现并格式化可供 Gemini 使用的工具信息。
async def run():
    asyncwith stdio_client(server_params) as (read, write):
        asyncwith ClientSession(read, write) as session:
            prompt"Find Flights from Atlanta to Las Vegas 2025-05-05"
            await session.initialize()
            mcp_tools = await session.list_tools()

            tools = [
                types.Tool(function_declarations=[
                    {
                        "name": tool.name,
                        "description": tool.description,
                        "parameters": {
                            k: v for k, v in tool.inputSchema.items()
                            if k notin ["additionalProperties""$schema"]
                        }
                    }
                ])
                for tool in mcp_tools.tools
            ]

            response = client.models.generate_content(
                model="gemini-2.5-pro-exp-03-25",
                contents=prompt,
                config=types.GenerateContentConfig(
                    temperature=0,
                    tools=tools
                ),
            )

让我们逐行解析代码,深入了解 MCP 客户端与服务器(以及 Gemini 大模型)之间是如何在底层进行通信的。

stdio_client 是一个异步上下文管理器,主要负责以下几项任务:

  • 以子进程的形式启动 MCP 服务器;
  • 管理与服务器之间的输入/输出流,用于交换消息;

其中的 read 和 write 是异步流对象:

  • read:用于从 MCP 服务器读取响应或工具注册信息;
  • write:用于向服务器发送请求或发起工具调用。
 prompt = f"Find Flights from Atlanta to Las Vegas 2025-05-05"

上述的 prompt 是我们要发送给 Gemini 模型的自然语言查询,Gemini 会将其解析并转换为结构化的工具调用请求。

await session.initialize()

session.initialize() 是触发客户端与 MCP 服务器之间初始握手的关键操作。

在此过程中,服务器会注册它所提供的全部工具(在我们的示例中是一个航班搜索工具)。

一旦初始化完成,当前会话就可以列出、调用并执行这些工具了。

 mcp_tools = await session.list_tools()

上述代码用于请求服务器所暴露的所有工具(函数)列表。

在 mcp_tools.tools 中的每一个工具都包含以下信息:

  • 工具名称(name)
  • 工具描述(description)
  • 输入参数的结构(input schema),即该工具接受哪些参数,格式为 JSON Schema

通过 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 notin ["additionalProperties""$schema"]
                },
            }
        ]
    )
    for tool in mcp_tools.tools
]

上述步骤将 MCP 工具的定义转换为 Gemini 所需的 function_declarations 格式。

此时,MCP 服务器已经启动,会话也已初始化,Gemini 模型可以通过这个会话发现并使用 MCP Server 所提供的工具。

Step 7:执行函数调用并获取航班数据

response = client.models.generate_content(
    model="gemini-2.5-pro-exp-03-25",
    contents=prompt,
    config=types.GenerateContentConfig(
        temperature=0,
        tools=tools,
    ),
)

最后,用户的提示词(prompt)会连同从 MCP 服务器发现到的工具列表一起发送给 Gemini 模型。

如果 Gemini 判断该提示词符合某个工具的函数定义(schema),它就会返回一个 function_call 对象,其中包含要调用的工具名称和自动填充的参数。

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

如果 Gemini 判断该提示词与某个函数(基于名称、描述或参数)匹配,它就会返回一个结构化的 function_call 对象,格式如下:

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

此时,Gemini 大语言模型就从一个被动的文本生成模型,转变为一个主动的“决策执行者”,具备以下能力:

  • 理解自然语言输入;
  • 自动选择合适的工具;
  • 自动填充函数所需的参数;

我们完全没有编写任何解析逻辑,Gemini 模型仅凭用户的自然语言输入,就自动完成了所有字段的填充。

最终生成的函数调用是结构化的,并且已准备好交由工具执行。

最终演示:Gemini 2.5 Pro 搭配 MCP 协议

下面的调试日志清晰地展示了 Gemini 与 Model Context Protocol(MCP)如何协同工作:

  • 解析用户意图,
  • 匹配合适的工具,
  • 并调用工具获取实时数据返回结果。

🧩 总结

本文以“自然语言航班搜索”为例,手把手带你实践:

  • 如何通过 Gemini 理解用户语言;
  • 如何用 MCP 暴露结构化工具;
  • 如何打通 LLM + 实时数据的通路;

结合 Gemini 2.5 Pro 实验版 + MCP,我们构建了一个可以自主理解、动态决策、自动调用工具并返回结构化结果的智能系统 —— 无需硬编码任何逻辑。

📦 GitHub 项目地址 完整代码已发布至: 👉 `arjunprabhulal/mcp-gemini-search`

更多AI大模型开发学习视频籽料,都在这>>Github<<