【MCP】从一个天气查询服务带你了解MCP
1. 前言
这篇文章将通过一个集成高德天气查询的 MCP Server 用例,带你上手开发自己的 MCP Server ,文章将通过以下三种方式(自己编写 Client 端代码,使用 mcp-cli 自带页面,集成到 Claude 桌面版等)带你测试自己的 MCP Server。
PS:文章中的每一步都经过自己亲自上手。整理不易,请不要令色你的赞和收藏。
2. MCP介绍
2.1 什么是MCP?
MCP (Model Context Protocol) 是一个开放协议,由 Anthropic 公司推出的开放标准,用于标准化应用程序如何向 LLM 提供上下文。它可以比作 AI 应用程序的 USB-C 接口,提供了一种标准化方式将 AI 模型连接到不同的数据源和工具。
2.2 架构介绍
MCP 遵循 client-server (客户端-服务端) 架构,并允许一个主机应用程序同时连接多个服务器。下面是其核心架构图:
2.3 传输机制
MCP 中 Server 和 Client 之间主要支持以下两种通信方式,并且都使用 JSON-RPC 2.0 (一种轻量级的远程过程调用(RPC)协议) 交换消息:
-
Stdio 传输:使用标准输入/输出,适合本地通信。
-
SSE 传输:使用 Server-Sent Events 和 HTTP POST 请求,实现响应式输出,适合远程通信。
2.4 你的疑问?
2.4.1 什么是MCP Servers?
MCP Servers 是提供上下文、工具和提示给 AI 客户端的系统。它们可以暴露数据源,如文件、文档、数据库和 API 集成,允许 AI 助手以安全的方式访问实时信息
2.4.2 MCP Servers能提供什么?
MCP Servers 可以共享资源(文件、文档、数据)、暴露工具(API 集成、操作)并提供提示(模板交互)。它们控制自己的资源并维护清晰的系统边界以保障安全。
2.4.3 MCP Servers是如何工作的?
MCP Servers 通过简单的客户端-服务器架构工作。它们通过标准协议公开数据和工具,与主机应用程序(如 Claude 桌面)中的客户端保持安全的 1:1 连接。
2.4.4 MCP Servers安全吗?
是的,安全性已内置到 MCP 协议中。服务器控制自己的资源,无需与LLM提供商共享 API 密钥,并且系统保持清晰的边界。每个服务器管理自己的身份验证和访问控制。
3. 前提条件
这篇文章使用 Python 来开发 MCP Server ,使用高德地图的 API 来查询天气。阅读之前,你需要具备以下条件:
-
已安装 Python 3.10 或更高版本。
-
已申请高德 web 服务 API_KEY,访问 高德开放平台 申请。
我使用的 Python 版本是 3.12,我的系统是 win11。
拓展:目前官方已提供以下几种语言的 SDK:Python、TypeScript、Java、C#、Kotlin等,详情可访问文末的参考文档。
4. 开发
4.1 创建一个Pyhon项目
推荐使用 uv 做为 Python 包管理工具。
1. 安装 uv:
pip install uv
2. 使用uv创建一个 mcp-demo 项目:
uv init mcp-demo
3. 创建uv虚拟环境:
# 进入到刚创建的项目目录下
cd .\mcp-demo\# 创建uv虚拟环境
uv venv .venv
执行完上述命令后,当前目录下会创建一个名为 .venv 的虚拟环境文件夹。
4. 激活虚拟环境:
.\.venv\Scripts\activate
5. 安装 python mcp 依赖:
uv add "mcp[cli]"
6. PyCharm中引入该项目:
使用 PyCharm 打开这个项目,并在【Settings - Python Interpreter】中查看python解释器是否正确(地址为项目路径下的".venv\Scripts\python.exe")。
4.2 MCP Server开发
4.2.1 核心功能
MCP 主要提供一下三种功能:
-
资源(Resources):客户端可读取的文件类数据(如 API 响应或文件内容)。
-
工具(Tools):LLM 可调用的函数(需要用户批准)。
-
提示(Prompts):帮助用户完成特定任务的预编写模板。
通过这篇文章,你可以快速构建一个 MCP Server,使 LLM 能够访问实时天气数据。MCP 提供了统一的接口,可以简化 LLM 与外部数据源的集成过程。
4.2.2 代码
这篇文章主要关注工具(Tools)的使用。
4.2.2.1 创建.env文件
首先在项目路径下创建一个 .env 的文件,用来存储配置信息:
AMAP_API_KEY=<你的高德API_KEY>
4.2.2.2 创建weather-mcp-server.py文件
这篇文章使用官方的 FastMCP 框架构建 MCP 服务端和客户端。
完整代码:
import os
from typing import Dict, Any, Optionalimport httpx
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP# 定义一个 FastMCp 实例
mcp = FastMCP("LocalWeatherServer")# 高德天气API配置信息
load_dotenv()
AMAP_WEATHER_API_BASE_URL = "https://restapi.amap.com/v3/weather/weatherInfo"
AMAP_API_KEY = os.getenv("AMAP_API_KEY")async def get_amap_weather(city: str) -> Optional[Dict[str, Any]]:"""调用高德天气接口,获取天气数据"""params = {"city": city,"key": AMAP_API_KEY,"extensions": "all", # all:预报天气,base:实况天气"output": "JSON",}try:async with httpx.AsyncClient(timeout=5.0) as client:response = await client.get(AMAP_WEATHER_API_BASE_URL, params=params)response.raise_for_status()return response.json()except httpx.HTTPError as e:return {"error": f"天气服务请求失败:{e}"}def parse_forecast(cast: Dict[str, str]) -> str:""" 格式化单日天气信息 """return (f"日期:{cast.get('date', '未知')},"f"星期:{cast.get('week', '未知')},"f"白天天气:{cast.get('dayweather', '未知')},"f"夜晚天气:{cast.get('nightweather', '未知')},"f"温度:{cast.get('nighttemp', '未知')}~{cast.get('daytemp', '未知')}℃,"f"风向:{cast.get('daywind', '未知')}~{cast.get('nightwind', '未知')},"f"白天风力:{cast.get('daypower', '未知')}级,"f"夜晚风力:{cast.get('nightpower', '未知')}级。")def format_weather_data(weather_data: Dict[str, Any]) -> str:"""格式化天气响应数据"""if "error" in weather_data:return weather_data["error"]forecasts = weather_data.get("forecasts", [])if not forecasts:return "未找到该城市的天气信息。"forecast = forecasts[0]city = forecast.get("city", "未知城市")casts = forecast.get("casts", [])if not casts:return "未找到该城市的天气信息。"today = parse_forecast(casts[0])future = "\n".join(parse_forecast(c) for c in casts[1:])result = [f"{city}今天的天气:{today}"]if future:result.append(f"未来几天天气:\n{future}")return "\n".join(result)@mcp.tool()
async def fetch_weather(city: str) -> str:"""获取城市天气"""weather_data = await get_amap_weather(city)return format_weather_data(weather_data)if __name__ == "__main__":# 运行 MCP 服务器,默认传输协议 stdiomcp.run(transport="stdio")
5. 测试
5.1 通过编写Client端代码测试
5.1.1 客户端实现完整代码:
创建一个 mcp-client.py 的文件:
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client# 创建标准输入输出(stdio)连接的服务器参数配置
server_params = StdioServerParameters(command="python", # 要执行的命令/可执行文件args=["weather-mcp-server.py"], # 传递给命令的参数列表env=None,
)async def run():"""主运行函数,处理客户端会话逻辑"""# 使用stdio_client建立连接,获取读写通道async with stdio_client(server_params) as (read, write):# 创建客户端会话async with ClientSession(read, write) as session:# 初始化连接(握手协议等)await session.initialize()# 列出所有可用的提示模板# prompts = await session.list_prompts()# 获取特定提示模板,可传入参数# prompt = await session.get_prompt(# "example-prompt", # 提示模板名称# arguments={"arg1": "value"} # 模板参数# )# 列出所有可用资源# resources = await session.list_resources()# 列出所有可用工具tools = await session.list_tools()print(f"工具列表:{tools}")# 读取特定资源内容# content, mime_type = await session.read_resource(# "file://some/path" # 资源URI# )# 调用指定工具result = await session.call_tool("fetch_weather", # 工具名称arguments={"city": "南京"} # 工具参数)print(f"查询结果:{result}")if __name__ == "__main__":import asyncio# 运行主异步函数asyncio.run(run())
5.1.2 启动服务端
首先需要启动 MCP 服务端,PyCharm 中右键启动:
5.1.3 测试
以同样的方式运行客户端测试,其结果如下:
5.2 使用mcp-cli自带页面测试
该方式需要安装 node.js 。
5.2.1 启动服务端
命令行键入:
mcp dev weather-mcp-server.py
运行结果:
5.2.2 测试
浏览器打开 http://127.0.0.1:6274
5.3 集成到 Claude 桌面端测试
首先你需要 下载 Claude 桌面端 。
5.3.1 启动服务端
同 5.2.1
5.3.2 配置claude_desktop_config.json文件
打开 Claude 桌面端 - File- Settings - Developer - Edit Config(我这里已经配置,这个界面会不同)。
点击 Edit Config,进入 Claude 运行目录,找到 claude_desktop_config.json 文件,键入以下配置,将 AMAP_API_KEY 值替换为你的高德 API_KEY:
{"mcpServers": {"LocalWeatherServer": {"command": "uv","args": ["--directory","F:\\workspace\\python\\demos\\mcp-demo","run","weather-mcp-server.py"],"env": {"AMAP_API_KEY": "<your_api_key>"}}}
}
配置完成后,重启 Claude 桌面端(需要在任务管理器杀掉 Calude 进程)。
重启后,对话框下方会出现如下锤子按钮。
5.3.3 测试
在聊天对话框输入 ‘ 南京天气 ’,首次调用会出现如下是否使用工具的提示,点击同意即可。
结果:
到这里,MCP的简单用例就开发完了。如果你想发现、分享和学习各种适用于 AI 应用的 MCP 服务器,可以访问 MCP Servers 。
6. 参考文档
- Model Context Protocol 官网
- MCP Python SDK