MCP协议实战:用Python从零搭建一个AI Agent工具服务器(保姆级教程)

前言

最近在搞 AI Agent 项目的时候,发现一个问题特别头疼:每个大模型(Claude、GPT、Gemini)的工具调用方式都不一样,写了一堆适配代码,换一个模型又得重写。

后来发现了 MCP(Model Context Protocol)这个协议,说白了就是 Anthropic 搞的一个标准,让 AI 模型和外部工具之间的通信有个统一规范。用了一圈下来,确实香。

今天就带大家从零用 Python 搭一个 MCP Server,实现一个能查天气、能搜网页的工具服务器。

什么是 MCP?

MCP 全称 Model Context Protocol,是 Anthropic 在 2024 年底开源的一个协议。你可以把它理解成 AI 世界的 USB-C ------ 不管你用什么模型,只要支持 MCP,就能无缝对接各种外部工具。

它的工作方式其实很简单:

  • MCP Server:工具提供方,比如你写的天气查询服务、数据库查询服务
  • MCP Client:AI 模型侧,负责调用这些工具
  • 通信协议:基于 JSON-RPC 2.0,支持 stdio 和 HTTP 两种传输方式

环境准备

先装好需要的依赖:

bash 复制代码
# 创建虚拟环境
python -m venv mcp-env
source mcp-env/bin/activate  # Windows: mcp-env\Scripts\activate

# 安装 MCP SDK
pip install mcp httpx

注意:Python 版本需要 3.10+,低版本会报错。

第一步:创建基础 MCP Server

先搭一个最简单的骨架:

python 复制代码
# server.py
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server

# 创建 MCP Server 实例
server = Server("my-weather-server")

@server.tool()
async def get_weather(city: str) -> str:
    """查询指定城市的天气信息"""
    # 这里先用模拟数据,后面接真实 API
    mock_data = {
        "北京": "晴天,25°C,湿度 40%",
        "上海": "多云,22°C,湿度 65%",
        "深圳": "阵雨,28°C,湿度 80%",
    }
    return mock_data.get(city, f"暂无 {city} 的天气数据")

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)

if __name__ == "__main__":
    asyncio.run(main())

就这么几行代码,一个 MCP Server 就搞定了。核心就是 @server.tool() 这个装饰器,它会自动把函数注册成一个可被 AI 调用的工具。

第二步:接入真实天气 API

模拟数据没意思,我们来接一个真实的天气服务。这里用和风天气的免费 API:

python 复制代码
# weather_api.py
import httpx

API_KEY = "你的API密钥"  # 去 dev.qweather.com 注册拿
BASE_URL = "https://devapi.qweather.com/v7"

async def fetch_weather(city: str) -> dict:
    """调用和风天气 API 获取实时天气"""
    async with httpx.AsyncClient() as client:
        # 先查城市 ID
        geo_url = "https://geoapi.qweather.com/v2/city/lookup"
        geo_resp = await client.get(geo_url, params={
            "location": city,
            "key": API_KEY
        })
        geo_data = geo_resp.json()

        if not geo_data.get("location"):
            return {"error": f"找不到城市: {city}"}

        city_id = geo_data["location"][0]["id"]

        # 再查天气
        weather_url = f"{BASE_URL}/weather/now"
        weather_resp = await client.get(weather_url, params={
            "location": city_id,
            "key": API_KEY
        })
        return weather_resp.json()

然后在 server 里调用它:

python 复制代码
@server.tool()
async def get_weather(city: str) -> str:
    """查询指定城市的实时天气"""
    from weather_api import fetch_weather
    data = await fetch_weather(city)

    if "error" in data:
        return data["error"]

    now = data.get("now", {})
    return f"{city}当前天气:{now.get('text', '未知')},温度 {now.get('temp', '?')}°C,体感 {now.get('feelsLike', '?')}°C,风向 {now.get('windDir', '无')}"

第三步:加一个网页搜索工具

一个工具太单调了,再来一个网页搜索功能:

python 复制代码
@server.tool()
async def search_web(query: str, num_results: int = 5) -> str:
    """搜索网页内容,返回标题和摘要"""
    async with httpx.AsyncClient() as client:
        # 用 DuckDuckGo 的即时搜索(国内可能需要代理)
        resp = await client.get(
            "https://api.duckduckgo.com/",
            params={"q": query, "format": "json", "no_redirect": 1},
            timeout=10.0
        )
        data = resp.json()

        results = []
        if data.get("Abstract"):
            results.append(f"摘要:{data['Abstract']}")

        for topic in data.get("RelatedTopics", [])[:num_results]:
            if "Text" in topic:
                results.append(f"- {topic['Text']}")

        return "\n".join(results) if results else "未找到相关结果"

第四步:测试你的 MCP Server

写好了服务,怎么测试呢?最简单的方式是用 Claude Desktop 连接它。

编辑 Claude Desktop 的配置文件:

json 复制代码
{
  "mcpServers": {
    "my-weather-server": {
      "command": "python",
      "args": ["/path/to/server.py"]
    }
  }
}

重启 Claude Desktop,你就能在对话里直接问天气了。比如输入"北京今天天气怎么样",Claude 会自动调用你写的 get_weather 工具。

常见问题 Q&A

Q1:报错 ModuleNotFoundError: No module named 'mcp'

确认你激活了虚拟环境,然后重新 pip install mcp。如果还是不行,试试 pip install mcp[cli]

Q2:Claude Desktop 连不上 Server

检查配置文件路径是否正确。macOS 在 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 在 %APPDATA%\Claude\claude_desktop_config.json

Q3:工具注册了但 AI 不调用

确保函数的 docstring 写清楚了,AI 靠它理解工具的用途。描述越精确,调用越准确。

Q4:想支持 HTTP 传输而不是 stdio?

MCP 也支持 SSE(Server-Sent Events)传输,适合远程部署。把 stdio_server 换成 sse_server 就行,不过配置会复杂一些。

总结

MCP 这个协议确实解决了 AI 工具调用碎片化的问题。几行 Python 代码就能把任何服务包装成 AI 可调用的工具,而且换模型不用改代码。

目前 MCP 生态还在早期,但已经有大量社区贡献的 Server(数据库、文件系统、GitHub、Slack 等等)。如果你在做 AI Agent 相关的项目,强烈建议现在就开始用起来。

下一步可以看看:

有问题欢迎评论区交流 👇

相关推荐
今天AI了吗6 小时前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
Warren2Lynch6 小时前
从提示词到架构:Visual Paradigm VPasCode AI 驱动更新完全指南
人工智能·架构
卷无止境6 小时前
Windows 上丝滑开发 Python,并稳定构建 Docker 镜像
后端·python·docker
ZGIAI6 小时前
ZGI 发布治理:同一个 Agent 服务多个入口
人工智能·架构
liuyicenysabel6 小时前
多服务上线日记三:
运维·服务器·笔记·学习
ZGIAI6 小时前
ZGI 批量测试:上线前验证 Agent
人工智能·架构
qq407855606 小时前
面向智能补货需求的进销存系统盘点
大数据·人工智能·低代码·制造
你是一个铁憨憨6 小时前
从 GIS 到 Spatial Agent:MCP 如何重新定义 GIS 的 AI 入口
arcgis·ai·agent·mcp·spatial
TELL5216 小时前
selenium webdriver 第二次初始化的异常
开发语言·python
Web3_Daisy6 小时前
从流动性到执行:如何降低 MEV 对 Web3 市场
大数据·人工智能·web3·区块链