基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-10 22:43

用 Spring AI 将内部接口接入 MCP

dev.to · AI#MCP#Java#Spring AI
Editor brief · 编辑速览

教程通过完整 Java 项目,将内部业务接口封装成 Claude、Cursor 等客户端可调用的 MCP 工具。服务端项目无需大模型 API 密钥即可运行,旨在减少不同 AI 客户端重复集成内部系统的工作。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

让 Claude 查一笔内部订单,难点往往不在模型能力,而在它接触不到订单系统。原文用 Spring AI 搭建 MCP Server,把查询、搜索和退款操作变成 Claude、Cursor 可以发现并调用的工具,试图减少每增加一个 AI 客户端就重写一套集成的成本。

值得读的是它把协议交互、Java 注解和工具描述串到了一起。但提供的原文在退款方法和 curl 验证命令处都有截断,因此它更适合作为实现思路参考,不能直接当成完整可运行项目。

MCP 减少的是重复集成,模型并不会因此自动懂业务

作者面对的是一个常见问题:订单、库存、日志分属不同系统,产品经理用 Claude Desktop,工程师用 Cursor,内部客服又有自己的 Agent。每条接入链路都要处理工具描述、参数和错误,系统与客户端越多,重复工作越多。

MCP 希望把这种关系从 M×N 变成 M+N:客户端遵守统一协议,业务系统通过统一接口发布能力,各自完成一侧适配。

这里有三个角色。Host 是用户操作的应用,例如 Claude Desktop、Cursor;Client 是 Host 内部连接某个 Server 的连接器;Server 则是开发者编写的能力提供方。一个 Host 可以启动多个 Client,分别连接多个 Server。

Server 提供的能力也有区别:

  • Tools 是模型可以选择调用的操作,例如查询订单。
  • Resources 是客户端可以读取并放入上下文的资料,例如排障手册。
  • Prompts 是用户通过界面选择的提示模板,例如退款审核清单。

模型并不直接处理 MCP。Host 负责把工具列表转换成模型理解的 Function Calling 格式,再把调用结果送回模型。

因此,工具接上了,不代表模型就会用对。作者建议把「查询订单」写成「按订单号查询详情,订单号以 SO 开头」,让描述同时交代用途、参数格式和操作边界。

工具描述是模型选择操作的依据,但不是业务规则的执行器。

先走通协议,再排查 Claude 和 Cursor

原文把一次调用拆成初始化、列举工具和执行工具。消息使用 JSON-RPC 2.0,初始化示例如下:

