引言
嗯,大家好呀!今天咱们来聊聊 MCP(Model Context Protocol) 的开发,从搭建一个简单的天气查询Server,再到写一个能调用Server功能的Client,整个过程都会一步一步讲解。
不知道你有没有遇到过这样的问题:
- 想用AI模型(比如DeepSeek、OpenAI)去调用一些外部API(比如天气查询、GitHub仓库管理),但不知道如何让AI和这些服务交互?或者,你想让AI自动帮你完成一些任务,比如查天气、爬取网页、管理文件,但不知道怎么让AI“学会”调用这些工具?
MCP 就是为了解决这个问题而生的! 它定义了一套标准化的协议,让AI模型可以轻松调用各种外部工具(Tools),就像人类使用USB接口一样方便。
那么,咱们今天的目标就是:
- 搭建一个MCP Server(天气查询服务)开发一个MCP Client(调用天气查询的AI助手)让AI模型学会自动调用MCP工具
准备好了吗?咱们开始吧!
1. MCP Server 开发:天气查询服务
1.1 环境准备
首先,咱们得把开发环境搭好,嗯,这一步可不能马虎!
安装 uv
(现代化的Python包管理工具)
pip install uv
或者用PowerShell安装(Windows用户推荐):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
初始化项目 & 创建虚拟环境
uv inituv venv .venv.venv\Scripts\activate # 激活虚拟环境(Windows)
1.2 编写天气查询Server
接下来,咱们要写一个 MCP Server,让它能调用OpenWeatherMap的API查询天气。
从这里openweathermap.org/ 去拿到自己的OpenWeather API Key
。
核心代码(weather.py
):
import jsonimport httpxfrom typing import Anyfrom mcp.server.fastmcp import FastMCP# 初始化 MCP 服务器,命名为"WeatherServer"# 嗯,这里相当于创建了一个天气服务的后台程序mcp = FastMCP("WeatherServer")# OpenWeather API 的配置信息# 注意:这个API_KEY是示例,你需要自己去OpenWeather官网申请一个哦!OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"API_KEY = "xxx" # 请替换为你自己的 OpenWeather API KeyUSER_AGENT = "weather-app/1.0" # 这个用来标识我们的应用async def fetch_weather(city: str) -> dict[str, Any] | None: """ 从 OpenWeather API 获取天气信息。 :param city: 城市名称(需使用英文,如 Beijing) :return: 天气数据字典;若出错返回包含 error 信息的字典 """ # 准备请求参数 params = { "q": city, # 城市名 "appid": API_KEY, # API密钥 "units": "metric", # 使用公制单位(摄氏度) "lang": "zh_cn" # 返回中文描述 } headers = {"User-Agent": USER_AGENT} # 设置请求头 # 使用httpx的异步客户端发送请求 async with httpx.AsyncClient() as client: try: # 发送GET请求,设置30秒超时 response = await client.get( OPENWEATHER_API_BASE, params=params, headers=headers, timeout=30.0 ) response.raise_for_status() # 如果响应不成功会抛出异常 return response.json() # 返回解析后的JSON数据 except httpx.HTTPStatusError as e: # 处理HTTP错误(比如404,401等) return {"error": f"HTTP 错误: {e.response.status_code}"} except Exception as e: # 处理其他异常(比如网络问题) return {"error": f"请求失败: {str(e)}"}def format_weather(data: dict[str, Any] | str) -> str: """ 将天气数据格式化为易读文本。 :param data: 天气数据(可以是字典或 JSON 字符串) :return: 格式化后的天气信息字符串 """ # 如果传入的是字符串,先尝试转换成字典 if isinstance(data, str): try: data = json.loads(data) except Exception as e: return f"无法解析天气数据: {e}" # 如果数据中包含错误信息,直接返回错误提示 if "error" in data: return f"⚠ {data['error']}" # 从返回数据中提取天气信息,使用get方法避免KeyError city = data.get("name", "未知") # 城市名 country = data.get("sys", {}).get("country", "未知") # 国家 temp = data.get("main", {}).get("temp", "N/A") # 温度 humidity = data.get("main", {}).get("humidity", "N/A") # 湿度 wind_speed = data.get("wind", {}).get("speed", "N/A") # 风速 # weather字段是个列表,可能为空,所以先给个默认值 weather_list = data.get("weather", [{}]) description = weather_list[0].get("description", "未知") # 天气描述 # 返回格式化的字符串,用了emoji让输出更直观 return ( f"🌍 {city}, {country}\n" f"🌡 温度: {temp}°C\n" f"💧 湿度: {humidity}%\n" f"🌬 风速: {wind_speed} m/s\n" f"⛅ 天气: {description}\n" )@mcp.tool() # 这个装饰器把这个函数注册为MCP可调用的工具async def query_weather(city: str) -> str: """ 输入指定城市的英文名称,返回今日天气查询结果。 :param city: 城市名称(需使用英文) :return: 格式化后的天气信息 """ data = await fetch_weather(city) # 先获取原始天气数据 return format_weather(data) # 然后格式化输出if __name__ == "__main__": # 以标准 I/O 方式运行 MCP 服务器 # 这样其他程序就可以通过标准输入输出和这个服务通信啦 mcp.run(transport='stdio')
关键点解析:
@mcp.tool()
这个装饰器告诉MCP:“嘿,这个函数是一个可以被AI调用的工具!”query_weather
函数会调用OpenWeather API,返回格式化后的天气数据。1.3 在Trae里配置MCP Server
为了让AI能调用这个Server,咱们得在 Trae(一个支持MCP的AI平台)里配置一下:
{ "mcpServers": { "weather": { "command": "uv", "args": ["run", "weather.py"] } }}
这样,Trae就知道怎么启动这个天气查询服务啦!
2. MCP Client 开发:让AI学会调用天气查询
2.1 安装依赖
咱们的Client需要调用OpenAI(或者DeepSeek)的模型,所以先装好依赖:
uv add openai python-dotenv
2.2 配置模型参数
在 .env
文件里写上你的API信息:
BASE_URL=https://api.deepseek.comMODEL=deepseek-chatAPI_KEY=你的API_KEY
这样代码就能安全读取你的密钥,不会泄露啦!
2.3 编写MCP Client
现在,咱们要写一个Client,让它能:
- 连接MCP Server让AI模型自动决定什么时候调用天气查询
核心代码(client.py
):
from openai import OpenAIfrom mcp import ClientSessionclient = OpenAI(api_key="你的API_KEY")async def ask_ai(query): response = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": query}], tools=[{ "type": "function", "function": { "name": "query_weather", "description": "查询指定城市的天气", "parameters": {"city": {"type": "string"}} } }] ) return response.choices[0].message
当运行Client并询问"今天北京天气怎么样?"时,AI会返回类似这样的格式化天气信息:
🌍 Beijing, CN🌡 温度: 25°C💧 湿度: 65%🌬 风速: 3.2 m/s⛅ 天气: 晴
ai识别当你问“北京天气”,ai自动回发现要去调query_weather
工具,然后就自动把北京
转成英文Beijing
作为参数。
然后就去调用OpenWeather
的api去发送请求获取北京天气,收到的数据是:
{ "name": "Beijing", "sys": {"country": "CN"}, "main": {"temp": 25, "humidity": 65}, "wind": {"speed": 3.2}, "weather": [{"description": "晴"}]}
3. 进阶:让MCP更强大
3.1 更多工具
除了天气查询,咱们还能让AI调用:
- GitHub仓库管理(查代码、提交PR)Figma设计稿解析(让AI看懂UI设计)本地文件管理(让AI帮你整理文件夹)
只要写好对应的 @mcp.tool()
,AI就能学会调用!
3.2 调试技巧
如果AI调工具出错了怎么办?可以用 MCP Inspector 调试:
npx @modelcontextprotocol/inspector uv run weather.py
它会显示AI调用了哪些工具、返回了什么数据,超级方便!
结语
好啦,今天咱们从 MCP Server 到 MCP Client 完整走了一遍,正好明白:
- MCP Server 提供工具(比如天气查询)MCP Client 让AI学会调用这些工具AI模型 自动决定什么时候该用哪个工具