Skip to main content
Glama
README.md10.1 kB
# weather-mcp `weather-mcp` 是一个独立的 **Capability Service(能力服务)**,对外提供“天气查询”这一 MCP 能力。 ## 为什么要拆成 weather-mcp 在已有后台系统中: - `admin`:唯一的用户与认证来源(登录、签发 Token、`/api/v1/auth/me`) - `weather-mcp`:只负责能力提供,不做用户系统 拆分的目标: - 清晰边界:避免多套用户体系 - 能力可复用:MCP 层独立于 HTTP,可被编排/复用 - 可演进:未来接入更多 MCP(空气质量/预报/第三方数据源) ## 与 admin 的关系(文字关系图) - Client -> `weather-mcp`:携带 `Authorization: Bearer <JWT>` - `weather-mcp`:验证 Token 是否可信(第一版为本地 HS256 验签) - `admin`:身份真实性与用户语义的权威来源 ## 鉴权设计 第一版采用 **方案 A:本地 HS256 验签**(与 `admin` 使用同一套 `SECRET_KEY`)。 - Header 读取:`Authorization: Bearer <token>` - 解析规则: - 算法:HS256 - `sub`:`user_id` - 不依赖 `roles/scopes` 工程化要求: - 鉴权逻辑在 `app/core/auth/` 与 `app/auth_client/` 中 - API 层通过 `Depends(get_auth_context)` 获取 `AuthContext` - handler 不直接处理 token、不写鉴权逻辑 可替换性: - 通过 `WEATHER_MCP_AUTH_MODE` 切换 - `local_jwt`:本地验签 - `admin_introspect`:调用 admin 的 `GET /api/v1/auth/me`(已预留实现) ## MCP 设计理念 MCP 是独立于 HTTP 的“能力协议层”: - 输入输出是结构化 DTO(Pydantic Model) - 不依赖 FastAPI `Request` - 易于单测与复用 目录: - `app/mcp/`:MCP 抽象与实现(例如 `WeatherMCP`) - `app/schemas/`:MCP 输入输出结构(与 HTTP 无关) - `app/api/`:HTTP API 层(校验/鉴权/调用 MCP) ## 运行 ### 依赖 使用 `uv` 管理依赖: - `uv sync` ### 环境变量 - `WEATHER_MCP_SECRET_KEY`:与 admin 一致的 HS256 对称密钥 - `WEATHER_MCP_AUTH_MODE`:默认 `local_jwt` 和风天气(QWeather)Web API: - `WEATHER_MCP_QWEATHER_API_HOST`:你的 QWeather API Host(在 QWeather Console -> Setting 查看) - `WEATHER_MCP_QWEATHER_API_KEY`:你的 QWeather API Key(务必只放在环境变量/密钥管理中) - `WEATHER_MCP_QWEATHER_TIMEOUT_SECONDS`:HTTP 超时(秒) ### 启动 - `uv run uvicorn app.main:app --reload --port 9001` ## API - `GET /health` ### MCP 能力:实时天气(Current Weather) 本服务通过 QWeather `GET /v7/weather/now` 提供实时天气能力,并将返回结构映射成统一的 MCP 输出。 #### 1) MCP 直连路由(兼容/调试) - `GET /mcp/weather?location=...&lang=...&unit=m|i` 说明: - `location` 支持多种输入形式(统一为一个字符串参数): - 城市名称(例如 `北京` / `Beijing`) - 经纬度(格式 `longitude,latitude`,例如 `116.41,39.92`) - Location ID(和风天气城市码,例如 `101010100`) - `lang`:天气描述语言(默认 `zh`,例如返回 `多云`) - `unit`:单位(`m`=metric,`i`=imperial;默认 `m`) 城市名解析策略: - 当 `location` 不是纯数字(LocationID)且不是 `lon,lat` 时,会先调用 QWeather GeoAPI `GET /geo/v2/city/lookup` 做解析,取 Top-1 结果。 - 解析时会使用英文 `geo_lang=en` 获取标准化地点名称(例如输出 `Beijing`),而天气接口仍使用 `lang=zh` 以保证天气状态中文显示。 #### 2) Tool 路由(推荐对外使用) - `POST /tools/weather.current` 请求示例: ``` POST /tools/weather.current Authorization: Bearer <jwt> Content-Type: application/json { "location": "北京" } ``` 返回示例: ```json { "location": "Beijing", "observed_at": "2025-12-13T15:00:00+08:00", "temperature": 12, "condition": "多云", "humidity": 55, "wind_speed": 5.4, "wind_dir": "西北风", "raw": { "code": "200", "now": { "...": "..." } } } ``` 字段映射说明(QWeather -> MCP): - `now.obsTime` -> `observed_at` - `now.temp` -> `temperature` - `now.text` -> `condition` - `now.humidity` -> `humidity` - `now.windSpeed` -> `wind_speed` - `now.windDir` -> `wind_dir` - 完整原始响应 -> `raw` 错误处理(HTTP 层): - 401:缺少/无效 JWT(由 `get_auth_context` 处理) - 500:服务端缺少 QWeather 配置(host/key) - 400:无效地点(上游返回 400/404) - 429:上游限流 - 502:上游网络或权限问题(QWeather 返回 401/403 等) ### MCP 能力:每日天气预报(Daily Forecast) 本服务通过 QWeather `GET /v7/weather/{days}` 提供每日天气预报能力,并将返回结构映射成统一的 MCP 输出。 #### Tool 路由 - `POST /tools/weather.forecast.daily` 请求示例: ``` POST /tools/weather.forecast.daily Authorization: Bearer <jwt> Content-Type: application/json { "location": "北京", "days": 3, "lang": "zh", "unit": "m" } ``` 参数说明: - `location`:城市名称 / `lon,lat` / LocationID - `days`:仅支持 `3|7|10|15`(对应上游 `3d/7d/10d/15d`) - `lang`:天气描述语言(默认 `zh`) - `unit`:单位(`m`=metric,`i`=imperial;默认 `m`) 返回示例: ```json { "location": "Beijing", "forecasts": [ { "date": "2025-12-14", "temp_max": 8, "temp_min": -2, "condition_day": "多云", "condition_night": "晴", "humidity": 35, "wind_speed": 10, "wind_dir": "西北风" } ], "raw": { "code": "200", "daily": [{ "...": "..." }] } } ``` 字段映射说明(QWeather -> MCP): - `daily.fxDate` -> `forecasts[].date` - `daily.tempMax` -> `forecasts[].temp_max` - `daily.tempMin` -> `forecasts[].temp_min` - `daily.textDay` -> `forecasts[].condition_day` - `daily.textNight` -> `forecasts[].condition_night` - `daily.humidity` -> `forecasts[].humidity` - `daily.windSpeedDay` -> `forecasts[].wind_speed` - `daily.windDirDay` -> `forecasts[].wind_dir` - 完整原始响应 -> `raw` ### MCP 能力:每小时天气预报(Hourly Forecast) 本服务通过 QWeather `GET /v7/weather/{hours}` 提供每小时天气预报能力,并将返回结构映射成统一的 MCP 输出。 #### Tool 路由 - `POST /tools/weather.forecast.hourly` 请求示例: ``` POST /tools/weather.forecast.hourly Authorization: Bearer <jwt> Content-Type: application/json { "location": "北京", "hours": 24, "lang": "zh", "unit": "m" } ``` 参数说明: - `location`:城市名称 / `lon,lat` / LocationID - `hours`:仅支持 `24|72|168`(对应上游 `24h/72h/168h`) - `lang`:天气描述语言(默认 `zh`) - `unit`:单位(`m`=metric,`i`=imperial;默认 `m`) 返回示例: ```json { "location": "Beijing", "hourly": [ { "time": "2025-12-13T18:00:00+08:00", "temperature": 2, "condition": "多云", "wind_speed": 12, "wind_dir": "北风", "humidity": 40 } ], "raw": { "code": "200", "hourly": [{ "...": "..." }] } } ``` 字段映射说明(QWeather -> MCP): - `hourly.fxTime` -> `hourly[].time` - `hourly.temp` -> `hourly[].temperature` - `hourly.text` -> `hourly[].condition` - `hourly.windSpeed` -> `hourly[].wind_speed` - `hourly.windDir` -> `hourly[].wind_dir` - `hourly.humidity` -> `hourly[].humidity` - 完整原始响应 -> `raw` ### MCP 能力:空气质量(Current Air Quality) 本服务通过 QWeather Air Quality v1 `GET /airquality/v1/current/{latitude}/{longitude}` 提供空气质量能力。 说明: - 该能力需要经纬度。若传入的是城市名或 LocationID,会先调用 GeoAPI 获取 `lat/lon`。 #### Tool 路由 - `POST /tools/air_quality.current` 请求示例: ``` POST /tools/air_quality.current Authorization: Bearer <jwt> Content-Type: application/json { "location": "北京" } ``` 返回示例: ```json { "location": "Beijing", "aqi": 46, "category": "Good", "primary_pollutant": "PM 2.5", "pm2p5": 11.0, "pm10": 12.0, "o3": 0.02, "no2": 6.77, "so2": 1.0, "co": 0.25, "raw": { "indexes": [{ "...": "..." }], "pollutants": [{ "...": "..." }] } } ``` 字段映射说明(QWeather -> MCP): - `indexes[0].aqi` -> `aqi`(优先选择 `code=us-epa`) - `indexes[0].category` -> `category` - `indexes[0].primaryPollutant.name`(或 `.code`)-> `primary_pollutant` - `pollutants[].concentration.value`(按 `code` 匹配)-> `pm2p5/pm10/o3/no2/so2/co` - 完整原始响应 -> `raw` ### MCP 能力:极端天气预警(Weather Alerts) 本服务通过 QWeather `GET /v7/warning/now` 提供天气预警能力。 说明: - QWeather 文档中标注该接口为“弃用”,但目前仍可按现有返回结构使用。 - 当查询地区当前没有预警信息时,上游返回 `warning=[]`,本服务返回 `alerts=[]`。 #### Tool 路由 - `POST /tools/weather.alerts` 请求示例: ``` POST /tools/weather.alerts Authorization: Bearer <jwt> Content-Type: application/json { "location": "北京", "lang": "zh" } ``` 返回示例: ```json { "location": "Beijing", "alerts": [ { "type": "大风", "level": "Blue", "title": "发布大风蓝色预警", "description": "预计将出现大风", "start": "2025-12-13T10:30:00+08:00", "end": "2025-12-14T10:30:00+08:00" } ], "raw": { "code": "200", "warning": [{ "...": "..." }] } } ``` 字段映射说明(QWeather -> MCP): - `warning.typeName`(或 `warning.type`)-> `alerts[].type` - `warning.severityColor`(或 `warning.severity`)-> `alerts[].level` - `warning.title` -> `alerts[].title` - `warning.text` -> `alerts[].description` - `warning.startTime` -> `alerts[].start` - `warning.endTime` -> `alerts[].end` - 完整原始响应 -> `raw` ## 测试 依赖由 `uv` 管理,推荐直接运行: - `uv run pytest -q` ## 后续演进方向 - 多 MCP:`AirQualityMCP`、`ForecastMCP` - MCP 编排:一个请求触发多个 MCP,或链式执行 - 内部 RPC / Agent 化:HTTP 之外的复用入口 - 可观测性:日志/trace、限流、缓存与熔断

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jayleonc/weather-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server