@astramindapp/mcp-server 0.17.0 → 0.18.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/dist/mind-client.d.ts +74 -1
- package/dist/mind-client.d.ts.map +1 -1
- package/dist/mind-client.js +38 -4
- package/dist/mind-client.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +219 -15
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/server.js
CHANGED
|
@@ -453,7 +453,7 @@ function createMindMcpServer(client) {
|
|
|
453
453
|
// ─── mind_life ──────────────────────────────────────────
|
|
454
454
|
// Read/write goals, projects, tasks, calendar events, stats.
|
|
455
455
|
// Enhanced: calendar CRUD, stats, move, get.
|
|
456
|
-
server.tool("mind_life", "Manage
|
|
456
|
+
server.tool("mind_life", "Manage Focus → Project → Outcome hierarchy + calendar in MIND Life. Items are either projects (top-level domain/client buckets that live inside a Focus) or outcomes (deliverables that live under a parent project). Use `item_type` + `parent_id` + `focus_id` on create/update to wire the hierarchy. Use list filters (item_type, parent_id, focus_id, top_level_only) to slice the board.", {
|
|
457
457
|
action: zod_1.z
|
|
458
458
|
.enum([
|
|
459
459
|
"list", "create", "update", "complete", "delete", "bulk_delete", "move", "get",
|
|
@@ -484,17 +484,61 @@ function createMindMcpServer(client) {
|
|
|
484
484
|
.optional()
|
|
485
485
|
.describe("Left-border color stripe on the board card. Use to group items (e.g. Astra=red, Atlas=blue)."),
|
|
486
486
|
target_date: zod_1.z.string().optional().describe("Target completion date in YYYY-MM-DD format — when the project should be done. Powers the countdown badge on the card."),
|
|
487
|
-
|
|
487
|
+
item_type: zod_1.z
|
|
488
|
+
.enum(["project", "outcome"])
|
|
489
|
+
.optional()
|
|
490
|
+
.describe("'project' (top-level domain/client bucket; lives inside a Focus) or 'outcome' (deliverable under a parent project). Defaults to 'outcome' on create. Pass on list to filter."),
|
|
491
|
+
parent_id: zod_1.z
|
|
492
|
+
.string()
|
|
493
|
+
.optional()
|
|
494
|
+
.describe("For outcomes — the item_id of the parent project. Pass empty string on update to detach (make top-level). On list, pass an item_id to fetch its outcomes, or 'none' for items with no parent."),
|
|
495
|
+
focus_id: zod_1.z
|
|
496
|
+
.string()
|
|
497
|
+
.optional()
|
|
498
|
+
.describe("For projects — the focus_id this project belongs to. Pass empty string on update to detach (No Focus). On list, pass a focus_id to filter to that focus, or 'none' for unfiled projects."),
|
|
499
|
+
agent_ids: zod_1.z.array(zod_1.z.string()).optional().describe("Agents bound to this project (project only). On update, REPLACES the existing list."),
|
|
500
|
+
workflow_ids: zod_1.z.array(zod_1.z.string()).optional().describe("Workflows bound to this project (project only). On update, REPLACES the existing list."),
|
|
501
|
+
top_level_only: zod_1.z.boolean().optional().describe("On list — true returns only items with no parent (board roots: projects + unassigned outcomes)."),
|
|
502
|
+
include_completed: zod_1.z.boolean().optional().describe("On list — false hides completed items. Defaults true."),
|
|
503
|
+
limit: zod_1.z.number().int().min(1).max(500).optional().describe("On list — max items to return (1–500, default 30)."),
|
|
504
|
+
}, async ({ action, title, description, status, priority, due_date, item_id, item_ids, start_time, end_time, event_id, all_day, tags, color, target_date, item_type, parent_id, focus_id, agent_ids, workflow_ids, top_level_only, include_completed, limit }) => {
|
|
488
505
|
try {
|
|
489
506
|
switch (action) {
|
|
490
507
|
case "list": {
|
|
491
|
-
const result = await client.listLifeItems(
|
|
508
|
+
const result = await client.listLifeItems({
|
|
509
|
+
status,
|
|
510
|
+
item_type,
|
|
511
|
+
parent_id,
|
|
512
|
+
focus_id,
|
|
513
|
+
top_level_only,
|
|
514
|
+
include_completed,
|
|
515
|
+
limit,
|
|
516
|
+
});
|
|
492
517
|
const items = result.items ?? [];
|
|
493
518
|
if (items.length === 0) {
|
|
494
519
|
return { content: [{ type: "text", text: "No life items found." }] };
|
|
495
520
|
}
|
|
496
|
-
const lines = items.map((i) =>
|
|
497
|
-
|
|
521
|
+
const lines = items.map((i) => {
|
|
522
|
+
const tag = i.item_type === "project" ? "📁 project" : "🎯 outcome";
|
|
523
|
+
const parts = [`[${i.priority ?? "—"}] ${tag} ${i.title}`];
|
|
524
|
+
parts.push(`status: ${i.status ?? "—"}`);
|
|
525
|
+
if (i.due_date)
|
|
526
|
+
parts.push(`due: ${i.due_date}`);
|
|
527
|
+
if (i.item_type === "project") {
|
|
528
|
+
if (i.focus_id)
|
|
529
|
+
parts.push(`focus: ${i.focus_id}`);
|
|
530
|
+
if (typeof i.subtask_count === "number")
|
|
531
|
+
parts.push(`outcomes: ${i.subtasks_completed ?? 0}/${i.subtask_count}`);
|
|
532
|
+
}
|
|
533
|
+
else if (i.parent_id) {
|
|
534
|
+
parts.push(`parent: ${i.parent_id}`);
|
|
535
|
+
}
|
|
536
|
+
return `• ${parts.join(" · ")} — id: ${i.item_id}`;
|
|
537
|
+
});
|
|
538
|
+
const header = typeof result.total === "number" ? `Showing ${items.length} of ${result.total} items.` : null;
|
|
539
|
+
return {
|
|
540
|
+
content: [{ type: "text", text: [header, ...lines].filter(Boolean).join("\n") }],
|
|
541
|
+
};
|
|
498
542
|
}
|
|
499
543
|
case "create": {
|
|
500
544
|
if (!title) {
|
|
@@ -512,8 +556,19 @@ function createMindMcpServer(client) {
|
|
|
512
556
|
tags,
|
|
513
557
|
color,
|
|
514
558
|
target_date,
|
|
559
|
+
item_type,
|
|
560
|
+
parent_id,
|
|
561
|
+
focus_id,
|
|
562
|
+
agent_ids,
|
|
563
|
+
workflow_ids,
|
|
515
564
|
});
|
|
516
565
|
const extras = [];
|
|
566
|
+
if (result.item_type)
|
|
567
|
+
extras.push(`type: ${result.item_type}`);
|
|
568
|
+
if (result.parent_id)
|
|
569
|
+
extras.push(`parent: ${result.parent_id}`);
|
|
570
|
+
if (result.focus_id)
|
|
571
|
+
extras.push(`focus: ${result.focus_id}`);
|
|
517
572
|
if (result.tags && result.tags.length > 0)
|
|
518
573
|
extras.push(`tags: ${result.tags.join(", ")}`);
|
|
519
574
|
if (result.color && result.color !== "default")
|
|
@@ -539,22 +594,39 @@ function createMindMcpServer(client) {
|
|
|
539
594
|
const patch = {};
|
|
540
595
|
if (title)
|
|
541
596
|
patch.title = title;
|
|
542
|
-
if (description)
|
|
597
|
+
if (description !== undefined)
|
|
543
598
|
patch.description = description;
|
|
544
599
|
if (status)
|
|
545
600
|
patch.status = status;
|
|
546
601
|
if (priority)
|
|
547
602
|
patch.priority = priority;
|
|
548
|
-
if (due_date)
|
|
603
|
+
if (due_date !== undefined)
|
|
549
604
|
patch.due_date = due_date;
|
|
550
605
|
if (tags)
|
|
551
606
|
patch.tags = tags;
|
|
552
607
|
if (color)
|
|
553
608
|
patch.color = color;
|
|
554
|
-
if (target_date)
|
|
609
|
+
if (target_date !== undefined)
|
|
555
610
|
patch.target_date = target_date;
|
|
611
|
+
if (item_type !== undefined)
|
|
612
|
+
patch.item_type = item_type;
|
|
613
|
+
// parent_id / focus_id: pass empty string explicitly to clear; pass undefined to leave unchanged
|
|
614
|
+
if (parent_id !== undefined)
|
|
615
|
+
patch.parent_id = parent_id;
|
|
616
|
+
if (focus_id !== undefined)
|
|
617
|
+
patch.focus_id = focus_id;
|
|
618
|
+
if (agent_ids !== undefined)
|
|
619
|
+
patch.agent_ids = agent_ids;
|
|
620
|
+
if (workflow_ids !== undefined)
|
|
621
|
+
patch.workflow_ids = workflow_ids;
|
|
556
622
|
const result = await client.updateLifeItem(item_id, patch);
|
|
557
623
|
const extras = [];
|
|
624
|
+
if (result.item_type)
|
|
625
|
+
extras.push(`type: ${result.item_type}`);
|
|
626
|
+
if (result.parent_id)
|
|
627
|
+
extras.push(`parent: ${result.parent_id}`);
|
|
628
|
+
if (result.focus_id)
|
|
629
|
+
extras.push(`focus: ${result.focus_id}`);
|
|
558
630
|
if (result.tags && result.tags.length > 0)
|
|
559
631
|
extras.push(`tags: ${result.tags.join(", ")}`);
|
|
560
632
|
if (result.color && result.color !== "default")
|
|
@@ -625,16 +697,25 @@ function createMindMcpServer(client) {
|
|
|
625
697
|
};
|
|
626
698
|
}
|
|
627
699
|
const result = await client.getLifeItem(item_id);
|
|
700
|
+
const r = result;
|
|
628
701
|
const lines = [
|
|
629
|
-
`**${result.title}
|
|
702
|
+
`**${result.title}** (id: ${result.item_id})`,
|
|
630
703
|
`Status: ${result.status ?? "—"} | Priority: ${result.priority ?? "—"} | Due: ${result.due_date ?? "none"}`,
|
|
704
|
+
`Type: ${r.item_type ?? "outcome"}${r.parent_id ? ` | Parent: ${r.parent_id}` : ""}${r.focus_id ? ` | Focus: ${r.focus_id}` : ""}`,
|
|
631
705
|
];
|
|
632
|
-
if (
|
|
633
|
-
lines.push(`
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
706
|
+
if (r.item_type === "project" && typeof r.subtask_count === "number") {
|
|
707
|
+
lines.push(`Outcomes: ${r.subtasks_completed ?? 0}/${r.subtask_count} complete`);
|
|
708
|
+
}
|
|
709
|
+
if (r.agent_ids && r.agent_ids.length > 0)
|
|
710
|
+
lines.push(`Agents: ${r.agent_ids.join(", ")}`);
|
|
711
|
+
if (r.workflow_ids && r.workflow_ids.length > 0)
|
|
712
|
+
lines.push(`Workflows: ${r.workflow_ids.join(", ")}`);
|
|
713
|
+
if (r.color && r.color !== "default")
|
|
714
|
+
lines.push(`Color: ${r.color}`);
|
|
715
|
+
if (r.target_date)
|
|
716
|
+
lines.push(`Target: ${r.target_date}`);
|
|
717
|
+
if (r.tags && r.tags.length > 0)
|
|
718
|
+
lines.push(`Tags: ${r.tags.join(", ")}`);
|
|
638
719
|
if (result.description)
|
|
639
720
|
lines.push(`\n${result.description}`);
|
|
640
721
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
@@ -729,6 +810,129 @@ function createMindMcpServer(client) {
|
|
|
729
810
|
};
|
|
730
811
|
}
|
|
731
812
|
});
|
|
813
|
+
// ─── mind_focuses ──────────────────────────────────────
|
|
814
|
+
// Top of the Focus → Project → Outcome → Task hierarchy.
|
|
815
|
+
// A Focus is a per-user bucket that groups multiple Life Projects, and
|
|
816
|
+
// can carry shared agents/workflows that apply to every project inside.
|
|
817
|
+
server.tool("mind_focuses", "Manage Focuses — the top-level buckets that group Life Projects. Every project lives inside one focus (or 'No Focus'). Use list to see all focuses + their project counts, create to add a new bucket (e.g. 'Astra', 'Atlas', 'Fundraising'), update/delete to maintain them. Pass the returned focus_id to mind_life when creating projects.", {
|
|
818
|
+
action: zod_1.z
|
|
819
|
+
.enum(["list", "get", "create", "update", "delete"])
|
|
820
|
+
.describe("list/get/create/update/delete focuses. 'delete' soft-archives by default; pass hard=true to remove permanently."),
|
|
821
|
+
focus_id: zod_1.z.string().optional().describe("Focus id — required for get/update/delete"),
|
|
822
|
+
name: zod_1.z.string().optional().describe("Display name — required for create"),
|
|
823
|
+
description: zod_1.z.string().optional().describe("Long-form description"),
|
|
824
|
+
color: zod_1.z
|
|
825
|
+
.enum(["default", "red", "orange", "yellow", "green", "blue", "purple", "pink"])
|
|
826
|
+
.optional()
|
|
827
|
+
.describe("Color stripe used in the UI"),
|
|
828
|
+
icon: zod_1.z.string().optional().describe("Lucide icon name (e.g. 'briefcase', 'rocket'). Defaults to 'folder'."),
|
|
829
|
+
position: zod_1.z.number().int().optional().describe("Sort position (lower = earlier)"),
|
|
830
|
+
agent_ids: zod_1.z.array(zod_1.z.string()).optional().describe("Agents bound to every project inside this focus. On update, REPLACES the existing list."),
|
|
831
|
+
workflow_ids: zod_1.z.array(zod_1.z.string()).optional().describe("Workflows bound to every project inside this focus. On update, REPLACES the existing list."),
|
|
832
|
+
include_archived: zod_1.z.boolean().optional().describe("On list — true to include archived focuses (default false)"),
|
|
833
|
+
hard: zod_1.z.boolean().optional().describe("On delete — true to remove permanently (default false = soft archive)"),
|
|
834
|
+
}, async ({ action, focus_id, name, description, color, icon, position, agent_ids, workflow_ids, include_archived, hard }) => {
|
|
835
|
+
try {
|
|
836
|
+
switch (action) {
|
|
837
|
+
case "list": {
|
|
838
|
+
const result = await client.listFocuses(include_archived ?? false);
|
|
839
|
+
const focuses = result.focuses ?? [];
|
|
840
|
+
if (focuses.length === 0 && (result.unfiled_project_count ?? 0) === 0) {
|
|
841
|
+
return { content: [{ type: "text", text: "No focuses yet. Create one with action='create'." }] };
|
|
842
|
+
}
|
|
843
|
+
const lines = focuses.map((f) => {
|
|
844
|
+
const c = f.color && f.color !== "default" ? ` (${f.color})` : "";
|
|
845
|
+
const counts = `${f.project_count_active ?? 0} active / ${f.project_count ?? 0} total`;
|
|
846
|
+
return `• 📁 ${f.name}${c} — ${counts} projects — id: ${f.focus_id}`;
|
|
847
|
+
});
|
|
848
|
+
if (typeof result.unfiled_project_count === "number" && result.unfiled_project_count > 0) {
|
|
849
|
+
lines.push(`• 🗂 No Focus — ${result.unfiled_project_count} unfiled project(s)`);
|
|
850
|
+
}
|
|
851
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
852
|
+
}
|
|
853
|
+
case "get": {
|
|
854
|
+
if (!focus_id) {
|
|
855
|
+
return { content: [{ type: "text", text: "Error: focus_id is required for get" }], isError: true };
|
|
856
|
+
}
|
|
857
|
+
const f = await client.getFocus(focus_id);
|
|
858
|
+
const lines = [
|
|
859
|
+
`**${f.name}** (id: ${f.focus_id})`,
|
|
860
|
+
`Color: ${f.color ?? "default"} | Icon: ${f.icon ?? "folder"} | Position: ${f.position ?? 0}`,
|
|
861
|
+
`Projects: ${f.project_count_active ?? 0} active / ${f.project_count_completed ?? 0} completed / ${f.project_count ?? 0} total`,
|
|
862
|
+
];
|
|
863
|
+
if (f.agent_ids && f.agent_ids.length > 0)
|
|
864
|
+
lines.push(`Agents: ${f.agent_ids.join(", ")}`);
|
|
865
|
+
if (f.workflow_ids && f.workflow_ids.length > 0)
|
|
866
|
+
lines.push(`Workflows: ${f.workflow_ids.join(", ")}`);
|
|
867
|
+
if (f.archived_at)
|
|
868
|
+
lines.push(`Archived at: ${f.archived_at}`);
|
|
869
|
+
if (f.description)
|
|
870
|
+
lines.push(`\n${f.description}`);
|
|
871
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
872
|
+
}
|
|
873
|
+
case "create": {
|
|
874
|
+
if (!name) {
|
|
875
|
+
return { content: [{ type: "text", text: "Error: name is required to create a focus" }], isError: true };
|
|
876
|
+
}
|
|
877
|
+
const f = await client.createFocus({
|
|
878
|
+
name,
|
|
879
|
+
description,
|
|
880
|
+
color,
|
|
881
|
+
icon,
|
|
882
|
+
position,
|
|
883
|
+
agent_ids,
|
|
884
|
+
workflow_ids,
|
|
885
|
+
});
|
|
886
|
+
return {
|
|
887
|
+
content: [
|
|
888
|
+
{
|
|
889
|
+
type: "text",
|
|
890
|
+
text: `✅ Created focus: "${f.name}" (id: ${f.focus_id}, color: ${f.color ?? "default"}, icon: ${f.icon ?? "folder"})`,
|
|
891
|
+
},
|
|
892
|
+
],
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
case "update": {
|
|
896
|
+
if (!focus_id) {
|
|
897
|
+
return { content: [{ type: "text", text: "Error: focus_id is required for update" }], isError: true };
|
|
898
|
+
}
|
|
899
|
+
const patch = {};
|
|
900
|
+
if (name !== undefined)
|
|
901
|
+
patch.name = name;
|
|
902
|
+
if (description !== undefined)
|
|
903
|
+
patch.description = description;
|
|
904
|
+
if (color !== undefined)
|
|
905
|
+
patch.color = color;
|
|
906
|
+
if (icon !== undefined)
|
|
907
|
+
patch.icon = icon;
|
|
908
|
+
if (position !== undefined)
|
|
909
|
+
patch.position = position;
|
|
910
|
+
if (agent_ids !== undefined)
|
|
911
|
+
patch.agent_ids = agent_ids;
|
|
912
|
+
if (workflow_ids !== undefined)
|
|
913
|
+
patch.workflow_ids = workflow_ids;
|
|
914
|
+
const f = await client.updateFocus(focus_id, patch);
|
|
915
|
+
return {
|
|
916
|
+
content: [{ type: "text", text: `✅ Updated focus: "${f.name}" (id: ${f.focus_id})` }],
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
case "delete": {
|
|
920
|
+
if (!focus_id) {
|
|
921
|
+
return { content: [{ type: "text", text: "Error: focus_id is required for delete" }], isError: true };
|
|
922
|
+
}
|
|
923
|
+
const r = await client.deleteFocus(focus_id, hard ?? false);
|
|
924
|
+
const verb = r.deleted ? "Deleted" : "Archived";
|
|
925
|
+
return { content: [{ type: "text", text: `✅ ${verb} focus ${r.focus_id} (projects inside detached to 'No Focus').` }] };
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
catch (err) {
|
|
930
|
+
return {
|
|
931
|
+
content: [{ type: "text", text: `Error in mind_focuses: ${err}` }],
|
|
932
|
+
isError: true,
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
});
|
|
732
936
|
// ─── mind_tasks ─────────────────────────────────────────
|
|
733
937
|
// Site-wide tasks: assignable, completable work items that attach to a
|
|
734
938
|
// Life project, a CRM contact, an agent, or stand alone.
|