李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 左邻右舍
  • 博友圈
  • 关于我
    • 关于我
    • 另一个网站
    • 我的导航站
    • 网站地图
    • 赞助
  • 留言
  • 走心评论
  • 系列文章
  • Now
  • 每日心情
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. AI
  3. 正文

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

2025年11月18日 约 3,699 字13 分钟 44点热度 0人点赞 2条评论
本文最后更新于 2025年11月18日,距今已 263 天,其中的信息可能已经发生变化,请注意甄别。

在 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日

岁月同一天 8 月 9 日

回望过去的今天,你在写什么

  • 4 年前 2022年8月9日
    RocketMQ的push消费方式实现详解

    MQ消费方式 消费方式就是指消费者如何从MQ中获取到消息,分为两种方式,push(推方式)和pull(拉方式)。 1、p…

相关文章
  • 6款核心MCP协议工具让AI深度融入业务,告别“纸上谈兵”2025年12月11日
  • MCP深度解析:从协议本质到实战落地,彻底搞懂 AI 工具交互的标准化方案2025年11月11日
  • LangChain 1.0 智能体实战:MCP 协议赋能工具标准化调用(从开发到落地)2025年11月13日
  • 企业级自动化 Agent 架构深析:Prompt 演进驱动的智能工作流落地2025年12月1日
  • hnswlib installation failed2023年5月26日

李锋镝

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

打赏 点赞
< 上一篇
下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

  • 彬红茶Lv 2友

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

    WindowsChrome 116.0.0.0 中国-揭阳市
    2025年12月6日
    00 回复
    • 李锋镝管理

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

      macOSChrome 142.0.0.0 中国-北京市
      2025年12月6日
      00 回复
  • 文章合为时而著,歌诗合为事而作。

    听点儿音乐吧 朋友~
    文章目录
    最新 热点 随机
    最新 热点 随机
    Kratos+ v1.1.14版本更新说明 Spring Boot 指定外部配置文件的方式 Spring Boot 配置加载优先级总结 Claude Fable 5(claude-fable-5)深度详解 如何通过命令查看Java应用内存中对象数量 关于服务的探活端口和业务端口不一致有什么问题
    给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能AI时代,个人技术博客的出路在哪里?增加了两套复古皮肤-牛皮纸、千禧网页这个域名注册整整十年了,十年时间,真快啊WordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了
    使用RocketMQ时,服务启动过程中,Consumer在服务未启动时消费消息问题处理 JVM详细参数说明 Kratos+ —— Kratos 主题二次开发记录 MySQL语句执行顺序 一款开源的社交分享插件——share.js 笑死、腹肌……根本不可能有腹肌的~~
    最近评论
    老张博客 发布于 16 小时前(08月08日) 做的越来越精美了,好看。
    Huo 发布于 1 天前(08月07日) 挺有特色的主题,还是感觉 WP 的确是强大
    李锋镝 发布于 2 天前(08月07日) 没理解你想说啥
    aboss 发布于 2 天前(08月07日) 你的后台web-login?
    李锋镝 发布于 2 天前(08月07日) 这个专门的插件实现的功能更好更全,还能对接支付之类的
    标签聚合
    数据库 WordPress docker Claude JVM 分布式 日常 ElasticSearch K8s AI SpringBoot 架构 AI编程 Spring MySQL SQL JAVA 多线程 IDEA Redis
    友情链接
    • 志文工作室
    • 皮皮社
    • Mr.Sun的博客
    • 风渡言
    • 韩小韩博客
    • 搬砖日记
    • 临窗旋墨
    • 知向前端
    • 哥斯拉
    • Blogs·CN
    • 瓦匠个人小站
    • 旧时繁华
    • 彬红茶日记
    • Honesty
    • 韩情脉脉
    • 林羽凡
    • 老张博客
    • 拾趣博客导航
    • 懋和道人

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    正在博友圈履约中

    域名年龄

    Theme Kratos+ By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号