plan_analysis
Analyze a plan for impact, critical path, bottlenecks, or coherence to identify how changes affect tasks and dependencies.
Instructions
Advanced plan reads: impact analysis (delay/block/remove), critical path, bottleneck list, or coherence check.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| plan_id | Yes | ||
| type | Yes | ||
| node_id | No | ||
| scenario | No |
Implementation Reference
- src/tools/bdi/beliefs.js:534-553 (handler)The handler function that executes the plan_analysis tool logic. It dispatches on the 'type' argument (critical_path, bottlenecks, impact, coherence) and makes API calls or runs coherence checks, returning formatted results.
async function planAnalysisHandler(args, apiClient) { const { plan_id, type, node_id, scenario } = args; try { let result; if (type === 'critical_path') { result = (await apiClient.axiosInstance.get(`/plans/${plan_id}/critical-path`)).data; } else if (type === 'bottlenecks') { result = (await apiClient.axiosInstance.get(`/plans/${plan_id}/bottlenecks`)).data; } else if (type === 'impact') { if (!node_id) return errorResponse('invalid_arg', 'plan_analysis type=impact requires node_id'); const params = new URLSearchParams({ scenario: scenario || 'block' }); result = (await apiClient.axiosInstance.get(`/plans/${plan_id}/nodes/${node_id}/impact?${params}`)).data; } else if (type === 'coherence') { result = await apiClient.coherence.runCheck(plan_id); } return formatResponse({ as_of: asOf(), type, results: result || {} }); } catch (err) { return errorResponse('upstream_unavailable', `plan_analysis failed: ${err.response?.data?.error || err.message}`); } } - src/tools/bdi/beliefs.js:517-532 (schema)The schema/definition for the plan_analysis tool, including its name, description, and inputSchema with properties for plan_id, type (enum), node_id, and scenario (enum).
const planAnalysisDefinition = { name: 'plan_analysis', description: "Advanced plan reads: impact analysis (delay/block/remove), critical path, " + "bottleneck list, or coherence check.", inputSchema: { type: 'object', properties: { plan_id: { type: 'string' }, type: { type: 'string', enum: ['impact', 'critical_path', 'bottlenecks', 'coherence'] }, node_id: { type: 'string' }, scenario: { type: 'string', enum: ['delay', 'block', 'remove'] }, }, required: ['plan_id', 'type'], }, }; - src/tools/bdi/beliefs.js:555-574 (registration)The tool is registered in the module.exports of beliefs.js, exported as part of the 'definitions' array and 'handlers' map under the key 'plan_analysis'.
module.exports = { definitions: [ briefingDefinition, taskContextDefinition, goalStateDefinition, recallKnowledgeDefinition, listPlansDefinition, searchDefinition, planAnalysisDefinition, ], handlers: { briefing: briefingHandler, task_context: taskContextHandler, goal_state: goalStateHandler, recall_knowledge: recallKnowledgeHandler, list_plans: listPlansHandler, search: searchHandler, plan_analysis: planAnalysisHandler, }, }; - src/tools/bdi/index.js:16-46 (registration)The BDI index.js aggregates all definitions (including planAnalysisDefinition) into bdiToolDefinitions and all handlers (including planAnalysisHandler) into the handlers map, which are then exported and wired into the MCP server.
const definitions = [ ...beliefs.definitions, ...desires.definitions, ...intentions.definitions, ...utility.definitions, ]; const handlers = { ...beliefs.handlers, ...desires.handlers, ...intentions.handlers, ...utility.handlers, }; const names = new Set(definitions.map((t) => t.name)); /** * Dispatch a BDI tool call. * @returns formatted MCP response, or undefined if the name isn't a BDI tool. */ async function bdiToolHandler(name, args, apiClient) { if (!names.has(name)) return undefined; const handler = handlers[name]; return handler(args || {}, apiClient); } module.exports = { bdiToolDefinitions: definitions, bdiToolHandler, bdiToolNames: names, }; - src/tools/bdi/_shared.js:5-23 (helper)Shared helper utilities (asOf, formatResponse, errorResponse) used by the planAnalysisHandler to format responses and errors.
function asOf() { return new Date().toISOString(); } function formatResponse(data) { if (data && data.error) { return { isError: true, content: [{ type: 'text', text: data.error }], }; } return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], }; } function errorResponse(error_type, message, extra = {}) { return formatResponse({ error: message, error_type, ...extra }); }