Skip to main content
在本教程中,我们会构建一个简单的 MCP 天气服务器,并将它连接到一个 host:Claude for Desktop。

我们将构建什么

我们将构建一个暴露两个 tools 的服务器:get_alertsget_forecast。然后把该服务器连接到 MCP host(本例中是 Claude for Desktop):
服务器可以连接到任何客户端。为了简化说明,这里选择 Claude for Desktop;你也可以参考构建自己的客户端指南。

MCP 核心概念

MCP 服务器可以提供三类主要能力:
  1. Resources:可由客户端读取的类文件数据,例如 API 响应或文件内容。
  2. Tools:可由 LLM 调用的函数,通常需要用户批准。
  3. Prompts:帮助用户完成特定任务的预写模板。
本教程主要关注 tools。
开始构建天气服务器。这里可以找到本教程将构建内容的完整代码。

前置知识

本快速开始假设你熟悉:
  • Python
  • LLMs like Claude

MCP 服务器中的日志

实现 MCP 服务器时,请谨慎处理日志:对于基于 STDIO 的服务器: 永远不要写入 stdout。写入 stdout 会破坏 JSON-RPC 消息并导致服务器异常。print() 默认写入 stdout,但配合 file=sys.stderr 可以安全使用。对于基于 HTTP 的服务器: 标准输出日志是可以的,因为它不会干扰 HTTP 响应。

最佳实践

  • 使用写入 stderr 或文件的日志库。

快速示例

import sys
import logging

# ❌ Bad (STDIO)
print("Processing request")

# ✅ Good (STDIO)
print("Processing request", file=sys.stderr)

# ✅ Good (STDIO)
logging.info("Processing request")

系统要求

  • 已安装 Python 3.10 或更高版本。
  • 必须使用 Python MCP SDK 1.2.0 或更高版本。

设置环境

首先安装 uv,并设置 Python 项目和环境:
curl -LsSf https://astral.sh/uv/install.sh | sh
安装后请重启终端,确保可以识别 uv 命令。现在创建并设置项目:
# Create a new directory for our project
uv init weather
cd weather

# Create virtual environment and activate it
uv venv
source .venv/bin/activate

# Install dependencies
uv add "mcp[cli]" httpx

# Create our server file
touch weather.py
现在开始构建服务器。

构建服务器

导入包并设置实例

将以下内容添加到 weather.py 顶部:
from typing import Any

import httpx
from mcp.server.fastmcp import FastMCP

# Initialize FastMCP server
mcp = FastMCP("weather")

# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
FastMCP 类会使用 Python 类型提示和 docstring 自动生成 tool 定义,使 MCP tools 的创建和维护更简单。

辅助函数

接下来添加辅助函数,用于查询并格式化 National Weather Service API 的数据:
async def make_nws_request(url: str) -> dict[str, Any] | None:
    """Make a request to the NWS API with proper error handling."""
    headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, headers=headers, timeout=30.0)
            response.raise_for_status()
            return response.json()
        except Exception:
            return None


def format_alert(feature: dict) -> str:
    """Format an alert feature into a readable string."""
    props = feature["properties"]
    return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""

实现工具执行

工具执行处理器负责真正执行每个 tool 的逻辑。添加如下代码:
@mcp.tool()
async def get_alerts(state: str) -> str:
    """Get weather alerts for a US state.

    Args:
        state: Two-letter US state code (e.g. CA, NY)
    """
    url = f"{NWS_API_BASE}/alerts/active/area/{state}"
    data = await make_nws_request(url)

    if not data or "features" not in data:
        return "Unable to fetch alerts or no alerts found."

    if not data["features"]:
        return "No active alerts for this state."

    alerts = [format_alert(feature) for feature in data["features"]]
    return "\n---\n".join(alerts)


@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """Get weather forecast for a location.

    Args:
        latitude: Latitude of the location
        longitude: Longitude of the location
    """
    # First get the forecast grid endpoint
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)

    if not points_data:
        return "Unable to fetch forecast data for this location."

    # Get the forecast URL from the points response
    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)

    if not forecast_data:
        return "Unable to fetch detailed forecast."

    # Format the periods into a readable forecast
    periods = forecast_data["properties"]["periods"]
    forecasts = []
    for period in periods[:5]:  # Only show next 5 periods
        forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
        forecasts.append(forecast)

    return "\n---\n".join(forecasts)

运行服务器

最后,初始化并运行服务器:
def main():
    # Initialize and run the server
    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()
