agent-planner-mcp 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENT_GUIDE.md CHANGED
@@ -5,6 +5,8 @@ This guide is optimized for AI agents using AgentPlanner MCP tools.
5
5
  ## Core Workflow
6
6
 
7
7
  ```
8
+ 0. check_coherence_pending() → See if plans/goals need alignment review
9
+ → If stale items: run_coherence_check(plan_id) on each
8
10
  1. suggest_next_tasks(plan_id) → Find ready tasks (dependency-aware)
9
11
  2. get_task_context(node_id, depth=2) → Load progressive context
10
12
  3. Work on tasks (quick_status to track)
@@ -15,6 +17,16 @@ This guide is optimized for AI agents using AgentPlanner MCP tools.
15
17
 
16
18
  ## Essential Tools
17
19
 
20
+ ### Preflight: Alignment Check
21
+ ```javascript
22
+ check_coherence_pending()
23
+ // → Returns stale plans/goals that changed since last review
24
+
25
+ run_coherence_check({ plan_id: "..." })
26
+ // → Evaluates quality (coverage, specificity, ordering, knowledge)
27
+ // → Stamps plan as reviewed, returns score breakdown
28
+ ```
29
+
18
30
  ### Before Starting Work
19
31
  ```javascript
20
32
  get_plan_context({ plan_id: "..." })
package/README.md CHANGED
@@ -149,6 +149,10 @@ Add the same JSON config to your Cline MCP settings in VS Code.
149
149
  - `claim_task` / `release_task` - Task locking
150
150
  - `share_plan` - Collaboration management
151
151
 
152
+ ### Alignment & Review
153
+ - `check_coherence_pending` - See which plans/goals need alignment review (staleness check)
154
+ - `run_coherence_check` - Evaluate plan quality and stamp as reviewed
155
+
152
156
  ## LLM Skill Reference
153
157
 
154
158
  See **[SKILL.md](./SKILL.md)** for a complete reference designed to be consumed by LLMs. Include it in system prompts or agent configurations to give any LLM full knowledge of how to use AgentPlanner tools effectively.
package/SKILL.md CHANGED
@@ -31,12 +31,43 @@ You have access to the AgentPlanner MCP tools. AgentPlanner is a collaborative p
31
31
  - You need to coordinate with humans on multi-step projects
32
32
  - You want to persist findings, decisions, or progress across sessions
33
33
  - You are asked to plan, research, or implement something as part of a tracked workflow
34
+ - A user wants help defining or refining a goal
35
+
36
+ ## Goal Coaching
37
+
38
+ When a user expresses an intent, objective, or want — help them turn it into a well-structured goal. Don't just create a goal from their words. Coach them through it:
39
+
40
+ ```
41
+ 1. Listen to the user's intent (however vague)
42
+ 2. recall_knowledge() → Search for related context in the knowledge graph
43
+ 3. list_goals() → Check for overlap with existing goals
44
+ 4. list_plans() → Find related work that might link to this goal
45
+ 5. Propose a structured goal:
46
+ - Clear title
47
+ - Description explaining why this matters
48
+ - Success criteria with specific metrics + targets
49
+ - Linked plans (existing or suggest new ones)
50
+ 6. create_goal() + link plans
51
+ 7. assess_goal_quality() → Check quality and get improvement suggestions
52
+ 8. Iterate with the user until quality is high
53
+ ```
54
+
55
+ **What makes a good goal:**
56
+ - **Clear** — has a title and description that explain what and why
57
+ - **Measurable** — has success criteria with specific metrics and targets (e.g., "API latency < 100ms p99")
58
+ - **Actionable** — has at least one linked plan with concrete tasks
59
+ - **Knowledge-grounded** — related facts exist in the knowledge graph (if not, suggest researching first)
60
+ - **Committed** — promoted from desire to intention when ready, with a time reference
61
+
62
+ Use `assess_goal_quality(goal_id)` after creation to check quality and surface suggestions. Share the results with the user and help them address gaps.
34
63
 
35
64
  ## Workflow
36
65
 
37
66
  Follow this sequence when working on a plan:
38
67
 
