当前位置: 首页 > news >正文

从零开发MCP插件:手把手实现AI天气助手工具

引言

如果你最近关注过AI工具生态,一定听说过MCP(Model Context Protocol)。这个由Anthropic推出的开放协议,为大语言模型和外部工具之间搭起了一座标准化的桥梁。借助MCP,AI助手不再只能依赖静态的训练数据,而可以实时调用你开发的插件——查询数据库、操作文件、访问API,甚至控制硬件设备。

本文将从零开始,带你一步步开发一个实用的MCP插件:一个天气查询工具。你将看到完整的Python代码、环境搭建过程以及调试技巧。读完本文,你不仅能拥有一个可运行的MCP服务器,还将理解MCP的核心概念,为开发更复杂的AI插件打下坚实基础。

所有代码均经过验证,可以直接复制运行。让我们现在开始。

核心概念:MCP的“三角关系”

在动手写代码之前,我们需要先理解MCP的体系结构。一个完整的MCP交互包含三个角色:

  1. MCP Host(宿主应用):例如Claude Desktop、VS Code插件等,这些应用内置了MCP客户端,负责与用户交互并调用工具。
  2. MCP Client(客户端):嵌入在Host中,负责与服务器建立连接、发送请求、接收结果。
  3. MCP Server(服务器/插件):我们即将开发的部分。它暴露一组工具(Tools)资源(Resources)提示(Prompts),供AI模型发现和调用。

在这个体系中,AI模型本身并不直接调用外部函数,而是通过以下流程:

  • AI模型生成一个“工具调用”请求(包含函数名和参数),交给客户端。
  • 客户端将此请求标准化,通过协议(stdio或SSE)发送给服务器。
  • 服务器执行对应的Python函数,并把结果返回给客户端。
  • 客户端将结果注入回模型的上下文中,模型据此生成最终回答。

因此,我们的工作就是实现一个MCP Server,定义一个或多个工具函数,并让它们能被AI安全地调用。

实战示例:开发天气查询MCP服务器

我们的目标是:当用户在Claude Desktop中询问“北京今天天气怎么样?”时,Claude能够自动调用我们的MCP插件,获取实时天气数据,并给出友好回答。

我们将使用FastMCP库,它是基于官方MCP SDK的高级封装,能极大简化服务器的创建。最终效果如下(在Claude Desktop中):

用户:杭州现在多少度?
Claude:[调用get_current_weather工具,参数:city="杭州"]
工具返回:杭州当前温度18°C,多云,湿度65%...
Claude:杭州现在的温度是18°C,多云,湿度65%,体感比较舒适。

1. 环境准备

首先确保你安装了Python 3.10+,然后创建项目并安装依赖:

mkdir mcp-weather-plugin cd mcp-weather-plugin python -m venv venv source venv/bin/activate # Windows用 venv\Scripts\activate pip install fastmcp==1.3.0 httpx python-dotenv

httpx用于异步HTTP请求,python-dotenv管理API密钥。我们将使用OpenWeatherMap的免费API,你需要先注册获取一个API key。当然,也可以换成任何其他天气API逻辑。

创建.env文件保存密钥:

OPENWEATHER_API_KEY=你的真实API密钥

2. 编写工具函数

新建weather.py,定义获取天气的异步函数:

import os import httpx from dotenv import load_dotenv load_dotenv() # 加载 .env 文件 API_KEY = os.getenv("OPENWEATHER_API_KEY") BASE_URL = "https://api.openweathermap.org/data/2.5/weather" async def fetch_weather(city: str) -> dict: """使用OpenWeatherMap API获取当前天气""" if not API_KEY: return {"error": "未配置API密钥,请检查 .env 文件"} params = { "q": city, "appid": API_KEY, "units": "metric", # 摄氏度 "lang": "zh_cn" # 中文描述 } async with httpx.AsyncClient() as client: try: resp = await client.get(BASE_URL, params=params, timeout=10.0) resp.raise_for_status() data = resp.json() except httpx.HTTPStatusError as e: return {"error": f"API请求失败:{e.response.status_code}"} except Exception as e: return {"error": f"请求异常:{str(e)}"} # 提取我们需要的信息 try: description = data["weather"][0]["description"] temp = data["main"]["temp"] feels_like = data["main"]["feels_like"] humidity = data["main"]["humidity"] wind_speed = data["wind"]["speed"] city_name = data["name"] result = { "城市": city_name, "天气": description, "温度(℃)": temp, "体感温度(℃)": feels_like, "湿度(%)": humidity, "风速(m/s)": wind_speed } return result except KeyError: return {"error": "未找到该城市信息,请检查城市名称"}

