天气数据获取工具

一个基于Model Context Protocol (MCP)的概念验证工具,通过stdio传输协议提供天气数据获取功能,可作为协议适配器连接REST API与LLM客户端。

  • by bsozer06
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 bsozer06/poc-basic-weather-mcp

使用说明

MCP天气PoC

A. 模型上下文协议(MCP) 概念证明,揭示了 get_weather 工具完毕 标准 运输。MCP服务器充当 协议适配器 -它本身不生成数据,而是通过HTTP从REST API获取数据,然后通过MCP将其提供给LLM客户端。


架构概述

该项目遵循 三层架构 它清晰地将关注点分开:

LLM Client (client.py)
    ↓  stdio (MCP protocol / JSON-RPC)
MCP Server (server.py)            ← protocol adapter, no data logic
    ↓  HTTP (httpx)
REST API   (weather_api.py)       ← data source (mock for PoC)
组件 文件 角色
REST API weather_api.py 提供天气数据的FastAPI服务。当前返回模拟/仿真数据;将URL交换为生产中的真实API(例如OpenWeatherMap)。
MCP服务器 server.py 注册 get_weather 工具via FastMCP,继续听 标准,并使用将请求代理到REST API httpx.
MCP客户端 client.py 启动模拟API、生成MCP服务器、发现工具、运行验证测试并拆除一切的测试工具。

关键设计决策

  • 关注点分离 --MCP服务器包含零数据逻辑;它只在MCP协议和HTTP之间进行转换。这使得从模拟到真实API的切换成为一行配置更改。
  • 基于环境的配置 --set WEATHER_API_BASE_URL 将MCP服务器指向任何兼容的REST端点。
  • stdio传输 --客户端将服务器作为子进程生成;所有JSON-RPC消息都通过stdin/stdout管道流动。
  • 输入验证 --城市名称仅限于字母、空格和连字符;单位必须 celsius 或 fahrenheit.验证发生在MCP服务器(飞行前)和REST API层。

顺序图

sequenceDiagram
    participant User
    participant Client as MCP Client<br/>(client.py)
    participant Server as MCP Server<br/>(server.py)
    participant API as REST API<br/>(weather_api.py)

    User->>Client: Run client
    Client->>API: Start mock API (subprocess)
    API-->>Client: Health check OK

    Client->>Server: Spawn subprocess (stdio)
    Client->>Server: initialize handshake
    Server-->>Client: ServerInfo & capabilities

    Client->>Server: tools/list
    Server-->>Client: Available tools [get_weather]

    Client->>Server: tools/call → get_weather(city, unit)

    Note over Server: Validate inputs

    Server->>API: GET /weather?city=...&unit=...
    API-->>Server: JSON {city, temperature, ...}

    Server-->>Client: MCP result {city, temperature, unit, condition, timestamp}
    Client-->>User: Display weather result
    Client->>Server: Close stdio session
    Client->>API: Terminate API process

数据流图

flowchart TD
    A[User] -->|city, unit| B[MCP Client]
    B -->|stdio spawn| C[MCP Server]
    C -->|HTTP GET /weather| D[REST API]
    D --> E{City in KNOWN_CITIES?}
    E -- Yes --> F[Return hardcoded weather]
    E -- No --> G[Generate random weather]
    F --> H[Build response JSON]
    G --> H
    H -->|HTTP JSON response| C
    C -->|JSON-RPC over stdio| B
    B -->|Formatted output| A

    style D fill:#f9f,stroke:#333
    style C fill:#bbf,stroke:#333

响应架构

这 get_weather 工具返回一个具有以下结构的JSON对象:

{
  "city": "Istanbul",
  "temperature": 18.5,
  "unit": "celsius",
  "condition": "Cloudy",
  "timestamp": "2026-02-22T12:00:00Z"
}
字段 类型 描述
city string 标题大小写的城市名称
temperature float 所需单位的温度
unit string "celsius" 或 "fahrenheit"
condition enum 其中之一 Sunny, Cloudy, Rainy, Snowy
timestamp string ISO 8601 UTC时间戳

入门指南

1.安装依赖项

pip install -r requirements.txt

2.启动模拟REST API

uvicorn weather_api:app --host 127.0.0.1 --port 8000

3.独立运行MCP服务器(stdio)

在单独的终端中(服务器从stdin读取JSON-RPC):

# Uses the default API URL http://127.0.0.1:8000
python server.py

# Or point to a different API:
# set WEATHER_API_BASE_URL=https://real-api.example.com
# python server.py

4.运行完整的测试套件(自动启动所有内容)

python client.py

测试客户端自动启动mock API,运行所有测试,并关闭一切。


切换到真正的API

MCP服务器使用 WEATHER_API_BASE_URL 环境变量来定位数据源。将其指向真实天气API:

set WEATHER_API_BASE_URL=https://api.openweathermap.org/data/2.5
python server.py

注: 如果实际API的响应模式与PoC模式不同,则可能需要一个瘦适配器层。


与MCP主机(克劳德桌面、VS代码等)一起使用

先决条件: REST API必须正在运行(或 WEATHER_API_BASE_URL 必须指向活动端点)。

将以下内容添加到MCP客户端配置中:

{
  "mcpServers": {
    "weather-service": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": {
        "WEATHER_API_BASE_URL": "http://127.0.0.1:8000"
      }
    }
  }
}

项目结构

├── weather_api.py             # Mock REST API (FastAPI) – data source
├── server.py                  # MCP server – protocol adapter (httpx → MCP)
├── client.py                  # MCP client – test harness with validation
├── requirements.txt           # Python dependencies
├── mcp-weather-poc-spec.md    # Original specification document
└── README.md                  # This file