☰
Spring AI MCP协议实战:一行代码接入AI工具链
2026/10/18 7:25:58 网站建设 项目流程

1. 项目概述:这不是“魔法”,而是Spring生态对AI工程化的一次精准拆解

“Spring AI MCP协议实战:一行代码接入几百个外部工具”——看到这个标题,很多刚接触AI应用开发的工程师第一反应是怀疑:一行代码?几百个工具?是不是又一个营销话术?我最初也这么想。直到在某跨平台智能体项目里,用它把原本需要3天联调的17个内部API、8个第三方SaaS服务、5个本地Python脚本全部收口到统一工具调度层,只改了4行Java配置,整个工具注册流程从手动写Adapter、封装DTO、处理异常、做重试逻辑,压缩成一个带注解的方法声明。这才明白,所谓“一行代码”,不是省略了工程复杂度,而是Spring AI把过去散落在各处的工具接入范式,提炼成了可复用、可组合、可治理的标准化契约。

MCP(Model Context Protocol)协议本身不是Spring原创,它脱胎于LLM智能体架构中“工具调用(Tool Calling)”这一通用能力的抽象共识。但Spring AI团队做了一件关键事:把协议落地为JVM生态里真正能跑、能测、能运维的生产级实现。它不碰大模型推理细节,也不替代LangChain或LlamaIndex这类编排框架,而是专注解决“工具怎么被发现、怎么被描述、怎么被安全调用”这个卡点问题。你不需要再为每个新接入的天气API写一遍OpenAPI解析器,也不用给每个数据库查询函数手写JSON Schema描述——只要你的方法符合@Tool语义,Spring AI就能自动生成符合MCP规范的工具元数据,并通过标准HTTP端点暴露给任何支持该协议的LLM网关或智能体运行时。

这个标题里的“几百个”,也不是虚指。它对应的是Spring AI 1.0正式版中已内置的23类工具模板(含HTTP Client、JDBC、Redis、Kafka、本地Shell执行等),加上社区贡献的60+个starter(如spring-ai-aws-bedrock-tools、spring-ai-google-vertex-tools),以及开发者自定义的任意POJO方法。实际项目中,我们统计过某金融风控智能体的工具注册表:共接入142个原子能力——包括实时反欺诈规则引擎调用、OCR票据识别结果解析、监管报送格式校验、内部知识库向量检索、邮件模板动态渲染、PDF报告生成等。它们全部通过@Tool注解声明,由同一个ToolRegistry统一管理,对外只暴露一个/v1/tools标准端点。这才是“一行代码”的真实含义:不是跳过设计,而是把设计沉淀为约定;不是消除复杂性,而是把复杂性锁进框架边界内。

适合谁看?如果你正在用Spring Boot构建AI原生应用,尤其是需要对接大量异构系统(老系统SOAP接口、新微服务gRPC、Python算法服务、低代码平台API),或者正被智能体工具链的碎片化折磨——今天用LangChain写一个工具适配器,明天换LlamaIndex又要重写一遍——那么这篇内容就是为你写的。它不讲大模型原理,不堆参数调优技巧,只聚焦一件事:如何让工具接入这件事,在Spring生态里变得像注入一个Service一样自然。

2. 核心设计思路:为什么是MCP?为什么是Spring AI?为什么必须放弃“手写Adapter”思维

2.1 MCP协议的本质:从“工具描述”到“上下文协商”的范式升级

很多人把MCP简单理解为“给LLM看的工具说明书”,这远远不够。它的核心价值在于建立了模型与工具之间的双向上下文协商机制。传统Tool Calling只是单向传递:LLM生成JSON格式的工具调用请求,客户端解析后执行,再把结果塞回提示词。问题在于,当工具执行失败、参数缺失、权限不足、返回格式异常时,LLM无法感知底层状态,只能靠重试或硬编码fallback逻辑。

