news 2026/4/14 15:34:17

McpAgentExecutor + McpClient:让 Agent 直接操作文件系统和数据库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
McpAgentExecutor + McpClient:让 Agent 直接操作文件系统和数据库

标签JavaMCPNPXAgentj-langchainMcpAgentExecutor文件系统数据库
前置阅读:Java Agent 集成 MCP 工具协议 → McpAgentExecutor:用几行代码让模型自主调用 HTTP 工具
适合人群:已配置好 NPX MCP 服务器,希望 Agent 直接操作文件、数据库等本地资源的 Java 开发者


一、HTTP 工具之外的能力

上篇文章用McpManager把 HTTP API 接入了 Agent,模型能自主查询公网 IP、天气等网络服务。但有一类能力是 HTTP API 覆盖不了的:

  • 读取服务器上的日志文件、配置文件
  • 查询本地 PostgreSQL 数据库,不想写 JDBC
  • 让 Agent 记住跨轮次的状态(键值存储)
  • 操作 GitHub 仓库、执行浏览器自动化

这些能力对应的是NPX MCP 服务器——由 MCP 官方或社区维护的独立进程,通过npx一行命令启动,暴露标准的 MCP 工具接口。文章 08 已经介绍了如何用McpClient连接这些服务器,本篇把它和McpAgentExecutor结合起来,让模型自主调用这些工具。


二、和上篇的唯一区别

先看代码,对比会非常直观。

上篇(HTTP 工具):

McpAgentExecutoragent=McpAgentExecutor.builder(chainActor).llm(...).tools(mcpManager,"default")// 从 mcp.config.json 加载 HTTP 工具.systemPrompt("...").build();

本篇(NPX MCP 服务器):

McpAgentExecutoragent=McpAgentExecutor.builder(chainActor).llm(...).tools(mcpClient,"filesystem")// 从 mcp.server.config.json 加载 NPX 服务器工具.systemPrompt("...").build();

只改了一行:把tools(mcpManager, "default")换成tools(mcpClient, "filesystem")。其余所有配置——LLM、系统提示、maxIterations、回调——完全不变。这正是McpAgentExecutor设计的价值所在:工具来源可以随意切换,Agent 层的代码不用跟着改


三、配置文件

mcp.server.config.json描述要启动哪些 NPX 服务器:

{"mcpServers":{"filesystem":{"command":"npx","args":["-y","@modelcontextprotocol/server-filesystem","/tmp"],"env":{"NODE_ENV":"production"}}}}

McpClient在 Spring 启动时会根据别名filesystem拉起这个进程,服务器启动后会向外暴露一组标准工具:list_directoryread_filewrite_filecreate_directory等。McpAgentExecutor拿到这份工具列表后,转成 Function Calling Schema 注册给模型,后续的工具选择和调用由模型自主完成。


四、完整代码