39
68
  ```
69
+ 0. PREFLIGHT → check_coherence_pending to see if anything needs alignment review
70
+ ↳ If stale plans found, run_coherence_check on each before starting task work
40
71
  1. ORIENT → suggest_next_tasks or get_task_context to understand what needs doing
41
72
  2. CLAIM → quick_status to mark the task in_progress
42
73
  3. WORK → Do the actual work (code, research, analysis, etc.)
@@ -46,6 +77,22 @@ Follow this sequence when working on a plan:
46
77
  6. NEXT → suggest_next_tasks to find the next ready task
47
78
  ```
48
79
 
80
+ ### Preflight: Alignment Check
81
+
82
+ Before diving into tasks, check if goals, plans, and knowledge are aligned:
83
+
84
+ ```
85
+ check_coherence_pending()
86
+ → Returns stale plans/goals that changed since last review
87
+ → If stale items found:
88
+ run_coherence_check({ plan_id: "<plan_id>" })
89
+ → Evaluates quality (coverage, specificity, ordering, knowledge)
90
+ → Stamps the plan as reviewed
91
+ → Returns quality breakdown + coherence issues
92
+ ```
93
+
94
+ This is a lightweight check (seconds, not minutes). Do it at the start of each work session. Skip if you already checked recently.
95
+
49
96
  ## Loading Context
50
97
 
51
98
  Always load context before starting work. Use `get_task_context` — it gives you exactly the right amount of information based on depth level.
