MCP天气查询服务器server与使用

1. MCP服务器概念介绍

根据MCP协议定义,Server可以提供三种类型的标准能力,Resources、Tools、Prompts,每个Server可同时提供者三种类型能力或其中一种。

  • **Resources:**资源,类似于文件数据读取,可以是文件资源或是API响应返回的内容。

  • **Tools:**工具,第三方服务、功能函数,通过此可控制LLM可调用哪些函数。

  • **Prompts:**提示词,为用户预先定义好的完成特定任务的模板。

2. MCP服务器通讯机制

Model Context Protocol(MCP)是一种由 Anthropic 开源的协议,旨在将大型语言模型直接连接至数据源,实现无缝集成。根据 MCP 的规范,当前支持两种传输方式:标准输入输出(stdio)和基于 HTTP 的服务器推送事件(SSE)。而近期,开发者在 MCP 的 GitHub 仓库中提交了一项提案,建议采用“可流式传输的 HTTP”来替代现有的 HTTP+SSE 方案。此举旨在解决当前远程 MCP 传输方式的关键限制,同时保留其优势。 HTTP 和 SSE(服务器推送事件)在数据传输方式上存在明显区别:

  • 通信方式

    • HTTP:采用请求-响应模式,客户端发送请求,服务器返回响应,每次请求都是独立的。

    • SSE:允许服务器通过单个持久的 HTTP 连接,持续向客户端推送数据,实现实时更新。

  • 连接特性

    • HTTP:每次请求通常建立新的连接,虽然在 HTTP/1.1 中引入了持久连接,但默认情况下仍是短连接。

    • SSE:基于长连接,客户端与服务器之间保持持续的连接,服务器可以在任意时间推送数据。

  • 适用场景

    • HTTP:适用于传统的请求-响应场景,如网页加载、表单提交等。

    • SSE:适用于需要服务器主动向客户端推送数据的场景,如实时通知、股票行情更新等。

需要注意的是,SSE 仅支持服务器向客户端的单向通信,而 WebSocket 则支持双向通信。

这里我们尝试一个入门级的示例,那就是创建一个天气查询的服务器。通过使用OpenWeather API,创建一个能够实时查询天气的服务器(server),并使用stdio方式进行通信。

api的注册参考: 

零基础开发AI智能体教程(5)|在智能体中调用外部工具的实现指南——以天气查询为例_智能体平台如何通过导入外部api生成工具-CSDN博客

测试api:

curl -s "https://api.openweathermap.org/data/2.5/weather?q=Beijing&appid='YOUR_API_KEY'&units=metric&lang=zh_cn"

 注意,api不需要加单引号

能够正常输出

3. 天气查询服务器Server创建流程

3.1 服务器依赖安装

由于我们需要使用http请求来查询天气,因此需要在当前虚拟环境中添加如下依赖

uv add mcp httpx --index-url https://mirrors.aliyun.com/pypi/simple/
3.2 服务器代码编写

接下来尝试创建服务器代码,此时MCP基本执行流程如下:

对应server服务器代码为:

import json
import httpx
from typing import Any
from mcp.server.fastmcp import FastMCP

# 初始化 MCP 服务器
mcp = FastMCP("WeatherServer")

# OpenWeather API 配置
OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"
API_KEY = "YOUR_API_KEY"  # 请替换为你自己的 OpenWeather API Key
USER_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,
        "units": "metric",
        "lang": "zh_cn"
    }
    headers = {"User-Agent": USER_AGENT}

    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers, timeout=30.0)
            response.raise_for_status()
            return response.json()  # 返回字典类型
        except httpx.HTTPStatusError as e:
            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']}"

    # 提取数据时做容错处理
    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 可能为空列表,因此用 [0] 前先提供默认字典
    weather_list = data.get("weather", [{}])
    description = weather_list[0].get("description", "未知")

    return (
        f"🌍 {city}, {country}\n"
        f"🌡 温度: {temp}°C\n"
        f"💧 湿度: {humidity}%\n"
        f"🌬 风速: {wind_speed} m/s\n"
        f"🌤 天气: {description}\n"
    )

@mcp.tool()
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')

代码解释如下:

