ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring AI接MCP:ChatClient要显式接线

Spring AI接MCP:ChatClient要显式接线 Spring AI 2.0把 MCP 工具接到 ChatClient别指望自动绑定本地Tool不够用、工具散落多服务时Spring AI 2.0 用显式接线把 MCP 收进同一套 tool loop。一、痛点本地工具边界到了多源工具怎么进 Agent团队已经在 Spring Boot 上跑业务用Tool暴露订单查询、库存扣减一类本进程能力路径很顺。痛点通常出现在下一步工具跨进程检索、浏览器自动化、内部网关能力在别的服务里不想为每个源写一套私有 SDK工具要标准化希望用 MCP 这类协议统一 list/call客户端只认一种契约而不是 N 套 HTTP 约定本地与远程要并存核心域仍用本地Tool事务、权限、领域校验都在本 JVM外围能力走 MCP模型侧却应看到同一套可调用面。如果以为「加了 MCP Client starterChatClient 就自动带上所有远程工具」启动日志会安静得过分SyncMcpToolCallbackProviderbean 建好了请求却从没把那些工具定义发给模型。联调时表现成「模型只会聊天、从不调远程工具」很容易被误判成 prompt 或模型能力问题。下面按官方 Tool Calling、MCP Server Boot Starter 文档和 2026-06-15 的官方博文讲Client 显式接线、ServerMcpTool、STREAMABLE / STATELESS / 弃用 SSE、混合命名与安全红线。协议层的无状态演进见本账号 2026-09-23 那篇这里只谈Spring AI 2.0 落地接线协议史不再重复。二、Spring AI 2.0 tool loop先认清执行面2.0 把 tool calling 从各ChatModel私有循环里抬到ChatClient的 advisor 链。官方架构要点可以压缩成四步你定义工具Tool/ programmatic callback / MCP provider 产出的 callback并交给ChatClientChatClient自动注册ToolCallingAdvisor驱动循环模型决定调用哪些工具ToolCallingManager执行有 tool call 就回灌对话历史再请求模型直到模型产出不含 tool call 的响应返回调用方。对已经跑在 Boot 上的团队来说MCP 只是同一条可组合 tool 循环上的一类回调源并没有另起一套并行的 Agent 运行时。本地方法、函数式 callback、远程 MCP 代理最终都落到ToolCallback。官方 2026-06-15 博文《Tool Calling in Spring AI 2.0: A Composable, Agentic Architecture》把「循环可组合、可观察、可扩展」这条主线讲得很清楚。接入 MCP拿到的还是同一套执行语义不用再学第二套框架。所以「工具有没有进模型上下文」完全取决于你有没有把对应的ToolCallback/ToolCallbackProvider传进.tools(...)或.defaultTools(...)。Starter 只负责连接与发现不替你做最后一跳。三、Client接 MCP但必须显式 wire依赖dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-mcp-client/artifactId/dependencystdio 连接示例文档模式可按环境换成真实 command/argsspring.ai.mcp.client.stdio.connections.my-server.commandnpx spring.ai.mcp.client.stdio.connections.my-server.args-y,modelcontextprotocol/server-everything自动配置会连上已声明的 MCP server发现工具并暴露SyncMcpToolCallbackProviderSYNC 默认ASYNC 客户端类型对应AsyncMcpToolCallbackProvider。到这一步你只是「有了 provider bean」还没有「ChatClient 每轮都会带上这些工具」。关键设计MCP providers 故意不自动注册到 ChatClient。这条建议直接写进评审清单。官方给的理由它们虽然实现了ToolCallbackProvider但如果启动阶段就急着listTools每个已连接的 MCP server 都要多打一轮网络往返。正确做法是注入 provider再用.defaultTools(mcpTools)对该 builder 构建的每次请求默认可用或单次请求的.tools(mcpTools)显式挂上AutowiredSyncMcpToolCallbackProvidermcpTools;// 作为该 ChatClient 的默认工具面ChatClientchatClientChatClient.builder(chatModel).defaultTools(mcpTools).build();// 或仅本轮追加与 defaults 取并集文档语义为 append 而非替换chatClient.prompt().user(Search the web for the latest Spring AI release notes).tools(mcpTools).call().content();Tool callback 自动配置默认开启若只要维护 MCP 连接、暂不把回调交给 ChatClient可关spring.ai.mcp.client.toolcallback.enabledfalse排障看三点starter 有 ≠ ChatClient 有工具——先确认 provider bean再确认 builder / 调用链是否传入defaults 与 per-call 都要有意识——全局放「只读、低风险」工具破坏性操作更适合 per-call 挂载关 toolcallback 是显式选择——联调期临时关掉可以但不要把「关掉后模型当然调不到」当成玄学。四、Server用McpTool把 Spring Bean 暴露出去反过来把本服务的能力提供给外部 MCP 客户端。WebMVC 路径dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-mcp-server-webmvc/artifactId/dependencyComponentpublicclassWeatherTools{McpTool(descriptionGet the current weather for a given city)publicStringgetWeather(McpToolParam(descriptionCity name)Stringcity){returnweatherService.fetch(city);}}注意注解分工对外 MCP 暴露McpTool/McpToolParam本进程给 ChatClient 用仍是Tool以及 Spring AI 的ToolParam。自动配置会扫描带 MCP 注解的 Bean生成参数 JSON Schema注册到 MCP server。服务端这一侧是「扫注解即注册」别把这套「自动」误推到 Client→ChatClient 那一侧。协议用属性选定同一 WebMVC starterspring.ai.mcp.server.protocolSTREAMABLE选型对照只做定性比较不给延迟、吞吐数字协议配置值适用直觉备注Streamable-HTTPSTREAMABLE独立进程、多客户端 HTTP官方推荐方向替代 SSEStatelessSTATELESS简化部署、偏云原生、弱会话诉求与协议无状态部署友好SSESSE存量自 2.0.0 弃用勿新开STDIO另用 stdio server starter stdiotrue进程内宿主不经 HTTP新项目默认写STREAMABLE明确要「无会话、进一步简化」时再评估STATELESS。SSE 只该留在迁移清单里别再进模板仓库当默认值。五、安全红线HTTP MCP 默认无鉴权官方 Server Boot Starter 文档写得很直SSE、Streamable-HTTP、Stateless 这几类HTTP 传输默认暴露未认证的 JSON-RPC 端点starter不会自带认证授权。默认路径如POST /mcp接受请求意味着能打到端点的客户端就可以枚举并调用已注册的工具、资源与 prompt。落地要求可直接贴进安全评审非 localhost 暴露前必须放置 Spring Security 或其它明确边界文档亦将 MCP Security 等列为可选加固路径把「注册一个McpTool」当成「决定对外暴露该能力」——注解即暴露边界STDIO跑在进程内、不走网络不适用上述 HTTP 裸奔警告但仍受本机进程与宿主信任边界约束。评审里要是只写「先联调、鉴权以后再说」就等于把 list/call 面挂在可达网络上。这怪不到 MCP 协议头上问题出在边界缺失。Client 侧也一样你连的远程 MCP server 工具面是否可信、有没有过滤决定了模型拿到工具定义后能碰到多大的操作半径。六、混合本地 MCP以及命名冲突谁负责本地Tool方法与远程 MCP 工具共享同一ToolCallback接口模型与ToolCallingAdvisor并不区分来源。.tools(...)/.defaultTools(...)是异构参数列表一次调用里可以混挂chatClient.prompt().tools(newLocalTools(),mcpTools).call().content();冲突与过滤规则要记准DefaultMcpToolNamePrefixGenerator处理跨 MCP server的重名加前缀消歧它不管「本地Tool名」与「某个 MCP 工具名」撞车——需要你自己改名或用McpToolFilter按 server 身份、工具名、描述过滤远程面MCP 工具来自你不完全可控的外部源时Filter 就是缩小爆炸半径的首选手段别当可选项。生产建议核心写路径、带事务与鉴权的能力保留本地Tool并严格命名空间例如order.cancel风格外围只读/检索类能力走 MCP并通过 Filter 白名单放行破坏性工具优先 per-call.tools(...)少放进全局.defaultTools(...)。七、决策清单给已上 Boot 的团队可复制到技术方案或 PR 描述场景分流本进程业务能力 → 本地Tool跨服务标准契约 → MCP Client对外输出能力 → MCP ServerMcpTool。协议新 HTTP 服务优先STREAMABLE明确无会话诉求再选STATELESS不要新开SSE。接线注入SyncMcpToolCallbackProvider或 Async 对应类型.defaultTools/.tools显式绑定禁止假设自动绑定。开关不需要把 MCP 回调交给 ChatClient 时设spring.ai.mcp.client.toolcallback.enabledfalse。命名本地与 MCP 撞名自行处理多 server 依赖 PrefixGenerator再加McpToolFilter。安全HTTP 端点上线前必须鉴权STDIO 仅限信任进程边界把「注册工具」当暴露决策。与协议文互补读过 2026-09-23 MCP 无状态协议文的同事用本文补齐 Spring AI 侧 starter、注解与 ChatClient 接线避免两篇文章互相复述。八、常见误区落地评审常撞「加了 client starter 就会自动进 ChatClient」— 不会。官方明确 MCP provider 不 auto-register必须.defaultTools/.tools。「Server 扫了McpToolClient 侧也会自动扫」— 两边不对等Server 注解扫描是自动注册到 MCP serverClient 到 ChatClient 仍是显式接线。「SSE 还能当新项目默认」— 自 2.0.0 弃用新工作优先STREAMABLE。「HTTP 先裸奔联调鉴权后补」— 默认无鉴权意味着可达即 list/call非 localhost 前必须有边界。「PrefixGenerator 能解决本地与 MCP 重名」— 不能它只覆盖跨 MCP server本地冲突靠改名或McpToolFilter。九、小结Spring AI 2.0 把 MCP 收进与本地工具同一套ToolCallingAdvisor循环但MCP 不会自动挂上 ChatClient——必须显式.defaultTools/.tools。Clientspring-ai-starter-mcp-client→SyncMcpToolCallbackProviderSYNC 默认→ 注入后接线可用toolcallback.enabledfalse关闭回调自动配置。Serverspring-ai-starter-mcp-server-webmvcMcpTool/McpToolParam新项目spring.ai.mcp.server.protocolSTREAMABLE避开自 2.0.0 弃用的 SSE。HTTP MCPSSE / Streamable / Stateless默认无鉴权非本机必须加 Spring Security 或等价边界。本地与 MCP 可混合跨 MCP 重名有 PrefixGenerator本地 vs MCP 撞名要自己改名或 Filter。封面建议浅色技术风左侧 MCP Serversstdio / STREAMABLE箭头指向中间 SyncMcpToolCallbackProvider右侧 ChatClient 标注「须 .defaultTools/.tools」底部红字「HTTP 默认无鉴权」主标题「别指望自动绑定」副标题「Spring AI 2.0 × MCP」蓝/橙对比避免大段代码截图。END
返回列表