李锋镝的博客

  • 首页
  • 时间轴
  • 评论区显眼包🔥
  • 左邻右舍
  • 博友圈
  • 关于我
    • 关于我
    • 另一个网站
    • 我的导航站
    • 网站地图
    • 赞助
  • 留言
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. AI
  3. 正文

从零开发 MCP 协议工具:从原理到实战的完整指南(Python 版)

2025年11月18日 221点热度 0人点赞 2条评论

在 AI 智能体开发中,工具调用的标准化是提升效率的关键。MCP(Model Context Protocol,模型上下文协议)作为连接大模型与外部工具的通用标准,让开发者能快速构建可复用、跨平台的 AI 工具。本文将从协议原理、环境搭建、工具开发、调试部署到生态扩展,全方位拆解 MCP 的开发流程,补充详细的技术细节、错误处理和进阶技巧,帮你轻松打造自己的第一个 MCP 工具。

一、MCP 协议核心解析:为什么需要标准化工具协议?

1. MCP 的本质与价值

MCP 是一套规范大模型与外部工具交互的协议,核心作用是作为“中间层”,让大模型通过统一格式调用各类工具(API、本地程序、硬件设备等)。其核心价值在于:

  • 标准化交互:统一工具描述、参数格式、通信方式,避免不同工具的适配成本;
  • 跨平台兼容:支持 STDIO(本地调用)和 SSE(远程调用)两种传输方式,适配本地开发与云端部署;
  • 生态复用:开发的 MCP 工具可无缝接入支持 MCP 协议的 AI 客户端(如 Cherry Studio、Cursor 等),无需重复适配。

2. 两种传输方式对比(实战选型指南)

传输方式 核心原理 优势 劣势 适用场景
STDIO 大模型通过标准输入/输出与 MCP 工具通信 无需网络、延迟低、配置简单 仅支持本地调用、不支持多客户端共享 本地开发调试、单机工具调用
SSE 基于 HTTP 协议的服务器推送,大模型通过网络调用 MCP 服务 支持远程调用、多客户端共享 需部署服务器、有网络依赖 团队协作、云端工具服务

3. MCP 工具的核心组成

一个完整的 MCP 工具包含三部分:

  • 工具函数:实现具体功能(如网页搜索、数据计算),需添加类型注解和功能描述;
  • 协议封装:通过 MCP SDK 暴露工具,遵循协议格式;
  • 通信模块:处理 STDIO 或 SSE 传输,负责与大模型的消息交互。

二、开发环境搭建:从工具安装到项目初始化

1. 核心工具选型与安装

(1)Python 环境管理:uv(替代 pip+virtualenv)

uv 是 Rust 编写的 Python 环境管理工具,具有依赖解析快、安装高效的优势,是 MCP 开发的首选工具:

# macOS/Linux 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows 安装(PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# 验证安装
uv --version  # 输出 uv x.y.z 即成功

(2)Python 版本选择

MCP 协议推荐使用 Python 3.10+,本文以 Python 3.13.7 为例:

# 安装指定版本 Python
uv python install 3.13.7

# 查看已安装 Python 版本
uv python list

2. 项目初始化流程

(1)创建项目并初始化

# 初始化 MCP 项目(指定 Python 版本)
uv init mcp-web-search -p 3.13
cd mcp-web-search

# 创建并激活虚拟环境
uv venv
# Windows 激活
.venv\Scripts\activate.bat
# macOS/Linux 激活
source .venv/bin/activate

# 安装核心依赖
uv add "mcp[cli]"  # MCP 核心 SDK
uv add httpx  # HTTP 请求库(用于调用外部 API)
uv add python-dotenv  # 环境变量管理
uv add openai  # 可选,用于大模型交互测试
uv add logging  # 日志管理

(2)项目结构说明

初始化后项目核心文件:

mcp-web-search/
├── .env              # 环境变量配置(存储 API Key 等敏感信息)
├── pyproject.toml    # 项目依赖与配置
├── .venv/            # 虚拟环境
└── web_search.py     # MCP 工具核心代码