Part 1. 异步获取天气数据

  • 函数 fetch_weather(city: str)

    • 使用 httpx.AsyncClient() 发送异步 GET 请求到 OpenWeather API。

    • 如果请求成功,则调用 response.json() 返回一个字典。

    • 出现异常时,返回包含错误信息的字典。

Part 2. 格式化天气数据

  • 函数 format_weather(data: dict | str)

    • 首先检查传入的数据是否为字符串,如果是,则使用 json.loads 将其转换为字典。

    • 检查数据中是否包含 "error" 字段,如果有,直接返回错误提示。

    • 使用 .get() 方法提取 namesys.countrymain.tempmain.humiditywind.speedweather[0].description 等数据,并为可能缺失的字段提供默认值。

    • 将提取的信息拼接成一个格式化字符串,方便阅读。

Part 3. MCP 工具 query_weather(city: str)

  • 函数 query_weather

    • 通过 @mcp.tool() 装饰器注册为 MCP 服务器的工具,使其能够被客户端调用。

    • 调用 fetch_weather(city) 获取天气数据,然后用 format_weather(data) 将数据格式化为易读文本,最后返回该字符串。

Part 4. 运行服务器

  • if __name__ == "__main__":

    • 调用 mcp.run(transport='stdio') 启动 MCP 服务器,采用标准 I/O 通信方式,等待客户端调用。

此外,上述代码有两个注意事项,

  1. query_weather函数的函数说明至关重要,相当于是此后客户端对函数进行识别的基本依据,因此需要谨慎编写;

  2. 当指定 transport='stdio' 运行 MCP 服务器时,客户端必须在启动时同时启动当前这个脚本,否则无法顺利通信。这是因为 stdio 模式是一种本地进程间通信(IPC,Inter-Process Communication)方式,它需要服务器作为子进程运行,并通过标准输入输出(stdin/stdout)进行数据交换。

因此,当我们编写完服务器后,并不能直接调用这个服务器,而是需要创建一个对应的能够进行stdio的客户端,才能顺利进行通信。

### 关于 MCP天气查询 API 或功能集成 MCP(Microservice Cloud Platform)作为一个微服务平台,在 API 开发领域具有重要地位。通过 Apifox 提供的支持,可以实现更高效的 API 工作流管理[^1]。 对于天气查询的功能集成,可以通过 Python 构建一个基于 MCP 平台的天气 API 客户端来完成。以下是具体的技术细节: #### 实现天气查询的核心功能 1. **7天天气预报** 使用 `v7/weather/7d` 接口获取未来七天的天气数据。此接口返回的数据通常包括日期、温度范围、天气状况等信息[^2]。 2. **实时天气查询** 调用 `v7/weather/now` 接口可获得当前时间点的天气情况,例如气温、湿度以及风速等参数。 3. **空气质量生活指数** 此类服务可能涉及额外的 API 地址调用,比如针对空气质量和生活建议的具体 URL 请求路径。 下面是一个简单的 Python 示例代码用于演示如何利用上述提到的服务地址发起 HTTP GET 请求并解析 JSON 数据: ```python import requests def fetch_weather(api_key, location, service_type='now'): base_url = 'https://api.example.com/v7/weather/' if service_type == '7d': url = f"{base_url}7d?location={location}&key={api_key}" elif service_type == 'air_quality' or service_type == 'life_index': # 假设存在这些类型的请求处理逻辑 pass else: url = f"{base_url}{service_type}?location={location}&key={api_key}" response = requests.get(url) data = response.json() return data # Example usage of the function with a hypothetical key and location. weather_data_now = fetch_weather('your_api_key', 'Beijing') print(weather_data_now) forecast_7_days = fetch_weather('your_api_key', 'Shanghai', '7d') print(forecast_7_days) ``` 以上脚本展示了基本框架结构;实际应用时需替换真实的 API 密钥 (`your_api_key`) 及目标城市名称 (如 Beijing 或 Shanghai),同时确保网络环境允许外部访问指定服务器资源。 #### 注意事项 当设计此类应用程序时需要注意安全性考量,保护好个人隐私资料不被泄露给未经授权方,并遵循各地区法律法规关于气象信息服务的规定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值