@TestpublicvoidmcpClientAgent(){McpAgentExecutoragent=McpAgentExecutor.builder(chainActor).llm(ChatAliyun.builder().model("qwen3.6-plus").temperature(0f).build()).tools(mcpClient,"filesystem")// 加载 filesystem 服务器的全部工具.systemPrompt(""" 你是一个文件管理助手,可以浏览和读取 /tmp 目录中的文件。 请直接执行操作,不要询问用户额外确认。 """).maxIterations(5).onToolCall(tc->System.out.println(">> Tool call: "+tc)).onObservation(obs->System.out.println(">> Observation: "+obs)).build();ChatGenerationresult=agent.invoke("列出 /tmp 目录下的所有文件,并告诉我有多少个文件");System.out.println("\n=== 最终答案 ===");System.out.println(result.getText());}

五、执行效果

>> Tool call: list_directory -> {"path": "/tmp"} >> Observation: {"files": ["ticket_result.txt", "demo.log", "config.yaml", ...]} === 最终答案 === /tmp 目录下共有 8 个文件,包括 ticket_result.txt、demo.log、config.yaml 等。

模型拿到list_directory的返回值后,直接统计文件数量并输出结论,整个过程只需要一次工具调用。如果任务更复杂,比如"读取 config.yaml 并告诉我其中的数据库地址",模型会自动追加一次read_file调用,不需要任何额外代码。


六、换一个服务器:PostgreSQL

filesystem 只是众多 NPX MCP 服务器中的一个。把别名换成postgres,Agent 就能直接查询数据库,不用写任何 JDBC 代码:

mcp.server.config.json中添加:

{"mcpServers":{"filesystem":{...},"postgres":{"command":"npx","args":["-y","@modelcontextprotocol/server-postgres","postgresql://user:password@localhost:5432/mydb"],"env":{}}}}

Agent 代码只改一处:

McpAgentExecutoragent=McpAgentExecutor.builder(chainActor).llm(ChatAliyun.builder().model("qwen3.6-plus").temperature(0f).build()).tools(mcpClient,"postgres")// 换成 postgres 服务器.systemPrompt("你是一个数据库助手,可以查询数据库中的表结构和数据。").maxIterations(5).build();ChatGenerationresult=agent.invoke("查询 orders 表中最近 5 条记录");

@modelcontextprotocol/server-postgres暴露的工具包括query(执行 SQL)、list_tables(列出所有表)、describe_table(查看表结构)。模型会根据问题自动选择合适的工具,拼装 SQL,返回结果。


七、生产环境注意事项

路径安全:filesystem 服务器默认能访问启动命令中指定的目录,务必传入受限路径(如/tmp或专用的工作目录),不要传入系统根目录或含敏感文件的路径。

数据库权限:postgres 服务器使用的连接串对应的数据库账号,应只赋予 SELECT 权限(只读场景)或明确需要的最小权限,避免 Agent 误执行破坏性操作。

审计日志onToolCallonObservation两个回调在生产环境中不只是调试工具,可以接入日志系统,完整记录每次文件读写或 SQL 执行,满足合规审计的要求。

并发共享:同一个McpClient实例(对应同一个服务器进程)可以被多个 Agent 共享。如果需要隔离不同 Agent 的访问路径,可以在mcp.server.config.json中配置多个别名,分别指向不同参数的同类服务器。


八、总结

McpAgentExecutor + McpClient的接入方式和上篇的McpManager版本几乎完全一样,学习成本接近零。区别只在于工具来源:HTTP API 用McpManager,NPX 服务器用McpClient

切换工具来源时,Agent 层的代码只改一行。这意味着你可以先用McpManager接 HTTP 工具快速验证业务逻辑,确认效果后再把部分工具替换成更稳定的 NPX 服务器,整个迁移成本极低。

如果你的场景需要同时使用 HTTP 工具和 NPX 服务器,下一篇会介绍如何把两者合并到同一个 Agent 中。


📎 相关资源

  • 完整示例:Article13McpClientAgent.java,对应方法mcpClientAgent()
  • 服务器配置:mcp.server.config.json
  • 常用 NPX MCP 服务器:@modelcontextprotocol/server-filesystemserver-postgresserver-memoryserver-github
  • j-langchain GitHub:https://github.com/flower-trees/j-langchain
  • j-langchain Gitee 镜像:https://gitee.com/flower-trees-z/j-langchain
  • 运行环境:需配置阿里云 API Key,示例模型qwen3.6-plus;需本地安装 Node.js 以运行 npx
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 15:32:13

Android audio中的AUDIO_OUTPUT_FLAG_NON_BLOCKING

什么是AUDIO_OUTPUT_FLAG_NON_BLOCKING如字面意思,非阻塞式写入,在以下文件中也有相关定义。AudioOutputFlags.aidl /*** Write operations must return as fast as possible instead of* being blocked until all provided data has been consumed.*/ N…

作者头像 李华
网站建设 2026/4/14 15:32:11

【图像融合】基于小波变换实现红外和可见光图像融合算法设计(含融合图像评估:信息熵EN 空间频率SF 平均梯度AG 标准差SD 互信息 MI)附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子书…

作者头像 李华
网站建设 2026/4/14 15:30:14

SpringBoot与MybatisPlus结合:深入解析IPage分页机制与实战应用

1. 为什么需要分页功能? 想象一下你去图书馆借书,管理员把全馆100万本书一次性堆在你面前让你挑,这场景是不是很崩溃?数据库查询也是同样的道理。当数据量达到百万级时,一次性加载所有数据会导致内存溢出、网络阻塞、页…

作者头像 李华
网站建设 2026/4/14 15:27:55

STM32F407烧录全攻略:从CubeMX配置到ST-Link/V2连接(含SWD接线图)

STM32F407烧录全攻略:从CubeMX配置到ST-Link/V2连接 第一次拿到STM32F407开发板时,最令人兴奋的莫过于点亮第一个LED。但在此之前,我们需要跨越从代码生成到成功烧录的整个流程。本文将手把手带你完成这个关键过程,避开那些新手常…

作者头像 李华
网站建设 2026/4/14 15:27:31

轻松掌握虚拟游戏控制器:3步搞定Windows设备兼容性难题

轻松掌握虚拟游戏控制器:3步搞定Windows设备兼容性难题 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否遇到过心爱的游戏手柄无法在Window…

作者头像 李华