(3)VS Code 开发配置

为提升开发效率,推荐安装以下插件:

  • Python:核心开发支持;
  • Python Debugger:调试工具;
  • DotENV:.env 文件语法高亮;
  • Pylance:类型提示与语法检查。

三、实战开发:打造多功能 MCP 工具

本文将开发一个包含“网页搜索”“数值计算”“主机信息查询”三大功能的 MCP 工具,覆盖 API 调用、本地系统交互、错误处理等核心场景。

1. 环境变量配置(敏感信息管理)

创建 .env 文件,存储 API Key 等敏感信息(避免硬编码):

# .env 文件内容
ZHI_PU_AI_API_KEY=你的智谱 AI API Key  # 用于网页搜索功能

2. 核心代码实现(web_search.py)

import httpx
import json
import os
import logging
import platform
from dotenv import load_dotenv
from mcp.server import FastMCP

# 1. 初始化配置
# 加载环境变量
load_dotenv()
# 配置日志(便于调试)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger("mcp-web-search")

# 2. 初始化 MCP 服务器(服务名称:web-search)
app = FastMCP("web-search")

# 3. 验证敏感配置
ZHI_PU_API_KEY = os.getenv("ZHI_PU_AI_API_KEY")
if not ZHI_PU_API_KEY:
    logger.error("未配置 ZHI_PU_AI_API_KEY 环境变量")
    raise ValueError("请在 .env 文件中配置 ZHI_PU_AI_API_KEY")

# 4. 工具函数 1:网页搜索(调用智谱 AI 网页搜索 API)
@app.tool()
async def web_search(query: str) -> str:
    """
    搜索互联网最新信息,支持各类公开内容查询(如新闻、知识、数据)
    :param query: 搜索关键词(如"2025 年 AI 发展趋势")
    :return: 搜索结果的结构化总结(多个结果用三个换行分隔)
    """
    async with httpx.AsyncClient(timeout=30.0) as client:
        try:
            # 构建请求参数
            request_data = {
                "tool": "web-search-pro",
                "messages": [{"role": "user", "content": query}],
                "stream": False
            }
            # 发送请求
            response = await client.post(
                url="https://open.bigmodel.cn/api/paas/v4/tools",
                headers={"Authorization": ZHI_PU_API_KEY},
                json=request_data
            )
            # 处理 HTTP 错误(非 200 状态码抛出异常)
            response.raise_for_status()
            response_json = response.json()

            # 解析搜索结果
            search_results = []
            for choice in response_json.get("choices", []):
                tool_calls = choice.get("message", {}).get("tool_calls", [])
                for tool_call in tool_calls:
                    result_list = tool_call.get("search_result", [])
                    for result in result_list:
                        content = result.get("content", "")
                        if content.strip():
                            search_results.append(content)

            # 无结果处理
            if not search_results:
                return "未找到相关搜索结果,请尝试调整关键词"
            return "\n\n\n".join(search_results)

        except httpx.HTTPStatusError as e:
            error_msg = f"HTTP 错误:状态码 {e.response.status_code},内容:{e.response.text[:200]}"
            logger.error(error_msg)
            return f"网页搜索失败:{error_msg}"
        except httpx.RequestError as e:
            error_msg = f"网络请求失败:{str(e)}"
            logger.error(error_msg)
            return f"网页搜索失败:{error_msg}"
        except json.JSONDecodeError as e:
            error_msg = f"响应解析失败:{str(e)}"
            logger.error(error_msg)
            return f"网页搜索失败:{error_msg}"
        except Exception as e:
            logger.exception("网页搜索发生未知错误")
            return f"网页搜索失败:未知错误 - {str(e)}"

# 5. 工具函数 2:数值加法(本地计算工具)
@app.tool()
def add(a: int, b: int) -> int:
    """
    计算两个整数的和,支持正负整数运算
    :param a: 第一个整数
    :param b: 第二个整数
    :return: 两个整数的和
    """
    try:
        result = a + b
        logger.info(f"加法运算:{a} + {b} = {result}")
        return result
    except Exception as e:
        logger.error(f"加法运算失败:{str(e)}")
        raise ValueError(f"计算失败:{str(e)}")

