Conductor MCP 集成指南:以 LIST_MCP_TOOLS 与 CALL_MCP_TOOL 构建可发现、可编排、可审计的 Agent 工具调用
【免费下载链接】conductorConductor is an event driven agentic workflow engine providing durable and highly resilient execution engine for applications and AI Agents项目地址: https://gitcode.com/GitHub_Trending/co/conductor
Model Context Protocol(MCP)是 AI Agent 发现与调用工具的事实标准协议。Conductor 将 MCP 作为一等公民集成进工作流引擎:LIST_MCP_TOOLS负责向 MCP 服务器查询能力清单,CALL_MCP_TOOL负责执行具体工具,每一次 MCP 调用都以原生系统任务(system task)的形式运行,天然获得与工作流其他步骤相同的重试、可观测性与执行历史。读完本文,你将掌握在 Conductor 工作流中连接任意 HTTP MCP 服务器、动态发现工具、由 LLM 编排跨服务器工具调用、以及将工作流本身反向暴露为 MCP 工具供其他 Agent 调用的完整实战方案。
MCP 是什么
MCP 定义了 AI Agent 发现和使用工具的协议。相比把每个工具集成都写成硬编码的定制代码(不同鉴权方式、不同 schema、不同错误处理),MCP 将工具标准化:一次接入,即可使用任何兼容 MCP 的工具服务器。
- 没有 MCP:每次工具集成都是定制代码——不同的鉴权、不同的 schema、不同的错误处理。
- 有了 MCP:工具被标准化。连接一次,即可使用任何 MCP 兼容的工具服务器。
Agent 的工作模式从"为每个 API 写死适配层"变为:向 MCP 服务器询问"你有什么工具?",拿到结构化清单,由 Agent(或 LLM)挑选合适的工具,再交由 MCP 服务器执行。
Conductor 以两个原生系统任务实现 MCP 的一等集成:
| 系统任务 | 作用 |
|---|---|
LIST_MCP_TOOLS | 查询 MCP 服务器,返回其提供的工具清单(名称、描述、参数 schema) |
CALL_MCP_TOOL | 以给定参数调用 MCP 服务器上的某个具体工具 |
在源码层面,这两个任务由 MCPWorkers.java 中的@WorkerTask("LIST_MCP_TOOLS")与@WorkerTask("CALL_MCP_TOOL")注解方法实现,并通过@Conditional(AIIntegrationEnabledCondition.class)受 AI 集成开关控制,任务类型常量定义于 CallMCPToolTaskMapper.java 与 ListMCPToolsTaskMapper.java。
原生 MCP 系统任务
LIST_MCP_TOOLS — 发现可用工具
LIST_MCP_TOOLS查询 MCP 服务器并返回其提供的工具列表,包括名称、描述与参数 schema:
{ "name": "discover_tools", "taskReferenceName": "discover", "type": "LIST_MCP_TOOLS", "inputParameters": { "mcpServer": "${workflow.input.mcpServerUrl}" } }输出:结构化工具列表及其 schema。可以直接将其传给 LLM,让它决定调用哪个工具。从 MCPWorkers.java 可以看到,输出被简化为ToolInfo(含name、description、inputSchema三个字段)并挂载在tools输出参数下。
为什么重要:工具发现发生在运行时。你的 Agent 在设计期无需知道存在哪些工具——它动态发现。向 MCP 服务器添加一个新工具,所有使用它的 Agent 立即获得该能力,无需改动任何工作流定义。
CALL_MCP_TOOL — 执行工具
CALL_MCP_TOOL以给定参数调用 MCP 服务器上的具体工具:
{ "name": "execute_tool", "taskReferenceName": "execute", "type": "CALL_MCP_TOOL", "inputParameters": { "mcpServer": "${workflow.input.mcpServerUrl}", "method": "${plan.output.result.method}", "arguments": "${plan.output.result.arguments}" } }输入参数模型定义于 MCPToolCallRequest.java:除mcpServer、method、headers三个保留字段外,所有额外的输入参数都会自动作为工具参数透传给 MCP 工具。这意味着你既可以显式传入arguments对象,也可以直接平铺传参。仓库自带的 09-mcp-call-tool.json 展示了这种平铺用法:
{ "name": "mcp_weather_workflow", "version": 1, "schemaVersion": 2, "tasks": [ { "name": "get_weather", "taskReferenceName": "weather", "type": "CALL_MCP_TOOL", "inputParameters": { "mcpServer": "http://localhost:3001/mcp", "method": "get_weather", "location": "New York", "units": "fahrenheit" } } ] }这里location、units即为透传给get_weather工具的参数。
Conductor 在原生 MCP 之上叠加的能力:
- 持久化执行(Durable execution)——工具调用失败时,Conductor 依据任务的重试策略自动重试。重试是自动且可配置的(固定延迟、指数退避、线性退避)。
- 完整审计轨迹(Full audit trail)——每次工具调用都被持久化:方法、参数、响应、耗时与重试历史。你可以精确审查 Agent 到底做了什么。
- 崩溃恢复(Crash recovery)——如果服务器在工具调用之间崩溃,工作流从最后完成的步骤恢复,工具调用绝不会被静默丢失。
- 超时处理(Timeout handling)——配置
responseTimeoutSeconds防止卡死的工具调用阻塞你的 Agent。
连接 MCP 服务器
Conductor 通过 HTTP 连接任意 MCP 服务器。服务器 URL 可作为工作流输入传入,也可硬编码在任务定义中:
{ "mcpServer": "http://localhost:3001/mcp" }从源码看,MCPService.java 支持两类 HTTP 风格端点:http://localhost:3000/sse(SSE 传输)与https://api.example.com/mcp(Streamable HTTP / JSON-RPC 端点)。底层通过JSON-RPC 2.0直接调用(tools/list与tools/call方法),并在请求头声明Accept: application/json, text/event-stream,因此能同时兼容直接返回 JSON 与 SSE 流式响应两种服务端实现。
对于需要鉴权的 MCP 服务器,请求模型支持通过headers字段携带自定义 HTTP 头(如Authorization)。安全方面,MCPService.java 对重定向做了严格防护:默认不自动跟随重定向,手动跟踪最多 5 跳;若请求携带Authorization、Cookie、Proxy-Authorization等敏感头,则拒绝跨域转发凭据,避免凭证泄露给第三方来源。响应体同样有边界保护:超过 10 MiB 的响应会被拒绝(MCP response exceeds the 10 MiB payload limit)。
使用多个 MCP 服务器
同一个工作流中的 Agent 可以连接多个 MCP 服务器:分别发现各服务器的工具,合并工具清单,让 LLM 在全部工具之间做选择:
{ "name": "multi_tool_agent", "version": 1, "schemaVersion": 2, "tasks": [ { "name": "discover_github_tools", "taskReferenceName": "github_tools", "type": "LIST_MCP_TOOLS", "inputParameters": { "mcpServer": "http://localhost:3001/mcp" } }, { "name": "discover_db_tools", "taskReferenceName": "db_tools", "type": "LIST_MCP_TOOLS", "inputParameters": { "mcpServer": "http://localhost:3002/mcp" } }, { "name": "plan_with_all_tools", "taskReferenceName": "plan", "type": "LLM_CHAT_COMPLETE", "inputParameters": { "llmProvider": "openai", "model": "gpt-4o-mini", "messages": [ { "role": "system", "message": "Available tools: GitHub: ${github_tools.output.tools}, Database: ${db_tools.output.tools}. User task: ${workflow.input.task}. Pick the best tool. Respond with JSON: {\"server\": \"github\" or \"db\", \"method\": \"tool_name\", \"arguments\": {}}" } ], "temperature": 0.1 } } ] }LLM 通过github_tools.output.tools与db_tools.output.tools拿到两个服务器的工具清单,其输出 JSON(选择哪个 server、哪个 method、什么参数)可以继续通过CALL_MCP_TOOL路由到对应的 MCP 服务器执行。
源码级实现剖析:MCP 调用链路
要理解"一次 MCP 调用如何变成持久化任务",可以沿着 ai 模块 的代码链路走一遍:
- 任务映射(Task Mapper):CallMCPToolTaskMapper.java 与 ListMCPToolsTaskMapper.java 将工作流定义中的
CALL_MCP_TOOL/LIST_MCP_TOOLS任务类型映射为请求模型MCPToolCallRequest/MCPListToolsRequest。 - Worker 执行:MCPWorkers.java 以
AnnotatedSystemTaskWorker实现任务执行,调用MCPService并做结果结构转换(ToolInfo/ToolCallResult/ContentItem)。 - 协议层:MCPService.java 构建 JSON-RPC 2.0 请求(
jsonrpc、method、id、params),通过 OkHttp 发送,按响应 Content-Type 分流解析(text/event-stream走 SSE 解析,否则直接 JSON 解析)。 - 结果后处理:对
CALL_MCP_TOOL返回的content中type == "text"的条目,JsonTextParser 会尝试把文本解析为 JSON,并追加parsed字段,便于下游 LLM 直接消费结构化数据而非纯文本。
正因为每次 MCP 调用都是一个真正的 Conductor 任务,它自动继承了引擎的重试、超时、审计、持久化语义,这正是"以 MCP 为协议、以工作流为运行时"的核心价值所在。
将工作流暴露为 MCP 工具
任何 Conductor 工作流都可以通过MCP Gateway暴露为 MCP 工具。这意味着其他 Agent 和 LLM 可以用 MCP 协议发现并调用你的工作流:
Agent → LIST_MCP_TOOLS → discovers your workflow Agent → CALL_MCP_TOOL → starts your workflow Conductor → executes with full durability Agent → receives structured output工作流的inputParameters成为工具的输入 schema,outputParameters成为工具的输出。工作流在完整持久化执行保证下运行——重试、持久化、补偿——而对调用方 Agent 而言,它只是一个简单的工具调用。
这构建了一种可组合架构:工作流调用 MCP 工具,同时工作流本身就是MCP 工具。Agent 可以调用其他 Agent 的工作流,而无需知道对方是工作流。
MCP vs HTTP vs 自定义 Worker
| 方案 | 适用场景 |
|---|---|
MCP(LIST_MCP_TOOLS+CALL_MCP_TOOL) | 通过 MCP 服务器暴露的工具。需要动态工具发现。Agent 在运行时决定调用哪个工具。 |
HTTP(HTTP系统任务) | 端点已知的直接 API 调用。无需工具发现。 |
自定义 Worker(SIMPLE任务) | 需要定制代码的复杂业务逻辑。多步骤处理。 |
当你的 Agent 需要动态发现工具,或希望跨多个 Agent 标准化工具访问时,MCP 是首选。简单、端点明确的 API 调用用 HTTP;无法纳入单次 API 调用的逻辑用自定义 Worker。
完整示例:带审批的 MCP Agent
下面是一个生产可用的 Agent 工作流:发现工具 → LLM 规划 → 人工审批 → 执行工具 → 汇总结果:
{ "name": "mcp_agent_with_approval", "description": "Discover tools, plan, execute with approval, summarize", "version": 1, "schemaVersion": 2, "inputParameters": ["task", "mcpServerUrl"], "tasks": [ { "name": "list_available_tools", "taskReferenceName": "discover_tools", "type": "LIST_MCP_TOOLS", "inputParameters": { "mcpServer": "${workflow.input.mcpServerUrl}" } }, { "name": "decide_which_tools_to_use", "taskReferenceName": "plan", "type": "LLM_CHAT_COMPLETE", "inputParameters": { "llmProvider": "anthropic", "model": "claude-sonnet-4-20250514", "messages": [ { "role": "system", "message": "You are an AI agent. Available tools: ${discover_tools.output.tools}. User wants to: ${workflow.input.task}" }, { "role": "user", "message": "Which tool should I use and what parameters? Respond with JSON: {\"method\": \"string\", \"arguments\": {}}" } ], "temperature": 0.1, "maxTokens": 500 } }, { "name": "human_review", "taskReferenceName": "approval", "type": "HUMAN", "inputParameters": { "plannedAction": "${plan.output.result}" } }, { "name": "execute_tool", "taskReferenceName": "execute", "type": "CALL_MCP_TOOL", "inputParameters": { "mcpServer": "${workflow.input.mcpServerUrl}", "method": "${plan.output.result.method}", "arguments": "${plan.output.result.arguments}" } }, { "name": "summarize_result", "taskReferenceName": "summarize", "type": "LLM_CHAT_COMPLETE", "inputParameters": { "llmProvider": "anthropic", "model": "claude-sonnet-4-20250514", "messages": [ { "role": "user", "message": "The user asked: ${workflow.input.task}\n\nTool result: ${execute.output.content}\n\nSummarize this result for the user." } ], "maxTokens": 500 } } ], "outputParameters": { "plan": "${plan.output.result}", "toolResult": "${execute.output.content}", "summary": "${summarize.output.result}", "approvedBy": "${approval.output.reviewer}" } }注意其中的每个任务类型——LIST_MCP_TOOLS、LLM_CHAT_COMPLETE、CALL_MCP_TOOL、HUMAN——都是 Conductor 的原生系统任务,无需编写任何自定义代码。HUMAN审批节点通过plannedAction将 LLM 的规划呈现给人工审核者,审批通过后CALL_MCP_TOOL才真正执行外部工具,最后 LLM 汇总结果并连同审批人、规划、工具结果一起写入工作流输出。这也是在 human-in-the-loop 场景中对 MCP 工具调用做人工把关的推荐模式。
启用前提与配置
MCP 系统任务属于 AI 集成能力,受配置开关控制。在 server/src/main/resources/application.properties 中:
conductor.integrations.ai.enabled=true该开关与AIIntegrationEnabledCondition对应(MCPWorkers.java、MCPService.java 均以此为条件装配)。相关 AI 出站策略还包括conductor.ai.outbound.allowed-origins与conductor.ai.outbound.allow-private-networks等选项(默认配置中已注释示例),用于限制 AI 任务可以访问的端点。开启此开关后,即可在工作流定义中直接使用LIST_MCP_TOOLS与CALL_MCP_TOOL任务类型。
下一步
- Production Agent Architecture——在 Agent 产出首个结果后对其进行治理与运维。
- Build Your First Agentic Workflow Graph——用 SDK 编写 Agent 并将其与持久化工作流任务组合。
- Dynamic Workflows——由 Agent 自行生成执行计划的动态工作流。
- Human-in-the-Loop——MCP 工具调用的人工审批模式。
- LLM Orchestration——12 个原生 LLM Provider、向量数据库与内容生成能力。
【免费下载链接】conductorConductor is an event driven agentic workflow engine providing durable and highly resilient execution engine for applications and AI Agents项目地址: https://gitcode.com/GitHub_Trending/co/conductor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考