这段代码包含了错误处理和结构化输出,AI模型可以轻松提取其中的字段给用户。

3. 创建FastMCP服务器

新建server.py,使用FastMCP快速搭建服务器,并将上面的fetch_weather注册为工具:

#!/usr/bin/env python3 from fastmcp import FastMCP from weather import fetch_weather import json # 创建一个MCP服务器实例,命名为"Weather Assistant" mcp = FastMCP("Weather Assistant") # 注册工具:get_current_weather @mcp.tool() async def get_current_weather(city: str) -> str: """查询指定城市的实时天气情况 Args: city: 城市名称,支持中文或英文,例如 "北京" 或 "Beijing" """ weather_data = await fetch_weather(city) # 将字典转为格式化的JSON字符串,方便AI解析 return json.dumps(weather_data, ensure_ascii=False, indent=2) if __name__ == "__main__": # 以标准I/O方式启动服务器,这是桌面应用最常用的连接方式 mcp.run(transport="stdio")

这就是完整的MCP服务器!让我们剖析一下关键点:

  • FastMCP("Weather Assistant"):实例化时指定服务器名称,客户端会以此标识插件。
  • @mcp.tool()装饰器:将函数注册为MCP工具。函数名、参数列表和docstring自动成为工具的元数据,AI模型会据此理解工具的用途。
  • 工具函数必须异步,返回类型建议为str,因为客户端与服务器之间传递的是文本。我们使用json.dumps将字典序列化。
  • mcp.run(transport="stdio"):启动一个基于标准输入输出的服务器,这是MCP最常见的传输方式,Claude Desktop、Cursor等客户端支持通过stdio与子进程通信。

4. 配置Claude Desktop使用插件

启动服务器只是第一步,我们还需要让Claude Desktop知道它。编辑(或创建)Claude Desktop的配置文件:

  • macOS:~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json

添加如下配置项:

{ "mcpServers": { "weather": { "command": "python", "args": ["/完整路径/mcp-weather-plugin/server.py"], "env": { "OPENWEATHER_API_KEY": "你的API密钥" } } } }

注意:command可以指定为虚拟环境中的Python解释器,例如"venv/bin/python"env中直接注入环境变量,避免依赖.env文件。保存后完全退出并重启Claude Desktop。

检查是否成功:打开Claude Desktop,点击输入框左侧的🔌图标(或直接输入斜线/),你应该能看到可用的工具get_current_weather。如果出现,说明插件已加载成功。

5. 测试与交互

现在向Claude提问:“帮我查一下深圳现在的天气”,Claude会自动判断需要调用工具,并生成如下调用:

Tool: get_current_weather Arguments: {"city": "深圳"}

我们的服务器会执行函数,返回类似:

{ "城市": "深圳", "天气": "多云", "温度(℃)": 26.1, "体感温度(℃)": 27.3, "湿度(%)": 78, "风速(m/s)": 3.2 }

Claude据此回答:“深圳当前多云,气温26.1摄氏度,体感温度27.3度,湿度78%,风速3.2米每秒,出门记得带伞哦~”

你也可以测试未配置API密钥时的错误情况,会看到工具返回{"error": ...},Claude会友好地提示用户检查配置。

常见问题与注意事项

1. 服务器启动失败或工具不显示

  • 检查claude_desktop_config.json路径和格式是否正确,JSON必须合法。
  • 确保Python环境中有fastmcp及其依赖。最稳妥的方式是使用虚拟环境并指定完整Python路径。
  • 查看Claude Desktop的开发者控制台(macOS:Cmd+Option+I),Console面板会显示服务器连接错误日志。
  • 常见问题:Windows下路径分隔符需使用双反斜杠或正斜杠。

2. 传输方式选择

  • stdio:适合本地子进程,Claude Desktop、Continue等客户端采用这种方式。配置简单,无需网络。
  • SSE(Server-Sent Events):适用于远程服务器或多人共享的工具。需要监听HTTP端点。FastMCP也支持,只需将transport改为"sse"并指定端口。本文为简化演示使用stdio。

