@agent-plan/mcp 0.2.19-next.13 → 0.2.19-next.15
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 +106 -35
- 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":";AA4iCA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
4
4
|
import * as z from "zod/v4";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
|
-
import { PlanStore, ExportService, withFeatureLock, needsMotivation, findPhaseByRef, findTaskByRef, buildRecap, migrateToGlobalSequence } from "@agent-plan/core";
|
|
7
|
+
import { PlanStore, ExportService, withFeatureLock, needsMotivation, findPhaseByRef, findTaskByRef, buildRecap, migrateToGlobalSequence, addChecklistItem, removeChecklistItem, toggleChecklistItem } from "@agent-plan/core";
|
|
8
8
|
import { serve } from "@agent-plan/server";
|
|
9
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"];
|
|
@@ -124,7 +124,7 @@ server.registerTool("planner-export", {
|
|
|
124
124
|
const markdown = exportService.exportToMarkdown(plan, full);
|
|
125
125
|
const fs = await import("node:fs/promises");
|
|
126
126
|
await fs.writeFile(join(st.root, "EXPORT.md"), markdown, "utf-8");
|
|
127
|
-
return text(`Project export generated. Summary results:\n\n${markdown.slice(0, 1000)}${markdown.length > 1000 ? "... (full report in .planner/EXPORT.md)" : ""}
|
|
127
|
+
return text(`Project export generated. Summary results:\n\n${markdown.slice(0, 1000)}${markdown.length > 1000 ? "... (full report in .planner/EXPORT.md)" : ""}`);
|
|
128
128
|
});
|
|
129
129
|
server.registerTool("planner-authorize-bypass", {
|
|
130
130
|
description: "Authorize a temporary guard bypass (default 15 minutes) so edit/write tools can proceed even when no task is in-progress. Use ONLY after the user explicitly authorizes proceeding without a task. Harness-agnostic: stored in resume.json so all adapters (Pi, Claude Code, Codex, ...) respect it.",
|
|
@@ -165,19 +165,43 @@ server.registerTool("planner-init", {
|
|
|
165
165
|
return writeAndSummarize(st, `.planner/ initialized for "${project.name}"`);
|
|
166
166
|
});
|
|
167
167
|
server.registerTool("planner-show", {
|
|
168
|
-
description: "Show
|
|
168
|
+
description: "Show a compact planner overview: project metadata, counts, and a one-line summary of each feature (F00x · shortId — name (status; N phases, M tasks)). Does NOT include full descriptions, phases, or tasks — use planner-feature-list / planner-phase-list / planner-task-list for discovery and planner-*-show for full detail of a single entity. Keeps the result small to avoid token overflow.",
|
|
169
169
|
}, async () => {
|
|
170
170
|
const st = await requireStore();
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
`
|
|
180
|
-
|
|
171
|
+
const features = (await st.loadFeatures()).features;
|
|
172
|
+
const phases = await st.loadAllPhases();
|
|
173
|
+
const totalTasks = phases.reduce((total, phase) => total + phase.tasks.length, 0);
|
|
174
|
+
const project = await st.loadProject();
|
|
175
|
+
const manifest = await st.loadManifest();
|
|
176
|
+
const featureLines = features.map((feature) => {
|
|
177
|
+
const featurePhases = phases.filter((phase) => phase.featureId === feature.id);
|
|
178
|
+
const taskCount = featurePhases.reduce((total, phase) => total + phase.tasks.length, 0);
|
|
179
|
+
return `- ${formatFeatureRef(feature.number)}${feature.shortId ? ` · ${feature.shortId}` : ""} — ${feature.name} (${feature.status}; ${featurePhases.length} phases, ${taskCount} tasks)`;
|
|
180
|
+
});
|
|
181
|
+
const summary = [
|
|
182
|
+
`📋 ${project.name}`,
|
|
183
|
+
`Description: ${project.description || "(not set)"}`,
|
|
184
|
+
`Goal: ${project.goal || "(not set)"}`,
|
|
185
|
+
`Features: ${features.length} | Phases: ${phases.length} | Tasks: ${totalTasks}`,
|
|
186
|
+
`Updated: ${manifest.updatedAt || "(unknown)"}`,
|
|
187
|
+
"",
|
|
188
|
+
"Features:",
|
|
189
|
+
featureLines.join("\n") || "(none)",
|
|
190
|
+
].join("\n");
|
|
191
|
+
// Compact structured overview (no full plan: avoids 1M+ char token overflow).
|
|
192
|
+
const overview = {
|
|
193
|
+
project: { name: project.name, description: project.description || null, goal: project.goal || null, updatedAt: manifest.updatedAt || null },
|
|
194
|
+
counts: { features: features.length, phases: phases.length, tasks: totalTasks },
|
|
195
|
+
features: features.map((feature) => ({
|
|
196
|
+
ref: formatFeatureRef(feature.number),
|
|
197
|
+
shortId: feature.shortId || null,
|
|
198
|
+
name: feature.name,
|
|
199
|
+
status: feature.status,
|
|
200
|
+
phases: phases.filter((p) => p.featureId === feature.id).length,
|
|
201
|
+
tasks: phases.filter((p) => p.featureId === feature.id).reduce((t, p) => t + p.tasks.length, 0),
|
|
202
|
+
})),
|
|
203
|
+
};
|
|
204
|
+
return text(summary, { overview });
|
|
181
205
|
});
|
|
182
206
|
server.registerTool("planner-repair", {
|
|
183
207
|
description: "Repair dangling feature→phase references, rebuild phase containment from each task's own phaseId (heals the migrateToGlobalSequence task-shuffle bug where tasks land in the wrong phase file), and report integrity.",
|
|
@@ -758,9 +782,9 @@ server.registerTool("planner-task-update", {
|
|
|
758
782
|
server.registerTool("planner-task-checklist-toggle", {
|
|
759
783
|
description: "Tick/untick a task checklist item (a 'step') without rewriting the whole list. Accepts the item as C{n} (e.g. C2), the item id, or the title (case-insensitive, first match). Pass checked=true/false to set explicitly, or omit to toggle. Use this instead of writing DONE in step titles. Items are numbered C1/C2… per task.",
|
|
760
784
|
inputSchema: {
|
|
761
|
-
task: z.string().min(1),
|
|
762
|
-
item: z.string().min(1),
|
|
763
|
-
checked: z.boolean().optional(),
|
|
785
|
+
task: z.string().min(1).describe("Task ref: F00x/P00x/T00x, bare T00x (global), 5-char shortId, UUID, or title"),
|
|
786
|
+
item: z.string().min(1).describe("Checklist item selector: C{n} (e.g. C2), item id, or title (case-insensitive)"),
|
|
787
|
+
checked: z.boolean().optional().describe("Set explicitly: true=done, false=open. Omit to toggle."),
|
|
764
788
|
},
|
|
765
789
|
}, async ({ task: ref, item, checked }) => {
|
|
766
790
|
const st = await requireStore();
|
|
@@ -779,32 +803,79 @@ server.registerTool("planner-task-checklist-toggle", {
|
|
|
779
803
|
result = `Task "${found.task.title}" has no checklist.`;
|
|
780
804
|
return phase;
|
|
781
805
|
}
|
|
782
|
-
|
|
783
|
-
const cMatch = item.match(/^C(\d+)$/i);
|
|
784
|
-
if (cMatch) {
|
|
785
|
-
const idx = parseInt(cMatch[1], 10) - 1;
|
|
786
|
-
if (idx < 0 || idx >= ck.length) {
|
|
787
|
-
result = `C${idx + 1} not found (1..${ck.length}).`;
|
|
788
|
-
return phase;
|
|
789
|
-
}
|
|
790
|
-
target = ck[idx];
|
|
791
|
-
}
|
|
792
|
-
else {
|
|
793
|
-
const needle = item.trim().toLowerCase();
|
|
794
|
-
target = ck.find((i) => i.id === item)
|
|
795
|
-
?? ck.find((i) => i.title.trim().toLowerCase() === needle)
|
|
796
|
-
?? ck.find((i) => i.title.trim().toLowerCase().includes(needle));
|
|
797
|
-
}
|
|
806
|
+
const target = toggleChecklistItem(ck, item, checked);
|
|
798
807
|
if (!target) {
|
|
799
808
|
result = `No checklist item matching "${item}".`;
|
|
800
809
|
return phase;
|
|
801
810
|
}
|
|
802
|
-
const newValue = checked ?? !target.checked;
|
|
803
|
-
target.checked = newValue;
|
|
804
811
|
task.updatedAt = nowISO();
|
|
805
812
|
phase.updatedAt = nowISO();
|
|
806
813
|
const doneCount = ck.filter((i) => i.checked).length;
|
|
807
|
-
result = `C${target.number} "${target.title}" → ${
|
|
814
|
+
result = `C${target.number} "${target.title}" → ${target.checked ? "done" : "open"} (${doneCount}/${ck.length} checked)`;
|
|
815
|
+
return phase;
|
|
816
|
+
});
|
|
817
|
+
return writeAndSummarize(st, `✅ ${result}`);
|
|
818
|
+
});
|
|
819
|
+
server.registerTool("planner-task-checklist-add", {
|
|
820
|
+
description: "Add a single checklist item (a 'step') to a task without rewriting the list. The new item is appended as C{n} (next progressive number, stable id, unchecked). Use this to subdivide a task into smaller steps INSTEAD of spawning sub-tasks — the checklist keeps description, notes, statusLog and steps concentrated in one task (sub-tasks disperse context). Also use for granular adds instead of replacing the whole checklist via planner-task-update.",
|
|
821
|
+
inputSchema: {
|
|
822
|
+
task: z.string().min(1).describe("Task ref: F00x/P00x/T00x, bare T00x (global), 5-char shortId, UUID, or title"),
|
|
823
|
+
title: z.string().min(1).describe("Checklist item text (a single step)"),
|
|
824
|
+
},
|
|
825
|
+
}, async ({ task: ref, title }) => {
|
|
826
|
+
const st = await requireStore();
|
|
827
|
+
const found = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, ref);
|
|
828
|
+
if (!found)
|
|
829
|
+
return text(`Task not found: ${ref}`);
|
|
830
|
+
let result = "";
|
|
831
|
+
await st.updatePhase(found.phase.id, (phase) => {
|
|
832
|
+
const task = phase.tasks.find((entry) => entry.id === found.task.id);
|
|
833
|
+
if (!task) {
|
|
834
|
+
result = `Task not found: ${ref}`;
|
|
835
|
+
return phase;
|
|
836
|
+
}
|
|
837
|
+
const ck = task.checklist ?? [];
|
|
838
|
+
const item = addChecklistItem(ck, task.id, title);
|
|
839
|
+
ck.push(item);
|
|
840
|
+
task.checklist = ck;
|
|
841
|
+
task.updatedAt = nowISO();
|
|
842
|
+
phase.updatedAt = nowISO();
|
|
843
|
+
result = `Added C${item.number} "${item.title}" (${ck.length} items)`;
|
|
844
|
+
return phase;
|
|
845
|
+
});
|
|
846
|
+
return writeAndSummarize(st, `✅ ${result}`);
|
|
847
|
+
});
|
|
848
|
+
server.registerTool("planner-task-checklist-remove", {
|
|
849
|
+
description: "Remove a single checklist item (a 'step') from a task by C{n} (e.g. C2), item id, or title (case-insensitive). Remaining items are renumbered C1..Cn for readability; their stable ids are preserved. Use this for granular removes instead of replacing the whole checklist via planner-task-update.",
|
|
850
|
+
inputSchema: {
|
|
851
|
+
task: z.string().min(1).describe("Task ref: F00x/P00x/T00x, bare T00x (global), 5-char shortId, UUID, or title"),
|
|
852
|
+
item: z.string().min(1).describe("Checklist item selector: C{n} (e.g. C2), item id, or title (case-insensitive)"),
|
|
853
|
+
},
|
|
854
|
+
}, async ({ task: ref, item }) => {
|
|
855
|
+
const st = await requireStore();
|
|
856
|
+
const found = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, ref);
|
|
857
|
+
if (!found)
|
|
858
|
+
return text(`Task not found: ${ref}`);
|
|
859
|
+
let result = "";
|
|
860
|
+
await st.updatePhase(found.phase.id, (phase) => {
|
|
861
|
+
const task = phase.tasks.find((entry) => entry.id === found.task.id);
|
|
862
|
+
if (!task) {
|
|
863
|
+
result = `Task not found: ${ref}`;
|
|
864
|
+
return phase;
|
|
865
|
+
}
|
|
866
|
+
const ck = task.checklist ?? [];
|
|
867
|
+
if (ck.length === 0) {
|
|
868
|
+
result = `Task "${found.task.title}" has no checklist.`;
|
|
869
|
+
return phase;
|
|
870
|
+
}
|
|
871
|
+
const removed = removeChecklistItem(ck, item);
|
|
872
|
+
if (!removed) {
|
|
873
|
+
result = `No checklist item matching "${item}".`;
|
|
874
|
+
return phase;
|
|
875
|
+
}
|
|
876
|
+
task.updatedAt = nowISO();
|
|
877
|
+
phase.updatedAt = nowISO();
|
|
878
|
+
result = `Removed C${removed.number} "${removed.title}" (${ck.length} items left)`;
|
|
808
879
|
return phase;
|
|
809
880
|
});
|
|
810
881
|
return writeAndSummarize(st, `✅ ${result}`);
|
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.15",
|
|
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.15",
|
|
45
|
+
"@agent-plan/server": "0.2.19-next.15"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsc -p tsconfig.json",
|