MCP Server 实现一个 天气查询

Step1. 环境配置

安装 uv

curl -LsSf https://astral.sh/uv/install.sh | sh

Question: 什么是 uv 呢和 conda 比有什么区别?
Answer: 一个用 Rust 编写的超快速 (100x) Python 包管理器和环境管理工具,由 Astral 开发。定位为 pip 和 venv 的替代品,专注于速度、简单性和现代 Python 工作流。

创建项目目录

uv init mcp_server_test
cd mcp_server_test

创建虚拟环境并激活

uv venv
source .venv/bin/activate

安装依赖包

uv add "mcp[cli]" httpx requests

Step2. 实现 MCP Server

创建 weather.py

import requests
from mcp.server.fastmcp import FastMCP# 初始化 MCP 服务器
mcp = FastMCP("WeatherServer")HEWEATHER_API_KEY = "你的 key"  # ← 填入你的和风天气Key 去https://dev.qweather.com/这里申请def get_city_id(city_name: str) -> str:"""根据中文城市名获取和风天气 location ID"""url = "https://geoapi.qweather.com/v2/city/lookup"params = {"location": city_name,"key": HEWEATHER_API_KEY}response = requests.get(url, params=params)data = response.json()if data.get("code") == "200" and data.get("location"):print(data)return data["location"][0]["id"]else:raise ValueError(f"找不到城市: {city_name},错误信息: {data}")def get_weather(city_name: str) -> str:"""根据城市中文名返回当前天气中文描述"""try:location_id = get_city_id(city_name)url = "https://devapi.qweather.com/v7/weather/now"params = {"location": location_id,"key": HEWEATHER_API_KEY}response = requests.get(url, params=params)data = response.json()if data.get("code") != "200":return f"天气查询失败:{data.get('code')}"now = data["now"]return (f"🌍 城市: {city_name}\n"f"🌤 天气: {now['text']}\n"f"🌡 温度: {now['temp']}°C\n"f"💧 湿度: {now['humidity']}%\n"f"🌬 风速: {now['windSpeed']} m/s\n")except Exception as e:return f"查询出错:{str(e)}"@mcp.tool('query_weather', '查询城市天气')
def query_weather(city: str) -> str:"""输入指定城市的中文名称,返回当前天气查询结果。:param city: 城市名称:return: 格式化后的天气信息"""return get_weather(city)if __name__ == "__main__":# 以标准 I/O 方式运行 MCP 服务器mcp.run(transport='stdio')

Step3. 测试 MCP Server

运行测试

mcp dev weather.py

看到下面输出就启动成功了

mcp dev weather.py
Starting MCP inspector...
Proxy server listening on port 3000🔍 MCP Inspector is up and running at http://localhost:5173 🚀

请添加图片描述

Step4. 修改MCP Server 做成 SSE 服务

import mcp.types as types
import requests
import uvicorn
from mcp.server.lowlevel import Server
from mcp.server.sse import SseServerTransport
from starlette.applications import Starlette
from starlette.routing import Mount, Route# ================================
# 1) 你的和风天气API Key
# ================================
HEWEATHER_API_KEY = ""  # ← 填入你的和风天气Key(例如 "abc123xxxxxx")# ================================
# 2) 查询天气核心逻辑
# ================================
def get_city_id(city_name: str) -> str:"""根据中文城市名获取和风天气 location ID"""url = "https://geoapi.qweather.com/v2/city/lookup"params = {"location": city_name,"key": HEWEATHER_API_KEY}response = requests.get(url, params=params)data = response.json()if data.get("code") == "200" and data.get("location"):# 如果成功找到城市return data["location"][0]["id"]else:raise ValueError(f"找不到城市: {city_name},错误信息: {data}")def get_weather(city_name: str) -> str:"""根据城市中文名返回当前天气(中文描述、温度、湿度、风速)"""try:location_id = get_city_id(city_name)url = "https://devapi.qweather.com/v7/weather/now"params = {"location": location_id,"key": HEWEATHER_API_KEY}response = requests.get(url, params=params)data = response.json()if data.get("code") != "200":return f"天气查询失败:{data.get('code')}"now = data["now"]return (f"🌍 城市: {city_name}\n"f"🌤 天气: {now['text']}\n"f"🌡 温度: {now['temp']}°C\n"f"💧 湿度: {now['humidity']}%\n"f"🌬 风速: {now['windSpeed']} m/s\n")except Exception as e:return f"查询出错:{str(e)}"# ================================
# 3) MCP Server 定义
# ================================
app = Server("mcp-weather")# (A) 工具调用处理器:根据工具名称选择执行逻辑
@app.call_tool()
async def call_tool_handler(name: str, arguments: dict
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:"""MCP 工具调用处理器"""if name == "query_weather":if "city" not in arguments:raise ValueError("Missing required argument 'city'")# 调用上面封装好的 get_weatherweather_info = get_weather(arguments["city"])return [types.TextContent(type="text", text=weather_info)]else:raise ValueError(f"Unsupported tool name: {name}")# (B) 工具列表:告知 MCP 端都有哪些可调用的工具
@app.list_tools()
async def list_tools() -> list[types.Tool]:"""定义可用的 MCP 工具列表"""return [types.Tool(name="query_weather",description="查询指定城市天气信息(基于和风天气API)",inputSchema={"type": "object","required": ["city"],"properties": {"city": {"type": "string","description": "要查询的城市名(中文)"}},},),]# ================================
# 4) SSE + Starlette 路由
# ================================
sse = SseServerTransport("/messages/")async def handle_sse(request):"""处理 /sse 路由的 SSE 连接,并将其接入 MCP Server。"""async with sse.connect_sse(request.scope, request.receive, request._send) as streams:# 运行 MCP 应用,处理输入输出await app.run(streams[0], streams[1], app.create_initialization_options())starlette_app = Starlette(debug=True,routes=[Route("/sse", endpoint=handle_sse),Mount("/messages/", app=sse.handle_post_message),],
)# ================================
# 5) 启动服务器
# ================================
if __name__ == "__main__":uvicorn.run(starlette_app, host="127.0.0.1", port=8081)