# 6. 工具函数 3:获取主机信息(本地系统工具)
@app.tool()
def get_host_info() -> str:
    """
    获取当前主机的系统信息,包括操作系统、硬件架构等
    :return: 结构化的主机信息(JSON 字符串格式)
    """
    try:
        host_info = {
            "操作系统": platform.system(),
            "主机名": platform.node(),
            "系统版本": platform.release(),
            "内核版本": platform.version(),
            "硬件架构": platform.machine(),
            "处理器": platform.processor() or "未知"
        }
        # 格式化 JSON 输出(便于大模型解析)
        return json.dumps(host_info, ensure_ascii=False, indent=4)
    except Exception as e:
        logger.error(f"获取主机信息失败:{str(e)}")
        return f"获取主机信息失败:{str(e)}"

# 7. 启动 MCP 服务(默认 STDIO 传输)
if __name__ == "__main__":
    logger.info("MCP 工具服务启动中...")
    # 支持通过命令行参数指定传输方式(如 --transport sse)
    app.run(transport="stdio")

3. 关键代码解析(MCP 开发核心规范)

(1)工具函数编写规范

  • 功能描述:函数文档字符串(docstring)必须清晰,大模型通过该描述判断工具用途;
  • 类型注解:参数和返回值必须添加类型注解(如 query: str),帮助大模型精准传参;
  • 错误处理:每个工具函数需捕获异常并返回友好提示,避免服务崩溃;
  • 装饰器:
    • @app.tool():用于有副作用的工具(如 API 调用、数据修改);
    • @app.resource():用于只读工具(如数据查询),类比 HTTP 的 GET 方法(本文暂未使用)。

(2)敏感信息管理

  • 优先使用 python-dotenv 加载环境变量,避免硬编码 API Key;
  • 生产环境可将环境变量配置在系统中(如 Linux 的 ~/.zshrc),提升安全性。

四、调试与测试:确保 MCP 工具可用

1. 本地调试(STDIO 传输)

(1)直接运行测试

# 启动 MCP 工具(STDIO 模式)
uv run web_search.py

启动后,工具会等待大模型的输入,可通过 MCP 调试工具发送测试请求。

(2)使用 MCP Inspector 调试

MCP 官方提供调试工具,可快速验证工具功能:

# 安装 MCP Inspector(需 Node.js 20+)
npm install -g @modelcontextprotocol/inspector

# 启动调试
mcp-inspector uv run web_search.py
  • 打开调试界面后,可选择工具函数(如 web_search),输入参数并执行,查看返回结果;
  • 调试过程中,日志会实时输出,便于定位问题。

2. 接入 AI 客户端(Cherry Studio 示例)

(1)配置步骤

  1. 打开 Cherry Studio,进入「设置」→「MCP 服务器」;
  2. 点击「添加 MCP」,配置项目路径和启动命令:
    • 目录:选择 mcp-web-search 项目根目录;
    • 启动命令:uv run web_search.py;
  3. 点击「启动」,若右上角无红色警告,说明连接成功。

(2)功能验证

在 Cherry Studio 中输入自然语言指令,测试工具调用:

  • 测试加法:“计算 123 + 456”(应调用 add 工具);
  • 测试网页搜索:“2025 年 Python 最新特性”(应调用 web_search 工具);
  • 测试主机信息:“显示当前电脑的系统信息”(应调用 get_host_info 工具)。

五、进阶部署:支持远程调用(SSE 传输)

若需让团队共享 MCP 工具,可部署为 SSE 服务,支持远程调用:

1. 修改启动方式(SSE 模式)

