# demo_mcp **Repository Path**: August08/demo_mcp ## Basic Information - **Project Name**: demo_mcp - **Description**: demo_mcp - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-07 - **Last Updated**: 2026-02-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Java MCP Demo 基于 Spring Boot + Spring AI 的 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 服务端示例,通过 SSE 对外提供 MCP 工具,可与 Cursor、MCP Inspector 等客户端对接。 ## 技术栈 - **JDK** ≥ 17 - **Spring Boot** 3.4.x - **Spring AI** 1.0.0-M7(MCP Server/Client) - **MCP SDK** 0.8.1(`mcp`、`mcp-spring-webmvc`,SSE 传输) - **Fastjson2** 2.0.14.graal ## 项目结构 ``` src/main/java/com/example/java_mcp/ ├── JavaMcpApplication.java # 启动类 ├── config/ │ ├── McpConfig.java # MCP SSE 与工具注册配置 │ └── McpToolFlag.java # 标记「作为 MCP 工具」的注解 └── service/ ├── MyServer.java # MCP 同步服务器初始化(仅 serverInfo/capabilities) ├── WeatherService.java # 天气相关 MCP 工具(注解方式) └── SearchPersonService.java # 人物查询 MCP 工具(注解方式) ``` ## 核心说明 ### 1. 传输方式:SSE - 使用 `WebMvcSseServerTransportProvider` 暴露 SSE 端点: - **消息**:`/message` - **SSE**:`/sse` - 在 `McpConfig` 中注册 `RouterFunction`,将上述路径挂到当前 Web 应用。 ### 2. 工具注册方式(推荐:仅用注解,无需在 MyServer 里手写) | 方式 | 说明 | 推荐度 | |----------|----------------------------------------------------------------------|--------| | **注解** | 在 Spring Bean 上使用 `@McpToolFlag`,方法上使用 `@Tool` / `@ToolParam`,由 McpConfig 的 `ToolCallbackProvider` 自动扫描并注册 | ✅ 推荐:新增工具只需加 Service,不用改 MyServer | | ~~编程式~~ | 在 MyServer 里 `addTool(...)` 手写注册 | ❌ 已弃用:易重复、难维护,本示例已移除 | **结论**:所有 MCP 工具都放在各自 Service 中(如 WeatherService、SearchPersonService),**不需要**也不建议在 MyServer 中手动注册。 ### 3. 已提供的 MCP 工具 | 工具名 | 说明 | 参数 | 来源 | |--------------------------------|--------------------------|------------------------------|-------------------| | `getWeatherForecastByLocation` | 按经纬度查询天气预报 | `latitude`, `longitude` | WeatherService | | `getAlerts` | 查询美国某州的天气警报 | `state`(两字母州代码,如 CA、NY) | WeatherService | | `searchPerson` | 按姓名查询人物(示例实现,返回模拟数据) | `name` | SearchPersonService | - 天气数据来自 [api.weather.gov](https://api.weather.gov)。 - `searchPerson` 当前返回固定结构的 JSON(含 `user_name`、`user_account`、`search_time`),仅作演示。 ### 4. 配置 - `application.properties`: - `spring.application.name=java_mcp` - `server.port=8082` - `spring.ai.mcp.server.capabilities.logging=false`:关闭 MCP 的 logging 能力,避免与部分客户端(如 MCP Inspector)对 LoggingLevel 反序列化格式不兼容导致 -32603。 ## 环境要求 1. **JDK** ≥ 17 2. **Node.js** ≥ 20(用于 MCP Inspector 调试) ## 运行与调试 ### 启动本服务 ```bash mvn spring-boot:run ``` 服务在 **http://localhost:8082** 启动,MCP 使用路径 `/message` 与 `/sse`。 ### 使用 MCP Inspector 调试 1. 安装 Node.js ≥ 20 2. 在项目目录或任意目录执行: ```bash npx @modelcontextprotocol/inspector ``` 3. 在 Inspector 中配置: - **Transport**:SSE - **URL**:`http://localhost:8082/sse`(必须带 `/sse` 路径) - **Connection type**:Direct ### 连接失败排查(Request timed out / Connection error) - **确认本服务已启动**:终端执行 `mvn spring-boot:run`,看到 "Started JavaMcpApplication" 后再用 Inspector 连接。 - **确认 URL**:填 `http://localhost:8082/sse`,不要漏掉 `/sse`。 - **CORS**:本项目已在 McpConfig 中为 `/message`、`/sse` 配置跨域(允许 `http://localhost:*`、`http://127.0.0.1:*`),Inspector 在浏览器打开时即可直连。若仍超时,先在同一台机器用浏览器访问 `http://localhost:8082/sse` 看是否有响应。 - **Proxy token**:若 Inspector 是通过 Cursor 打开的(地址带 `MCP_PROXY_AUTH_TOKEN`),一般无需改 token;若提示 token 错误,请按 Cursor 文档检查代理与 token 是否一致。 - **MCP error -32603 / LoggingLevel 反序列化错误**:若报错含 `Cannot deserialize value of type ... LoggingLevel from Object value`,说明客户端收到的 capabilities 里 `logging` 是对象格式,而 Inspector 期望为简单值。本项目已在 MyServer 中不声明 `logging` 能力,**请务必重启本服务**后再连。若重启后仍报错,可能是 MCP SDK 在「协议版本协商」响应里自动加了 `logging`,可尝试:用命令行单独启动 Inspector(`npx @modelcontextprotocol/inspector`),在浏览器新标签页里连接,或换用其他 MCP 客户端版本。 - **服务端日志 "Client requested unsupported protocol version: 2025-11-25, so the server will suggest the 2024-11-05 version instead"**:属于正常现象。Inspector 可能请求 2025-11-25,本服务使用 MCP 2024-11-05,服务端会建议客户端使用 2024-11-05;连接仍可建立,若随后出现 -32603,按上一条排查。 ## 调用方如何了解接口 / 接口文档 本服务是 **MCP 协议服务**,不是传统 REST API,因此“接口详情”的获取方式与 Swagger 文档的 REST 接口不同。 ### MCP 下接口(工具)如何被了解 1. **协议内发现** MCP 客户端连接后,会通过协议自带的 **List Tools** 等能力向服务端请求“有哪些工具、每个工具的名称、描述、参数 Schema”。服务端会返回当前注册的所有工具及其 JSON Schema,调用方据此即可知道接口详情,无需单独打开一份“接口文档”。 2. **用 MCP Inspector 当“接口文档”** 用 MCP Inspector 连上本服务后,在界面里可以看到所有工具列表、每个工具的名称与描述,并可直接发起调用测试,相当于“可交互的接口文档”。 3. **本 README 作为人工文档** 上文「已提供的 MCP 工具」表格就是给人类看的接口说明:工具名、说明、参数、来源。对接方可以直接看 README 了解有哪些能力。 ### 若希望有类似 Swagger 的文档 - **当前项目**:没有集成 Swagger/OpenAPI。对外暴露的是 MCP 的 `/message`、`/sse` 等协议端点,不是 REST 的 `GET /api/xxx`,因此传统 Swagger 无法直接描述“MCP 工具”这一层。 - **可选做法**: - **只文档化 HTTP 端点**:集成 [SpringDoc OpenAPI](https://springdoc.org/)(或 Swagger 2 的 `springfox`),为 `/message`、`/sse` 等写简要说明,方便调用方知道“连哪个 URL、什么用途”。工具列表仍以 MCP 协议或 README 为准。 - **自建“工具清单”接口**:单独写一个 REST 接口(如 `GET /tools`),返回当前所有 MCP 工具的名称、描述、参数 Schema(可从 `ToolCallbackProvider` 或现有 Bean 收集),再在 SpringDoc 中展示该接口,就能在 Swagger UI 里看到类似“接口文档”的工具列表。 总结:**调用方了解接口**主要靠 MCP 协议发现 + MCP Inspector 或本 README;若需要 Swagger 风格文档,可在此基础上增加 SpringDoc 并文档化 HTTP 端点或自建工具列表接口。 ## 开发说明 - **新增 MCP 工具**:新建一个 `@Service`,类上加 `@McpToolFlag`,方法上加 `@Tool`、`@ToolParam` 即可;McpConfig 会自动扫描并注册,**无需在 MyServer 中手动注册**。 - **MyServer 的职责**:仅负责创建 MCP 同步服务器并声明 serverInfo、capabilities;工具列表由 McpConfig 从所有 `@McpToolFlag` Bean 中收集。 - 当前 `pom.xml` 中 Surefire 配置为跳过测试(`skip=true`);如需跑测试,可去掉或改为 `false`。