news 2026/6/11 1:23:54

从零开发MCP插件:手把手构建你的第一个AI工具服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零开发MCP插件:手把手构建你的第一个AI工具服务

引言

大语言模型(LLM)的能力已经不仅仅局限于对话,越来越多的AI应用需要与外部工具、API和数据源交互。但长期以来,让模型调用自定义工具的过程充满碎片化——每个平台都有自己的函数调用格式,开发者不得不为 ChatGPT、Claude、开源模型分别实现不同的适配逻辑。

Anthropic 推出的Model Context Protocol(MCP)正在改变这一局面。它提供了一套开放标准,让 AI 应用能够通过统一的协议发现和调用工具,无论是本地脚本、远程 API 还是数据库查询,都可以被封装成 MCP 插件(MCP Server)。这意味着你只需编写一次工具,就可以被任何支持 MCP 的客户端(如 Claude Desktop、VS Code 扩展)直接使用。

本文将以实战为导向,带你从零开发一个完整的 MCP 插件。我们会先理解 MCP 的核心架构,然后用 Python 编写一个可运行的天气查询插件,最后探讨生产环境中的常见问题与最佳实践。读完你会发现,构建一个 MCP 插件比你想象的要简单得多。

核心概念:MCP 是如何工作的?

在动手编码前,有必要先理清 MCP 的几个关键角色和通信方式。

MCP 的基本架构

MCP 采用经典的客户端-服务器模型,但针对 AI 场景进行了优化:

  • MCP Host:运行 AI 模型的主程序,比如 Claude Desktop、IDE 插件。
  • MCP Client:运行在 Host 内部的协议客户端,负责与 MCP Server 建立连接、管理生命周期。
  • MCP Server:你将要开发的插件,它对外暴露一组工具(Tools)、资源(Resources)、提示词(Prompts)。

其中,工具(Tool)是 MCP 中最常用的概念,对应一个可以被模型调用的具体功能(例如get_weather)。当用户向 AI 询问“北京今天天气怎么样?”,Host 会通过 MCP Client 请求 Server,Server 执行工具并返回结果,LLM 再将结果组织成自然语言回复。

两种传输方式

MCP 支持两种底层传输协议:

  1. stdio(标准输入/输出):Server 作为子进程启动,通过标准 I/O 与 Client 通信。适合本地开发、个人工具。
  2. SSE(Server-Sent Events):基于 HTTP,支持远程 Server,允许多个 Client 共享。适合团队或生产环境。

本文的示例将使用 stdio 传输,因为它零配置、最适合快速上手。

工具定义的要素

一个 MCP 工具需要包含以下信息:

  • 名称:唯一标识,如get_weather
  • 描述:自然语言说明,模型会依据描述决定何时调用
  • 输入参数:JSON Schema 定义,包含参数名、类型、是否必填等
  • 执行逻辑:具体的业务代码,返回字符串或结构化数据

清楚了这些之后,我们立刻开始实战。

实战示例:开发一个天气查询 MCP 插件

环境准备

确保你的开发环境满足以下条件:

  • Python 3.10 或更高版本
  • pip 包管理器
  • 一个支持 MCP 的客户端用于测试,推荐使用官方 MCP Inspector 或 Claude Desktop

(如果你还没有 Claude Desktop,可以先用 Inspector 完成测试,安装方法后面会介绍。)

第一步:安装 MCP Python SDK

Anthropic 提供了官方 Python SDKmcp,它内置了FastMCP高层封装,让我们可以像写普通函数一样定义工具。

打开终端,创建项目目录并安装依赖:

mkdir weather-mcp-server cd weather-mcp-server python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install mcp

此时你的环境中就拥有了开发 MCP 插件的全部能力。

第二步:编写 Server 代码

新建文件weather_server.py,输入以下完整代码:

from mcp.server.fastmcp import FastMCP # 初始化 FastMCP 实例,参数为插件名称 mcp = FastMCP("Weather") # 使用 @mcp.tool() 装饰器定义工具 @mcp.tool() def get_weather(city: str) -> str: """ 获取指定城市的天气信息。 参数 city: 城市名称,例如 北京、上海。 """ # 模拟天气数据,实际项目中可以调用天气 API weather_data = { "北京": "晴,气温 25°C,湿度 40%", "上海": "多云转阴,气温 28°C,湿度 65%", "深圳": "阵雨,气温 30°C,湿度 80%", "纽约": "晴,气温 22°C,湿度 55%", } result = weather_data.get(city) if result is None: return f"抱歉,未找到城市“{city}”的天气信息" return f"{city}天气:{result}" if __name__ == "__main__": # 启动服务器,默认使用 stdio 传输 mcp.run()

