> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waytomcp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 面向服务器开发者

> 开始构建您自己的服务器，以在 Claude for Desktop 和其他客户端中使用。

在本教程中，我们将构建一个简单的 MCP 天气服务器，并将其连接到 Claude for Desktop。我们将从基本设置开始，然后逐步深入到更复杂的用例。

### 我们将构建的内容

许多 LLM 目前无法获取天气预报和恶劣天气警报。让我们使用 MCP 来解决这个问题！

我们将构建一个暴露两个工具的服务器：`get-alerts` 和 `get-forecast`。然后，我们将服务器连接到 MCP 主机（在本例中为 Claude for Desktop）：

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/weather-alerts.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=8187775ebb59e46ee33e2e0f027b6ccc" width="2809" height="1850" data-path="images/weather-alerts.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/current-weather.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=ec550509425234210e5b7adb5cd65957" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>

<Note>
  服务器可以连接到任何客户端。我们在这里选择 Claude for Desktop 是为了简单起见，但我们也有关于[构建您自己的客户端](/quickstart/client)的指南，以及[其他客户端的列表](/clients)。
</Note>

<Accordion title="为什么选择 Claude for Desktop 而不是 Claude.ai？">
  由于服务器是本地运行的，MCP 目前仅支持桌面主机。远程主机正在积极开发中。
</Accordion>

### MCP 核心概念

MCP 服务器可以提供三种主要类型的功能：

1. **资源**：客户端可以读取的类似文件的数据（如 API 响应或文件内容）
2. **工具**：LLM 可以调用的函数（需用户批准）
3. **提示**：帮助用户完成特定任务的预写模板

本教程将主要关注工具。

