@agent-plan/mcp 0.2.19-next.2 → 0.2.19-next.4
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -20
- package/package.json +3 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA45BA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import { PlanStore, ExportService, withFeatureLock, needsMotivation, findPhaseByRef, buildRecap } from "@agent-plan/core";
|
|
8
8
|
import { serve } from "@agent-plan/server";
|
|
9
|
-
import { createChecklistItemId, createFeatureId, createPhaseId, createShortId, createTaskId, clampSlug, normalizeSlug, formatPhaseRef } from "@agent-plan/core/naming";
|
|
9
|
+
import { createChecklistItemId, createFeatureId, createPhaseId, createShortId, createTaskId, clampSlug, normalizeSlug, formatPhaseRef, formatFeatureRef } from "@agent-plan/core/naming";
|
|
10
10
|
const STATUS_VALUES = ["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"];
|
|
11
11
|
const PHASE_STATUS_VALUES = ["draft", "discovery", ...STATUS_VALUES];
|
|
12
12
|
function text(textValue, structuredContent) {
|
|
@@ -189,7 +189,7 @@ server.registerTool("planner-init", {
|
|
|
189
189
|
if (goal !== undefined)
|
|
190
190
|
project.goal = goal.trim();
|
|
191
191
|
await st.saveProject(project);
|
|
192
|
-
return writeAndSummarize(st, `.planner/ initialized for "${project.name}"
|
|
192
|
+
return writeAndSummarize(st, `.planner/ initialized for "${project.name}"`);
|
|
193
193
|
});
|
|
194
194
|
server.registerTool("planner-show", {
|
|
195
195
|
description: "Show the current planner overview.",
|
|
@@ -227,7 +227,7 @@ server.registerTool("planner-project-language", {
|
|
|
227
227
|
if (chatLanguage !== undefined)
|
|
228
228
|
project.chatLanguage = chatLanguage.trim();
|
|
229
229
|
await st.saveProject(project);
|
|
230
|
-
return writeAndSummarize(st, `Saved language preferences: content=${project.contentLanguage || "(unset)"}, chat=${project.chatLanguage || "(unset)"}
|
|
230
|
+
return writeAndSummarize(st, `Saved language preferences: content=${project.contentLanguage || "(unset)"}, chat=${project.chatLanguage || "(unset)"}`);
|
|
231
231
|
});
|
|
232
232
|
server.registerTool("planner-project-discuss", {
|
|
233
233
|
description: "Record/update project-level discovery fields. This is the MCP equivalent of grouped project discuss without Pi UI prompts.",
|
|
@@ -258,7 +258,7 @@ server.registerTool("planner-project-discuss", {
|
|
|
258
258
|
if (params.decisions !== undefined)
|
|
259
259
|
project.decisions = params.decisions.map((entry) => entry.trim()).filter(Boolean);
|
|
260
260
|
await st.saveProject(project);
|
|
261
|
-
return writeAndSummarize(st, `Project discussed/updated: ${project.name}
|
|
261
|
+
return writeAndSummarize(st, `Project discussed/updated: ${project.name}`);
|
|
262
262
|
});
|
|
263
263
|
server.registerTool("planner-feature-list", {
|
|
264
264
|
description: "List features with phase/task counts.",
|
|
@@ -312,7 +312,7 @@ server.registerTool("planner-feature-add", {
|
|
|
312
312
|
doc.features.push(feature);
|
|
313
313
|
return doc;
|
|
314
314
|
});
|
|
315
|
-
return writeAndSummarize(st,
|
|
315
|
+
return writeAndSummarize(st, `✅ Feature created: ${formatFeatureRef(feature.number)} — ${feature.name}${feature.shortId ? ` · ${feature.shortId}` : ""}`);
|
|
316
316
|
});
|
|
317
317
|
server.registerTool("planner-feature-show", {
|
|
318
318
|
description: "Show a feature by id or name.",
|
|
@@ -369,7 +369,7 @@ server.registerTool("planner-feature-update", {
|
|
|
369
369
|
return doc;
|
|
370
370
|
});
|
|
371
371
|
const result = updated.features.find((entry) => entry.id === feature.id);
|
|
372
|
-
return writeAndSummarize(st,
|
|
372
|
+
return writeAndSummarize(st, `✅ Feature updated: ${formatFeatureRef(result.number)} — ${result.name}${result.shortId ? ` · ${result.shortId}` : ""}`);
|
|
373
373
|
});
|
|
374
374
|
server.registerTool("planner-feature-delete", {
|
|
375
375
|
description: "Delete a feature. By default, phases are unlinked rather than deleted.",
|
|
@@ -452,6 +452,8 @@ server.registerTool("planner-phase-add", {
|
|
|
452
452
|
updatedAt: timestamp,
|
|
453
453
|
handoff: "",
|
|
454
454
|
handoffUpdatedAt: "",
|
|
455
|
+
handoffReadAt: "",
|
|
456
|
+
handoffHistory: [],
|
|
455
457
|
};
|
|
456
458
|
await st.savePhase(phase);
|
|
457
459
|
if (feature) {
|
|
@@ -466,7 +468,7 @@ server.registerTool("planner-phase-add", {
|
|
|
466
468
|
});
|
|
467
469
|
if (!phase)
|
|
468
470
|
return text("Phase creation failed.");
|
|
469
|
-
return writeAndSummarize(st,
|
|
471
|
+
return writeAndSummarize(st, `✅ Phase created: ${formatPhaseRef(phase.number, feature?.number)} — ${phase.title}${phase.shortId ? ` · ${phase.shortId}` : ""}`);
|
|
470
472
|
});
|
|
471
473
|
server.registerTool("planner-phase-show", {
|
|
472
474
|
description: "Show a phase by id or name.",
|
|
@@ -492,7 +494,8 @@ server.registerTool("planner-phase-discuss", {
|
|
|
492
494
|
},
|
|
493
495
|
}, async ({ phase: ref, ...updates }) => {
|
|
494
496
|
const st = await requireStore();
|
|
495
|
-
const
|
|
497
|
+
const features = (await st.loadFeatures()).features;
|
|
498
|
+
const found = findPhaseByRef(await st.loadAllPhases(), features, ref);
|
|
496
499
|
if (!found)
|
|
497
500
|
return text(`Phase not found: ${ref}`);
|
|
498
501
|
const phase = await st.updatePhase(found.id, (entry) => {
|
|
@@ -517,7 +520,7 @@ server.registerTool("planner-phase-discuss", {
|
|
|
517
520
|
entry.updatedAt = nowISO();
|
|
518
521
|
return entry;
|
|
519
522
|
});
|
|
520
|
-
return writeAndSummarize(st,
|
|
523
|
+
return writeAndSummarize(st, `✅ Phase discussed/planned: ${formatPhaseRef(found.number, featureNumberOfPhase(found, features))} — ${phase.title}${phase.shortId ? ` · ${phase.shortId}` : ""}`);
|
|
521
524
|
});
|
|
522
525
|
server.registerTool("planner-phase-update", {
|
|
523
526
|
description: "Update phase fields.",
|
|
@@ -531,7 +534,8 @@ server.registerTool("planner-phase-update", {
|
|
|
531
534
|
},
|
|
532
535
|
}, async ({ phase: ref, ...updates }) => {
|
|
533
536
|
const st = await requireStore();
|
|
534
|
-
const
|
|
537
|
+
const features = (await st.loadFeatures()).features;
|
|
538
|
+
const found = findPhaseByRef(await st.loadAllPhases(), features, ref);
|
|
535
539
|
if (!found)
|
|
536
540
|
return text(`Phase not found: ${ref}`);
|
|
537
541
|
const phase = await st.updatePhase(found.id, (entry) => {
|
|
@@ -548,7 +552,7 @@ server.registerTool("planner-phase-update", {
|
|
|
548
552
|
entry.updatedAt = nowISO();
|
|
549
553
|
return entry;
|
|
550
554
|
});
|
|
551
|
-
return writeAndSummarize(st,
|
|
555
|
+
return writeAndSummarize(st, `✅ Phase updated: ${formatPhaseRef(found.number, featureNumberOfPhase(found, features))} — ${phase.title}${phase.shortId ? ` · ${phase.shortId}` : ""}`);
|
|
552
556
|
});
|
|
553
557
|
server.registerTool("planner-phase-delete", {
|
|
554
558
|
description: "Delete a phase and unlink it from features.",
|
|
@@ -733,16 +737,22 @@ server.registerTool("planner-task-start", {
|
|
|
733
737
|
inputSchema: { task: z.string().min(1) },
|
|
734
738
|
}, async ({ task: ref }) => {
|
|
735
739
|
const st = await requireStore();
|
|
736
|
-
// Hygiene notice (non-blocking): surface an existing handoff but never block
|
|
737
|
-
// task_start — the handoff is a captured-context artifact, not a lock (e.g. a
|
|
738
|
-
// small modification after writing a handoff should start without forcing
|
|
739
|
-
// deletion, which would lose context).
|
|
740
|
-
const handoffNotice = (await st.listHandoffs()).length > 0
|
|
741
|
-
? "ℹ️ One or more phases have a pending handoff — if relevant to the task you're starting, read it with planner-handoff-show <ref>, then clear with planner-handoff-clear. Proceeding with task start.\n"
|
|
742
|
-
: "";
|
|
743
740
|
const found = findTaskByRef(await st.loadAllPhases(), ref);
|
|
744
741
|
if (!found)
|
|
745
742
|
return text(`Task not found: ${ref}`);
|
|
743
|
+
// Auto-archive the handoff on THIS task's phase (reason: task-started) — the
|
|
744
|
+
// agent is now actively working, so the captured context is consumed. Other
|
|
745
|
+
// phases' handoffs are left untouched (informational, non-blocking).
|
|
746
|
+
const allHandoffs = await st.listHandoffs();
|
|
747
|
+
let handoffNotice = "";
|
|
748
|
+
if ((found.phase.handoff ?? "") !== "") {
|
|
749
|
+
await st.clearPhaseHandoff(found.phase.id, "task-started").catch(() => { });
|
|
750
|
+
handoffNotice = "📦 Archived handoff for this phase (task started) — recover via planner-handoff-list + .planner/handoff-archive/.\n";
|
|
751
|
+
}
|
|
752
|
+
const _otherHandoffs = allHandoffs.filter((h) => h.phaseId !== found.phase.id);
|
|
753
|
+
if (_otherHandoffs.length > 0) {
|
|
754
|
+
handoffNotice += `ℹ️ ${_otherHandoffs.length} other phase handoff(s) pending — review with planner-handoff-list if relevant.\n`;
|
|
755
|
+
}
|
|
746
756
|
const timestamp = nowISO();
|
|
747
757
|
let updatedTask;
|
|
748
758
|
await st.updatePhase(found.phase.id, (phase) => {
|
|
@@ -870,8 +880,8 @@ server.registerTool("planner-handoff-clear", {
|
|
|
870
880
|
const r = await resolvePhaseForHandoff(st, phaseRef);
|
|
871
881
|
if (!r.ok)
|
|
872
882
|
return text(`❌ ${r.error}`);
|
|
873
|
-
await st.clearPhaseHandoff(r.phase.id);
|
|
874
|
-
return text(`✅ Cleared handoff on ${r.compositeRef}
|
|
883
|
+
await st.clearPhaseHandoff(r.phase.id, "manual");
|
|
884
|
+
return text(`✅ Cleared handoff on ${r.compositeRef} (handoffUpdatedAt preserved as audit; archived to .planner/handoff-archive/).`, { phaseRef: r.compositeRef, phaseId: r.phase.id });
|
|
875
885
|
});
|
|
876
886
|
server.registerTool("planner-web", {
|
|
877
887
|
description: "Manage the planner web dashboard (start/status/stop) from MCP stdio. Runs an in-process HTTP+WS server bound to LAN; it lives as long as this MCP process. plan-root comes from AGENT_PLAN_ROOT or cwd()/.planner.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/mcp",
|
|
3
|
-
"version": "0.2.19-next.
|
|
3
|
+
"version": "0.2.19-next.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "MCP server for Agent Plan, exposing planner-* tools over stdio.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.17.0",
|
|
43
43
|
"zod": "^3.24.0",
|
|
44
|
-
"@agent-plan/core": "0.2.19-next.
|
|
45
|
-
"@agent-plan/server": "0.2.19-next.
|
|
44
|
+
"@agent-plan/core": "0.2.19-next.4",
|
|
45
|
+
"@agent-plan/server": "0.2.19-next.4"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsc -p tsconfig.json",
|