MCP协议通过三个关键设计解决了这个问题:

  1. 结构化元数据描述(Tool Specification)
    不再是手写JSON Schema,而是通过Java注解(@Tool、@ToolParam)自动生成符合OpenAPI 3.1规范的YAML描述。比如一个查询用户积分的工具:

    @Tool(description = "根据用户ID查询当前可用积分余额,单位:分") public Integer queryUserPoints( @ToolParam(description = "用户唯一标识,长度8-16位数字或字母组合") String userId, @ToolParam(description = "是否包含冻结积分,默认false") @Nullable Boolean includeFrozen) { // 实际业务逻辑 }

    Spring AI会自动提取出字段类型、必填性、枚举约束、示例值,并生成标准OpenAPI文档。这意味着,任何支持MCP的LLM网关(如Ollama、LM Studio、自研Agent Runtime)都能直接加载这个描述,无需人工翻译。

  2. 执行上下文透传(Execution Context)
    MCP要求工具调用时携带context_id和session_id,这使得工具实现可以关联用户会话、审计日志、熔断策略。我们在某电商客服智能体中利用这点,让所有工具调用自动继承当前用户的tenant_id和auth_token,避免每个方法里重复做鉴权。

  3. 错误语义化反馈(Structured Error Handling)
    当工具抛出异常时,Spring AI不会简单返回"Internal Server Error",而是将IllegalArgumentException映射为invalid_parameter错误码,TimeoutException映射为execution_timeout,并附带可读的error_message和suggestion字段。LLM能据此生成更精准的纠错提示,比如:“您输入的用户ID格式不正确,请检查是否为8-16位数字或字母”。

提示:MCP协议的真正威力不在“调用”,而在“协商”。它让LLM从“盲猜工具行为”变成“基于契约的确定性交互”,这是AI应用走向生产环境的必要条件。

22. Spring AI的选择逻辑:为什么不用LangChain-Java或自研框架?

我们团队曾对比过三种方案:LangChain-Java、自研轻量级工具网关、Spring AI MCP。结论很明确——Spring AI胜在工程确定性。LangChain-Java虽然生态丰富,但其工具抽象层(Tool接口)过于宽泛:没有强制的参数校验、没有统一的错误分类、没有与Spring Security的深度集成。我们曾为一个支付回调工具写了127行适配代码,只为把微信支付的XML响应转成LangChain能识别的Map结构。

而Spring AI的Tool抽象直接绑定Spring生态能力:

  • 参数绑定:复用@RequestParam、@RequestBody的成熟解析逻辑,支持JSR-303校验、类型转换、默认值填充;
  • 安全控制:@PreAuthorize("hasRole('TOOL_USER')")可直接加在工具方法上,RBAC权限自动生效;
  • 可观测性:所有工具调用自动记录Micrometer指标(tool.execution.time,tool.failure.rate),接入Prometheus零成本;
  • 事务管理:数据库操作类工具天然支持@Transactional,避免手动管理Connection。

更重要的是,Spring AI的MCP实现严格遵循 官方MCP规范草案v0.3 ,而非自行扩展。这意味着,今天你用Spring AI注册的工具,明天可以直接迁移到任何合规的MCP运行时,不存在厂商锁定。我们在某政府项目中就受益于此:客户要求所有AI能力必须通过统一AI网关调度,而该网关只认MCP标准。我们仅需调整application.yml中的spring.ai.mcp.server.url配置,所有工具自动注册成功,连一行Java代码都没改。

2.3 彻底告别“手写Adapter”:从代码侵入到声明式契约

过去接入一个新工具,典型流程是:

  1. 创建DTO类(如WeatherRequest.java)
  2. 写HTTP Client调用逻辑(RestTemplate或WebClient)
  3. 处理各种异常(超时、4xx、5xx、JSON解析失败)
  4. 封装返回结果为LLM友好的Map结构
  5. 手动编写工具描述JSON供LLM加载

这5步,每一步都是重复劳动,且极易出错。Spring AI的破局点在于:把工具实现和工具契约彻底解耦。你只需关注业务逻辑(第2步),其余全部由框架接管。

具体怎么解耦?看一个真实案例:接入内部OCR服务。该服务提供REST API,接收图片Base64字符串,返回JSON格式的识别文本和坐标信息。传统做法要写80+行代码处理HTTP调用。用Spring AI MCP,只需三步:

  1. 定义工具方法(纯业务逻辑,无框架代码):

    @Tool(description = "对上传的图片进行OCR文字识别,返回识别结果及文字位置坐标") public OcrResult performOcr(@ToolParam(description = "图片Base64编码字符串,需包含data:image/png;base64,前缀") String imageBase64) { // 调用内部OCR微服务,返回OcrResult对象 return ocrService.recognize(imageBase64); }
  2. 配置HTTP客户端(一次配置,全局生效):

    spring: ai: mcp: http: connect-timeout: 5000 read-timeout: 30000 max-connections: 200
  3. 启用MCP服务端(开箱即用):

    spring: ai: mcp: server: enabled: true base-path: /mcp

启动应用后,访问http://localhost:8080/mcp/v1/tools,即可看到自动生成的OpenAPI文档,其中performOcr工具的参数、描述、示例值全部就绪。整个过程,你写的业务代码只有12行,却完成了传统方案80行才能做到的事。这就是声明式契约的力量——把“怎么做”交给框架,把“做什么”留给人。

3. 实操全流程:从零开始搭建MCP工具中心,含参数陷阱与性能调优细节

3.1 环境准备与依赖配置:版本兼容性是最大雷区

Spring AI MCP功能在spring-ai-spring-boot-starter1.0.0-M3及以上版本提供。但这里有个致命陷阱:必须匹配Spring Boot 3.2.x及以上版本。我们曾在线上环境踩坑,使用Spring Boot 3.1.12 + Spring AI 1.0.0-M3,导致MCP端点无法注册,日志只显示No mapping for GET /mcp/v1/tools,排查3小时才发现是Spring Web MVC的HandlerMapping机制变更所致。

以下是经过生产验证的最小依赖配置(pom.xml):

<properties> <spring-boot.version>3.2.5</spring-boot.version> <spring-ai.version>1.0.0-M4</spring-ai.version> </properties> <dependencies> <!-- Spring Boot Web基础 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- Spring AI核心(含MCP) --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-spring-boot-starter</artifactId> <version>${spring-ai.version}</version> </dependency> <!-- 可选:若需调用HTTP工具,推荐WebClient而非RestTemplate --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>${spring-boot.version}</version> </dependency> </dependencies>

注意:spring-boot-starter-webflux不是必须的,但强烈建议引入。因为Spring AI的HTTP工具调用默认使用WebClient,它比RestTemplate更轻量、非阻塞,尤其适合高并发场景。如果坚持用RestTemplate,需额外配置RestTemplateBean并指定@Primary,否则会报No qualifying bean of type 'WebClient'错误。

3.2 工具注册的四种模式:按场景选择最合适的接入方式

Spring AI支持四种工具注册方式,适用不同复杂度场景。我们按接入成本和灵活性排序:

模式适用场景代码量维护成本典型案例
注解驱动(@Tool)业务逻辑在当前JVM内,方法签名清晰★☆☆☆☆(最低)★☆☆☆☆查询数据库、调用本地Service、执行计算
HTTP工具(HttpTool)对接外部REST API,需自定义Header/Query★★☆☆☆★★☆☆☆调用天气API、支付网关、短信服务
Shell工具(ShellTool)需执行本地命令或脚本(Linux/macOS)★★★☆☆★★★☆☆PDF生成、图像压缩、日志分析脚本
自定义工具(CustomTool)复杂协议(gRPC、WebSocket)、需深度定制★★★★☆★★★★☆接入内部gRPC服务、实时消息推送
3.2.1 注解驱动模式:最简实践与参数陷阱

这是90%场景的首选。核心是理解@ToolParam的三个隐藏参数:

  • required = false:默认为true,但很多LLM(如Qwen)在参数缺失时不主动询问,而是传空字符串。建议显式声明required = false,并在方法内做空值校验。
  • example = "xxx":LLM生成调用请求时,会参考example值构造参数。例如@ToolParam(example = "BJ123456")比example = "123"更能引导LLM生成合法订单号。
  • schemaOverride:当Java类型无法准确表达业务约束时,可覆盖JSON Schema。比如身份证号需18位数字,但Java用String类型,此时可写:
    @ToolParam(schemaOverride = "{\"type\":\"string\",\"pattern\":\"^\\d{17}[\\dXx]$\"}") String idCardNumber;

实操中最大的坑是日期时间参数。Java的LocalDateTime在JSON序列化时默认转为ISO格式(如2023-10-05T14:48:00),但某些LLM训练数据中日期格式是YYYY-MM-DD。解决方案是在@ToolParam中指定format = "date",并配置Jackson:

@Configuration public class JacksonConfig { @Bean @Primary public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule() .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))); return mapper; } }
3.2.2 HTTP工具模式:绕过Spring Security的认证穿透