修改 web_search.py 的启动代码,支持指定传输方式和端口:

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="MCP 工具服务(支持 STDIO/SSE)")
    parser.add_argument("--transport", default="stdio", choices=["stdio", "sse"], help="传输方式")
    parser.add_argument("--host", default="0.0.0.0", help="SSE 服务绑定地址")
    parser.add_argument("--port", default=8000, type=int, help="SSE 服务端口")
    args = parser.parse_args()

    logger.info(f"MCP 服务启动:传输方式={args.transport},端口={args.port}")
    if args.transport == "sse":
        app.run(transport="sse", host=args.host, port=args.port)
    else:
        app.run(transport="stdio")

2. 启动 SSE 服务

# 启动 SSE 服务(绑定 8000 端口)
uv run web_search.py --transport sse --port 8000

3. 远程调用配置

AI 客户端需通过 HTTP 地址连接 SSE 服务:

  • 服务地址:http://你的服务器IP:8000/mcp;
  • 配置方式:在 AI 客户端的 MCP 设置中,选择「SSE 传输」,输入服务地址即可。

4. 生产环境优化

  • 端口开放:防火墙开放 8000 端口(或自定义端口);
  • 进程守护:使用 nohup 或 systemd 确保服务后台运行;
  • 日志持久化:将日志输出到文件,便于问题排查;
  • 权限控制:添加 API Key 验证,防止未授权访问。

六、MCP 生态扩展:工具发布与复用

1. 工具发布(供他人复用)

(1)本地工具发布(STDIO 模式)

  • Python 项目:通过 PyPI 发布,他人可通过 pip install 安装后直接运行;
  • Node.js 项目:通过 npm 发布,他人可通过 npx 快速调用。

(2)云端服务发布(SSE 模式)

  • 部署到云服务器(如阿里云、腾讯云),提供公开访问地址;
  • 注册到 MCP 工具市场(如 Anthropic MCP Hub),供全球开发者使用。

2. 常用 MCP 开发技巧

  • 工具组合:多个 MCP 工具可组合使用(如“网页搜索 + 数据处理 + 报告生成”);
  • 参数校验:使用 Pydantic 增强参数校验(如字符串长度、数值范围限制);
  • 性能优化:高频工具添加缓存(如 lru_cache),减少重复计算或 API 调用;
  • 多语言支持:MCP 支持 Python、Node.js 等多种语言,可根据场景选择开发语言。

七、常见问题与故障排查

1. 环境变量加载失败

  • 原因:.env 文件路径错误、变量名称拼写错误;
  • 解决方案:
    • 确保 .env 文件在项目根目录;
    • 使用 print(os.getenv("ZHI_PU_AI_API_KEY")) 验证变量是否加载。

2. MCP 服务启动失败

  • 原因:依赖未安装、Python 版本不兼容、端口被占用;
  • 解决方案:
    • 重新安装依赖:uv install;
    • 确认 Python 版本 ≥3.10;
    • SSE 模式端口被占用时,更换端口(如 --port 8001)。

3. 大模型无法调用工具

  • 原因:工具描述不清晰、类型注解缺失、传输方式不匹配;
  • 解决方案:
    • 完善函数文档字符串,明确工具用途;
    • 确保所有参数和返回值添加类型注解;
    • 确认 AI 客户端的传输方式与 MCP 服务一致(STDIO/SSE)。

4. 网页搜索返回失败

  • 原因:API Key 无效、网络问题、API 接口变更;
  • 解决方案:
    • 验证 API Key 有效性,重新申请或刷新;
    • 检查网络是否能访问智谱 AI API;
    • 参考官方文档,确认接口参数是否变更。

八、总结:MCP 开发的核心价值与未来方向

MCP 协议的核心优势在于“标准化”与“复用性”——一次开发,可在所有支持 MCP 的 AI 客户端中使用,无需重复适配。本文开发的 MCP 工具覆盖了 API 调用、本地计算、系统交互三大典型场景,可直接用于日常开发、智能体搭建等场景。

未来,MCP 生态将进一步完善,支持更多传输方式(如 gRPC)、多模态工具(如语音、图像处理)和权限控制机制。作为开发者,掌握 MCP 协议能让你在 AI 工具开发中抢占先机,打造可复用、高兼容的工具产品。