3. 安全与最佳实践

  • 不要在代码中硬编码API密钥,使用环境变量或配置文件注入。
  • 做好输入校验:我们的city参数直接传入API,虽然天气服务无害,但其他工具(如数据库操作)要防止注入。
  • 工具函数应设计为幂等且无副作用,除非明确需要写操作。
  • 返回信息要结构化(JSON),方便AI模型解析,同时对用户友好。

4. 调试工具

除了依赖Claude Desktop的日志,还可以使用官方的mcpCLI工具进行独立测试。安装pip install mcp,然后运行:

mcp dev server.py

这会启动一个交互式的校验器,你可以在命令行中模拟客户端调用工具,查看返回值。

5. 扩展思路

学会了天气查询,你可以举一反三:
- 写一个文件管理插件,让AI读写本地文件。
- 对接数据库,用自然语言进行SQL查询。
- 连接智能家居API,实现语音控制家电。

FastMCP还支持资源(提供文件内容、数据库表结构等上下文)和提示(可复用的对话模板),让你的插件功能更加立体。

总结

本文我们从零开始,完整实现了一个MCP天气查询插件。核心步骤包括:理解MCP的三层架构、用FastMCP编写工具函数、配置Claude Desktop作为宿主、以及调试排错。你收获的不仅仅是一个天气工具,更是一套开发任何MCP插件的通用流程。

MCP正在快速成长为AI应用的“USB-C接口”,它让各类工具和模型能够即插即用。现在就开始构建你的第一个MCP插件吧,让AI助手真正能为你做事。

完整代码已经准备好,你可以直接克隆这个GitHub仓库(替换为实际链接)或复制文中的代码动手实践。有任何问题欢迎在评论区交流,我会尽量回复。

写作不易,如果文章对你有帮助,欢迎点赞、收藏、关注,你的支持是我持续分享的最大动力。

http://www.jsqmd.com/news/1142739/

相关文章:

  • 医疗人工智能的Harness Engineering:面向安全、可控与合规的大模型系统工程(九)
  • python系列【仅供参考】:Selenium Grid入门详解
  • 禅道文件下载漏洞复现:从原理到RCE实战与安全加固
  • AI科技热点日报 | 2026年07月04日
  • 2026跨境电商独立站运营避坑:9个新手常踩的亏损陷阱及低成本获客实操技巧
  • 2026年AI应用开发外包公司选型榜单:D-coding与服务商评价维度解析
  • AzurLaneLive2DExtract:3步轻松提取碧蓝航线Live2D模型资源
  • 电子合同:数字化转型的最佳切入点
  • 7.6号学习记录
  • 2026红河黄金回收白银回收铂金回收旧料回收怎么选?五家高实价铂金白银线下门店测评清单 + 联系方式
  • 解放双手的72小时:Fate/Grand Automata如何重塑你的FGO游戏体验
  • 【小白友好】|OpenClaw 桌面数字员工搭建方案,无需手动配置 Python、Node 依赖(含安装包)
  • WarcraftHelper:魔兽争霸III终极兼容性优化完整解决方案
  • 黑苹果配置的终极简化方案:OpCore-Simplify让你15分钟完成专业级EFI配置
  • 深度解析OpenFace:多模态面部行为分析的架构设计与技术实现
  • FactoryBluePrints:5000+戴森球计划蓝图库,新手也能轻松建造宇宙工厂
  • 2026最新2款AI编程工具vibe coding深度对比实测
  • 央行沟通文本数据集
  • Google Colab 免费 GPU 性能实测:T4 vs L4 vs A100,3款GPU推理速度与成本对比
  • 单机建模卡顿运维繁琐!中小型机械制造厂云飞云 3D 云桌面落地
  • 金融交易系统网络测试:为什么你的“弱网测试“测不出交易系统的真实问题
  • 九个 JVM 垃圾回收器,一篇从头捋到尾
  • 【JAVA毕设源码分享】基于 Vue+SpringBoot 的养老服务平台设计与实现(程序+文档+代码讲解+一条龙定制)
  • 2026短视频矩阵服务商揭秘:这些核心优势你不可错过
  • 给 Agent 装“外挂“:Middleware 让我的代码开始像生产环境
  • 纽扣电池低功耗方案:NBM5100A与PIC18F4680优化设计
  • 多参数水质在线监测设备—水环境实时管控解决方案
  • 工程经营管理软件怎么选型,统筹营收成本回款规避项目经营亏损
  • GitHub热榜开源项目,Claude Code 10模块系统学习指南
  • 一文读懂 2026 AI Infra 推理加速选型与硬核优化方案