{"jsonrpc":"2.0","id":1,"method":"initialize",
 "params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"cursor","version":"1.0"}}}

重点是 protocolVersion。它表达客户端使用的协议版本;clientInfo.version 中的 1.0 是另一项客户端信息,两者不能混为一谈。

初始化之后,Client 发送 notifications/initialized 表示就绪。它没有 id,属于通知,不应等待对应的 JSON-RPC 响应。随后通过 tools/list 获取工具名称、描述和 inputSchema,再用 tools/call 提交工具名与参数。执行结果放在 content 数组里,供模型继续处理。

传输方式有两种。stdio 由 Host 启动子进程,通过标准输入输出交换消息,适合本地工具。它最容易踩的坑是日志污染:stdout 必须只输出协议数据,额外的 System.out.println 或 INFO 日志都可能破坏解析。

Streamable HTTP 更适合独立部署、供多个客户端访问。原文指出,2025-03-26 规范修订引入这种方式,替代早期收发分离的 HTTP+SSE 设计。示例把入口统一为 /mcp,响应可以是 JSON,也可以采用服务器发送事件(SSE)格式。

作者展示的有状态流程会从响应头取得 Mcp-Session-Id,后续请求携带它关联会话。不过,原文对断线恢复的描述比较笼统,没有提供相关服务端配置,不能据此认定所有部署都能自动续接。

排障顺序很实用:先用 mvn spring-boot:run 启动,再用 curl 验证协议,最后连接 AI 客户端。遗憾的是,提供的 curl 内容在第二步请求头处截断,无法照抄完成验证。

Spring AI 省掉协议代码,参数和写操作仍要自己管

示例采用 Java 21、Spring Boot 4.1.2、Spring AI 2.0.2,通过 spring-ai-bom 管理依赖,并引入 spring-ai-starter-mcp-server-webmvc。这些是原文列出的版本组合,提供的材料没有附带构建结果。

服务监听 8080,应用名为 mcp-order-server,MCP Server 名为 order-admin、版本为 1.0.0;配置使用 protocol: streamable 和 type: sync。tool-response-mime-type 将 get_order 标记为 application/json。

Spring AI 扫描 @McpTool 方法,根据签名和 @McpToolParam 生成 JSON Schema,注册工具,再在收到调用时执行方法、序列化结果。下面这段展示了如何把订单查询变成工具:

    @McpTool(
            name = "get_order",
            description = "按订单号查询订单详情,返回状态、金额、下单时间。订单号格式为 SO 加日期加序号。这是只读操作。",
            annotations = @McpTool.McpAnnotations(readOnlyHint = true, openWorldHint = false))
    public Order getOrder(
            @McpToolParam(description = "订单号,例如 SO20261027001", required = true) String orderNo) {
        Order order = orders.get(orderNo.trim().toUpperCase(Locale.ROOT));
        if (order == null) {
            throw new IllegalArgumentException("订单不存在: " + orderNo);
        }
        return order;
    }

要看的是参数声明这一行:@McpToolParam 只有 description 和 required,参数名依赖编译后的字节码,因此需要 -parameters。作者说明 Spring Boot 父 POM 默认启用它;迁移旧项目或使用公司统一编译配置时,应检查生成的 Schema 是否出现 arg0、arg1。

另外两个工具是 search_orders 和 create_refund_ticket。搜索支持客户姓名、状态与页码,页码从 1 开始,每页 10 条;状态包括 PAID、SHIPPED、REFUNDING、CLOSED。分页的目的很直接:避免把大量订单塞进模型上下文。

退款工具带有 readOnlyHint = false、destructiveHint = true、idempotentHint = false,并要求调用前确认订单号和原因。可见代码会把状态改成 REFUNDING,拒绝 CLOSED 订单,但方法尾部缺失,也没有展示持久化工单流程。

Resource 用 @McpResource 暴露 ops://runbook/{service},返回 text/markdown 排障手册。Prompt 用 @McpPrompt 注册 refund-review,通过 @McpArg 接收订单号和原因;@McpComplete 提供示例订单号的前缀补全。这让业务操作、参考资料和人工发起的工作流各有入口。

我的判断

我认同它最有用的两点:复用协议适配,以及先验证服务、再连接客户端。前者适合确实存在多个 AI 入口的团队,后者能缩小排障范围。只有一个内部 Agent、少量固定接口时,直接使用 Function Calling 也可以,原文没有提供两种方案的成本对照。

工具命名、明确错误和分页都是合理的工程建议,但作者没有给出工具选择准确率、失败重试率或 token 消耗的对照数据。「描述改好后命中率立刻变化」应当视为经验判断。

更需要打问号的是确认机制。原文把 destructiveHint 与客户端确认弹窗联系得很紧,却没有提供客户端版本、配置或验证记录。提示和注解可以表达意图,不能替代服务端授权、状态校验与幂等控制。

示例数据也保存在 ConcurrentHashMap 中。它展示了调用路径,尚未覆盖真实订单系统的持久化与操作审计。服务端不需要 LLM API key,则是因为它只发布能力;模型如何接入仍由客户端负责。

能拿来做什么

  • 如果团队同时用 Claude Desktop、Cursor 和内部 Agent 查业务数据,可以先用一个只读 get_order 验证复用价值,检查三个入口是否能理解同一份工具描述与参数。
  • 接入现有 Java 服务时,先检查 -parameters 和 tools/list 的输出,再调模型提示,避免把参数名丢失误判为模型能力问题。
  • 做订单搜索时,沿用分页、明确状态值和显式错误的设计,让模型获得可解释、可继续处理的结果。
  • 增加退款等写操作前,先补齐服务端权限、状态检查和幂等处理,再验证客户端如何呈现确认;不要把 instructions 中的确认要求当成操作保障。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
修改小模型权重,减少反复校验耗费
下一篇
六周提交143个 PR,智能体贡献经验复盘

资讯速览

dev.to · AI · 2026-11-10 22:43

AI 评分 8.0 / 10

相关标签

#MCP#Java#Spring AI

继续阅读

  • 用桌面角色提醒 Claude Code 等待确认
  • 修改小模型权重,减少反复校验耗费
  • 六周提交143个 PR,智能体贡献经验复盘
  • 智能体排障遗漏了上游检索决策
  • 实时特征偏差,可能藏在 Flink 水位线里