<Tabs>
  <Tab title="Python">
    让我们开始构建我们的天气服务器！[您可以在此处找到我们将构建的完整代码。](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)

    ### 先决知识

    本快速入门假设您熟悉：

    * Python
    * 像 Claude 这样的 LLM

    ### 系统要求

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

    ### 设置您的环境

    首先，让我们安装 `uv` 并设置我们的 Python 项目和环境：

    <CodeGroup>
      ```bash MacOS/Linux theme={null}
      curl -LsSf https://astral.sh/uv/install.sh | sh
      ```

      ```powershell Windows theme={null}
      powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
      ```
    </CodeGroup>

    安装完成后，请重新启动终端以确保 `uv` 命令生效。

    现在，让我们创建并设置我们的项目：

    <CodeGroup>
      ```bash MacOS/Linux theme={null}
      # 为我们的项目创建一个新目录
      uv init weather
      cd weather

      # 创建虚拟环境并激活它
      uv venv
      source .venv/bin/activate

      # 安装依赖项
      uv add "mcp[cli]" httpx

      # 创建我们的服务器文件
      touch weather.py
      ```

      ```powershell Windows theme={null}
      # 为我们的项目创建一个新目录
      uv init weather
      cd weather

      # 创建虚拟环境并激活它
      uv venv
      .venv\Scripts\activate

      # 安装依赖项
      uv add mcp[cli] httpx

      # 创建我们的服务器文件
      new-item weather.py
      ```
    </CodeGroup>

    现在让我们深入构建您的服务器。

    ## 构建您的服务器

    ### 导入包并设置实例

    将这些内容添加到 `weather.py` 的顶部：

    ```python theme={null}
    from typing import Any
    import httpx
    from mcp.server.fastmcp import FastMCP

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

    # 常量
    NWS_API_BASE = "https://api.weather.gov"
    USER_AGENT = "weather-app/1.0"
    ```

    FastMCP 类使用 Python 类型提示和文档字符串自动生成工具定义，使得创建和维护 MCP 工具变得容易。

    ### 辅助函数

    接下来，让我们添加用于查询和格式化国家气象局 API 数据的辅助函数：

    ```python theme={null}
    async def make_nws_request(url: str) -> dict[str, Any] | None:
        """向 NWS API 发出请求并进行适当的错误处理。"""
        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:
        """将警报特征格式化为可读字符串。"""
        props = feature["properties"]
        return f"""
    事件: {props.get('event', 'Unknown')}
    区域: {props.get('areaDesc', 'Unknown')}
    严重程度: {props.get('severity', 'Unknown')}
    描述: {props.get('description', '无描述')}
    说明: {props.get('instruction', '无具体说明')}
    """
    ```

    ### 实现工具执行

    工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它：

    ```python theme={null}
    @mcp.tool()
    async def get_alerts(state: str) -> str:
        """获取美国某个州的天气警报。

        参数：
            state: 两个字母的美国州代码（例如 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 "无法获取警报或未找到警报。"

        if not data["features"]:
            return "该州没有活跃的警报。"

        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:
        """获取某个位置的天气预报。

        参数：
            latitude: 位置的纬度
            longitude: 位置的经度
        """
        # 首先获取预测网格端点
        points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
        points_data = await make_nws_request(points_url)

        if not points_data:
            return "无法获取该位置的预测数据。"

        # 从 points 响应中获取预测 URL
        forecast_url = points_data["properties"]["forecast"]
        forecast_data = await make_nws_request(forecast_url)

        if not forecast_data:
            return "无法获取详细的预测。"

        # 将周期格式化为可读的预测
        periods = forecast_data["properties"]["periods"]
        forecasts = []
        for period in periods[:5]:  # 仅显示接下来的 5 个周期
            forecast = f"""
    {period['name']}:
    温度: {period['temperature']}°{period['temperatureUnit']}
    风速: {period['windSpeed']} {period['windDirection']}
    预测: {period['detailedForecast']}
    """
            forecasts.append(forecast)

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

    ### 运行服务器

    最后，让我们初始化并运行服务器：

    ```python theme={null}
    if __name__ == "__main__":
        # 初始化并运行服务器
        mcp.run(transport='stdio')
    ```

    您的服务器已完成！运行 `uv run weather.py` 以确认一切正常。

    现在让我们在现有的 MCP 主机 Claude for Desktop 中测试您的服务器。

    ## 使用 Claude for Desktop 测试您的服务器

    <Note>
      Claude for Desktop 尚未在 Linux 上可用。Linux 用户可以继续学习[构建客户端](/quickstart/client)教程，以构建连接到我们刚刚构建的服务器的 MCP 客户端。
    </Note>

    首先，确保您已安装 Claude for Desktop。[您可以在此处安装最新版本。](https://claude.ai/download) 如果您已经安装了 Claude for Desktop，**请确保它已更新到最新版本。**

    我们需要为要使用的 MCP 服务器配置 Claude for Desktop。为此，请在文本编辑器中打开位于 `~/Library/Application Support/Claude/claude_desktop_config.json` 的 Claude for Desktop 应用程序配置。如果文件不存在，请创建它。

    例如，如果您安装了 [VS Code](https://code.visualstudio.com/)：

    <Tabs>
      <Tab title="MacOS/Linux">
        ```bash theme={null}
        code ~/Library/Application\ Support/Claude/claude_desktop_config.json
        ```
      </Tab>

      <Tab title="Windows">
        ```powershell theme={null}
        code $env:AppData\Claude\claude_desktop_config.json
        ```
      </Tab>
    </Tabs>

    然后，您将在 `mcpServers` 键中添加您的服务器。只有在至少正确配置了一个服务器时，MCP UI 元素才会出现在 Claude for Desktop 中。

    在本例中，我们将添加我们的单个天气服务器，如下所示：

    <Tabs>
      <Tab title="MacOS/Linux">
        ```json Python theme={null}
        {
            "mcpServers": {
                "weather": {
                    "command": "uv",
                    "args": [
                        "--directory",
                        "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
                        "run",
                        "weather.py"
                    ]
                }
            }
        }
        ```
      </Tab>

      <Tab title="Windows">
        ```json Python theme={null}
        {
            "mcpServers": {
                "weather": {
                    "command": "uv",
                    "args": [
                        "--directory",
                        "C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather",
                        "run",
                        "weather.py"
                    ]
                }
            }
        }
        ```
      </Tab>
    </Tabs>

    <Warning>
      您可能需要在 `command` 字段中提供 `uv` 可执行文件的完整路径。您可以通过在 MacOS/Linux 上运行 `which uv` 或在 Windows 上运行 `where uv` 来获取此路径。
    </Warning>

    <Note>
      确保传入服务器的绝对路径。
    </Note>

    这告诉 Claude for Desktop：

    1. 有一个名为 "weather" 的 MCP 服务器
    2. 通过运行 `uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py` 来启动它

    保存文件，然后重新启动 **Claude for Desktop**。
  </Tab>

  <Tab title="Node">
    让我们开始构建我们的天气服务器！[您可以在此处找到我们将构建的完整代码。](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-typescript)

    ### 先决知识

    本快速入门假设您熟悉：

    * TypeScript
    * 像 Claude 这样的 LLM

    ### 系统要求

    对于 TypeScript，请确保您已安装最新版本的 Node。

    ### 设置您的环境

    首先，如果尚未安装，请安装 Node.js 和 npm。您可以从 [nodejs.org](https://nodejs.org/) 下载它们。
    验证您的 Node.js 安装：

    ```bash theme={null}
    node --version
    npm --version
    ```

    对于本教程，您需要 Node.js 版本 16 或更高版本。

    现在，让我们创建并设置我们的项目：

    <CodeGroup>
      ```bash MacOS/Linux theme={null}
      # 为我们的项目创建一个新目录
      mkdir weather
      cd weather

      # 初始化一个新的 npm 项目
      npm init -y

      # 安装依赖项
      npm install @modelcontextprotocol/sdk zod
      npm install -D @types/node typescript

      # 创建我们的文件
      mkdir src
      touch src/index.ts
      ```

      ```powershell Windows theme={null}
      # 为我们的项目创建一个新目录
      md weather
      cd weather

      # 初始化一个新的 npm 项目
      npm init -y

      # 安装依赖项
      npm install @modelcontextprotocol/sdk zod
      npm install -D @types/node typescript

      # 创建我们的文件
      md src
      new-item src\index.ts
      ```
    </CodeGroup>

    更新您的 package.json 以添加 type: "module" 和构建脚本：

    ```json package.json theme={null}
    {
      "type": "module",
      "bin": {
        "weather": "./build/index.js"
      },
      "scripts": {
        "build": "tsc && chmod 755 build/index.js"
      },
      "files": [
        "build"
      ],
    }
    ```

    在项目的根目录中创建 `tsconfig.json`：

    ```json tsconfig.json theme={null}
    {
      "compilerOptions": {
        "target": "ES2022",
        "module": "Node16",
        "moduleResolution": "Node16",
        "outDir": "./build",
        "rootDir": "./src",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
      },
      "include": ["src/**/*"],
      "exclude": ["node_modules"]
    }
    ```

    现在让我们深入构建您的服务器。

    ## 构建您的服务器

    ### 导入包并设置实例

    将这些内容添加到 `src/index.ts` 的顶部：

    ```typescript theme={null}
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
    import { z } from "zod";

    const NWS_API_BASE = "https://api.weather.gov";
    const USER_AGENT = "weather-app/1.0";

    // 创建服务器实例
    const server = new McpServer({
      name: "weather",
      version: "1.0.0",
    });
    ```

    ### 辅助函数

    接下来，让我们添加用于查询和格式化国家气象局 API 数据的辅助函数：

    ```typescript theme={null}
    // 用于向 NWS API 发出请求的辅助函数
    async function makeNWSRequest<T>(url: string): Promise<T | null> {
      const headers = {
        "User-Agent": USER_AGENT,
        Accept: "application/geo+json",
      };

      try {
        const response = await fetch(url, { headers });
        if (!response.ok) {
          throw new Error(`HTTP 错误！状态：${response.status}`);
        }
        return (await response.json()) as T;
      } catch (error) {
        console.error("向 NWS 发出请求时出错：", error);
        return null;
      }
    }

    interface AlertFeature {
      properties: {
        event?: string;
        areaDesc?: string;
        severity?: string;
        status?: string;
        headline?: string;
      };
    }

    // 格式化警报数据
    function formatAlert(feature: AlertFeature): string {
      const props = feature.properties;
      return [
        `事件：${props.event || "未知"}`,
        `区域：${props.areaDesc || "未知"}`,
        `严重程度：${props.severity || "未知"}`,
        `状态：${props.status || "未知"}`,
        `标题：${props.headline || "无标题"}`,
        "---",
      ].join("\n");
    }

    interface ForecastPeriod {
      name?: string;
      temperature?: number;
      temperatureUnit?: string;
      windSpeed?: string;
      windDirection?: string;
      shortForecast?: string;
    }

    interface AlertsResponse {
      features: AlertFeature[];
    }

    interface PointsResponse {
      properties: {
        forecast?: string;
      };
    }

    interface ForecastResponse {
      properties: {
        periods: ForecastPeriod[];
      };
    }
    ```

    ### 实现工具执行

    工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它：

    ```typescript theme={null}
    // 注册天气工具
    server.tool(
      "get-alerts",
      "获取某个州的天气警报",
      {
        state: z.string().length(2).describe("两个字母的州代码（例如 CA, NY）"),
      },
      async ({ state }) => {
        const stateCode = state.toUpperCase();
        const alertsUrl = `${NWS_API_BASE}/alerts?area=${stateCode}`;
        const alertsData = await makeNWSRequest<AlertsResponse>(alertsUrl);

        if (!alertsData) {
          return {
            content: [
              {
                type: "text",
                text: "无法获取警报数据",
              },
            ],
          };
        }

        const features = alertsData.features || [];
        if (features.length === 0) {
          return {
            content: [
              {
                type: "text",
                text: `${stateCode} 没有活跃的警报`,
              },
            ],
          };
        }

        const formattedAlerts = features.map(formatAlert);
        const alertsText = `${stateCode} 的活跃警报：\n\n${formattedAlerts.join("\n")}`;

        return {
            content: [
              {
                type: "text",
                text: alertsText,
              },
            ],
          };
        },
    );

    server.tool(
      "get-forecast",
      "获取某个位置的天气预报",
      {
        latitude: z.number().min(-90).max(90).describe("位置的纬度"),
        longitude: z.number().min(-180).max(180).describe("位置的经度"),
      },
      async ({ latitude, longitude }) => {
        // 获取网格点数据
        const pointsUrl = `${NWS_API_BASE}/points/${latitude.toFixed(4)},${longitude.toFixed(4)}`;
        const pointsData = await makeNWSRequest<PointsResponse>(pointsUrl);

        if (!pointsData) {
          return {
            content: [
              {
                type: "text",
                text: `无法获取坐标：${latitude}, ${longitude} 的网格点数据。该位置可能不受 NWS API 支持（仅支持美国位置）。`,
              },
            ],
          };
        }

        const forecastUrl = pointsData.properties?.forecast;
        if (!forecastUrl) {
          return {
            content: [
              {
                type: "text",
                text: "无法从网格点数据获取预测 URL",
              },
            ],
          };
        }

        // 获取预测数据
        const forecastData = await makeNWSRequest<ForecastResponse>(forecastUrl);
        if (!forecastData) {
          return {
            content: [
              {
                type: "text",
                text: "无法获取预测数据",
              },
            ],
          };
        }

        const periods = forecastData.properties?.periods || [];
        if (periods.length === 0) {
          return {
            content: [
              {
                type: "text",
                text: "无预测周期可用",
              },
            ],
          };
        }

        // 格式化预测周期
        const formattedForecast = periods.map((period: ForecastPeriod) =>
          [
            `${period.name || "未知"}：`,
            `温度：${period.temperature || "未知"}°${period.temperatureUnit || "F"}`,
            `风速：${period.windSpeed || "未知"} ${period.windDirection || ""}`,
            `${period.shortForecast || "无预测可用"}`,
            "---",
          ].join("\n"),
        );

        const forecastText = `${latitude}, ${longitude} 的天气预报：\n\n${formattedForecast.join("\n")}`;

        return {
          content: [
            {
              type: "text",
              text: forecastText,
            },
          ],
        };
      },
    );
    ```

    ### 运行服务器

    最后，实现主函数以运行服务器：

    ```typescript theme={null}
    async function main() {
      const transport = new StdioServerTransport();
      await server.connect(transport);
      console.error("天气 MCP 服务器正在 stdio 上运行");
    }

    main().catch((error) => {
      console.error("main() 中的致命错误：", error);
      process.exit(1);
    });
    ```

    确保运行 `npm run build` 来构建您的服务器！这是让您的服务器成功连接的关键步骤。

    现在让我们在现有的 MCP 主机 Claude for Desktop 中测试您的服务器。

    ## 使用 Claude for Desktop 测试您的服务器

    <Note>
      Claude for Desktop 尚未在 Linux 上可用。Linux 用户可以继续学习[构建客户端](/quickstart/client)教程，以构建连接到我们刚刚构建的服务器的 MCP 客户端。
    </Note>

    首先，确保您已安装 Claude for Desktop。[您可以在此处安装最新版本。](https://claude.ai/download) 如果您已经安装了 Claude for Desktop，**请确保它已更新到最新版本。**

    我们需要为要使用的 MCP 服务器配置 Claude for Desktop。为此，请在文本编辑器中打开位于 `~/Library/Application Support/Claude/claude_desktop_config.json` 的 Claude for Desktop 应用程序配置。如果文件不存在，请创建它。

    例如，如果您安装了 [VS Code](https://code.visualstudio.com/)：

    <Tabs>
      <Tab title="MacOS/Linux">
        ```bash theme={null}
        code ~/Library/Application\ Support/Claude/claude_desktop_config.json
        ```
      </Tab>

      <Tab title="Windows">
        ```powershell theme={null}
        code $env:AppData\Claude\claude_desktop_config.json
        ```
      </Tab>
    </Tabs>

    然后，您将在 `mcpServers` 键中添加您的服务器。只有在至少正确配置了一个服务器时，MCP UI 元素才会出现在 Claude for Desktop 中。

    在本例中，我们将添加我们的单个天气服务器，如下所示：

    <Tabs>
      <Tab title="MacOS/Linux">
        <CodeGroup>
          ```json Node theme={null}
          {
              "mcpServers": {
                  "weather": {
                      "command": "node",
                      "args": [
                          "/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js"
                      ]
                  }
              }
          }
          ```
        </CodeGroup>
      </Tab>

      <Tab title="Windows">
        <CodeGroup>
          ```json Node theme={null}
          {
              "mcpServers": {
                  "weather": {
                      "command": "node",
                      "args": [
                          "C:\\PATH\\TO\\PARENT\\FOLDER\\weather\\build\\index.js"
                      ]
                  }
              }
          }
          ```
        </CodeGroup>
      </Tab>
    </Tabs>

    这告诉 Claude for Desktop：

    1. 有一个名为 "weather" 的 MCP 服务器
    2. 通过运行 `node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js` 来启动它

    保存文件，然后重新启动 **Claude for Desktop**。
  </Tab>

  <Tab title="Java">
    <Note>
      这是一个基于 Spring AI MCP 自动配置和 Boot Starters 的快速入门演示。\
      要学习如何手动创建同步和异步 MCP 服务器，请参阅 [Java SDK 服务器](/sdk/java/mcp-server) 文档。
    </Note>

    让我们开始构建我们的天气服务器！\
    [您可以在此处找到我们将构建的完整代码。](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-stdio-server)

    有关更多信息，请参阅 [MCP 服务器 Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html) 参考文档。\
    有关手动 MCP 服务器实现，请参阅 [MCP 服务器 Java SDK 文档](/sdk/java/mcp-server)。

    ### 系统要求

    * 已安装 Java 17 或更高版本。
    * [Spring Boot 3.3.x](https://docs.spring.io/spring-boot/installing.html) 或更高版本

    ### 设置您的环境

    使用 [Spring Initializr](https://start.spring.io/) 引导项目。

    您需要添加以下依赖项：

    <Tabs>
      <Tab title="Maven">
        ```xml theme={null}
        <dependencies>
              <dependency>
                  <groupId>org.springframework.ai</groupId>
                  <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
              </dependency>

              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-web</artifactId>
              </dependency>
        </dependencies>
        ```
      </Tab>

      <Tab title="Gradle">
        ```groovy theme={null}
        dependencies {
          implementation platform("org.springframework.ai:spring-ai-mcp-server-spring-boot-starter")
          implementation platform("org.springframework:spring-web")   
        }
        ```
      </Tab>
    </Tabs>

    然后通过设置应用程序属性来配置您的应用程序：

    <CodeGroup>
      ```bash application.properties theme={null}
      spring.main.bannerMode=off
      logging.pattern.console=
      ```

      ```yaml application.yml theme={null}
      logging:
        pattern:
          console:
      spring:
        main:
          banner-mode: off
      ```
    </CodeGroup>

    [服务器配置属性](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html#_configuration_properties) 文档中列出了所有可用属性。

    现在让我们深入构建您的服务器。

    ## 构建您的服务器

    ### 天气服务

    让我们实现一个 [WeatherService.java](https://github.com/spring-projects/spring-ai-examples/blob/main/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/WeatherService.java)，它使用 REST 客户端从国家气象局 API 查询数据：

    ```java theme={null}
    @Service
    public class WeatherService {

    	private final RestClient restClient;

    	public WeatherService() {
    		this.restClient = RestClient.builder()
    			.baseUrl("https://api.weather.gov")
    			.defaultHeader("Accept", "application/geo+json")
    			.defaultHeader("User-Agent", "WeatherApiClient/1.0 (your@email.com)")
    			.build();
    	}

      @Tool(description = "获取特定纬度/经度的天气预报")
      public String getWeatherForecastByLocation(
          double latitude,   // 纬度坐标
          double longitude   // 经度坐标
      ) {
          // 返回详细预测，包括：
          // - 温度和单位
          // - 风速和方向
          // - 详细预测描述
      }
    	
      @Tool(description = "获取美国某个州的天气警报")
      public String getAlerts(
          @ToolParam(description = "两个字母的美国州代码（例如 CA, NY") String state)
      ) {
          // 返回活跃警报，包括：
          // - 事件类型
          // - 受影响区域
          // - 严重程度
          // - 描述
          // - 安全说明
      }

      // ......
    }
    ```

    `@Service` 注解会自动将服务注册到您的应用程序上下文中。\
    Spring AI 的 `@Tool` 注解使得创建和维护 MCP 工具变得容易。

    自动配置会自动将这些工具注册到 MCP 服务器。

    ### 创建您的 Boot 应用程序

    ```java theme={null}
    @SpringBootApplication
    public class McpServerApplication {

    	public static void main(String[] args) {
    		SpringApplication.run(McpServerApplication.class, args);
    	}

    	@Bean
    	public ToolCallbackProvider weatherTools(WeatherService weatherService) {
    		return  MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
    	}
    }
    ```

    使用 `MethodToolCallbackProvider` 工具将 `@Tools` 转换为 MCP 服务器使用的可执行回调。

    ### 运行服务器

    最后，让我们构建服务器：

    ```bash theme={null}
    ./mvnw clean install
    ```

    这将在 `target` 文件夹中生成一个 `mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar` 文件。

    现在让我们在现有的 MCP 主机 Claude for Desktop 中测试您的服务器。

    ## 使用 Claude for Desktop 测试您的服务器

    <Note>
      Claude for Desktop 尚未在 Linux 上可用。
    </Note>

    首先，确保您已安装 Claude for Desktop。\
    [您可以在此处安装最新版本。](https://claude.ai/download) 如果您已经安装了 Claude for Desktop，**请确保它已更新到最新版本。**

    我们需要为要使用的 MCP 服务器配置 Claude for Desktop。\
    为此，请在文本编辑器中打开位于 `~/Library/Application Support/Claude/claude_desktop_config.json` 的 Claude for Desktop 应用程序配置。\
    如果文件不存在，请创建它。

    例如，如果您安装了 [VS Code](https://code.visualstudio.com/)：

    <Tabs>
      <Tab title="MacOS/Linux">
        ```bash theme={null}
        code ~/Library/Application\ Support/Claude/claude_desktop_config.json
        ```
      </Tab>

      <Tab title="Windows">
        ```powershell theme={null}
        code $env:AppData\Claude\claude_desktop_config.json
        ```
      </Tab>
    </Tabs>

    然后，您将在 `mcpServers` 键中添加您的服务器。\
    只有在至少正确配置了一个服务器时，MCP UI 元素才会出现在 Claude for Desktop 中。

    在本例中，我们将添加我们的单个天气服务器，如下所示：

    <Tabs>
      <Tab title="MacOS/Linux">
        ```json java theme={null}
        {
          "mcpServers": {
            "spring-ai-mcp-weather": {
              "command": "java",
              "args": [
                "-Dspring.ai.mcp.server.stdio=true",
                "-jar",
                "/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
              ]
            }
          }
        }
        ```
      </Tab>

      <Tab title="Windows">
        ```json java theme={null}
        {
          "mcpServers": {
            "spring-ai-mcp-weather": {
              "command": "java",
              "args": [
                "-Dspring.ai.mcp.server.transport=STDIO",
                "-jar",
                "C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
              ]
            }
          }
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      确保传入服务器的绝对路径。
    </Note>

    这告诉 Claude for Desktop：

    1. 有一个名为 "my-weather-server" 的 MCP 服务器
    2. 通过运行 `java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar` 来启动它

    保存文件，然后重新启动 **Claude for Desktop**。

    ## 使用 Java 客户端测试您的服务器

    ### 手动创建 MCP 客户端

    使用 `McpClient` 连接到服务器：

    ```java theme={null}
    var stdioParams = ServerParameters.builder("java")
      .args("-jar", "/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar")
      .build();

    var stdioTransport = new StdioClientTransport(stdioParams);

    var mcpClient = McpClient.sync(stdioTransport).build();

    mcpClient.initialize();

    ListToolsResult toolsList = mcpClient.listTools();

    CallToolResult weather = mcpClient.callTool(
      new CallToolRequest("getWeatherForecastByLocation",
          Map.of("latitude", "47.6062", "longitude", "-122.3321")));

    CallToolResult alert = mcpClient.callTool(
      new CallToolRequest("getAlerts", Map.of("state", "NY")));

    mcpClient.closeGracefully();
    ```

    ### 使用 MCP 客户端 Boot Starter

    使用 `spring-ai-mcp-client-spring-boot-starter` 依赖项创建一个新的 Boot Starter 应用程序：

    ```xml theme={null}
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
    </dependency>
    ```

    并将 `spring.ai.mcp.client.stdio.servers-configuration` 属性指向您的 `claude_desktop_config.json`。\
    您可以重用现有的 Anthropic 桌面配置：

    ```properties theme={null}
    spring.ai.mcp.client.stdio.servers-configuration=file:PATH/TO/claude_desktop_config.json
    ```

    当您启动客户端应用程序时，自动配置将从 `claude_desktop_config.json` 自动创建 MCP 客户端。

    有关更多信息，请参阅 [MCP 客户端 Boot Starters](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-client-docs.html) 参考文档。

    ## 更多 Java MCP 服务器示例

    [starter-webflux-server](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-webflux-server) 演示了如何使用 SSE 传输创建 MCP 服务器。\
    它展示了如何使用 Spring Boot 的自动配置功能定义和注册 MCP 工具、资源和提示。
  </Tab>
</Tabs>

### 使用命令测试

让我们确保 Claude for Desktop 能够识别我们在 `weather` 服务器中暴露的两个工具。您可以通过查找锤子 <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/claude-desktop-mcp-hammer-icon.svg?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=90c3e0caaa59f640ba2a3e35ec0681ba" style={{display: 'inline', margin: 0, height: '1.3em'}} width="32" height="32" data-path="images/claude-desktop-mcp-hammer-icon.svg" /> 图标来做到这一点：

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/visual-indicator-mcp-tools.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=b62a3970a2c321dff628ed42d1016d39" width="1358" height="272" data-path="images/visual-indicator-mcp-tools.png" />
</Frame>

点击锤子图标后，您应该看到列出的两个工具：

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/available-mcp-tools.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=2ff2ba8c187372e7e60d4ad3931c2bed" width="1048" height="604" data-path="images/available-mcp-tools.png" />
</Frame>

如果您的服务器未被 Claude for Desktop 识别，请继续阅读[故障排除](#troubleshooting)部分以获取调试提示。

如果锤子图标已显示，您现在可以通过在 Claude for Desktop 中运行以下命令来测试您的服务器：

* 萨克拉门托的天气如何？
* 德克萨斯州的活跃天气警报是什么？

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/current-weather.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=ec550509425234210e5b7adb5cd65957" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/datalite/Wxs4Dp_Rbe4p9MYx/images/weather-alerts.png?fit=max&auto=format&n=Wxs4Dp_Rbe4p9MYx&q=85&s=8187775ebb59e46ee33e2e0f027b6ccc" width="2809" height="1850" data-path="images/weather-alerts.png" />
</Frame>

<Note>
  由于这是美国国家气象局服务，查询仅适用于美国位置。
</Note>

## 幕后发生了什么

当您提出问题时：

1. 客户端将您的问题发送给 Claude
2. Claude 分析可用的工具并决定使用哪些工具
3. 客户端通过 MCP 服务器执行所选工具
4. 结果发送回 Claude
5. Claude 形成自然语言响应
6. 响应显示给您！

## 故障排除

<AccordionGroup>
  <Accordion title="Claude for Desktop 集成问题">
    **从 Claude for Desktop 获取日志**

    与 MCP 相关的 Claude.app 日志写入 `~/Library/Logs/Claude` 中的日志文件：

    * `mcp.log` 将包含有关 MCP 连接和连接失败的一般日志。
    * 名为 `mcp-server-SERVERNAME.log` 的文件将包含来自指定服务器的错误（stderr）日志。

    您可以运行以下命令以列出最近的日志并跟踪任何新日志：

    ```bash theme={null}
    # 检查 Claude 的日志以查找错误
    tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
    ```

    **服务器未显示在 Claude 中**

    1. 检查您的 `claude_desktop_config.json` 文件语法
    2. 确保项目路径是绝对路径而不是相对路径
    3. 完全重新启动 Claude for Desktop

    **工具调用静默失败**

    如果 Claude 尝试使用工具但失败：

    1. 检查 Claude 的日志以查找错误
    2. 验证您的服务器是否构建并运行无误
    3. 尝试重新启动 Claude for Desktop

    **这些方法都不起作用。我该怎么办？**

    请参阅我们的[调试指南](/docs/tools/debugging)以获取更好的调试工具和更详细的指导。
  </Accordion>

  <Accordion title="天气 API 问题">
    **错误：无法获取网格点数据**

    这通常意味着：

    1. 坐标在美国以外
    2. NWS API 出现问题
    3. 您被限速

    修复方法：

    * 验证您使用的是美国坐标
    * 在请求之间添加少量延迟
    * 检查 NWS API 状态页面

    **错误：\[STATE] 没有活跃的警报**

    这不是错误 - 只是意味着该州目前没有活跃的天气警报。尝试不同的州或在恶劣天气期间检查。
  </Accordion>
</AccordionGroup>

<Note>
  有关更高级的故障排除，请查看我们的 [调试 MCP](/docs/tools/debugging) 指南
</Note>

## 后续步骤

<CardGroup cols={2}>
  <Card title="构建客户端" icon="outlet" href="/quickstart/client">
    学习如何构建自己的 MCP 客户端以连接到您的服务器
  </Card>

  <Card title="示例服务器" icon="grid" href="/examples">
    查看我们的官方 MCP 服务器和实现库
  </Card>

  <Card title="调试指南" icon="bug" href="/docs/tools/debugging">
    学习如何有效调试 MCP 服务器和集成
  </Card>

  <Card title="使用 LLM 构建 MCP" icon="comments" href="/tutorials/building-mcp-with-llms">
    学习如何使用像 Claude 这样的 LLM 加速您的 MCP 开发
  </Card>
</CardGroup>
