# springai-mcp **Repository Path**: cjpyun/springai-mcp ## Basic Information - **Project Name**: springai-mcp - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-21 - **Last Updated**: 2026-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring AI + MCP 最佳实践完整案例 ## 📌 什么是 MCP? MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 推出的开放协议,它解决了一个核心痛点: > **大模型如何安全、标准化地访问外部工具和数据?** 在 MCP 出现之前,每个 AI 框架都有自己的一套工具调用方式,工具无法跨框架、跨语言复用。MCP 把这件事标准化了——工具怎么描述、怎么发现、怎么调用,统一走 JSON-RPC 2.0。 ### 核心概念 | 角色 | 职责 | 类比 | |---|---|---| | **MCP Server** | 暴露工具、资源、提示词 | 提供服务的"后端" | | **MCP Client** | 连接 Server,发现并调用工具 | 消费服务的"前端" | | **大模型(LLM)** | 自主决策何时调用哪个工具 | 智能调度者 | ### 三种传输模式 | 模式 | 适用场景 | 优缺点 | |---|---|---| | **STDIO** | 本地开发、单机工具 | 零依赖,但只能本地使用 | | **Streamable HTTP** | 微服务、远程部署 | ✅ 官方推荐,支持多客户端 | | HTTP + SSE | 旧版兼容 | ❌ 2.0 已弃用 | --- ## 🏗️ 项目结构 ``` springai-mcp-best-practice/ ├── mcp-server/ # MCP 服务端(暴露业务工具) │ ├── pom.xml │ └── src/main/ │ ├── java/com/example/mcp/server/ │ │ ├── McpServerApplication.java # 启动类 │ │ ├── tool/ │ │ │ ├── CalculatorTool.java # 计算器工具(基础示例) │ │ │ ├── WeatherTool.java # 天气查询工具(复杂返回值) │ │ │ └── EmployeeTool.java # 员工管理工具(企业级场景) │ │ └── resource/ │ │ └── KnowledgeBaseResource.java # MCP Resource 示例 │ └── resources/ │ └── application.yml │ └── mcp-client/ # MCP 客户端(AI 应用) ├── pom.xml └── src/main/ ├── java/com/example/mcp/client/ │ ├── McpClientApplication.java # 启动类 │ ├── config/ │ │ └── ChatClientConfig.java # ChatClient + MCP 工具配置 │ └── controller/ │ └── ChatController.java # 聊天接口 └── resources/ └── application.yml ``` --- ## 🚀 快速开始 ### 前置条件 - JDK 17+ - Maven 3.6+ - 一个可用的大模型 API Key(本示例用 DeepSeek,可替换为 OpenAI 等) ### 步骤 1:启动 MCP Server ```bash cd mcp-server mvn spring-boot:run ``` 服务启动在 `http://localhost:8081`,MCP 端点为 `POST /mcp`。 ### 步骤 2:配置并启动 MCP Client 设置环境变量(或修改 application.yml): ```bash export DEEPSEEK_API_KEY="你的 deepseek api key" export DEEPSEEK_BASE_URL="https://api.deepseek.com" ``` 启动客户端: ```bash cd mcp-client mvn spring-boot:run ``` ### 步骤 3:测试 ```bash # 数学计算 curl "http://localhost:8080/api/chat?question=12345加67890等于多少" # 天气查询 curl "http://localhost:8080/api/chat?question=北京今天天气怎么样" # 员工查询 curl "http://localhost:8080/api/chat?question=技术部有多少人,平均薪资是多少" # 薪资排名 curl "http://localhost:8080/api/chat?question=薪资最高的三个人是谁" # 流式响应 curl -N "http://localhost:8080/api/chat/stream?question=帮我分析一下各部门的薪资情况" ``` --- ## 🔑 最佳实践要点 ### 1. 工具描述越精准,调用越准确 **坏例子**: ```java @Tool(name = "calc", description = "计算器") ``` **好例子**: ```java @Tool( name = "calculator_add", description = "将两个数字相加,返回计算结果。当用户需要做加法运算时使用此工具。" ) ``` > description 要写清楚"什么时候用",而不是"是什么"。大模型是靠语义匹配来选择工具的。 ### 2. 一个工具类只做一类事 不要把所有工具方法塞到一个类里,按业务领域拆分: - `CalculatorTool` — 数学计算 - `WeatherTool` — 天气查询 - `EmployeeTool` — 员工管理 这样代码清晰,也方便大模型理解每个工具的用途。 ### 3. 用 @ToolParam 描述每个参数 ```java public int add( @ToolParam(description = "第一个加数", required = true) int a, @ToolParam(description = "第二个加数", required = true) int b ) ``` 参数描述是给大模型看的,它决定了大模型能不能正确传参。**尤其是复杂参数,一定要写清楚含义和取值范围。** ### 4. 返回值用结构化数据 工具方法的返回值会被大模型读取,建议返回: - `Map` — 灵活,适合大多数场景 - 自定义 POJO — 适合固定结构的业务数据 - `List` — 列表数据 **不要返回纯字符串**,大模型解析纯文本容易出错。 ### 5. 生产环境用 Streamable HTTP 模式 STDIO 只适合本地开发,生产环境必须用 HTTP 模式: - 支持多客户端并发连接 - 可以独立部署和扩缩容 - 日志输出不会干扰通信 - 支持负载均衡 ### 6. ChatClient 配置为单例 Bean ```java @Bean public ChatClient chatClient(ChatClient.Builder builder, ToolCallbackProvider mcpToolProvider) { return builder .defaultTools(mcpToolProvider) .defaultSystem("...") .build(); } ``` 不要在 Controller 里每次 `new ChatClient`,配置成 Bean 复用即可。 ### 7. 系统提示词引导工具使用 在 system prompt 中明确告诉大模型:**什么时候该用工具,不要瞎编数据**。 ``` 你是一个智能助手,可以使用提供的工具来回答用户问题。 当问题涉及数学计算、天气查询、员工信息等内容时, 请先调用对应的工具获取准确数据,再基于工具返回的结果回答。 不要编造数据,不确定的信息请通过工具查询。 ``` ### 8. 开启 MCP 调试日志 排查问题时打开: ```yaml logging: level: io.modelcontextprotocol: DEBUG org.springframework.ai.mcp: DEBUG ``` 可以看到完整的协议交互过程,包括工具列表、调用参数、返回结果。 --- ## 🎯 典型使用场景 ### 场景 1:存量系统接入 AI 已有 Spring Boot 业务系统 → 加 `@Tool` 注解 → 立即可被 AI 调用,零侵入改造。 ### 场景 2:企业内部知识库 用 MCP Resource 暴露公司文档、规章制度 → 大模型可以读取并基于这些知识回答问题。 ### 场景 3:多模型共享工具生态 工具用 MCP 协议实现一次 → 可以被 Spring AI、Claude Desktop、Cursor、Windsurf 等任何 MCP 客户端调用。 ### 场景 4:安全的数据访问 敏感数据不离开内网 → MCP Server 部署在内网 → 大模型只调用工具,不直接接触原始数据。 --- ## ⚠️ 常见问题 ### Q1:大模型不调用工具怎么办? 排查思路: 1. 工具的 `description` 是不是不够清晰?试试写得更详细 2. 系统提示词有没有明确引导使用工具? 3. 工具参数的描述是不是清晰?大模型可能不知道该传什么 4. 打开 DEBUG 日志,看工具列表有没有正确注册 ### Q2:MCP Server 连接失败? 1. 确认 Server 已经启动,端口正确 2. 检查客户端配置的 URL 是否正确(`http://localhost:8081/mcp`) 3. 确认 Server 端 protocol 和 Client 端传输模式匹配 4. 打开 DEBUG 日志看具体错误信息 ### Q3:工具返回值大模型理解错了? 1. 尽量返回结构化数据(Map / POJO),不要返回纯文本 2. 字段命名要语义清晰,不要用缩写 3. 可以在工具 description 里补充说明返回值格式 ### Q4:可以连接多个 MCP Server 吗? 可以!在配置里加多个 connections 就行: ```yaml spring: ai: mcp: client: streamable-http: connections: server1: url: http://server1:8081/mcp server2: url: http://server2:8082/mcp ``` 所有 Server 的工具都会被自动注册到大模型中。 --- ## 📚 参考资料 - [Spring AI 官方文档](https://docs.spring.io/spring-ai/reference/) - [MCP 官方规范](https://modelcontextprotocol.io/) - [MCP Java SDK](https://github.com/modelcontextprotocol/java-sdk)