用外卖小哥讲懂 AI Agent:Java 项目里接入 MCP,一键发 CSDN 再微信通知
1. 从外卖流程理解 Java 里的 AI Agent 到底在干什么外卖这件事拆开看其实是一条很清晰的链路你在 App 下单平台把单派给商家商家做饭骑手取餐最后你收到一条“已送达”的通知。你只点了一下按钮背后却有一堆角色在协作。AI Agent 在 Java 项目里的工作方式和这条链路几乎一模一样。很多人第一次听到 AI Agent会以为它就是个“会聊天的搜索框”。但真正跑起来你会发现它更像一个调度中枢大模型负责理解你的意图、拆解步骤、决定下一步该干什么而真正去“干活”的是那些被注册进来的工具。工具可以是发布文章、发微信通知、查数据库、调第三方接口。大模型自己不会“下锅炒菜”它需要锅铲这个锅铲就是工具调用。这篇要讲的场景很具体在一个 Java 项目里通过 MCP 接入 AI Agent让 Agent 完成“生成文章 → 发布到 CSDN → 发微信通知”这条闭环。核心角色有四个ChatClient 是收单入口负责把用户意图交给大模型ToolCallbackProvider 是工具菜单告诉 Agent 有哪些工具可以点MCP 是统一的配送接口屏蔽不同工具之间的差异saveArticle 和 weixinNotice 就是具体的两个工具一个负责上架文章一个负责推送通知。适合谁看如果你写过 Spring Boot用过 ChatClient但对“怎么让模型真正调用外部系统”还没跑通这篇就是给你准备的。我会给出可复制的 Maven 依赖、application.yml 配置、MCP 工具注册骨架以及一次端到端的验证动作。跟着做你能在本地把发布和通知这条链路跑起来。2. 前置准备TaoToken 接入与项目环境在写工具之前得先让项目能连上模型。这里我用 TaoToken 作为模型接入层它的 API 地址是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。你需要在控制台创建一个 API Key后面配置里会用到。先确认你的环境JDK 17 或以上Maven 3.8一个能跑 Spring Boot 3.x 的工程。如果你还没有工程用 Spring Initializr 建一个依赖勾上 Spring Web 和 Lombok 就够了剩下的我们手动加。Maven 依赖这块核心是 Spring AI 的 starter 和 MCP 相关模块。下面这份可以直接粘到pom.xml的dependencies里dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version1.0.0-M6/version /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-spring-boot-starter/artifactId version1.0.0-M6/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency版本号这块要注意Spring AI 还在快速迭代M6 是我实测下来比较稳的一个版本。如果你用的是别的版本接口名可能有细微差别遇到编译不过先对一下官方文档。注意MCP 的 starter 在不同版本里包名有调整如果spring-ai-mcp-spring-boot-starter拉不下来去 Maven Central 搜一下当前可用的 artifactId别硬套。接下来是application.yml。这里要配两件事模型接入信息和 MCP 客户端信息。模型这块指向 TaoToken 的 APIspring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7 mcp: client: enabled: true name: csdn-agent-client version: 1.0.0 request-timeout: 30sapi-key我用了环境变量${TAOTOKEN_API_KEY}这样不会把密钥写死在代码里。你在本地跑的时候可以在 IDE 的运行配置里加环境变量或者用.env文件配合插件加载。别直接把 key 提交到 Git这个坑我见过太多次了。MCP 客户端这块enabled: true打开客户端能力name和version是给服务端识别用的request-timeout设 30 秒因为发布文章和发通知都可能慢超时太短会误报失败。3. 可复制配置ChatClient 与 ToolCallbackProvider 骨架环境配好之后进入核心部分怎么把 ChatClient 和 ToolCallbackProvider 组装起来。你可以把 ChatClient 理解成“收单员”它接收用户的目标转交给大模型ToolCallbackProvider 是“菜单”Agent 从里面挑工具用。先写一个配置类把 ChatClient 暴露成 BeanConfiguration public class AgentConfig { Bean public ChatClient chatClient(OpenAiChatModel chatModel, ToolCallbackProvider toolCallbackProvider) { return ChatClient.builder(chatModel) .defaultToolCallbacks(toolCallbackProvider) .build(); } }这里的关键是.defaultToolCallbacks(toolCallbackProvider)它把工具菜单挂到了 ChatClient 上。这样每次调用时Agent 都能看到有哪些工具可用不需要在每次 prompt 里重复声明。然后是工具本身。MCP 的工具注册有两种方式一种是通过Tool注解在方法上声明另一种是走 MCP 服务端暴露。这里我用注解方式因为本地跑通最快。先定义两个工具方法Component public class CsdnTools { Tool(description 将文章发布到 CSDN返回文章 URL) public String saveArticle( ToolParam(description 文章标题) String title, ToolParam(description Markdown 正文) String content, ToolParam(description 标签逗号分隔) String tags) { // 这里替换成真实的 CSDN 发布逻辑 String url https://blog.csdn.net/demo/article/ Math.abs(title.hashCode()); return 发布成功URL: url; } Tool(description 发送微信通知给订阅用户) public String weixinNotice( ToolParam(description 通知内容) String message) { // 这里替换成真实的微信推送逻辑 return 通知已发送: message; } }Tool的description很重要Agent 就是靠这段描述来判断“这个工具是干什么的、什么时候该用”。描述写得含糊Agent 就可能选错工具或者干脆不选。我一般会把输入参数也写清楚用ToolParam标注这样模型生成调用参数时更准。工具写好后需要一个 Provider 把它们收集起来Configuration public class ToolProviderConfig { Bean public ToolCallbackProvider toolCallbackProvider(CsdnTools csdnTools) { return MethodToolCallbackProvider.builder() .toolObjects(csdnTools) .build(); } }MethodToolCallbackProvider会扫描csdnTools里所有带Tool的方法把它们注册成可调用的工具。到这里ChatClient 和 ToolCallbackProvider 就串起来了。提示如果你有多个工具类可以在.toolObjects()里传多个对象或者用Component让 Spring 自动收集。工具多了之后建议按业务域拆类别全堆在一个类里。4. 端到端验证一次发布加通知的完整请求配置和工具都就位了现在跑一次端到端验证。写一个测试类模拟用户目标“生成技术文章并发布到 CSDN然后发送微信通知”SpringBootTest class AgentMcpDemoTest { Autowired private ChatClient chatClient; Test void publishAndNotify() { String userGoal 写一篇关于 Java 接入 MCP 的技术文章 标题叫《Java 项目接入 MCP 实战》 发布到 CSDN标签用 Java,MCP,AI Agent 然后发微信通知告诉订阅用户文章已上线; String result chatClient.prompt() .user(userGoal) .call() .content(); System.out.println(Agent 最终回复: result); } }跑起来之后Agent 内部会做几件事先理解你的目标规划出“先生成文章再发布再通知”的步骤然后调用saveArticle把标题、正文、标签传进去拿到返回的 URL 后再调用weixinNotice把“文章已上线”的消息推出去最后把整个结果汇总成一段话返回给你。实测下来控制台会打印类似这样的内容Agent 最终回复: 文章《Java 项目接入 MCP 实战》已成功发布到 CSDN URL: https://blog.csdn.net/demo/article/123456并已发送微信通知给订阅用户。如果你在saveArticle里接了真实的 CSDN 发布接口这时候去 CSDN 后台就能看到文章如果接了真实的微信推送订阅用户那边也会收到消息。这条链路跑通说明 ChatClient、ToolCallbackProvider、MCP 工具注册三块都对了。这里有个细节值得说Agent 调用工具的顺序不是写死的是模型根据目标自己规划的。你可以在 prompt 里加一句“先发布再通知”它会按这个顺序走如果不加它一般也能推断出来但明确写出来更稳。5. 本篇常见错排查工具没注册、鉴权失败、超时与幂等跑这条链路最容易踩的坑集中在四个地方。我按出现频率排一下你遇到问题可以对着查。工具未注册Agent 找不到“商家”。表现是 Agent 回复“我无法完成发布”或者干脆不调用工具。原因通常是ToolCallbackProvider没把方法暴露出去。检查两点Tool注解有没有加在 public 方法上MethodToolCallbackProvider.builder().toolObjects()里有没有传对对象。如果工具类没被 Spring 扫描到也会导致 Provider 里是空的。鉴权失败MCP 连接或第三方 API 报 401/403。模型这块检查api-key环境变量有没有生效base-url是不是https://taotoken.net/api。第三方 API 这块CSDN 和微信的 token 要单独配别和模型 key 混在一起。我一般会把不同服务的密钥分开管理出问题好定位。超时与幂等发布后重试导致重复文章。发布文章和发通知都是网络操作超时很正常。request-timeout设 30 秒是个折中值太短容易误判失败太长会卡住整个请求。更关键的是幂等如果发布成功但返回超时Agent 可能重试结果发了两篇。解决办法是在saveArticle里做去重比如用标题加时间戳做唯一键发布前先查一下是否已存在。内容校验标题或标签格式不对被拒。CSDN 对标题长度、标签数量有要求Markdown 语法错了也会发布失败。建议在工具方法里加一层校验标题超过 80 字符就截断标签超过 5 个就丢弃多余的正文里如果有未闭合的代码块提前报错而不是等接口返回。注意排障时先把日志级别调到 DEBUGSpring AI 会打印工具调用的入参和返回能省很多猜测时间。6. 继续往下走把这条链路接进你的真实项目到这里本地跑通“发布 CSDN 加微信通知”这条链路已经没问题了。接下来你可以做几件事让它更实用。一是把工具换成真实实现。saveArticle里接 CSDN 的开放接口weixinNotice里接微信的模板消息或企业微信机器人。接口鉴权信息走配置中心别写死在代码里。二是把 Agent 接到你的业务入口。比如做一个定时任务每天早上自动生成一篇技术文章并发布或者做一个内部工具运营同学输入主题Agent 自动完成发布和通知。三是把模型调用和工具调用分开管理。模型这块TaoToken 的 API Key 在控制台创建地址是https://taotoken.net/api-keys接入文档在https://taotoken.net/doc。如果你要长期跑编码类或 Agent 类任务可以看看 Coding Plan地址是https://taotoken.net/coding-plan。想先验证模型对话效果用模型对话页面https://taotoken.net/chat最快。四是把 MCP 服务端独立出去。现在工具是本地注册的如果多个项目要共用可以把工具做成独立的 MCP 服务端通过 MCP 协议暴露这样 Java、Python、Node 的项目都能接。Claude Code 那边也有对应的接入方式参考https://taotoken.net/ClaudeCodeAnthropic。最后说个我自己的习惯每次加新工具先写一个最小测试只验证“Agent 能不能选中这个工具”再验证“工具执行结果对不对”。两步分开出问题的时候一眼就能看出是选工具的问题还是执行的问题。这条链路你跑通一次后面加工具就是复制粘贴改描述的事。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →