@agent-plan/mcp 0.2.19-next.5 → 0.2.19-next.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAw4BA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAg8BA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
package/dist/index.js CHANGED
@@ -234,17 +234,70 @@ server.registerTool("planner-project-discuss", {
234
234
  return writeAndSummarize(st, `Project discussed/updated: ${project.name}`);
235
235
  });
236
236
  server.registerTool("planner-feature-list", {
237
- description: "List features with phase/task counts.",
238
- }, async () => {
237
+ description: "List features (compact: F00x · shortId — name (status; N phases, M tasks)). Pass featureRef to filter. Use this to discover refs cheaply — do NOT read .planner/ files or planner-plan-get full=true to find entities.",
238
+ inputSchema: { featureRef: z.string().optional().describe("Optional: filter to one feature (F00x/shortId/UUID/name).") },
239
+ }, async ({ featureRef }) => {
239
240
  const st = await requireStore();
240
- const features = (await st.loadFeatures()).features;
241
+ const allFeatures = (await st.loadFeatures()).features;
242
+ const features = featureRef ? allFeatures.filter((f) => f.id === findFeatureByRef(allFeatures, featureRef)?.id) : allFeatures;
241
243
  const phases = await st.loadAllPhases();
242
244
  const lines = features.map((feature) => {
243
245
  const featurePhases = phases.filter((phase) => phase.featureId === feature.id);
244
246
  const taskCount = featurePhases.reduce((total, phase) => total + phase.tasks.length, 0);
245
- return `- ${feature.id} — ${feature.name} (${feature.status}; ${featurePhases.length} phases, ${taskCount} tasks)`;
247
+ return `- ${formatFeatureRef(feature.number)}${feature.shortId ? ` · ${feature.shortId}` : ""} — ${feature.name} (${feature.status}; ${featurePhases.length} phases, ${taskCount} tasks)`;
246
248
  });
247
- return text(lines.join("\n") || "No features", { features });
249
+ return text(lines.join("\n") || "No features");
250
+ });
251
+ server.registerTool("planner-phase-list", {
252
+ description: "List phases (compact: F00x/P00x · shortId — title (status; N tasks) [F00x]). Filters: featureRef, status. Cheap discovery — do NOT read .planner/ files or planner-plan-get full=true.",
253
+ inputSchema: { featureRef: z.string().optional().describe("Optional: filter to one feature (F00x/shortId/UUID/name)."), status: z.string().optional().describe("Optional: filter by status name.") },
254
+ }, async ({ featureRef, status }) => {
255
+ const st = await requireStore();
256
+ const features = (await st.loadFeatures()).features;
257
+ let phases = await st.loadAllPhases();
258
+ if (featureRef) {
259
+ const f = findFeatureByRef(features, featureRef);
260
+ if (!f)
261
+ return text(`Feature not found: ${featureRef}`);
262
+ phases = phases.filter((p) => p.featureId === f.id);
263
+ }
264
+ if (status)
265
+ phases = phases.filter((p) => p.status === status);
266
+ const lines = phases.map((phase) => {
267
+ const fNum = featureNumberOfPhase(phase, features);
268
+ const fTag = fNum !== undefined ? ` [F${String(fNum).padStart(3, "0")}]` : "";
269
+ return `- ${formatPhaseRef(phase.number, fNum)}${phase.shortId ? ` · ${phase.shortId}` : ""} — ${phase.title} (${phase.status}; ${phase.tasks.length} tasks)${fTag}`;
270
+ });
271
+ return text(lines.join("\n") || "No phases");
272
+ });
273
+ server.registerTool("planner-task-list", {
274
+ description: "List tasks (compact: F00x/P00x/T00x · shortId — title (status)). Filters: featureRef, phaseRef, status. Cheap discovery — do NOT read .planner/ files or planner-plan-get full=true.",
275
+ inputSchema: { featureRef: z.string().optional(), phaseRef: z.string().optional(), status: z.string().optional().describe("Optional: filter by status name.") },
276
+ }, async ({ featureRef, phaseRef, status }) => {
277
+ const st = await requireStore();
278
+ const features = (await st.loadFeatures()).features;
279
+ let phases = await st.loadAllPhases();
280
+ if (featureRef) {
281
+ const f = findFeatureByRef(features, featureRef);
282
+ if (!f)
283
+ return text(`Feature not found: ${featureRef}`);
284
+ phases = phases.filter((p) => p.featureId === f.id);
285
+ }
286
+ if (phaseRef) {
287
+ const p = findPhaseByRef(phases, features, phaseRef);
288
+ if (!p)
289
+ return text(`Phase not found: ${phaseRef}`);
290
+ phases = [p];
291
+ }
292
+ const out = [];
293
+ for (const phase of phases) {
294
+ for (const task of phase.tasks) {
295
+ if (status && task.status !== status)
296
+ continue;
297
+ out.push(`- ${taskCompositeRef(task, phase, features)}${task.shortId ? ` · ${task.shortId}` : ""} — ${task.title} (${task.status})`);
298
+ }
299
+ }
300
+ return text(out.join("\n") || "No tasks");
248
301
  });
249
302
  server.registerTool("planner-feature-add", {
250
303
  description: "Create a feature with a rich description. REQUIRED: description must include code references (file:line), current implementation state (what exists, what is unimplemented), systems/structs/traits involved, concrete goals, and behaviors to preserve. The description is the primary context for future agents resuming this feature; one-liners cause misalignment.",
@@ -289,15 +342,16 @@ server.registerTool("planner-feature-add", {
289
342
  });
290
343
  server.registerTool("planner-feature-show", {
291
344
  description: "Show a feature by id or name.",
292
- inputSchema: { feature: z.string().min(1).describe("Feature ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title.") },
293
- }, async ({ feature: ref }) => {
345
+ inputSchema: { feature: z.string().min(1).describe("Feature ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title."), full: z.boolean().optional().describe("If true, include the feature description. Default: compact identity only (saves tokens).") },
346
+ }, async ({ feature: ref, full }) => {
294
347
  const st = await requireStore();
295
348
  const features = (await st.loadFeatures()).features;
296
349
  const feature = findFeatureByRef(features, ref);
297
350
  if (!feature)
298
351
  return text(`Feature not found: ${ref}`);
299
352
  const phases = (await st.loadAllPhases()).filter((phase) => phase.featureId === feature.id);
300
- return text(`${feature.name} — ${formatFeatureRef(feature.number)}${feature.shortId ? ` · ${feature.shortId}` : ""} (${feature.status}; ${phases.length} phases)`, { feature, phases });
353
+ const summary = `${feature.name} — ${formatFeatureRef(feature.number)}${feature.shortId ? ` · ${feature.shortId}` : ""} (${feature.status}; ${phases.length} phases)`;
354
+ return text(full ? `${summary}\n\n${feature.description || ""}` : summary);
301
355
  });
302
356
  server.registerTool("planner-feature-update", {
303
357
  description: "Update a feature.",
@@ -445,14 +499,15 @@ server.registerTool("planner-phase-add", {
445
499
  });
446
500
  server.registerTool("planner-phase-show", {
447
501
  description: "Show a phase by id or name.",
448
- inputSchema: { phase: z.string().min(1).describe("Phase ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title.") },
449
- }, async ({ phase: ref }) => {
502
+ inputSchema: { phase: z.string().min(1).describe("Phase ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title."), full: z.boolean().optional().describe("If true, include the phase description. Default: compact identity only (saves tokens).") },
503
+ }, async ({ phase: ref, full }) => {
450
504
  const st = await requireStore();
451
505
  const features = (await st.loadFeatures()).features;
452
506
  const phase = findPhaseByRef(await st.loadAllPhases(), features, ref);
453
507
  if (!phase)
454
508
  return text(`Phase not found: ${ref}`);
455
- return text(`${phase.title} — ${formatPhaseRef(phase.number, featureNumberOfPhase(phase, features))}${phase.shortId ? ` · ${phase.shortId}` : ""} (${phase.status}; ${phase.tasks.length} tasks)`, { phase });
509
+ const summary = `${phase.title} — ${formatPhaseRef(phase.number, featureNumberOfPhase(phase, features))}${phase.shortId ? ` · ${phase.shortId}` : ""} (${phase.status}; ${phase.tasks.length} tasks)`;
510
+ return text(full ? `${summary}\n\n${phase.description || ""}` : summary);
456
511
  });
457
512
  server.registerTool("planner-phase-discuss", {
458
513
  description: "Persist phase discovery fields and mark phase planned.",
@@ -595,13 +650,18 @@ server.registerTool("planner-task-add", {
595
650
  });
596
651
  server.registerTool("planner-task-show", {
597
652
  description: "Show a task by id or name.",
598
- inputSchema: { task: z.string().min(1).describe("Task ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title.") },
599
- }, async ({ task: ref }) => {
653
+ inputSchema: { task: z.string().min(1).describe("Task ref. Accepts F00x/P00x/T00x composite, bare P00x/T00x (global), 5-char shortId, UUID, or title."), full: z.boolean().optional().describe("If true, include the task description + statusLog. Default: compact identity only (saves tokens).") },
654
+ }, async ({ task: ref, full }) => {
600
655
  const st = await requireStore();
601
656
  const found = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, ref);
602
657
  if (!found)
603
658
  return text(`Task not found: ${ref}`);
604
- return text(`${found.task.title} — ${taskCompositeRef(found.task, found.phase, (await st.loadFeatures()).features)}${found.task.shortId ? ` · ${found.task.shortId}` : ""} (${found.task.status}; phase ${formatPhaseRef(found.phase.number, featureNumberOfPhase(found.phase, (await st.loadFeatures()).features))})`, { task: found.task, phase: found.phase });
659
+ const features = (await st.loadFeatures()).features;
660
+ const summary = `${found.task.title} — ${taskCompositeRef(found.task, found.phase, features)}${found.task.shortId ? ` · ${found.task.shortId}` : ""} (${found.task.status}; phase ${formatPhaseRef(found.phase.number, featureNumberOfPhase(found.phase, features))})`;
661
+ if (!full)
662
+ return text(summary);
663
+ const log = (found.task.statusLog ?? []).map((e) => ` - ${e.date.slice(0, 10)} ${e.title}`).join("\n");
664
+ return text(`${summary}\n\n${found.task.description || ""}${log ? `\n\nStatus log:\n${log}` : ""}`);
605
665
  });
606
666
  server.registerTool("planner-task-discuss", {
607
667
  description: "Persist task execution notes/checklist.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-plan/mcp",
3
- "version": "0.2.19-next.5",
3
+ "version": "0.2.19-next.6",
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.5",
45
- "@agent-plan/server": "0.2.19-next.5"
44
+ "@agent-plan/core": "0.2.19-next.6",
45
+ "@agent-plan/server": "0.2.19-next.6"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsc -p tsconfig.json",