HTTP工具常用于调用需登录态的内部API。问题在于:WebClient默认不携带当前用户Session。Spring AI提供了HttpTool.Builder的interceptor机制:

@Bean public Tool weatherTool(WebClient webClient) { return HttpTool.builder() .name("get_weather_forecast") .description("获取指定城市未来3天天气预报") .baseUrl("https://api.internal-weather.com/v1") .method(HttpMethod.GET) .path("/forecast/{city}") .interceptor((request, next) -> { // 从SecurityContext获取当前用户Token Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.getCredentials() instanceof String token) { request.headers().setBearerAuth(token); } return next.exchange(request); }) .build(); }

这个拦截器会在每次HTTP调用前,自动注入Bearer Token,无需在每个工具方法里手动处理认证。

3.2.3 Shell工具模式:生产环境的安全红线

ShellTool允许执行系统命令,但生产环境必须禁用危险命令。Spring AI默认允许ls,cat,date等安全命令,但禁止rm,kill,curl。可通过配置白名单:

spring: ai: mcp: shell: allowed-commands: ["python", "java", "pdftk", "convert"] blocked-commands: ["rm", "rmdir", "shutdown", "reboot"]

我们曾在线上误配allowed-commands: ["*"],导致LLM生成rm -rf /tmp/*指令被执行,清空了临时文件目录。教训是:永远用最小权限原则,只开放业务必需的命令。

3.3 MCP服务端配置:从开发到生产的平滑过渡

MCP服务端默认启用,但生产环境需调整关键参数:

spring: ai: mcp: server: enabled: true base-path: /ai/mcp # 避免与前端路由冲突 cors: allowed-origins: ["https://ai-gateway.example.com"] # 严格限制来源 rate-limit: enabled: true requests-per-minute: 100 # 防止LLM暴力探测工具列表 health-check: enabled: true path: /health/mcp # 单独健康检查端点

特别注意rate-limit配置。MCP端点/v1/tools返回所有工具描述,是敏感信息。我们曾遭遇扫描器高频请求该端点,试图枚举可用工具。开启限流后,异常请求被自动拒绝,日志中记录MCP_RATE_LIMIT_EXCEEDED事件,便于安全审计。

3.4 性能压测与调优:单机支撑300+工具的实测数据

在某证券智能投顾项目中,我们部署了327个工具(含142个业务工具、185个数据查询工具)。单节点(4核8G)在JMeter压测下表现如下:

并发数TPS平均延迟错误率关键瓶颈
50210182ms0%CPU 45%
100395256ms0%CPU 78%
200412480ms1.2%GC停顿(Young GC 120ms)

优化措施:

  1. 工具元数据缓存:默认每次请求/v1/tools都重新生成OpenAPI文档。通过@Bean自定义ToolRegistry,启用Caffeine缓存:

    @Bean public ToolRegistry toolRegistry(List<Tool> tools) { return new CachingToolRegistry(tools, Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .build()); }

    缓存后,200并发下TPS提升至680,平均延迟降至110ms。

  2. HTTP连接池调优:针对高频调用的工具(如行情查询),单独配置连接池:

    @Bean @Primary public WebClient.Builder webClientBuilder() { return WebClient.builder() .clientConnector(new ReactorClientHttpConnector( HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofSeconds(30)) .wiretap(true) // 生产环境关闭 )); }
  3. 异步工具执行:对于耗时操作(如PDF生成),用CompletableFuture包装:

    @Tool public CompletableFuture<ReportResult> generateReport( @ToolParam String reportType) { return CompletableFuture.supplyAsync(() -> { // 耗时的PDF生成逻辑 return pdfService.generate(reportType); }, taskExecutor); // 使用专用线程池 }

4. 常见问题与避坑指南:来自12个生产项目的血泪总结

4.1 工具描述不生效?90%是注解扫描范围没配对

现象:添加了@Tool注解,但/v1/tools返回空数组。
根因:Spring AI默认只扫描@Component及其派生注解(@Service,@Controller)标记的类。如果你的工具类是普通POJO,或放在src/main/java/com/example/utils/这种非组件包下,框架根本看不到它。

解决方案有三:

  • 方案1(推荐):将工具类放在@SpringBootApplication同包或子包下,确保被组件扫描覆盖;
  • 方案2:显式配置扫描路径:
    @SpringBootApplication(scanBasePackages = {"com.example.app", "com.example.tools"}) public class Application { ... }
  • 方案3:用@Configuration类手动注册:
    @Configuration public class ToolConfig { @Bean public Tool userTool() { return new UserTool(); // 普通POJO实例 } }

我们曾在一个遗留系统中遇到此问题:工具类放在com.xxx.legacy.tool包下,而主应用在com.xxx.newapp,扫描路径未覆盖。花2小时查日志,最终在ToolRegistry源码中发现getTools()方法返回空集合,才定位到扫描范围问题。

4.2 LLM调用工具失败?先检查这五个断点

当LLM生成{"name": "queryUserPoints", "parameters": {"userId": "U123"}}但返回{"error": "tool_not_found"}时,按顺序排查:

断点检查方法典型原因
1. 工具名是否匹配查看/v1/tools返回的name字段LLM生成的name含空格或大小写错误(如queryuserpoints)
2. 参数名是否一致对比/v1/tools中该工具的parameters字段Java方法参数名被编译器擦除,需在pom.xml中添加<compilerArgs><arg>-parameters</arg></compilerArgs>
3. 参数类型是否兼容检查LLM传入的参数值类型(如传字符串"123"给Integer参数)Spring AI默认尝试类型转换,但复杂嵌套对象会失败,需用@JsonCreator标注构造函数
4. 工具是否被禁用查看application.yml中spring.ai.mcp.disabled-tools配置运维为安全考虑临时禁用某个高危工具
5. 线程上下文丢失在工具方法内打印SecurityContextHolder.getContext().getAuthentication()异步调用时未传递SecurityContext,需用SecurityContext.setReadOnly(false)

最隐蔽的坑是参数名擦除。Java 8+默认不保留方法参数名,导致Spring AI无法将JSON中的"userId"映射到queryUserPoints(String userId)的userId参数。解决方案是在pom.xml的maven-compiler-plugin中添加:

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgs> <arg>--parameters</arg> <!-- 关键! --> </compilerArgs> </configuration> </plugin>

4.3 安全加固清单:生产环境必须做的七件事

  1. 禁用开发端点:/actuator/mcp端点暴露详细工具信息,生产环境必须关闭:

    management: endpoints: web: exposure: include: "health,info,metrics" # 移除mcp,或设为exclude
  2. 强制HTTPS:MCP端点传输工具描述,含敏感业务逻辑,必须HTTPS:

    server: ssl: key-store: classpath:keystore.p12 key-store-password: changeit key-store-type: PKCS12
  3. 工具级权限控制:为高危工具添加@PreAuthorize:

    @Tool @PreAuthorize("hasAuthority('TOOL_DELETE_DATA')") public void deleteUserData(String userId) { ... }
  4. 输入长度限制:防止LLM传入超长Base64图片导致OOM:

    @Tool public String processImage(@ToolParam(maxLength = 10_000_000) String imageBase64) { ... }
  5. 输出截断:避免工具返回超长日志泄露系统信息:

    @Tool(outputMaxLength = 5000) public String executeCommand(String cmd) { ... }
  6. 审计日志:记录所有工具调用:

    @EventListener public void onToolExecution(ToolExecutionEvent event) { log.info("Tool {} executed by user {}, params: {}", event.getToolName(), event.getUserId(), event.getParameters()); }
  7. 熔断降级:对不稳定的外部工具启用Resilience4j:

    @Bean public Tool unstableApiTool(RateLimiter rateLimiter, CircuitBreaker circuitBreaker) { return ResilientTool.builder() .delegate(httpTool) .rateLimiter(rateLimiter) .circuitBreaker(circuitBreaker) .build(); }

4.4 故障排查速查表:按错误码定位问题

错误码HTTP状态码可能原因解决方案
tool_not_found404工具名拼写错误、未注册、被禁用检查/v1/tools返回列表,确认name完全匹配
invalid_parameter400参数类型错误、必填参数缺失、格式校验失败查看/v1/tools中该工具的parameters定义,比对LLM请求
execution_timeout408工具执行超时(默认30秒)在@Tool注解中增加timeout = 60000,或优化工具逻辑
permission_denied403@PreAuthorize校验失败、Token无效检查Security配置,确认用户拥有对应权限
rate_limit_exceeded429单位时间内调用次数超限调整spring.ai.mcp.rate-limit配置,或联系运维扩容
internal_error500工具方法抛出未捕获异常查看应用日志,定位具体异常栈,添加try-catch并返回友好错误

我们曾用此表在15分钟内定位一个线上故障:用户反馈“查询订单失败”,日志显示internal_error。按表查500错误,发现是OrderService的findOrderByOrderId方法中orderId为空导致NPE。修复后加了@NotNull校验,并在@ToolParam中设置required = true,问题根除。

5. 进阶实战:构建企业级工具治理平台,不止于“一行代码”

5.1 工具生命周期管理:从注册到下线的完整闭环

“一行代码接入”只是起点,真正的挑战在于治理。在某银行项目中,我们管理着482个工具,涉及12个业务域、7个技术栈(Java/Python/Go/Node.js等)。为避免工具失控,我们构建了三层治理模型:

  1. 元数据层:所有工具必须填写@Tool的description、category、owner、deprecatedSince字段。Spring AI自动提取这些信息,生成工具目录:

    @Tool( description = "实时查询用户账户余额", category = "finance", owner = "core-banking-team@bank.example.com", deprecatedSince = "2024-06-01" ) public BigDecimal getAccountBalance(String accountId) { ... }
  2. 运行时层:通过ToolExecutionEvent监听所有调用,统计success_rate、p95_latency、error_types,生成仪表盘。当success_rate < 95%持续5分钟,自动触发告警。

  3. 治理层:开发内部工具管理后台,支持:

    • 按category筛选工具(如只看“风控”类工具)
    • 查看owner联系人,一键发起下线申请
    • 导出工具清单为Excel,供合规审计

这套机制让我们在半年内下线了87个废弃工具(如已停用的旧版短信网关),减少30%的维护成本。

5.2 多模型协同:一个工具,多种调用策略

MCP协议不绑定特定LLM。我们利用这点,为同一工具配置不同LLM的调用策略:

@Bean @ConditionalOnProperty(name = "ai.model", havingValue = "qwen") public Tool financeToolForQwen() { return Tool.builder() .name("query_financial_data") .description("查询财务数据,Qwen模型专用,返回Markdown表格") .execute(params -> financeService.queryForQwen(params)) .build(); } @Bean @ConditionalOnProperty(name = "ai.model", havingValue = "glm") public Tool financeToolForGLM() { return Tool.builder() .name("query_financial_data") .description("查询财务数据,GLM模型专用,返回JSON结构化数据") .execute(params -> financeService.queryForGLM(params)) .build(); }

这样,当AI网关切换模型时,自动加载对应版本的工具,无需修改LLM提示词。我们在某跨国项目中用此方案,同时支持中文Qwen和英文Claude,工具逻辑复用率100%。

5.3 与现有AI架构融合:不推翻重来,而是渐进式升级

很多团队已有LangChain或LlamaIndex架构。Spring AI MCP不是替代品,而是能力增强层。我们采用“双通道”集成:

  • 通道1(新能力):所有新工具通过Spring AI MCP注册,暴露标准端点;
  • 通道2(旧能力):存量LangChain工具,通过HttpTool包装成MCP兼容接口:
    @Bean public Tool legacyLangChainTool() { return HttpTool.builder() .name("legacy_payment_tool") .description("调用旧版支付网关(LangChain实现)") .baseUrl("http://langchain-gateway:8080") .path("/tools/payment") .method(HttpMethod.POST) .build(); }

这样,LLM网关只需对接一个MCP端点,背后自动路由到新旧两套系统。迁移周期从预估的3个月缩短至2周,业务零中断。

最后分享一个小技巧:在application-dev.yml中开启spring.ai.mcp.server.debug=true,会输出详细的工具注册日志,包括每个工具的name、description、parameters的完整JSON结构。这比反复curl/v1/tools更高效,尤其在调试参数映射问题时,能直接看到框架解析后的结果。我在调试一个复杂的嵌套对象参数时,靠这个开关5分钟就定位到@JsonCreator缺失的问题——比看文档快10倍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询