MCP 驱动的 AI Agent 工作流:从任务分解到自动执行
探讨如何利用 Model Context Protocol 构建复杂的 AI Agent 工作流,包括任务分解、工具编排和结果聚合的完整实现。
AI Agent 的真正价值不在于回答问题,而在于自主完成任务。MCP 为 Agent 提供了丰富的工具集,使得复杂的自动化工作流成为可能。这篇文章将展示如何用 MCP 构建能够自主规划和执行任务的 Agent 工作流。
Agent 工作流的基本模式
ReAct 模式
ReAct(Reasoning + Acting)是最基础的 Agent 模式:LLM 先推理(Reasoning),再行动(Acting),观察结果后继续推理。
用户任务 → 推理 → 选择工具 → 执行 → 观察结果 → 推理 → ... → 最终回答
Plan-and-Execute 模式
先制定完整计划,再逐步执行:
用户任务 → 制定计划 [步骤1, 步骤2, ...] → 执行步骤1 → 执行步骤2 → ... → 汇总结果
反思模式
在执行后进行自我评估,必要时调整策略:
用户任务 → 执行 → 反思 → 调整 → 重新执行 → ... → 满意 → 输出
实现:自动化研究工作流
让我们实现一个完整的研究工作流——给定一个主题,Agent 自动搜索信息、分析数据、生成报告。
工作流架构
┌─────────────────────────────────────────┐
│ Orchestrator │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌─────┐ │
│ │规划器│→│研究员│→│分析师│→│写作者│ │
│ └──────┘ └──────┘ └──────┘ └─────┘ │
│ │
└─────────────────────────────────────────┘
↓ ↓ ↓
┌────────┐ ┌────────┐ ┌────────┐
│搜索 MCP│ │数据 MCP│ │文档 MCP│
│ Server │ │ Server │ │ Server │
└────────┘ └────────┘ └────────┘
实现代码
import Anthropic from '@anthropic-ai/sdk';
import { MCPClientManager } from './mcp-client.js';
const claude = new Anthropic();
const mcp = new MCPClientManager();
// 初始化 MCP Server
await mcp.addServer({
name: 'search',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-brave-search'],
env: { BRAVE_API_KEY: process.env.BRAVE_API_KEY! },
});
await mcp.addServer({
name: 'filesystem',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp/research'],
});
// 阶段 1:制定研究计划
async function planResearch(topic: string): Promise<string[]> {
const response = await claude.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1000,
messages: [{
role: 'user',
content: `为以下主题制定研究计划,输出 3-5 个具体的搜索查询:\n\n${topic}\n\n直接输出 JSON 数组格式的查询列表。`,
}],
});
const text = response.content[0].text;
return JSON.parse(text.match(/\[.*\]/s)?.[0] || '[]');
}
// 阶段 2:执行搜索
async function executeSearches(queries: string[]): Promise<string[]> {
const results: string[] = [];
for (const query of queries) {
try {
const result = await mcp.callTool('brave_web_search', {
query,
count: 5,
});
results.push(result.content[0].text);
} catch (error) {
console.error(`搜索失败: ${query}`, error);
}
}
return results;
}
// 阶段 3:分析和综合
async function analyzeResults(topic: string, searchResults: string[]): Promise<string> {
const response = await claude.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4000,
messages: [{
role: 'user',
content: `基于以下搜索结果,为主题 "${topic}" 生成一份深度分析报告。\n\n搜索结果:\n${searchResults.join('\n\n---\n\n')}\n\n要求:\n1. 提取关键事实和数据\n2. 识别趋势和模式\n3. 给出专业见解\n4. 输出 Markdown 格式`,
}],
});
return response.content[0].text;
}
// 阶段 4:保存报告
async function saveReport(topic: string, report: string): Promise<string> {
const filename = `/tmp/research/${topic.replace(/\s+/g, '-').toLowerCase()}.md`;
await mcp.callTool('write_file', {
path: filename,
content: report,
});
return filename;
}
// 主工作流
async function researchWorkflow(topic: string) {
console.error(`\n📋 研究主题: ${topic}\n`);
// 阶段 1: 规划
console.error('🔍 阶段 1: 制定研究计划...');
const queries = await planResearch(topic);
console.error(` 生成 ${queries.length} 个搜索查询`);
// 阶段 2: 搜索
console.error('🌐 阶段 2: 执行搜索...');
const searchResults = await executeSearches(queries);
console.error(` 收集 ${searchResults.length} 条搜索结果`);
// 阶段 3: 分析
console.error('📊 阶段 3: 分析和综合...');
const report = await analyzeResults(topic, searchResults);
// 阶段 4: 保存
console.error('💾 阶段 4: 保存报告...');
const path = await saveReport(topic, report);
console.error(`\n✅ 报告已保存: ${path}`);
return report;
}
// 执行
const report = await researchWorkflow('2026 年 MCP 协议发展趋势');
console.log(report);
await mcp.cleanup();
错误恢复机制
工作流中的每一步都可能失败,需要实现健壮的错误恢复:
async function resilientStep<T>(
name: string,
fn: () => Promise<T>,
maxRetries: number = 3
): Promise<T> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
console.error(`[Step ${name}] 尝试 ${attempt}/${maxRetries} 失败:`, error.message);
if (attempt === maxRetries) {
throw new Error(`步骤 ${name} 在 ${maxRetries} 次尝试后仍然失败`);
}
// 指数退避
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt - 1)));
}
}
throw new Error('Unreachable');
}
// 使用
const results = await resilientStep('search', () => executeSearches(queries));
工作流状态管理
对于长时间运行的工作流,需要持久化状态:
interface WorkflowState {
id: string;
status: 'planning' | 'searching' | 'analyzing' | 'completed' | 'failed';
currentStep: number;
results: Record<string, any>;
startedAt: string;
updatedAt: string;
}
class WorkflowManager {
private states: Map<string, WorkflowState> = new Map();
create(id: string): WorkflowState {
const state: WorkflowState = {
id,
status: 'planning',
currentStep: 0,
results: {},
startedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
this.states.set(id, state);
return state;
}
update(id: string, updates: Partial<WorkflowState>): WorkflowState {
const state = this.states.get(id);
if (!state) throw new Error(`Workflow ${id} not found`);
Object.assign(state, updates, { updatedAt: new Date().toISOString() });
return state;
}
get(id: string): WorkflowState | undefined {
return this.states.get(id);
}
}
常见问题(FAQ)
工作流中的 LLM 调用次数如何控制?
设置最大迭代次数。在 ReAct 模式中,限制推理-行动循环的次数。在 Plan-and-Execute 模式中,限制计划步骤的数量。
如何处理工作流中的歧义?
在关键决策点让 LLM 生成多个候选方案,根据置信度选择最合适的。如果置信度都不高,可以请求用户确认。
工作流可以并行执行吗?
可以。独立的步骤可以由不同的 Agent 并行执行。使用 Promise.all 或专门的工作流引擎来管理并行任务。
总结
MCP 为 Agent 工作流提供了标准化的工具调用能力。通过合理的模式选择(ReAct、Plan-and-Execute、反思模式)和健壮的错误处理,你可以构建出能够自主完成复杂任务的 AI Agent 系统。