如果你想进一步扩展工具功能(如添加文件处理、数据库查询),或需要部署为高可用的云端服务,不妨尝试本文的进阶技巧,或探索 MCP 官方 SDK 的更多高级特性。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/ren-gong-zhi-neng/4582

相关文章

  • AI Agent 扩展双雄:MCP 与 Agent Skill 深度拆解——从设计哲学到实战落地
  • 6款核心MCP协议工具让AI深度融入业务,告别“纸上谈兵”
  • 驾驭Claude的进阶之道:从对话工具到生产力中枢的10大高级技巧
  • 企业级自动化 Agent 架构深析:Prompt 演进驱动的智能工作流落地
  • 工程师专属 AI 自学路线:从入门到实战,避开90%的坑(2025 最新版)
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: AI智能体 MCP Python
最后更新:2025年11月18日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • 彬红茶青铜友

    👍我们社团好像教,但是不多😂😂

    Windows
    Chrome 116.0.0.0 中国-广东
    2025年12月6日
    回复
    • 李锋镝管理

      @彬红茶 基本都是教的入门,更多的还得自学

      macOS
      Chrome 142.0.0.0 中国-北京
      2025年12月6日
      回复
  • 1 2 3 4 5 6 7 8 9 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 57 58 60 61 62 63 64 65 66 67 69 72 74 76 77 78 79 80 81 82 85 86 87 90 92 93 94 95 96 97 98 99
    取消回复

    寻寻觅觅,冷冷清清,凄凄惨惨戚戚。乍暖还寒时候,最难将息。三杯两盏淡酒,怎敌他、晚来风急!雁过也,正伤心,却是旧时相识。
    满地黄花堆积,憔悴损,如今有谁堪摘?守着窗儿,独自怎生得黑!梧桐更兼细雨,到黄昏、点点滴滴。这次第,怎一个愁字了得!

    那年今日(01月25日)

    • 1979年:中国左翼文学运动开创者之一郑伯奇逝世
    • 1949年:日本帝国时期的政治家牧野伸显逝世
    • 1924年:第一届奥林匹克冬季运动会在夏蒙尼开幕
    • 1911年:中国第一部专门刑法典颁布
    • 1504年:意大利艺术家米开朗基罗完成大卫雕像
    • 更多历史事件
    最新 热点 随机
    最新 热点 随机
    AI时代,个人技术博客的出路在哪里? 什么是Meta Server? 千万级大表新增字段实战指南:告别锁表与业务中断 在 SQL 中做范围查询时,使用 BETWEEN AND 和直接用 >/=/ 深度解析 Disruptor:无锁队列的高性能实现与实践 精通Linux根目录:核心文件夹深度解析与实战指南
    玩博客的人是不是越来越少了?准备入手个亚太的ECS,友友们有什么建议吗?AI时代,个人技术博客的出路在哪里?使用WireGuard在Ubuntu 24.04系统搭建VPNWordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了
    基于Java8的Either类 居家办公了~ 祝大家六一儿童节快乐~~~ IntelliJ IDEA 2020.3.x永久白嫖(Windows/Mac) 看病难~取药难~~ 睡觉睡不踏实
    标签聚合
    WordPress K8s 分布式 AI编程 多线程 设计模式 JAVA ElasticSearch Redis SpringBoot JVM SQL AI docker IDEA 架构 MySQL 日常 数据库 Spring
    友情链接
    • Blogs·CN
    • Honesty
    • Mr.Sun的博客
    • 临窗旋墨
    • 哥斯拉
    • 彬红茶日记
    • 志文工作室
    • 懋和道人
    • 搬砖日记
    • 旧时繁华
    • 林羽凡
    • 瓦匠个人小站
    • 皮皮社
    • 知向前端
    • 蜗牛工作室
    • 韩小韩博客
    • 风渡言

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    域名年龄

    Theme Kratos Made By Dylan

    津ICP备2024022503号-3

    京公网安备11011502039375号