代码说明:

  • FastMCP("Weather")创建了一个名为Weather的 MCP Server,它将被客户端识别。
  • @mcp.tool()将下方的函数注册为一个工具。函数名get_weather自动成为工具名。
  • 函数文档字符串(docstring)会作为工具的描述信息,模型依赖该描述理解工具功能。
  • 参数city: str定义了输入模式,MCP SDK 会自动生成 JSON Schema,无需手动编写。
  • 主程序入口调用mcp.run()启动 stdio 服务器,监听来自客户端的请求。

这就是一个完整的 MCP 插件!没有复杂的配置,没有额外的注册步骤,你只需专注业务逻辑。

第三步:测试你的插件

使用 MCP Inspector 测试

MCP Inspector 是官方提供的调试工具,可以图形化地测试本地的 MCP Server。

首先全局安装 Inspector:

npx @modelcontextprotocol/inspector

(需要 Node.js 环境,如果没有请先安装。)

启动 Inspector 并连接到你的 Server:

npx @modelcontextprotocol/inspector python weather_server.py

浏览器会自动打开 http://localhost:5173,你将看到一个交互界面:
- 左侧列出了检测到的工具get_weather
- 点击工具,填写参数{"city": "北京"},点击执行
- 右侧会显示返回的结果

看到预期的天气信息,说明你的插件工作正常。

集成到 Claude Desktop

如果你安装了 Claude Desktop(目前支持 macOS 和 Windows),可以通过配置文件将我们的插件加入。

找到 Claude Desktop 的配置文件:
- macOS:~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:%APPDATA%\Claude\claude_desktop_config.json

如果没有该文件,手动创建一个。加入以下内容:

{ "mcpServers": { "weather": { "command": "python", "args": ["/你的路径/weather_server.py"] } } }

将路径替换为你的weather_server.py绝对路径。重启 Claude Desktop,然后尝试在对话中输入:“北京今天天气怎么样?”,模型会自动调用get_weather工具并给出回复。

进阶:开发一个支持异步和错误处理的生产级插件

上面的示例虽然能跑,但在真实项目中你可能需要调用外部 HTTP API、处理超时、优雅地返回错误。下面展示一个更健壮的版本,它使用httpx异步请求真实天气 API(以 OpenWeatherMap 为例,你需要注册获取 API Key)。

安装额外依赖:

pip install httpx python-dotenv

创建weather_pro_server.py

import os import httpx from mcp.server.fastmcp import FastMCP from dotenv import load_dotenv load_dotenv() # 加载 .env 中的 API_KEY mcp = FastMCP("WeatherPro") @mcp.tool() async def get_weather(city: str, units: str = "metric") -> str: """ 获取指定城市的实时天气数据。 city: 城市名,支持英文如 Beijing、London units: 温度单位,metric(摄氏度) 或 imperial(华氏度) """ api_key = os.getenv("OPENWEATHER_API_KEY") if not api_key: return "错误:未配置天气 API Key,请在 .env 文件中设置 OPENWEATHER_API_KEY" url = "https://api.openweathermap.org/data/2.5/weather" params = { "q": city, "appid": api_key, "units": units, "lang": "zh_cn" } try: async with httpx.AsyncClient(timeout=10.0) as client: resp = await client.get(url, params=params) resp.raise_for_status() data = resp.json() desc = data["weather"][0]["description"] temp = data["main"]["temp"] humidity = data["main"]["humidity"] return f"{city}天气:{desc},温度{temp}°,湿度{humidity}%" except httpx.HTTPStatusError as e: if e.response.status_code == 404: return f"城市“{city}”未找到" return f"API 请求失败,状态码:{e.response.status_code}" except Exception as e: return f"获取天气时发生异常:{str(e)}" if __name__ == "__main__": mcp.run()

这个版本展示了:
-异步工具:函数声明为async def,MCP SDK 原生支持异步执行,不会阻塞其他请求。
-环境变量管理:使用.env存储敏感信息,避免硬编码。
-结构化错误处理:针对 HTTP 错误、城市未找到、超时等情况返回有意义的提示,而不是抛出异常让客户端报错。

常见问题与注意事项

1. 工具函数的类型提示是必须的吗?

强烈建议加上。MCP SDK 会利用 Python 的类型注解自动生成 JSON Schema。如果不加类型提示,所有参数都会被当作any类型,客户端无法正确校验参数,模型的调用准确性也会下降。

2. 如何调试错误?

  • 查看 Server 的 stderr 输出:当使用 stdio 传输时,打印到sys.stderr的信息会显示在启动它的终端或客户端日志中。因此建议使用logging模块输出到 stderr。
  • 使用 MCP Inspector:它会在页面上显示任何工具执行时抛出的异常。
  • 增加详细的返回值:在开发阶段,让工具返回更详细的错误信息,帮助快速定位问题。