@@ -205,6 +252,16 @@ Cross-plan dependencies work the same as regular dependencies (`blocks`, `requir
205
252
  | `claim_task` | Claim exclusive ownership of a task (prevents agent collisions) |
206
253
  | `release_task` | Release a previously claimed task |
207
254
 
255
+ ### Alignment & Review
256
+
257
+ Check if goals, plans, and knowledge are aligned. Run as a preflight check before starting work.
258
+
259
+ | Tool | Purpose |
260
+ |------|---------|
261
+ | `check_coherence_pending` | See what needs review — returns stale plans/goals that changed since last check |
262
+ | `run_coherence_check` | Evaluate a plan's quality (coverage, specificity, ordering, knowledge) and stamp as reviewed |
263
+ | `assess_goal_quality` | Check how well-defined a goal is (clarity, measurability, actionability, knowledge, commitment) |
264
+
208
265
  ### Knowledge (Temporal Knowledge Graph)
209
266
 
210
267
  All knowledge is stored in the Graphiti temporal knowledge graph, which automatically extracts entities and relationships and enables cross-plan knowledge retrieval. The temporal graph is **cross-plan** and **persists across sessions** — anything recorded is available to all future agents and conversations within the organization.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-planner-mcp",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server for AgentPlanner — AI agent orchestration with planning, dependencies, knowledge graphs, and human oversight",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -552,45 +552,47 @@ const goals = {
552
552
  return response.data;
553
553
  },
554
554
 
555
- updateMetrics: async (goalId, metrics) => {
556
- const response = await apiClient.put(`/goals/${goalId}/metrics`, { metrics });
557
- return response.data;
558
- },
559
-
560
555
  delete: async (goalId) => {
561
556
  const response = await apiClient.delete(`/goals/${goalId}`);
562
557
  return response.data;
563
558
  },
564
-
559
+
565
560
  linkPlan: async (goalId, planId) => {
566
- const response = await apiClient.post(`/goals/${goalId}/plans/${planId}`);
561
+ const response = await apiClient.post(`/goals/${goalId}/links`, {
562
+ linkedType: 'plan', linkedId: planId
563
+ });
567
564
  return response.data;
568
565
  },
569
-
566
+
570
567
  unlinkPlan: async (goalId, planId) => {
571
- const response = await apiClient.delete(`/goals/${goalId}/plans/${planId}`);
568
+ const goal = await apiClient.get(`/goals/${goalId}`);
569
+ const link = (goal.data.links || []).find(
570
+ l => l.linkedType === 'plan' && l.linkedId === planId
571
+ );
572
+ if (!link) return { success: false, message: 'Link not found' };
573
+ const response = await apiClient.delete(`/goals/${goalId}/links/${link.id}`);
572
574
  return response.data;
573
575
  },
574
576
 
575
577
  // v2 goal-dependency endpoints
576
578
  getPath: async (goalId, maxDepth) => {
577
579
  const params = maxDepth ? `?max_depth=${maxDepth}` : '';
578
- const response = await apiClient.get(`/goals/v2/${goalId}/path${params}`);
580
+ const response = await apiClient.get(`/goals/${goalId}/path${params}`);
579
581
  return response.data;
580
582
  },
581
583
 
582
584
  getProgress: async (goalId) => {
583
- const response = await apiClient.get(`/goals/v2/${goalId}/progress`);
585
+ const response = await apiClient.get(`/goals/${goalId}/progress`);
584
586
  return response.data;
585
587
  },
586
588
 
587
589
  listAchievers: async (goalId) => {
588
- const response = await apiClient.get(`/goals/v2/${goalId}/achievers`);
590
+ const response = await apiClient.get(`/goals/${goalId}/achievers`);
589
591
  return response.data;
590
592
  },
591
593
 
592
594
  addAchiever: async (goalId, sourceNodeId, weight) => {
593
- const response = await apiClient.post(`/goals/v2/${goalId}/achievers`, {
595
+ const response = await apiClient.post(`/goals/${goalId}/achievers`, {
594
596
  source_node_id: sourceNodeId,
595
597
  weight: weight ?? 1,
596
598
  });
@@ -598,17 +600,22 @@ const goals = {
598
600
  },
599
601
 
600
602
  removeAchiever: async (goalId, depId) => {
601
- const response = await apiClient.delete(`/goals/v2/${goalId}/achievers/${depId}`);
603
+ const response = await apiClient.delete(`/goals/${goalId}/achievers/${depId}`);
602
604
  return response.data;
603
605
  },
604
606
 
605
607
  getKnowledgeGaps: async (goalId) => {
606
- const response = await apiClient.get(`/goals/v2/${goalId}/knowledge-gaps`);
608
+ const response = await apiClient.get(`/goals/${goalId}/knowledge-gaps`);
607
609
  return response.data;
608
610
  },
609
611
 
610
612
  getDashboard: async () => {
611
- const response = await apiClient.get('/goals/v2/dashboard');
613
+ const response = await apiClient.get('/goals/dashboard');
614
+ return response.data;
615
+ },
616
+
617
+ getQuality: async (goalId) => {
618
+ const response = await apiClient.get(`/goals/${goalId}/quality`);
612
619
  return response.data;
613
620
  },
614
621
  };
@@ -866,17 +873,21 @@ function createApiClient(token) {
866
873
  get: async (goalId) => (await client.get(`/goals/${goalId}`)).data,
867
874
  create: async (data) => (await client.post('/goals', data)).data,
868
875
  update: async (goalId, data) => (await client.put(`/goals/${goalId}`, data)).data,
869
- updateMetrics: async (goalId, metrics) => (await client.put(`/goals/${goalId}/metrics`, { metrics })).data,
870
876
  delete: async (goalId) => (await client.delete(`/goals/${goalId}`)).data,
871
- linkPlan: async (goalId, planId) => (await client.post(`/goals/${goalId}/plans/${planId}`)).data,
872
- unlinkPlan: async (goalId, planId) => (await client.delete(`/goals/${goalId}/plans/${planId}`)).data,
873
- getPath: async (goalId, maxDepth) => { const p = maxDepth ? `?max_depth=${maxDepth}` : ''; return (await client.get(`/goals/v2/${goalId}/path${p}`)).data; },
874
- getProgress: async (goalId) => (await client.get(`/goals/v2/${goalId}/progress`)).data,
875
- listAchievers: async (goalId) => (await client.get(`/goals/v2/${goalId}/achievers`)).data,
876
- addAchiever: async (goalId, sourceNodeId, weight) => (await client.post(`/goals/v2/${goalId}/achievers`, { source_node_id: sourceNodeId, weight: weight ?? 1 })).data,
877
- removeAchiever: async (goalId, depId) => (await client.delete(`/goals/v2/${goalId}/achievers/${depId}`)).data,
878
- getKnowledgeGaps: async (goalId) => (await client.get(`/goals/v2/${goalId}/knowledge-gaps`)).data,
879
- getDashboard: async () => (await client.get('/goals/v2/dashboard')).data,
877
+ linkPlan: async (goalId, planId) => (await client.post(`/goals/${goalId}/links`, { linkedType: 'plan', linkedId: planId })).data,
878
+ unlinkPlan: async (goalId, planId) => {
879
+ const goal = await client.get(`/goals/${goalId}`);
880
+ const link = (goal.data.links || []).find(l => l.linkedType === 'plan' && l.linkedId === planId);
881
+ if (!link) return { success: false, message: 'Link not found' };
882
+ return (await client.delete(`/goals/${goalId}/links/${link.id}`)).data;
883
+ },
884
+ getPath: async (goalId, maxDepth) => { const p = maxDepth ? `?max_depth=${maxDepth}` : ''; return (await client.get(`/goals/${goalId}/path${p}`)).data; },
885
+ getProgress: async (goalId) => (await client.get(`/goals/${goalId}/progress`)).data,
886
+ listAchievers: async (goalId) => (await client.get(`/goals/${goalId}/achievers`)).data,
887
+ addAchiever: async (goalId, sourceNodeId, weight) => (await client.post(`/goals/${goalId}/achievers`, { source_node_id: sourceNodeId, weight: weight ?? 1 })).data,
888
+ removeAchiever: async (goalId, depId) => (await client.delete(`/goals/${goalId}/achievers/${depId}`)).data,
889
+ getKnowledgeGaps: async (goalId) => (await client.get(`/goals/${goalId}/knowledge-gaps`)).data,
890
+ getDashboard: async () => (await client.get('/goals/dashboard')).data,
880
891
  },
881
892
  context: {
882
893
  getNodeContext: async (nodeId, options = {}) => {
@@ -913,6 +924,13 @@ function createApiClient(token) {
913
924
  // Export the axios instance for direct use
914
925
  const axiosInstance = apiClient;
915
926
 
927
+ // ─── Coherence ────────────────────────────────────────────────
928
+ const coherence = {
929
+ getPending: () => apiClient.get('/coherence/pending').then(r => r.data),
930
+ runCheck: (planId, goalId) => apiClient.post(`/plans/${planId}/coherence/check`, goalId ? { goal_id: goalId } : {}).then(r => r.data),
931
+ getPlanCoherence: (planId) => apiClient.get(`/plans/${planId}/coherence`).then(r => r.data),
932
+ };
933
+
916
934
  module.exports = {
917
935
  plans,
918
936
  nodes,
@@ -926,6 +944,7 @@ module.exports = {
926
944
  context,
927
945
  graphiti,
928
946
  dependencies,
947
+ coherence,
929
948
  axiosInstance, // Export for direct API calls
930
949
  createApiClient // Factory for per-session clients (HTTP mode)
931
950
  };
package/src/index.js CHANGED
@@ -42,12 +42,9 @@ async function main() {
42
42
  console.error(`MCP Server Name: ${process.env.MCP_SERVER_NAME || 'planning-system-mcp'}`);
43
43
  console.error(`MCP Server Version: ${process.env.MCP_SERVER_VERSION || version}`);
44
44
 
45
- // Validate required environment variables
46
- if (!userApiToken) {
47
- throw new Error('USER_API_TOKEN environment variable is required. Please generate one from the Agent Planner UI and set it in .env file.');
48
- }
49
-
50
45
  if (transport === 'http') {
46
+ // HTTP mode: tokens come from the Authorization header on each request
47
+ // No USER_API_TOKEN needed — per-session clients are created in server-http.js
51
48
  // HTTP/SSE transport mode
52
49
  const httpServer = new MCPHTTPServer({
53
50
  port: process.env.PORT || 3100,
@@ -69,7 +66,11 @@ async function main() {
69
66
  process.exit(0);
70
67
  });
71
68
  } else {
72
- // Stdio transport mode (default)
69
+ // Stdio transport mode (default) — requires USER_API_TOKEN since there's no HTTP request
70
+ if (!userApiToken) {
71
+ throw new Error('USER_API_TOKEN environment variable is required for stdio mode. Please generate one from the Agent Planner UI and set it in .env file.');
72
+ }
73
+
73
74
  const server = new Server({
74
75
  name: process.env.MCP_SERVER_NAME || "planning-system-mcp",
75
76
  version: process.env.MCP_SERVER_VERSION || version
package/src/tools.js CHANGED
@@ -178,6 +178,41 @@ function setupTools(server, apiClientOverride) {
178
178
  }
179
179
  },
180
180
 
181
+ // ========================================
182
+ // COHERENCE - Check alignment across goals/plans/knowledge
183
+ // ========================================
184
+ {
185
+ name: "check_coherence_pending",
186
+ description: "Check what needs coherence review. Returns stale plans and goals that have changed since their last coherence check. Call this at the start of a maintenance cycle to discover what needs attention. Uses timestamp comparison (updated_at vs coherence_checked_at) — no expensive processing.",
187
+ inputSchema: {
188
+ type: "object",
189
+ properties: {}
190
+ }
191
+ },
192
+ {
193
+ name: "run_coherence_check",
194
+ description: "Run a coherence check on a specific plan. Evaluates quality (coverage, specificity, ordering, knowledge completeness), flags contradictions, and stamps the plan as checked. Returns quality breakdown with sub-scores and rationale.",
195
+ inputSchema: {
196
+ type: "object",
197
+ properties: {
198
+ plan_id: { type: "string", description: "Plan ID to check" },
199
+ goal_id: { type: "string", description: "Optional goal ID to evaluate coverage against" }
200
+ },
201
+ required: ["plan_id"]
202
+ }
203
+ },
204
+ {
205
+ name: "assess_goal_quality",
206
+ description: "Assess how well-defined a goal is. Evaluates 5 dimensions: clarity (title+description), measurability (success criteria), actionability (linked plans), knowledge grounding (related facts), and commitment (desire vs intention, deadline). Returns score, dimension breakdown, and specific improvement suggestions. Use this when helping users define or refine goals.",
207
+ inputSchema: {
208
+ type: "object",
209
+ properties: {
210
+ goal_id: { type: "string", description: "Goal ID to assess" }
211
+ },
212
+ required: ["goal_id"]
213
+ }
214
+ },
215
+
181
216
  // ========================================
182
217
  // CONTEXT LOADING - Get everything you need
183
218
  // Use before starting work on a plan/goal
@@ -858,21 +893,10 @@ function setupTools(server, apiClientOverride) {
858
893
  organization_id: { type: "string", description: "Organization ID" },
859
894
  title: { type: "string", description: "Goal title" },
860
895
  description: { type: "string", description: "Goal description" },
861
- success_metrics: {
862
- type: "array",
863
- description: "Success metrics array [{metric, target, current, unit}]",
864
- items: {
865
- type: "object",
866
- properties: {
867
- metric: { type: "string" },
868
- target: { type: "number" },
869
- current: { type: "number" },
870
- unit: { type: "string" }
871
- }
872
- }
873
- },
874
- time_horizon: { type: "string", description: "Target date (ISO format)" },
875
- github_repo_url: { type: "string", description: "Related GitHub repo URL" }
896
+ type: { type: "string", enum: ["outcome", "constraint", "metric", "principle"], description: "Goal type (default: outcome)" },
897
+ success_criteria: { type: "object", description: "Success criteria as JSON" },
898
+ priority: { type: "number", description: "Priority (higher = more important, default: 0)" },
899
+ parent_goal_id: { type: "string", description: "Parent goal ID for hierarchy" }
876
900
  },
877
901
  required: ["organization_id", "title"]
878
902
  }
@@ -886,13 +910,15 @@ function setupTools(server, apiClientOverride) {
886
910
  goal_id: { type: "string", description: "Goal ID" },
887
911
  title: { type: "string", description: "New title" },
888
912
  description: { type: "string", description: "New description" },
889
- status: {
890
- type: "string",
913
+ type: { type: "string", enum: ["outcome", "constraint", "metric", "principle"], description: "Goal type" },
914
+ status: {
915
+ type: "string",
891
916
  description: "New status",
892
- enum: ["active", "achieved", "at_risk", "abandoned"]
917
+ enum: ["active", "achieved", "paused", "abandoned"]
893
918
  },
894
- success_metrics: { type: "array", description: "Updated metrics" },
895
- time_horizon: { type: "string", description: "New target date" }
919
+ success_criteria: { type: "object", description: "Success criteria as JSON" },
920
+ priority: { type: "number", description: "Priority (higher = more important)" },
921
+ parent_goal_id: { type: "string", description: "Parent goal ID for hierarchy" }
896
922
  },
897
923
  required: ["goal_id"]
898
924
  }
@@ -2036,20 +2062,24 @@ function setupTools(server, apiClientOverride) {
2036
2062
  }
2037
2063
 
2038
2064
  if (name === "create_goal") {
2039
- const { organization_id, title, description, success_metrics, time_horizon, github_repo_url } = args;
2065
+ const { organization_id, title, description, type, success_criteria, priority, parent_goal_id } = args;
2040
2066
  const result = await apiClient.goals.create({
2041
2067
  organization_id,
2042
2068
  title,
2043
2069
  description,
2044
- success_metrics,
2045
- time_horizon,
2046
- github_repo_url
2070
+ type: type || 'outcome',
2071
+ successCriteria: success_criteria || null,
2072
+ priority: priority || 0,
2073
+ parentGoalId: parent_goal_id || null,
2047
2074
  });
2048
2075
  return formatResponse(result);
2049
2076
  }
2050
2077
 
2051
2078
  if (name === "update_goal") {
2052
- const { goal_id, ...updateData } = args;
2079
+ const { goal_id, parent_goal_id, success_criteria, ...rest } = args;
2080
+ const updateData = { ...rest };
2081
+ if (parent_goal_id !== undefined) updateData.parentGoalId = parent_goal_id;
2082
+ if (success_criteria !== undefined) updateData.successCriteria = success_criteria;
2053
2083
  const result = await apiClient.goals.update(goal_id, updateData);
2054
2084
  return formatResponse(result);
2055
2085
  }
@@ -2238,12 +2268,14 @@ function setupTools(server, apiClientOverride) {
2238
2268
  "Knowledge - Persistent storage for decisions, context, constraints, and learnings"
2239
2269
  ],
2240
2270
  recommended_workflow: [
2241
- "1. Check list_goals to understand current objectives",
2242
- "2. Use list_plans to see existing plans",
2243
- "3. Before working on a plan, use get_plan_context to get the full picture",
2244
- "4. Update task statuses as you work (update_node with status)",
2245
- "5. Store important decisions and learnings using add_learning",
2246
- "6. Check recall_knowledge before making decisions to see past context"
2271
+ "1. PREFLIGHT: check_coherence_pending to see if any plans/goals need alignment review",
2272
+ " If stale items found, run_coherence_check on each before starting task work",
2273
+ "2. Check list_goals to understand current objectives",
2274
+ "3. Use list_plans to see existing plans",
2275
+ "4. Before working on a plan, use get_plan_context to get the full picture",
2276
+ "5. Update task statuses as you work (update_node with status)",
2277
+ "6. Store important decisions and learnings using add_learning",
2278
+ "7. Check recall_knowledge before making decisions to see past context"
2247
2279
  ],
2248
2280
  quick_tips: [
2249
2281
  "Always capture WHY decisions were made, not just WHAT",
@@ -2380,6 +2412,43 @@ function setupTools(server, apiClientOverride) {
2380
2412
  });
2381
2413
  }
2382
2414
 
2415
+ // ===== COHERENCE =====
2416
+ if (name === "check_coherence_pending") {
2417
+ const result = await apiClient.coherence.getPending();
2418
+ const totalStale = (result.stale_plans?.length || 0) + (result.stale_goals?.length || 0);
2419
+ return formatResponse({
2420
+ ...result,
2421
+ tip: totalStale > 0
2422
+ ? "Review stale items. For each stale plan, call run_coherence_check to evaluate quality and stamp as checked."
2423
+ : "Everything is up to date. No coherence review needed."
2424
+ });
2425
+ }
2426
+
2427
+ if (name === "assess_goal_quality") {
2428
+ const { goal_id } = args;
2429
+ const result = await apiClient.goals.getQuality(goal_id);
2430
+ const lowDims = Object.entries(result.dimensions || {})
2431
+ .filter(([, v]) => v.score < 0.5)
2432
+ .map(([k]) => k);
2433
+ return formatResponse({
2434
+ ...result,
2435
+ tip: result.suggestions?.length > 0
2436
+ ? `Goal needs improvement in: ${lowDims.join(', ') || 'minor areas'}. Follow the suggestions to strengthen it.`
2437
+ : 'Goal is well-defined. Ready for agent execution.'
2438
+ });
2439
+ }
2440
+
2441
+ if (name === "run_coherence_check") {
2442
+ const { plan_id, goal_id } = args;
2443
+ const result = await apiClient.coherence.runCheck(plan_id, goal_id);
2444
+ return formatResponse({
2445
+ ...result,
2446
+ tip: result.coherence_issues_count > 0
2447
+ ? `${result.coherence_issues_count} coherence issues found. Review tasks with stale_beliefs or contradiction_detected status.`
2448
+ : "Plan is coherent. Quality score and checked_at timestamp updated."
2449
+ });
2450
+ }
2451
+
2383
2452
  // Tool not found
2384
2453
  throw new Error(`Unknown tool: ${name}`);
2385
2454
  } catch (error) {