mcp-ai-agent-guidelines
Version:
A comprehensive Model Context Protocol server providing advanced tools, resources, and prompts for implementing AI agent best practices
360 lines • 12.7 kB
JavaScript
/**
* Agent Orchestrator Tool
*
* High-level MCP tool for Agent-to-Agent (A2A) orchestration.
* Enables declarative workflow execution using registered tools.
*
* Features:
* - Execute pre-defined workflow templates
* - Custom workflow execution from user-provided plans
* - Automatic context management and tracing
* - Error handling with fallback strategies
* - Execution visualization and reporting
*/
import { z } from "zod";
import { createA2AContext, getExecutionSummary, } from "./shared/a2a-context.js";
import { executeChain, } from "./shared/execution-controller.js";
import { logger } from "./shared/logger.js";
import { createTraceFromContext, traceLogger } from "./shared/trace-logger.js";
/**
* Input schema for agent orchestrator
*/
const AgentOrchestratorSchema = z.object({
// Workflow execution mode
mode: z
.enum(["template", "custom"])
.describe("Execution mode: template for pre-defined workflows, custom for user-defined"),
// Template workflow (for mode: template)
template: z
.enum([
"quality-audit",
"security-scan",
"code-analysis-pipeline",
"documentation-generation",
])
.optional()
.describe("Pre-defined workflow template to execute"),
// Custom execution plan (for mode: custom)
executionPlan: z
.object({
strategy: z.enum([
"sequential",
"parallel",
"parallel-with-join",
"conditional",
"retry-with-backoff",
]),
steps: z.array(z.object({
id: z.string(),
toolName: z.string(),
args: z.unknown().describe("Arguments to pass to the tool"),
dependencies: z.array(z.string()).optional(),
})),
onError: z.enum(["abort", "skip", "fallback"]),
fallbackTool: z.string().optional(),
fallbackArgs: z
.unknown()
.optional()
.describe("Arguments for fallback tool"),
})
.optional()
.describe("Custom execution plan for the workflow"),
// Workflow parameters (passed to tools in the workflow)
parameters: z
.record(z.unknown())
.optional()
.describe("Parameters to pass to workflow steps"),
// Orchestration config
config: z
.object({
maxDepth: z.number().optional().describe("Maximum recursion depth"),
timeoutMs: z
.number()
.optional()
.describe("Per-tool timeout in milliseconds"),
chainTimeoutMs: z
.number()
.optional()
.describe("Total chain timeout in milliseconds"),
correlationId: z
.string()
.optional()
.describe("Custom correlation ID for tracing"),
})
.optional()
.describe("Orchestration configuration"),
// Output options
includeTrace: z
.boolean()
.optional()
.default(true)
.describe("Include execution trace in output"),
includeVisualization: z
.boolean()
.optional()
.default(false)
.describe("Include Mermaid visualization of execution"),
});
/**
* Agent Orchestrator Tool
*
* Orchestrates multi-tool workflows with A2A chaining capabilities.
*
* @param args - Orchestrator configuration
* @returns Workflow execution result with trace and summary
*/
export async function agentOrchestrator(args) {
const input = AgentOrchestratorSchema.parse(args);
logger.info("Starting agent orchestration", {
mode: input.mode,
template: input.template,
});
// Create A2A context
const context = createA2AContext(input.config?.correlationId, input.config);
// Start tracing
if (input.includeTrace) {
traceLogger.startChain(context);
}
try {
// Get execution plan
let plan;
if (input.mode === "template") {
if (!input.template) {
throw new Error("Template name is required for template mode");
}
plan = getTemplateWorkflow(input.template, input.parameters || {});
}
else {
if (!input.executionPlan) {
throw new Error("Execution plan is required for custom mode");
}
plan = convertCustomPlan(input.executionPlan, input.parameters || {});
}
// Execute workflow
const result = await executeChain(plan, context);
// End tracing
if (input.includeTrace) {
traceLogger.endChain(context, result.success);
}
// Get execution summary
const summary = getExecutionSummary(context);
// Build response
const response = {
success: result.success,
finalOutput: result.finalOutput,
summary: {
...result.summary,
correlationId: summary.correlationId,
maxDepthReached: summary.maxDepthReached,
},
};
// Add trace if requested
if (input.includeTrace) {
const trace = createTraceFromContext(context);
response.trace = {
correlationId: trace.correlationId,
spans: trace.spans.map((span) => ({
toolName: span.toolName,
durationMs: span.durationMs,
status: span.status,
depth: span.depth,
})),
};
}
// Add visualization if requested
if (input.includeVisualization) {
response.visualization = generateWorkflowVisualization(context, result);
}
// Add step details
response.steps = Array.from(result.stepResults.entries()).map(([id, stepResult]) => ({
id,
success: stepResult.success,
error: stepResult.error,
}));
return {
content: [
{
type: "text",
text: JSON.stringify(response, null, 2),
},
],
};
}
catch (error) {
// End tracing with error
if (input.includeTrace) {
traceLogger.endChain(context, false, error instanceof Error ? error.message : String(error));
}
logger.error("Agent orchestration failed", {
error: error instanceof Error ? error.message : String(error),
correlationId: context.correlationId,
});
return {
content: [
{
type: "text",
text: JSON.stringify({
success: false,
error: error instanceof Error ? error.message : String(error),
correlationId: context.correlationId,
}, null, 2),
},
],
isError: true,
};
}
}
/**
* Get pre-defined workflow template
*/
function getTemplateWorkflow(template, parameters) {
switch (template) {
case "quality-audit":
return {
strategy: "sequential",
onError: "abort",
steps: [
{
id: "clean-code",
toolName: "clean-code-scorer",
args: {
projectPath: parameters.projectPath || ".",
...parameters,
},
},
{
id: "code-hygiene",
toolName: "code-hygiene-analyzer",
args: {
codeContent: parameters.codeContent || "",
language: parameters.language || "typescript",
...parameters,
},
dependencies: ["clean-code"],
},
],
};
case "security-scan":
return {
strategy: "parallel",
onError: "skip",
steps: [
{
id: "dependency-audit",
toolName: "dependency-auditor",
args: {
dependencyContent: parameters.dependencyContent || "",
...parameters,
},
},
{
id: "security-hardening",
toolName: "security-hardening-prompt-builder",
args: {
codeContext: parameters.codeContext || "",
...parameters,
},
},
],
};
case "code-analysis-pipeline":
return {
strategy: "sequential",
onError: "abort",
steps: [
{
id: "semantic-analysis",
toolName: "semantic-code-analyzer",
args: {
codeContent: parameters.codeContent || "",
...parameters,
},
},
{
id: "clean-code-score",
toolName: "clean-code-scorer",
args: {
projectPath: parameters.projectPath || ".",
...parameters,
},
dependencies: ["semantic-analysis"],
},
{
id: "diagram-generation",
toolName: "mermaid-diagram-generator",
args: {
description: parameters.description || "Code analysis results",
diagramType: "flowchart",
...parameters,
},
dependencies: ["clean-code-score"],
},
],
};
case "documentation-generation":
return {
strategy: "sequential",
onError: "abort",
steps: [
{
id: "project-onboarding",
toolName: "project-onboarding",
args: {
projectPath: parameters.projectPath || ".",
...parameters,
},
},
{
id: "doc-generation",
toolName: "documentation-generator-prompt-builder",
args: {
contentType: parameters.contentType || "API",
...parameters,
},
dependencies: ["project-onboarding"],
},
],
};
}
}
/**
* Convert custom execution plan to internal format
*/
function convertCustomPlan(customPlan, parameters) {
const steps = customPlan.steps.map((step) => ({
id: step.id,
toolName: step.toolName,
args: typeof step.args === "object" && step.args !== null
? { ...step.args, ...parameters }
: parameters || step.args,
dependencies: step.dependencies,
}));
return {
strategy: customPlan.strategy,
steps,
onError: customPlan.onError,
fallbackTool: customPlan.fallbackTool,
fallbackArgs: customPlan.fallbackArgs,
};
}
/**
* Generate Mermaid visualization of workflow execution
*/
function generateWorkflowVisualization(context, _result) {
const lines = ["```mermaid", "graph TD"];
// Add nodes for each tool invocation
for (const entry of context.executionLog) {
const nodeId = `${entry.toolName}_${entry.depth}`;
const status = entry.status === "success" ? "✅" : "❌";
const label = `${status} ${entry.toolName}<br/>${entry.durationMs}ms`;
lines.push(` ${nodeId}["${label}"]`);
// Add edge from parent if exists
if (entry.parentToolName) {
const parentId = `${entry.parentToolName}_${entry.depth - 1}`;
lines.push(` ${parentId} --> ${nodeId}`);
}
}
lines.push("```");
return lines.join("\n");
}
//# sourceMappingURL=agent-orchestrator.js.map