服务器已经完成。运行 uv run weather.py 启动 MCP 服务器,它会监听来自 MCP hosts 的消息。现在从现有 MCP host Claude for Desktop 测试服务器。

使用 Claude for Desktop 测试服务器

Claude for Desktop 目前尚不支持 Linux。Linux 用户可以继续阅读构建客户端教程,构建一个连接到刚才服务器的 MCP client。
首先,确保已经安装 Claude for Desktop。你可以在这里安装最新版本。 如果已经安装 Claude for Desktop,请确保它已更新到最新版本。你需要在 Claude for Desktop 中配置想要使用的 MCP 服务器。为此,请用文本编辑器打开 Claude for Desktop 应用配置文件 ~/Library/Application Support/Claude/claude_desktop_config.json。如果文件不存在,请先创建它。例如,如果已安装 VS Code
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
接着在 mcpServers 键中添加服务器。只有至少正确配置了一个服务器,MCP UI 元素才会出现在 Claude for Desktop 中。本例中,我们按如下方式添加单个天气服务器:
{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
        "run",
        "weather.py"
      ]
    }
  }
}
你可能需要在 command 字段中填入 uv 可执行文件的完整路径。可在 macOS/Linux 上运行 which uv,或在 Windows 上运行 where uv 获取。
请确保传入服务器的绝对路径。可在 macOS/Linux 上运行 pwd,或在 Windows Command Prompt 中运行 cd 获取。Windows 上请记得在 JSON 路径中使用双反斜杠(\\)或正斜杠(/)。
这会告诉 Claude for Desktop:
  1. 有一个名为 "weather" 的 MCP server。
  2. 通过运行 uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py 启动它。
保存文件并重启 Claude for Desktop

使用命令测试

确认 Claude for Desktop 能识别 weather server 暴露的两个 tools。可以查找 “Add files, connectors, and more /” 图标:
点击加号图标后,悬停到 “Connectors” 菜单。你应该能看到列出的 weather servers:
如果 Claude for Desktop 没有识别到 server,请跳到排障部分查看调试建议。 如果 server 已出现在 “Connectors” 菜单中,现在可以在 Claude for Desktop 中运行以下命令测试 server:
  • What’s the weather in Sacramento?
  • What are the active weather alerts in Texas?
Since this is the US National Weather service, the queries will only work for US locations.

底层发生了什么

提问时:
  1. The client sends your question to Claude
  2. Claude analyzes the available tools and decides which one(s) to use
  3. The client executes the chosen tool(s) through the MCP server
  4. The results are sent back to Claude
  5. Claude formulates a natural language response
  6. The response is displayed to you!

排障

Getting logs from Claude for DesktopClaude.app logging related to MCP is written to log files in ~/Library/Logs/Claude:
  • mcp.log will contain general logging about MCP connections and connection failures.
  • Files named mcp-server-SERVERNAME.log will contain error (stderr) logging from the named server.
可以运行以下命令列出最近日志并持续查看新增日志:
# Check Claude's logs for errors
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
Server not showing up in Claude
  1. Check your claude_desktop_config.json file syntax
  2. Make sure the path to your project is absolute and not relative
  3. Restart Claude for Desktop completely
要正确重启 Claude for Desktop,必须完全退出应用:
  • Windows: Right-click the Claude icon in the system tray (which may be hidden in the “hidden icons” menu) and select “Quit” or “Exit”.
  • macOS: Use Cmd+Q or select “Quit Claude” from the menu bar.
Simply closing the window does not fully quit the application, and your MCP server configuration changes will not take effect.
Tool calls failing silently如果 Claude 尝试使用 tools 但失败:
  1. Check Claude’s logs for errors
  2. Verify your server builds and runs without errors
  3. Try restarting Claude for Desktop
None of this is working. What do I do?Please refer to our debugging guide for better debugging tools and more detailed guidance.
Error: Failed to retrieve grid point data这通常意味着:
  1. The coordinates are outside the US
  2. The NWS API is having issues
  3. You’re being rate limited
Fix:
  • Verify you’re using US coordinates
  • Add a small delay between requests
  • Check the NWS API status page
Error: No active alerts for [STATE]这不是错误,只表示该州当前没有天气警报。可以尝试其他州,或在恶劣天气期间再检查。
如需更高级排障,请查看调试 MCP指南。

后续步骤

Building a client

Learn how to build your own MCP client that can connect to your server

Example servers

Check out our gallery of official MCP servers and implementations

Debugging Guide

Learn how to effectively debug MCP servers and integrations

Build with Agent Skills

Use agent skills to guide AI coding assistants through server design