Step5. 配置 Cherry Studio

安装 Cherry Studio

https://cherry-ai.com/

配置模型 api

https://api.baystoneai.com/

请添加图片描述

这里需要选择 工具 推理 这两项

请添加图片描述

然后是在这里选择你的 MCP 服务

请添加图片描述

接下来就可以对话啦,让我们看看测试效果

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42069.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL执行计划

MySQL 的 执行计划(Execution Plan) 是优化器根据 SQL 语句生成的查询执行路径的详细说明。通过分析执行计划,可以了解 MySQL 如何处理 SQL 查询(如索引使用情况、表连接顺序等),进而优化查询性能。 1. 获…

数据大屏点亮工业互联网的智慧之眼

在当今数字化飞速发展的时代,数据已成为企业决策的核心依据,而数据大屏作为数据可视化的重要工具,正逐渐成为工业互联网领域不可或缺的一部分。通过直观、动态的可视化展示,数据大屏能够将复杂的数据转化为易于理解的图表和图形&a…

GPT-SoVITS本地部署:低成本实现语音克隆远程生成音频全流程实战

文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 今天要给大家安利一个绝对能让你大呼过瘾的声音黑科技——GPT-SoVITS!这款由花儿不哭大佬精心打造的语音克隆神…

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek 通义万相制作AI视频流程 4.1 D…

【Unity】合批处理和GPU实例化的底层优化原理(完)

【Unity】批处理和实例化的底层优化原理 URP1.基础概念SetPassCallsDrawCallsBatches 2.重要性排序既然如此为什么仍然要合批? 3.unity主流的合批优化方案和优先级Early-Z透明物体情况 4.合批(小场景但是很复杂很多小物件刚需)合并纹理图集更…

当人类关系重构:从“相互需要”到“鹅卵石化”——生成式人工智能(GAI)认证的角色与影响

在数字化浪潮的席卷之下,人类社会正经历着前所未有的变革。人与人之间的连接方式、互动模式以及价值认同,都在悄然发生着变化。这一过程中,一个显著的现象是,人与人之间的关系逐渐从传统的“相互需要”模式,转变为一种更为复杂、多元且稳定的“鹅卵石化”结构。在此背景下…

ctfhow——web入门171~175

sql简介 web入门171 ——判断注入点: -1 union select 1,2,3 -- 其实在这之前可以先判断多少列,即 -1‘ group(order) by 3 -- group by用于将具有相同值的行分组成一个汇总行,可以查看是否报错确定列数 2&#x…

vue遗漏的知识点(动态组件.组件库的操作使用)

----动态组件&#xff08;vue2vue3通用&#xff09; <component :is"..."> 的作用 <component> 是 Vue 的内置组件&#xff0c;用于动态渲染其他组件。:is 属性 用于指定要渲染的组件。它的值可以是&#xff1a; 组件的名称&#xff08;字符串&#xf…

ip改变导致的数据库连接不上

前言 需要用到路由器&#xff0c;所以先把家里的路由器给拆了先用着。新的路由器到了之后&#xff0c;更换上新的路由器之后&#xff0c;调用到服务会有报错&#xff0c;记录一下更换路由器之后ip重新分配服务可能会报的错. 进一步可以看到有关网路在服务当中的影响。 正文 …

