李锋镝的博客

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

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

2025年11月18日 402点热度 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
    取消回复

    愿将腰下剑,直为斩楼兰。

    那年今日(04月20日)

    • 1971年:中国著名法学家周鲠生逝世
    • 1901年:著名建筑学家梁思成出生于日本东京,祖籍广东新会
    • 1889年:德国纳粹党元首希特勒出生于奥地利布劳瑙
    • 1808年:法兰西第二帝国皇帝拿破仑出生
    • 429年:中国古代数学家祖冲之出生
    • 更多历史事件
    最新 热点 随机
    最新 热点 随机
    Everything Claude Code 详细使用文档 配置Jackson使用字段而不是getter/setter来序列化和反序列化 这个域名注册整整十年了,十年时间,真快啊 Claude Code全维度实战指南:从入门到精通,解锁AI编程新范式 Apollo配置中心中的protalDB的作用是什么 org.apache.ibatis.plugin.Interceptor类详细介绍及使用
    AI时代,个人技术博客的出路在哪里?使用WireGuard在Ubuntu 24.04系统搭建VPN这个域名注册整整十年了,十年时间,真快啊WordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了做了一个WordPress文章热力图插件
    使用WireGuard在Ubuntu 24.04系统搭建VPN 为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案? 妹妹的画【2019.07.03】 jmap命令(jdk1.8) 我要狠狠的反驳“公司禁止使用 Lombok ”的观点! Java之五种遍历Map集合的方式
    标签聚合
    SpringBoot 多线程 分布式 AI docker 数据库 AI编程 ElasticSearch Redis Spring JVM 设计模式 WordPress IDEA SQL JAVA 架构 日常 MySQL K8s
    友情链接
    • Blogs·CN
    • Honesty
    • Mr.Sun的博客
    • 临窗旋墨
    • 哥斯拉
    • 彬红茶日记
    • 志文工作室
    • 懋和道人
    • 拾趣博客导航
    • 搬砖日记
    • 旧时繁华
    • 林羽凡
    • 瓦匠个人小站
    • 皮皮社
    • 知向前端
    • 蜗牛工作室
    • 韩小韩博客
    • 风渡言

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    域名年龄

    Theme Kratos Made By Dylan

    津ICP备2024022503号-3

    京公网安备11011502039375号