【AgentScope Java新手村系列】(15)MCP协议工具
第十五章 MCP 协议工具tools.json 声明式接入 MCP Server配置即集成我们想把 GitHub MCP server、PostgreSQL MCP server、Slack MCP server 一起接进 agent。1.x 时代我们写 3 个Tool子类2.0 用workspace/tools.json一行声明一个 MCP serveragent 启动时自动发现工具。这是 2.0 推荐的『配置即集成』。本章你将学到MCP server 是什么、tools.json里怎么写 MCP 段、如何在 Java 端补强 MCP、常见 MCP server 接入示例。15.1 MCP 是什么Model Context ProtocolMCP是 Anthropic 在 2024 年推出的开放协议让 LLM 应用以统一方式发现并调用外部工具。AgentScope 2.0 把 MCP server 作为 agent 工具的一种来源——你在tools.json里声明一个 MCP serveragent 启动时通过stdio或sse协议连上它自动把 server 暴露的工具当作 agent 自己的 tool。15.2 第一个 MCP 集成{ mcpServers: { github: { command: npx, args: [-y, modelcontextprotocol/server-github], env: { GITHUB_PERSONAL_ACCESS_TOKEN: ${env:GITHUB_TOKEN} } } } }HarnessAgent.builder().workspace(path)启动时会自动扫描workspace/tools.json的mcpServers段、连接每个 server、把工具注册到 agent——不需要额外开关。HarnessAgent agent HarnessAgent.builder() ... .workspace(Path.of(./workspace)) .build();跑起来后agent 就能调用 GitHub MCP server 暴露的create_issue/list_repos/search_code等工具了。15.3 三种连接方式协议适用声明方式stdio本地进程最常见commandargssse远程 HTTP SSE serverurl headersws双向 WebSocketurl headersstdio 例子{ mcpServers: { filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, ./data] } } }sse 例子{ mcpServers: { remote-knowledge: { url: https://mcp.example.com/sse, headers: { Authorization: Bearer ${env:MCP_TOKEN} } } } }15.4 不想写 JSON 文件可以在 Java 代码里直接配用 JSON 文件当然可以但有时候你想在代码里动态拼参数——比如 token 从环境变量读、超时按环境切换。这时候直接用ToolsConfigMcpServerConfig在 Java 代码里配效果和tools.json完全一样import io.agentscope.harness.agent.tools.McpServerConfig; import io.agentscope.harness.agent.tools.ToolsConfig; ToolsConfig cfg new ToolsConfig(); MapString, McpServerConfig servers new LinkedHashMap(); McpServerConfig github new McpServerConfig(); github.setTransport(stdio); github.setCommand(npx); github.setArgs(List.of(-y, modelcontextprotocol/server-github)); github.setEnv(Map.of( GITHUB_PERSONAL_ACCESS_TOKEN, System.getenv(GITHUB_TOKEN))); servers.put(github, github); cfg.setMcpServers(servers); HarnessAgent agent HarnessAgent.builder() ... .toolsConfig(cfg) .build();McpServerConfigio.agentscope.harness.agent.tools支持transport/command/args/env/url/headers/timeout等字段与tools.json的mcpServers段一一对应。15.5 与 Permission 协作MCP 工具默认会经过Permission系统——你可以在 rule 里直接写 MCP 工具名PermissionContextState perms PermissionContextState.builder() .mode(PermissionMode.ACCEPT_EDITS) // 大部分操作直接放行 .addAskRule(create_issue, // create_issue 是 MCP GitHub server 的工具 new PermissionRule(create_issue, null, PermissionBehavior.ASK, userSettings)) // 建 Issue 前要弹窗问用户 .addDenyRule(drop_table, // drop_table 是本地工具 new PermissionRule(drop_table, null, PermissionBehavior.DENY, userSettings)) // 删表直接拒绝 .build();MCP 工具和本地Tool工具在 Permission 系统里地位完全平等——create_issue来自 GitHub MCP server和drop_table来自本地 Java 类同等待遇。15.6 常见 MCP server 一览名称工具集modelcontextprotocol/server-github仓库、Issue、PRmodelcontextprotocol/server-filesystem读、写、列目录modelcontextprotocol/server-postgres查 SQL、DDLmodelcontextprotocol/server-slack发消息、查频道modelcontextprotocol/server-puppeteer浏览器自动化modelcontextprotocol/server-gitgit 操作完整列表见 MCP 官方 server 仓库。15.7 工具命名冲突如果两个 MCP server 都暴露了同名工具AgentScope 会按下列优先级保留一个Toolkit中 Java 端注册的工具最高第一个启动成功的 MCP server后面的同名工具被忽略 启动日志里 WARN要避免冲突用toolFilter限定{ mcpServers: { ...: ... }, toolFilter: { deny: [github_legacy_*] } }15.8 完整可运行示例这个例子在演示什么你有一个 devops agent可以查 GitHub Issue 和操作本地文件。生产环境通过workspace/tools.json声明两个 MCP serverGitHub、Filesystem开发环境先用Tool模拟 MCP 行为避免依赖外部进程。两种方式代码结构相同仅工具来源不同。public class Chapter15_McpTools { // Mock MCP GitHub server 工具 public static class MockGitHubTools { Tool(name create_issue, description 创建 GitHub Issue) public String createIssue(String repo, String title) { return Issue \ title \ 已创建到 repo 。; } Tool(name list_repos, description 列出用户的仓库) public String listRepos() { return - agentscope/agentscope-java\n- agentscope/agentscope-python; } Tool(name search_code, description 在代码仓库中搜索) public String searchCode(String query) { return 搜索 \ query \ 的结果。; } } // Mock MCP Filesystem server 工具 public static class MockFilesystemTools { Tool(name read_file, description 读取文件内容) public String readFile(String path) { return 文件 path 的内容。; } Tool(name list_directory, description 列出目录内容) public String listDirectory(String path) { return 目录 path 的内容。; } } public static void main(String[] args) { Toolkit toolkit new Toolkit(); toolkit.registerTool(new MockGitHubTools()); toolkit.registerTool(new MockFilesystemTools()); HarnessAgent agent HarnessAgent.builder() .name(devops) .sysPrompt(你是一个 devops 助理可以查 GitHub issue 和操作本地文件。) .model(model()) .workspace(Path.of(./workspace)) .toolkit(toolkit) .build(); agent.call( List.of(new UserMessage(user, 看看 agentscope/agentscope-java 最近有什么 Issue。)), RuntimeContext.empty()) .block(); } }workspace/tools.json生产环境用替代上面 Java 端的 mock{ mcpServers: { github: { transport: stdio, command: npx, args: [-y, modelcontextprotocol/server-github], env: { GITHUB_PERSONAL_ACCESS_TOKEN: ${env:GITHUB_TOKEN} } }, filesystem: { transport: stdio, command: npx, args: [-y, modelcontextprotocol/server-filesystem, ./data] } } }开发时用Toolmock生产时去掉 mock 换成tools.json——业务代码完全不变只改工具来源。15.9 MCP Tool Meta在工具调用中传递元数据RC2 新增McpMeta机制——你可以在RuntimeContext中放入元数据traceId、userId、回调地址等框架自动在 MCPCallToolRequest的meta参数中原样传递。import io.agentscope.core.tool.mcp.McpMeta; // 把 traceId 和 callbackUrl 放进 McpMeta McpMeta meta new McpMeta(Map.of( traceId, abc-123, // 链路追踪 ID callbackUrl, https://hook.example.com/cb // 结果回调地址 )); RuntimeContext ctx RuntimeContext.builder() .put(McpMeta.class, meta) // 注入 RuntimeContext .build(); // 当 agent 调 MCP 工具时meta 自动透传给 MCP server agent.call(List.of(new UserMessage(user, 创建 issue)), ctx).block();当 agent 调用 MCP 工具时traceId和callbackUrl会自动出现在 MCP server 收到的meta参数中。MCP server 可用这些 meta 做日志关联、结果推送等。只实现了McpMeta接口的对象才会被提取——普通RuntimeContext条目不会泄露给 MCP server。15.10 本章小结MCP server 通过stdio/sse/ws接入 agent。workspace/tools.json用mcpServers段声明运行时可改。Java 端McpServerSpec可补强超时、env、headers。MCP 工具与 Permission 系统无缝集成。