DeepSeek面试——模型架构和主要创新点

本文将介绍DeepSeek的模型架构多头潜在注意力&#xff08;MLA&#xff09;技术&#xff0c;混合专家&#xff08;MoE&#xff09;架构&#xff0c; 无辅助损失负载均衡技术&#xff0c;多Token 预测&#xff08;MTP&#xff09;策略。 一、模型架构 DeepSeek-R1的基本架构沿用…

基于HTML5的3D魔方项目开发实践

基于HTML5的3D魔方项目开发实践 这里写目录标题 基于HTML5的3D魔方项目开发实践项目概述核心技术实现1. 3D效果实现CSS3 3D变换魔方结构设计 2. 交互控制实现动画控制键盘控制触摸控制 技术难点与解决方案1. 3D变换控制2. 触摸体验优化3. 动画性能优化 项目收获总结项目展望 项…

23种设计模式-原型(Prototype)设计模式

原型设计模式 &#x1f6a9;什么是原型设计模式&#xff1f;&#x1f6a9;原型设计模式的特点&#x1f6a9;原型设计模式的结构&#x1f6a9;原型设计模式的优缺点&#x1f6a9;原型设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是原型设计模式…

【MATLAB例程】交互式多模型(IMM),模型使用:CV,CT左转、CT右转,二维平面,三个模型的IMM,滤波使用EKF。订阅专栏后可查看代码

简单的介绍:本文所述的代码实现了一种基于交互多模型(IMM)算法的目标跟踪仿真,适用于复杂运动目标(如匀速、转弯运动)的状态估计。代码通过三个运动模型(匀速CV、左转弯CT1、右转弯CT2)的协同滤波,动态调整模型概率,最终输出综合跟踪结果。代码包含完整的仿真数据生成…

搭建私人对外git空间

# 创建用户&#xff0c;指定不可登录的 Shell&#xff08;git-shell 或 /usr/sbin/nologin&#xff09; sudo adduser --system --shell /usr/bin/git-shell --group git # 验证用户配置 grep git /etc/passwd # 预期输出&#xff1a;git:x:998:998::/home/git:/usr/bin/git-s…

PHP中yield关键字的使用

PHP版本>5.5 原理&#xff1a;yield关键字会生成一个Generator类的对象&#xff0c;PHP通过Generator实例计算出下一次迭代的值&#xff0c;再次返回一个Generator对象并停止循环&#xff08;即循环一次执行一次&#xff09;。 理解&#xff1a;使用在for/foreach/while循…

Vue3 实战:基于 mxGraph 与 WebSocket 的动态流程图构建

本文将详细介绍如何在 Vue3 项目中集成 mxGraph 可视化库&#xff0c;并通过 WebSocket 实现画布元素的实时更新。适合有 Vue 基础的前端开发者学习参考。 一、技术栈准备 Vue3&#xff1a;采用 Composition API 开发mxGraph&#xff1a;JavaScript 流程图库&#xff08;版本 …

Linux目录及文件管理

目录 一.Linux目录基本结构 1.常见目录及其作用 二.常用文件处理命令 1.七类常见的linux的文件 2.cat&#xff08;查看文件内容&#xff09; 3.more(分页查看文件内容&#xff09; 4.less(分页查看文件内容&#xff09; 5.head&#xff08;从头部查看文件内容&#xff0…

电机控制常见面试问题(二十)

文章目录 一.整流电路绕组接法二.电机为什么需要转速器三.电机转矩产生原理四.电机控制中载波频率大小的确定五.开关周期 Tpwm 一.整流电路绕组接法 为了引出直流的输出&#xff0c;一定要在整流变压器的二次侧引出零线&#xff0c;所以二次侧绕组必须接成星形 一次绕组必须要…

arm之s3c2440的I2C的用法

基础概念 IC&#xff08;Inter-Integrated Circuit&#xff09;又称I2C&#xff0c;是是IICBus简称&#xff0c;所以中文应该叫集成电路总线。 IIC的总线的使用场景&#xff0c;所有挂载在IIC总线上的设备都有两根信号线&#xff0c;一根是数据线SDA&#xff0c;另一 根是时钟…

MyBatis-Plus(Ⅲ)IService详解

目录 一、逐一演示 1.save&#xff08;插入一条&#xff09; 结果 断言&#xff08;引入概念&#xff09; 2.saveBatch&#xff08;批量插入&#xff09; 结果 3.saveOrUpdateBatch&#xff08;批量插入&更新&#xff09; 结果 4.removeById&#xff08;通过id删除…