3. 可以选择 SSE 传输替代 stdio 吗?

可以。如果你的工具需要部署到服务器并被多个客户端远程调用,使用 SSE 更合适。修改方式很简单,将mcp.run()替换为:

mcp.run(transport="sse", host="0.0.0.0", port=8000)

然后客户端通过http://your-server:8000/sse连接。注意 SSE 需要处理跨域和鉴权,生产环境下建议在前面加一层反向代理(如 Nginx)。

4. 如何限制工具的调用权限?

MCP 协议本身不提供细粒度的权限模型。安全控制通常在这些层面实现:
- 在 Server 内部检查调用来源或进行用户认证(例如通过自定义 Header)。
- 如果你使用 Claude Desktop 等 Host,确保配置文件中的 command 和 args 都是安全可信的,防止任意代码执行。
- 对于敏感操作(如删除文件、执行命令),在工具内再次要求用户确认或记录审计日志。

5. 工具可以返回图片、文件等非文本内容吗?

MCP 资源(Resources)专门用于暴露文件、图片、数据库表等结构化内容。工具通常返回文本,但资源可以返回二进制数据。你可以同时暴露工具和资源,让模型根据需求选择调用。示例:

from mcp.server.fastmcp import FastMCP from mcp.types import Resource mcp = FastMCP("ImageProvider") @mcp.resource("image://{filename}") def get_image(filename: str) -> bytes: with open(f"./images/{filename}", "rb") as f: return f.read()

资源定义使用mcp.resource()装饰器,路径可以是 URI 模板。

总结

通过本文,我们完整地走过了从概念到代码的 MCP 插件开发流程。你学到了:

  • MCP 的客户端-服务器架构及 stdio、SSE 两种传输方式
  • 使用 FastMCP 定义工具、资源和异步处理
  • 用 MCP Inspector 和 Claude Desktop 进行测试
  • 生产环境中处理错误、安全、远程部署的注意事项

MCP 正在成为 AI Agent 与外部世界交互的“USB 接口”,越来越多的工具和平台开始原生支持。现在,你可以将任何 Python 函数封装成标准化的 MCP 工具,无论是本地脚本、企业内部 API 还是云端服务,都能无缝接入 AI 工作流。

下一步,你可以尝试将手头常用的脚本(数据库查询、文件操作、通知推送)改造成 MCP 插件,或者为团队开发一套标准化的研发工具集。整个协议是开放的,生态也在快速成长,早一步掌握 MCP 开发,就能早一步享受到统一接口带来的效率红利。

完整代码已同步在 GitHub Gist,欢迎取用并部署你的第一个 MCP 插件!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 1:23:53

七、LLM 基础设施层与提供商抽象:智能客服系统的模型接入统一架构

在智能客服问答系统中,LLM(大语言模型)是核心推理引擎。然而,现实中的 LLM 服务生态碎片化严重——OpenAI、Anthropic、DeepSeek、Ollama 本地模型各有不同的 API 格式、认证方式和能力边界。本文深入解析一个智能问答系统的 LLM …

作者头像 李华
网站建设 2026/6/11 1:20:53

Whisper-WebUI完整配置指南:构建专业级语音转字幕平台

Whisper-WebUI完整配置指南:构建专业级语音转字幕平台 【免费下载链接】Whisper-WebUI A Web UI for easy subtitle using whisper model. 项目地址: https://gitcode.com/gh_mirrors/wh/Whisper-WebUI Whisper-WebUI是一个基于OpenAI Whisper模型的Web界面工…

作者头像 李华
网站建设 2026/6/11 1:17:52

GetQzonehistory:3步实现QQ空间历史数据完整备份的智能解决方案

GetQzonehistory:3步实现QQ空间历史数据完整备份的智能解决方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字时代,个人社交数据已成为珍贵的数字遗产&a…

作者头像 李华
网站建设 2026/6/11 1:12:51

深入解析MC9S12XF内存映射控制(MMC):原理、配置与实战调试

1. 项目概述与核心价值在嵌入式系统开发,尤其是汽车电子和工业控制这类对实时性、可靠性和安全性要求极高的领域,微控制器(MCU)的内存管理绝非小事。它直接关系到程序的执行效率、多任务间的数据隔离、调试的便利性,乃…

作者头像 李华
网站建设 2026/6/11 1:12:51

2025 年华为发布鸿蒙 PC,SolonCode 无需适配即可兼容运行!

鸿蒙 PC 发布:中国操作系统里程碑事件2025 年,华为在成都正式发布搭载 HarmonyOS 5 的鸿蒙 PC----MateBook Pro 与 MateBook Fold 非凡大师。这标志着鸿蒙生态从手机、平板、手表正式延伸到桌面 computing 领域,中国自主操作系统迈出了关键一…

作者头像 李华