@astramindapp/mcp-server 0.3.1 → 0.5.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/server.js CHANGED
@@ -5,13 +5,22 @@
5
5
  * Exposes the MIND knowledge graph as MCP tools that any LLM agent can use.
6
6
  * This is the universal AI memory layer.
7
7
  *
8
- * Tools:
8
+ * Tools (15):
9
9
  * mind_query — Semantic search across the knowledge graph
10
- * mind_remember — Store content to the graph (auto-categorized)
10
+ * mind_remember — Store/manage content in the graph (auto-categorized)
11
11
  * mind_context — Get structured always-loaded context (soul/user/rules)
12
- * mind_life — Read/write goals, projects, tasks
13
- * mind_crm — Read/write contacts and interactions
14
- * mind_graph — Get graph statistics and health
12
+ * mind_life — Read/write goals, projects, tasks, calendar events, stats
13
+ * mind_crm — Read/write contacts, interactions, and activities
14
+ * mind_graph — Get graph statistics, diagnostics, and labels
15
+ * mind_admin — Admin-only user and featured mind management
16
+ * mind_sense — MINDsense emotional intelligence layer
17
+ * mind_research — Deep research agent jobs
18
+ * mind_train — Self-training and chat-to-KG sessions
19
+ * mind_social — Thoughts, communities, and feed
20
+ * mind_profile — Profile, prompts, and model preferences
21
+ * mind_insights — ALE insights and analytics
22
+ * mind_automate — Automations and triggers
23
+ * mind_notify — Notifications management
15
24
  */
16
25
  Object.defineProperty(exports, "__esModule", { value: true });
17
26
  exports.createMindMcpServer = createMindMcpServer;
@@ -20,7 +29,7 @@ const zod_1 = require("zod");
20
29
  function createMindMcpServer(client) {
21
30
  const server = new mcp_js_1.McpServer({
22
31
  name: "mind",
23
- version: "0.1.0",
32
+ version: "0.2.0",
24
33
  });
25
34
  // ─── mind_query ─────────────────────────────────────────
26
35
  // Semantic search across the user's knowledge graph.
@@ -28,10 +37,10 @@ function createMindMcpServer(client) {
28
37
  server.tool("mind_query", "Search your MIND knowledge graph. Returns AI-synthesized answer from your stored documents, entries, and thoughts. Use this BEFORE making decisions — MIND is your memory.", {
29
38
  query: zod_1.z.string().describe("What to search for in your knowledge graph"),
30
39
  mode: zod_1.z
31
- .enum(["mix", "hybrid", "graph", "vector"])
40
+ .enum(["mix", "hybrid", "global", "local", "naive"])
32
41
  .optional()
33
42
  .default("hybrid")
34
- .describe("Search mode: hybrid (default, best results — combines semantic + graph traversal), mix (balanced), graph (entity relationships), vector (semantic similarity)"),
43
+ .describe("Search mode: hybrid (default, best results — combines semantic + graph traversal), mix (balanced), global (broad graph search), local (focused graph search), naive (simple vector search)"),
35
44
  }, async ({ query, mode }) => {
36
45
  try {
37
46
  const result = await client.query({ query, mode });
@@ -43,7 +52,7 @@ function createMindMcpServer(client) {
43
52
  if (result.sources?.length) {
44
53
  text.push("");
45
54
  for (const s of result.sources.slice(0, 5)) {
46
- text.push(`• ${s.title ?? "Untitled"} (score: ${s.relevance_score?.toFixed(2) ?? "N/A"})`);
55
+ text.push(`• ${s}`);
47
56
  }
48
57
  }
49
58
  return { content: [{ type: "text", text: text.join("\n") }] };
@@ -56,10 +65,15 @@ function createMindMcpServer(client) {
56
65
  }
57
66
  });
58
67
  // ─── mind_remember ──────────────────────────────────────
59
- // Store content to the knowledge graph. Auto-categorized by type.
60
- // Replaces manual memory file writes.
61
- server.tool("mind_remember", "Store something in your MIND knowledge graph. Use for facts, decisions, learnings, research, notes — anything worth remembering. Auto-categorized. Always log outcomes here after completing tasks.", {
62
- content: zod_1.z.string().describe("What to remember — the actual content to store"),
68
+ // Store/manage content in the knowledge graph. Auto-categorized by type.
69
+ // Enhanced: now supports create, delete, search, get, list actions.
70
+ server.tool("mind_remember", "Store and manage content in your MIND knowledge graph. Use for facts, decisions, learnings, research, notes — anything worth remembering. Auto-categorized. Always log outcomes here after completing tasks. Supports create (default), delete, search, get, and list.", {
71
+ action: zod_1.z
72
+ .enum(["create", "delete", "search", "get", "list"])
73
+ .optional()
74
+ .default("create")
75
+ .describe("Action: create (store new content — default), delete (remove by ID), search (find entries), get (retrieve by ID), list (paginated listing)"),
76
+ content: zod_1.z.string().optional().describe("What to remember — the actual content to store (required for create)"),
63
77
  type: zod_1.z
64
78
  .enum(["document", "entry", "thought"])
65
79
  .optional()
@@ -78,44 +92,155 @@ function createMindMcpServer(client) {
78
92
  .optional()
79
93
  .default("mcp-agent")
80
94
  .describe("Source identifier (e.g. 'claude-code', 'openclaw', 'cursor')"),
81
- }, async ({ content, type, title, tags, source }) => {
95
+ item_id: zod_1.z
96
+ .string()
97
+ .optional()
98
+ .describe("Item ID for delete/get actions"),
99
+ query: zod_1.z
100
+ .string()
101
+ .optional()
102
+ .describe("Search query for search action"),
103
+ page: zod_1.z
104
+ .number()
105
+ .optional()
106
+ .describe("Page number for list action"),
107
+ limit: zod_1.z
108
+ .number()
109
+ .optional()
110
+ .describe("Max items to return for list/search"),
111
+ }, async ({ action, content, type, title, tags, source, item_id, query, page, limit }) => {
82
112
  try {
83
- let result;
84
- let storedAs;
85
- switch (type) {
86
- case "document":
87
- result = await client.createDocument({
88
- title: title ?? `Agent Document — ${new Date().toISOString().slice(0, 10)}`,
89
- content,
90
- source: source ?? "mcp-agent",
91
- tags,
92
- });
93
- storedAs = "document";
94
- break;
95
- case "thought":
96
- result = await client.createThought({ content });
97
- storedAs = "thought";
98
- break;
99
- case "entry":
100
- default:
101
- result = await client.createEntry({
102
- title,
103
- content,
104
- entry_type: "text",
105
- tags,
106
- });
107
- storedAs = "entry";
108
- break;
113
+ switch (action) {
114
+ case "create": {
115
+ if (!content) {
116
+ return {
117
+ content: [{ type: "text", text: "Error: content is required to create" }],
118
+ isError: true,
119
+ };
120
+ }
121
+ let result;
122
+ let storedAs;
123
+ switch (type) {
124
+ case "document":
125
+ result = await client.createDocument({
126
+ title: title ?? `Agent Document — ${new Date().toISOString().slice(0, 10)}`,
127
+ content,
128
+ source: source ?? "mcp-agent",
129
+ });
130
+ storedAs = "document";
131
+ break;
132
+ case "thought":
133
+ result = await client.createThought({ content });
134
+ storedAs = "thought";
135
+ break;
136
+ case "entry":
137
+ default:
138
+ result = await client.createEntry({
139
+ title,
140
+ content,
141
+ tags,
142
+ });
143
+ storedAs = "entry";
144
+ break;
145
+ }
146
+ const id = result.id ?? result.entry_id ?? result.thought_id ?? "unknown";
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: `✅ Stored to MIND as ${storedAs} (id: ${id})${title ? ` — "${title}"` : ""}`,
152
+ },
153
+ ],
154
+ };
155
+ }
156
+ case "delete": {
157
+ if (!item_id) {
158
+ return {
159
+ content: [{ type: "text", text: "Error: item_id is required for delete" }],
160
+ isError: true,
161
+ };
162
+ }
163
+ switch (type) {
164
+ case "document":
165
+ await client.deleteDocument(item_id);
166
+ break;
167
+ case "thought":
168
+ await client.deleteThought(item_id);
169
+ break;
170
+ case "entry":
171
+ default:
172
+ await client.deleteEntry(item_id);
173
+ break;
174
+ }
175
+ return {
176
+ content: [{ type: "text", text: `✅ Deleted ${type} ${item_id}` }],
177
+ };
178
+ }
179
+ case "search": {
180
+ if (!query) {
181
+ return {
182
+ content: [{ type: "text", text: "Error: query is required for search" }],
183
+ isError: true,
184
+ };
185
+ }
186
+ const result = await client.searchEntries(query, limit);
187
+ const items = result.entries ?? [];
188
+ if (items.length === 0) {
189
+ return { content: [{ type: "text", text: `No results for "${query}".` }] };
190
+ }
191
+ const lines = items.map((e) => `• ${e.title ?? "Untitled"} — ${e.content?.slice(0, 120) ?? ""}... (id: ${e.entry_id})`);
192
+ return { content: [{ type: "text", text: lines.join("\n") }] };
193
+ }
194
+ case "get": {
195
+ if (!item_id) {
196
+ return {
197
+ content: [{ type: "text", text: "Error: item_id is required for get" }],
198
+ isError: true,
199
+ };
200
+ }
201
+ const result = await client.getEntry(item_id);
202
+ const lines = [
203
+ `**${result.title ?? "Untitled"}**`,
204
+ `Type: ${result.entry_type ?? type} | Created: ${result.created_at ?? "unknown"}`,
205
+ `Tags: ${result.tags?.join(", ") ?? "none"}`,
206
+ "",
207
+ result.content ?? "",
208
+ ];
209
+ return { content: [{ type: "text", text: lines.join("\n") }] };
210
+ }
211
+ case "list": {
212
+ switch (type) {
213
+ case "document": {
214
+ const result = await client.listDocuments(page ?? 1, limit ?? 20);
215
+ const docs = result.documents ?? [];
216
+ if (docs.length === 0) {
217
+ return { content: [{ type: "text", text: "No documents found." }] };
218
+ }
219
+ const lines = docs.map((d) => `• ${d.title} (status: ${d.status}, source: ${d.source}) — id: ${d.id}`);
220
+ return { content: [{ type: "text", text: lines.join("\n") }] };
221
+ }
222
+ case "thought": {
223
+ const result = await client.listThoughts();
224
+ const thoughts = result.thoughts ?? [];
225
+ if (thoughts.length === 0) {
226
+ return { content: [{ type: "text", text: "No thoughts found." }] };
227
+ }
228
+ const lines = thoughts.map((t) => `• ${t.content?.slice(0, 100)}... — id: ${t.id ?? t.thought_id}`);
229
+ return { content: [{ type: "text", text: lines.join("\n") }] };
230
+ }
231
+ case "entry":
232
+ default: {
233
+ const result = await client.listEntries(limit ?? 20);
234
+ const entries = result.entries ?? [];
235
+ if (entries.length === 0) {
236
+ return { content: [{ type: "text", text: "No entries found." }] };
237
+ }
238
+ const lines = entries.map((e) => `• ${e.title ?? "Untitled"} (${e.entry_type ?? "text"}) — id: ${e.id ?? e.entry_id}`);
239
+ return { content: [{ type: "text", text: lines.join("\n") }] };
240
+ }
241
+ }
242
+ }
109
243
  }
110
- const id = result.id ?? result.entry_id ?? result.thought_id ?? "unknown";
111
- return {
112
- content: [
113
- {
114
- type: "text",
115
- text: `✅ Stored to MIND as ${storedAs} (id: ${id})${title ? ` — "${title}"` : ""}`,
116
- },
117
- ],
118
- };
119
244
  }
120
245
  catch (err) {
121
246
  return {
@@ -160,12 +285,17 @@ function createMindMcpServer(client) {
160
285
  }
161
286
  });
162
287
  // ─── mind_life ──────────────────────────────────────────
163
- // Read/write goals, projects, and tasks.
164
- server.tool("mind_life", "Manage goals, projects, and tasks in MIND Life. Use for tracking work, creating action items, updating progress, and completing tasks.", {
288
+ // Read/write goals, projects, tasks, calendar events, stats.
289
+ // Enhanced: calendar CRUD, stats, move, get.
290
+ server.tool("mind_life", "Manage goals, projects, tasks, and calendar events in MIND Life. Use for tracking work, creating action items, updating progress, completing tasks, managing calendar, and viewing stats.", {
165
291
  action: zod_1.z
166
- .enum(["list", "create", "update", "complete", "delete"])
167
- .describe("What to do: list (view items), create (new item), update (modify), complete (mark done), delete (remove)"),
168
- title: zod_1.z.string().optional().describe("Title for new items"),
292
+ .enum([
293
+ "list", "create", "update", "complete", "delete", "move", "get",
294
+ "calendar_list", "calendar_create", "calendar_update", "calendar_delete",
295
+ "stats",
296
+ ])
297
+ .describe("What to do: list/create/update/complete/delete/move/get items, calendar_list/calendar_create/calendar_update/calendar_delete events, stats (productivity overview)"),
298
+ title: zod_1.z.string().optional().describe("Title for new items or calendar events"),
169
299
  description: zod_1.z.string().optional().describe("Description for new items"),
170
300
  status: zod_1.z
171
301
  .string()
@@ -176,8 +306,12 @@ function createMindMcpServer(client) {
176
306
  .optional()
177
307
  .describe("Priority: low, medium, high, urgent"),
178
308
  due_date: zod_1.z.string().optional().describe("Due date in YYYY-MM-DD format"),
179
- item_id: zod_1.z.string().optional().describe("Item ID for update/complete/delete actions"),
180
- }, async ({ action, title, description, status, priority, due_date, item_id }) => {
309
+ item_id: zod_1.z.string().optional().describe("Item ID for update/complete/delete/move/get actions"),
310
+ start_time: zod_1.z.string().optional().describe("Start time for calendar events (ISO 8601)"),
311
+ end_time: zod_1.z.string().optional().describe("End time for calendar events (ISO 8601)"),
312
+ event_id: zod_1.z.string().optional().describe("Event ID for calendar_update/calendar_delete"),
313
+ all_day: zod_1.z.boolean().optional().describe("Whether the calendar event is all-day"),
314
+ }, async ({ action, title, description, status, priority, due_date, item_id, start_time, end_time, event_id, all_day }) => {
181
315
  try {
182
316
  switch (action) {
183
317
  case "list": {
@@ -259,6 +393,114 @@ function createMindMcpServer(client) {
259
393
  content: [{ type: "text", text: `✅ Deleted life item ${item_id}` }],
260
394
  };
261
395
  }
396
+ case "move": {
397
+ if (!item_id || !status) {
398
+ return {
399
+ content: [{ type: "text", text: "Error: item_id and status are required for move" }],
400
+ isError: true,
401
+ };
402
+ }
403
+ const result = await client.moveLifeItem(item_id, status);
404
+ return {
405
+ content: [{ type: "text", text: `✅ Moved "${result.title}" to ${result.status}` }],
406
+ };
407
+ }
408
+ case "get": {
409
+ if (!item_id) {
410
+ return {
411
+ content: [{ type: "text", text: "Error: item_id is required for get" }],
412
+ isError: true,
413
+ };
414
+ }
415
+ const result = await client.getLifeItem(item_id);
416
+ const lines = [
417
+ `**${result.title}**`,
418
+ `Status: ${result.status ?? "—"} | Priority: ${result.priority ?? "—"} | Due: ${result.due_date ?? "none"}`,
419
+ result.description ? `\n${result.description}` : "",
420
+ ];
421
+ return { content: [{ type: "text", text: lines.join("\n") }] };
422
+ }
423
+ case "calendar_list": {
424
+ const result = await client.listCalendarEvents();
425
+ const events = result.events ?? [];
426
+ if (events.length === 0) {
427
+ return { content: [{ type: "text", text: "No calendar events found." }] };
428
+ }
429
+ const lines = events.map((e) => `• ${e.title}${e.all_day ? " (all day)" : ""} — ${e.start_time ?? ""}${e.end_time ? ` to ${e.end_time}` : ""} — id: ${e.event_id}`);
430
+ return { content: [{ type: "text", text: lines.join("\n") }] };
431
+ }
432
+ case "calendar_create": {
433
+ if (!title || !start_time) {
434
+ return {
435
+ content: [{ type: "text", text: "Error: title and start_time are required for calendar_create" }],
436
+ isError: true,
437
+ };
438
+ }
439
+ const result = await client.createCalendarEvent({
440
+ title,
441
+ description,
442
+ start_time,
443
+ end_time,
444
+ all_day,
445
+ });
446
+ return {
447
+ content: [
448
+ {
449
+ type: "text",
450
+ text: `✅ Created calendar event: "${result.title}" (id: ${result.event_id})`,
451
+ },
452
+ ],
453
+ };
454
+ }
455
+ case "calendar_update": {
456
+ if (!event_id) {
457
+ return {
458
+ content: [{ type: "text", text: "Error: event_id is required for calendar_update" }],
459
+ isError: true,
460
+ };
461
+ }
462
+ const patch = {};
463
+ if (title)
464
+ patch.title = title;
465
+ if (description)
466
+ patch.description = description;
467
+ if (start_time)
468
+ patch.start_time = start_time;
469
+ if (end_time)
470
+ patch.end_time = end_time;
471
+ if (all_day !== undefined)
472
+ patch.all_day = all_day;
473
+ const result = await client.updateCalendarEvent(event_id, patch);
474
+ return {
475
+ content: [{ type: "text", text: `✅ Updated calendar event: "${result.title}"` }],
476
+ };
477
+ }
478
+ case "calendar_delete": {
479
+ if (!event_id) {
480
+ return {
481
+ content: [{ type: "text", text: "Error: event_id is required for calendar_delete" }],
482
+ isError: true,
483
+ };
484
+ }
485
+ await client.deleteCalendarEvent(event_id);
486
+ return {
487
+ content: [{ type: "text", text: `✅ Deleted calendar event ${event_id}` }],
488
+ };
489
+ }
490
+ case "stats": {
491
+ const result = await client.lifeStats();
492
+ const lines = [
493
+ "📊 MIND Life Stats",
494
+ `• Total items: ${result.total_items}`,
495
+ `• Completion rate: ${(result.completion_rate * 100).toFixed(1)}%`,
496
+ ];
497
+ if (result.status_counts) {
498
+ for (const [status, count] of Object.entries(result.status_counts)) {
499
+ lines.push(`• ${status}: ${count}`);
500
+ }
501
+ }
502
+ return { content: [{ type: "text", text: lines.join("\n") }] };
503
+ }
262
504
  }
263
505
  }
264
506
  catch (err) {
@@ -269,11 +511,12 @@ function createMindMcpServer(client) {
269
511
  }
270
512
  });
271
513
  // ─── mind_crm ───────────────────────────────────────────
272
- // Read/write contacts and interactions.
273
- server.tool("mind_crm", "Manage contacts and relationships in MIND CRM. Use for tracking people, companies, leads, and interaction history.", {
514
+ // Read/write contacts, interactions, and activities.
515
+ // Enhanced: delete, get, log_activity, list_activities.
516
+ server.tool("mind_crm", "Manage contacts and relationships in MIND CRM. Use for tracking people, companies, leads, interaction history, and activity logging.", {
274
517
  action: zod_1.z
275
- .enum(["list", "create", "update"])
276
- .describe("What to do: list contacts, create new contact, update existing"),
518
+ .enum(["list", "create", "update", "delete", "get", "log_activity", "list_activities"])
519
+ .describe("What to do: list/create/update/delete/get contacts, log_activity (record interaction), list_activities (view interaction history)"),
277
520
  name: zod_1.z.string().optional().describe("Contact name (required for create)"),
278
521
  email: zod_1.z.string().optional().describe("Contact email"),
279
522
  company: zod_1.z.string().optional().describe("Company/organization"),
@@ -281,8 +524,10 @@ function createMindMcpServer(client) {
281
524
  stage: zod_1.z.string().optional().describe("Pipeline stage: new, qualified, proposal, closed, lost"),
282
525
  source: zod_1.z.string().optional().describe("How you found them"),
283
526
  notes: zod_1.z.string().optional().describe("Notes about this contact"),
284
- contact_id: zod_1.z.string().optional().describe("Contact ID for updates"),
285
- }, async ({ action, name, email, company, type, stage, source, notes, contact_id }) => {
527
+ contact_id: zod_1.z.string().optional().describe("Contact ID for update/delete/get/log_activity/list_activities"),
528
+ activity_type: zod_1.z.string().optional().describe("Activity type for log_activity: call, email, meeting, note"),
529
+ activity_notes: zod_1.z.string().optional().describe("Notes for the activity being logged"),
530
+ }, async ({ action, name, email, company, type, stage, source, notes, contact_id, activity_type, activity_notes }) => {
286
531
  try {
287
532
  switch (action) {
288
533
  case "list": {
@@ -291,7 +536,7 @@ function createMindMcpServer(client) {
291
536
  if (contacts.length === 0) {
292
537
  return { content: [{ type: "text", text: "No contacts found." }] };
293
538
  }
294
- const lines = contacts.map((c) => `• ${c.name}${c.company ? ` @ ${c.company}` : ""}${c.email ? ` (${c.email})` : ""} — ${c.type ?? "—"} / ${c.stage ?? "—"} — id: ${c.id ?? c.contact_id}`);
539
+ const lines = contacts.map((c) => `• ${c.name}${c.company ? ` @ ${c.company}` : ""}${c.email ? ` (${c.email})` : ""} — ${c.type ?? "—"} / ${c.stage ?? "—"} — id: ${c.contact_id}`);
295
540
  return { content: [{ type: "text", text: lines.join("\n") }] };
296
541
  }
297
542
  case "create": {
@@ -314,7 +559,7 @@ function createMindMcpServer(client) {
314
559
  content: [
315
560
  {
316
561
  type: "text",
317
- text: `✅ Created contact: "${result.name}" (id: ${result.id ?? result.contact_id})`,
562
+ text: `✅ Created contact: "${result.name}" (id: ${result.contact_id})`,
318
563
  },
319
564
  ],
320
565
  };
@@ -344,6 +589,70 @@ function createMindMcpServer(client) {
344
589
  content: [{ type: "text", text: `✅ Updated contact: "${result.name}"` }],
345
590
  };
346
591
  }
592
+ case "delete": {
593
+ if (!contact_id) {
594
+ return {
595
+ content: [{ type: "text", text: "Error: contact_id is required for delete" }],
596
+ isError: true,
597
+ };
598
+ }
599
+ await client.deleteContact(contact_id);
600
+ return {
601
+ content: [{ type: "text", text: `✅ Deleted contact ${contact_id}` }],
602
+ };
603
+ }
604
+ case "get": {
605
+ if (!contact_id) {
606
+ return {
607
+ content: [{ type: "text", text: "Error: contact_id is required for get" }],
608
+ isError: true,
609
+ };
610
+ }
611
+ const result = await client.getContact(contact_id);
612
+ const lines = [
613
+ `**${result.name}**`,
614
+ `Email: ${result.email ?? "—"} | Company: ${result.company ?? "—"}`,
615
+ `Type: ${result.type ?? "—"} | Stage: ${result.stage ?? "—"}`,
616
+ `Created: ${result.created_at ?? "—"}`,
617
+ ];
618
+ return { content: [{ type: "text", text: lines.join("\n") }] };
619
+ }
620
+ case "log_activity": {
621
+ if (!contact_id || !activity_type) {
622
+ return {
623
+ content: [{ type: "text", text: "Error: contact_id and activity_type are required for log_activity" }],
624
+ isError: true,
625
+ };
626
+ }
627
+ const result = await client.logActivity(contact_id, {
628
+ type: activity_type,
629
+ title: activity_type,
630
+ description: activity_notes,
631
+ });
632
+ return {
633
+ content: [
634
+ {
635
+ type: "text",
636
+ text: `✅ Logged ${activity_type} activity for contact ${contact_id} (id: ${result.activity_id})`,
637
+ },
638
+ ],
639
+ };
640
+ }
641
+ case "list_activities": {
642
+ if (!contact_id) {
643
+ return {
644
+ content: [{ type: "text", text: "Error: contact_id is required for list_activities" }],
645
+ isError: true,
646
+ };
647
+ }
648
+ const result = await client.listContactActivities(contact_id);
649
+ const activities = result.activities ?? [];
650
+ if (activities.length === 0) {
651
+ return { content: [{ type: "text", text: "No activities found for this contact." }] };
652
+ }
653
+ const lines = activities.map((a) => `• [${a.type}] ${a.title ?? "—"} — ${a.description ?? "—"} — ${a.created_at ?? "—"}`);
654
+ return { content: [{ type: "text", text: lines.join("\n") }] };
655
+ }
347
656
  }
348
657
  }
349
658
  catch (err) {
@@ -354,29 +663,73 @@ function createMindMcpServer(client) {
354
663
  }
355
664
  });
356
665
  // ─── mind_graph ─────────────────────────────────────────
357
- // Get graph statistics and health.
358
- server.tool("mind_graph", "Get MIND knowledge graph statistics — how many entities, relationships, documents, and entries exist. Use to check graph health and growth.", {}, async () => {
666
+ // Get graph statistics, diagnostics, and labels.
667
+ // Enhanced: action param with stats (default), diagnostics, labels.
668
+ server.tool("mind_graph", "Get MIND knowledge graph statistics, diagnostics, and label details. Use to check graph health, growth, and entity breakdown.", {
669
+ action: zod_1.z
670
+ .enum(["stats", "diagnostics", "labels"])
671
+ .optional()
672
+ .default("stats")
673
+ .describe("Action: stats (default — overview), diagnostics (health check), labels (entity label breakdown)"),
674
+ }, async ({ action }) => {
359
675
  try {
360
- const [graph, profile] = await Promise.all([
361
- client.graphInfo(),
362
- client.credits().catch(() => null),
363
- ]);
364
- const lines = [
365
- "📊 MIND Graph Status",
366
- `• Entities: ${graph.total_entities}`,
367
- `• Relationships: ${graph.total_relationships}`,
368
- `• Storage: ${graph.storage_status?.status ?? "unknown"}`,
369
- ];
370
- if (graph.popular_labels?.length) {
371
- const docCount = graph.popular_labels.reduce((sum, l) => sum + l.count, 0);
372
- lines.push(`• Items in graph: ${docCount}`);
373
- }
374
- if (profile) {
375
- lines.push(`• Credits: ${profile.credits_balance}/${profile.credits_limit}`);
376
- lines.push(`• Tier: ${profile.tier}`);
377
- lines.push(`• Documents: ${profile.documents_used}/${profile.documents_limit}`);
676
+ switch (action) {
677
+ case "stats":
678
+ default: {
679
+ const [graph, profile] = await Promise.all([
680
+ client.graphInfo(),
681
+ client.credits().catch(() => null),
682
+ ]);
683
+ const lines = [
684
+ "📊 MIND Graph Status",
685
+ `• Entities: ${graph.total_entities}`,
686
+ `• Relationships: ${graph.total_relationships}`,
687
+ `• Storage: ${graph.storage_status?.status ?? "unknown"}`,
688
+ ];
689
+ if (graph.popular_labels?.length) {
690
+ const docCount = graph.popular_labels.reduce((sum, l) => sum + l.count, 0);
691
+ lines.push(`• Items in graph: ${docCount}`);
692
+ }
693
+ if (profile) {
694
+ lines.push(`• Credits: ${profile.credits_balance}/${profile.credits_limit}`);
695
+ lines.push(`• Tier: ${profile.tier}`);
696
+ lines.push(`• Documents: ${profile.documents_count} | Storage: ${profile.storage_used_mb}/${profile.storage_limit_mb} MB`);
697
+ }
698
+ return { content: [{ type: "text", text: lines.join("\n") }] };
699
+ }
700
+ case "diagnostics": {
701
+ const result = await client.graphDiagnostics();
702
+ const lines = [
703
+ "🔍 MIND Graph Diagnostics",
704
+ `• Status: ${result.status ?? "unknown"}`,
705
+ `• Entity count: ${result.entity_count ?? "—"}`,
706
+ `• Relationship count: ${result.relationship_count ?? "—"}`,
707
+ `• Orphaned entities: ${result.orphaned_entities ?? "—"}`,
708
+ `• Storage health: ${result.storage_health ?? "—"}`,
709
+ ];
710
+ const issues = result.issues;
711
+ if (issues?.length) {
712
+ lines.push("", "Issues:");
713
+ for (const issue of issues) {
714
+ lines.push(` ⚠ ${issue}`);
715
+ }
716
+ }
717
+ return { content: [{ type: "text", text: lines.join("\n") }] };
718
+ }
719
+ case "labels": {
720
+ // Use graphInfo and extract popular_labels
721
+ const result = await client.graphInfo();
722
+ const labels = result.popular_labels ?? [];
723
+ if (labels.length === 0) {
724
+ return { content: [{ type: "text", text: "No labels found in graph." }] };
725
+ }
726
+ const lines = ["🏷️ MIND Graph Labels", ""];
727
+ for (const l of labels) {
728
+ lines.push(`• ${l.label ?? "unlabeled"}: ${l.count} entities`);
729
+ }
730
+ return { content: [{ type: "text", text: lines.join("\n") }] };
731
+ }
378
732
  }
379
- return { content: [{ type: "text", text: lines.join("\n") }] };
380
733
  }
381
734
  catch (err) {
382
735
  return {
@@ -405,6 +758,8 @@ function createMindMcpServer(client) {
405
758
  email: zod_1.z.string().optional().describe("Email for new user"),
406
759
  password: zod_1.z.string().optional().describe("Password for new user (min 8 chars)"),
407
760
  source: zod_1.z.string().optional().describe("Source app/partner that created this user (e.g. 'myapp')"),
761
+ generate_api_key: zod_1.z.boolean().optional().describe("If true, also generate a developer API key (mind_...) for the new user"),
762
+ api_key_name: zod_1.z.string().optional().describe("Name for the generated API key (defaults to '{source} integration')"),
408
763
  // featured mind fields
409
764
  mind_id: zod_1.z.string().optional().describe("Featured mind ID for update operations"),
410
765
  title: zod_1.z.string().optional().describe("Display title for the featured mind"),
@@ -421,7 +776,7 @@ function createMindMcpServer(client) {
421
776
  // list fields
422
777
  query: zod_1.z.string().optional().describe("Search query for list_users"),
423
778
  page: zod_1.z.number().optional().describe("Page number for paginated results"),
424
- }, async ({ action, username, email, password, source, mind_id, title, description, tags, price, featured, display_order, is_public, avatar_url, tier, credits, query, page }) => {
779
+ }, async ({ action, username, email, password, source, generate_api_key, api_key_name, mind_id, title, description, tags, price, featured, display_order, is_public, avatar_url, tier, credits, query, page }) => {
425
780
  try {
426
781
  switch (action) {
427
782
  case "create_user": {
@@ -431,14 +786,13 @@ function createMindMcpServer(client) {
431
786
  isError: true,
432
787
  };
433
788
  }
434
- const result = await client.adminCreateUser({ username, email, password, source, tier });
789
+ const result = await client.adminCreateUser({ username, email, password, source, tier, generate_api_key, api_key_name });
790
+ let text = `✅ User created: @${result.user?.username} (workspace: ${result.user?.workspace_id}, tier: ${result.user?.tier})`;
791
+ if (result.api_key) {
792
+ text += `\n🔑 API key: ${result.api_key.key}\n Name: ${result.api_key.name}\n Scopes: ${result.api_key.scopes.length} (full access)`;
793
+ }
435
794
  return {
436
- content: [
437
- {
438
- type: "text",
439
- text: `✅ User created: @${result.user?.username} (workspace: ${result.user?.workspace_id}, tier: ${result.user?.tier})`,
440
- },
441
- ],
795
+ content: [{ type: "text", text }],
442
796
  };
443
797
  }
444
798
  case "create_featured_mind": {
@@ -559,6 +913,901 @@ function createMindMcpServer(client) {
559
913
  };
560
914
  }
561
915
  });
916
+ // ═══════════════════════════════════════════════════════════
917
+ // NEW TOOLS (Phase 2 + Phase 3)
918
+ // ═══════════════════════════════════════════════════════════
919
+ // ─── mind_sense ─────────────────────────────────────────
920
+ // MINDsense emotional intelligence layer.
921
+ server.tool("mind_sense", "Access MINDsense emotional intelligence — the user's living emotional state, signal history, emotional timeline, and KG entity weights. Use this to understand how the user is feeling and what emotionally significant events have occurred.", {
922
+ action: zod_1.z
923
+ .enum(["state", "signals", "timeline", "kg_weights", "spikes", "acknowledge", "summary"])
924
+ .describe("Action: state (current emotion), signals (recent signals), timeline (historical), kg_weights (emotionally weighted entities), spikes (recent spikes), acknowledge (ack a spike), summary (AI emotional summary)"),
925
+ signal_id: zod_1.z.string().optional().describe("Signal ID for acknowledge action"),
926
+ days: zod_1.z.number().optional().default(7).describe("Lookback days for timeline/signals"),
927
+ limit: zod_1.z.number().optional().default(20).describe("Max items to return"),
928
+ }, async ({ action, signal_id, days, limit }) => {
929
+ try {
930
+ switch (action) {
931
+ case "state": {
932
+ const result = await client.mindsenseState();
933
+ const lines = [
934
+ "🧠 MINDsense Emotional State",
935
+ `• Label: ${result.label ?? "neutral"}`,
936
+ `• Valence: ${result.valence ?? "—"} (positive/negative)`,
937
+ `• Arousal: ${result.arousal ?? "—"} (intensity)`,
938
+ `• Trend: ${result.trend ?? "stable"}`,
939
+ `• Sensitivity: ${result.sensitivity ?? "—"}`,
940
+ ];
941
+ if (result.dominant_emotion) {
942
+ lines.push(`• Dominant emotion: ${result.dominant_emotion}`);
943
+ }
944
+ return { content: [{ type: "text", text: lines.join("\n") }] };
945
+ }
946
+ case "signals": {
947
+ const result = await client.mindsenseSignals(days, limit);
948
+ const signals = result.signals ?? [];
949
+ if (signals.length === 0) {
950
+ return { content: [{ type: "text", text: "No emotional signals in the specified period." }] };
951
+ }
952
+ const lines = signals.map((s) => `• [${s.label ?? "—"}] valence: ${s.valence ?? "—"}, arousal: ${s.arousal ?? "—"} — ${s.created_at ?? "—"} (id: ${s.signal_id ?? s.id})`);
953
+ return { content: [{ type: "text", text: lines.join("\n") }] };
954
+ }
955
+ case "timeline": {
956
+ const result = await client.mindsenseTimeline(days);
957
+ const points = result.timeline ?? [];
958
+ if (points.length === 0) {
959
+ return { content: [{ type: "text", text: "No timeline data for the specified period." }] };
960
+ }
961
+ const lines = ["📈 Emotional Timeline", ""];
962
+ for (const p of points) {
963
+ lines.push(`• ${p.date ?? p.timestamp}: ${p.label ?? "—"} (v: ${p.valence ?? "—"}, a: ${p.arousal ?? "—"})`);
964
+ }
965
+ return { content: [{ type: "text", text: lines.join("\n") }] };
966
+ }
967
+ case "kg_weights": {
968
+ const result = await client.mindsenseKgWeights(limit);
969
+ const entities = result.entities ?? [];
970
+ if (entities.length === 0) {
971
+ return { content: [{ type: "text", text: "No emotionally weighted entities found." }] };
972
+ }
973
+ const lines = ["🎯 Emotionally Weighted KG Entities", ""];
974
+ for (const e of entities) {
975
+ lines.push(`• ${e.entity ?? e.name}: weight ${e.weight ?? e.score ?? "—"} (${e.emotion ?? "—"})`);
976
+ }
977
+ return { content: [{ type: "text", text: lines.join("\n") }] };
978
+ }
979
+ case "spikes": {
980
+ const result = await client.mindsenseSpikes(days, limit);
981
+ const spikes = result.spikes ?? [];
982
+ if (spikes.length === 0) {
983
+ return { content: [{ type: "text", text: "No emotional spikes detected." }] };
984
+ }
985
+ const lines = ["⚡ Emotional Spikes", ""];
986
+ for (const s of spikes) {
987
+ lines.push(`• [${s.acknowledged ? "ack" : "NEW"}] ${s.label ?? "—"} — valence: ${s.valence ?? "—"}, arousal: ${s.arousal ?? "—"} — ${s.created_at ?? "—"} (id: ${s.signal_id ?? s.id})`);
988
+ }
989
+ return { content: [{ type: "text", text: lines.join("\n") }] };
990
+ }
991
+ case "acknowledge": {
992
+ if (!signal_id) {
993
+ return {
994
+ content: [{ type: "text", text: "Error: signal_id is required for acknowledge" }],
995
+ isError: true,
996
+ };
997
+ }
998
+ await client.mindsenseAcknowledge(signal_id);
999
+ return {
1000
+ content: [{ type: "text", text: `✅ Acknowledged spike signal ${signal_id}` }],
1001
+ };
1002
+ }
1003
+ case "summary": {
1004
+ const result = await client.mindsenseSummary(days);
1005
+ return {
1006
+ content: [{ type: "text", text: result.summary ?? "No emotional summary available." }],
1007
+ };
1008
+ }
1009
+ }
1010
+ }
1011
+ catch (err) {
1012
+ return {
1013
+ content: [{ type: "text", text: `Error in mind_sense: ${err}` }],
1014
+ isError: true,
1015
+ };
1016
+ }
1017
+ });
1018
+ // ─── mind_research ──────────────────────────────────────
1019
+ // Deep research agent jobs.
1020
+ server.tool("mind_research", "Launch and manage deep research jobs. Research runs autonomously — it gathers information, analyzes it, and stores findings in the knowledge graph. Use for competitive analysis, market research, technical deep-dives.", {
1021
+ action: zod_1.z
1022
+ .enum(["start", "status", "list"])
1023
+ .describe("Action: start (launch research), status (check job progress), list (view all jobs)"),
1024
+ topic: zod_1.z.string().optional().describe("Research topic/question for start action"),
1025
+ job_id: zod_1.z.string().optional().describe("Job ID for status action"),
1026
+ limit: zod_1.z.number().optional().default(10).describe("Max jobs to return for list"),
1027
+ }, async ({ action, topic, job_id, limit }) => {
1028
+ try {
1029
+ switch (action) {
1030
+ case "start": {
1031
+ if (!topic) {
1032
+ return {
1033
+ content: [{ type: "text", text: "Error: topic is required to start research" }],
1034
+ isError: true,
1035
+ };
1036
+ }
1037
+ const result = await client.startResearch(topic);
1038
+ return {
1039
+ content: [
1040
+ {
1041
+ type: "text",
1042
+ text: `✅ Research started: "${topic}" (job_id: ${result.job_id})`,
1043
+ },
1044
+ ],
1045
+ };
1046
+ }
1047
+ case "status": {
1048
+ if (!job_id) {
1049
+ return {
1050
+ content: [{ type: "text", text: "Error: job_id is required for status" }],
1051
+ isError: true,
1052
+ };
1053
+ }
1054
+ const result = await client.getResearch(job_id);
1055
+ const lines = [
1056
+ `📋 Research Job: ${result.topic ?? result.title ?? job_id}`,
1057
+ `• Status: ${result.status}`,
1058
+ `• Papers found: ${result.papers_count ?? "—"}`,
1059
+ `• Credits used: ${result.credits_used ?? "—"}`,
1060
+ `• Started: ${result.created_at ?? "—"}`,
1061
+ ];
1062
+ if (result.research_summary) {
1063
+ lines.push("", `Summary: ${result.research_summary}`);
1064
+ }
1065
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1066
+ }
1067
+ case "list": {
1068
+ const result = await client.listResearch(limit);
1069
+ const jobs = result.jobs ?? [];
1070
+ if (jobs.length === 0) {
1071
+ return { content: [{ type: "text", text: "No research jobs found." }] };
1072
+ }
1073
+ const lines = jobs.map((j) => `• [${j.status}] "${j.topic ?? j.title}" — ${j.created_at ?? "—"} (id: ${j.job_id})`);
1074
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1075
+ }
1076
+ }
1077
+ }
1078
+ catch (err) {
1079
+ return {
1080
+ content: [{ type: "text", text: `Error in mind_research: ${err}` }],
1081
+ isError: true,
1082
+ };
1083
+ }
1084
+ });
1085
+ // ─── mind_train ─────────────────────────────────────────
1086
+ // Self-training and chat-to-KG sessions.
1087
+ server.tool("mind_train", "Train MIND's knowledge graph. Start guided training sessions to teach it about yourself, or save existing chat conversations into the knowledge graph for persistent memory.", {
1088
+ action: zod_1.z
1089
+ .enum(["start", "chat", "status", "list_sessions", "pause", "resume", "save_chat"])
1090
+ .describe("Action: start (begin training), chat (send message), status (check progress), list_sessions (view past), pause/resume (control session), save_chat (save chat to KG)"),
1091
+ message: zod_1.z.string().optional().describe("Training message for chat action"),
1092
+ session_type: zod_1.z
1093
+ .string()
1094
+ .optional()
1095
+ .describe("Training type: basics, network, expertise, history, goals, freeform"),
1096
+ session_id: zod_1.z.string().optional().describe("Session ID for save_chat/pause/resume actions"),
1097
+ }, async ({ action, message, session_type, session_id }) => {
1098
+ try {
1099
+ switch (action) {
1100
+ case "start": {
1101
+ const result = await client.trainingStart(session_type);
1102
+ const sid = String(result.session_id ?? result.id ?? "unknown");
1103
+ const prompt = String(result.prompt ?? result.message ?? "Ready to train.");
1104
+ return {
1105
+ content: [
1106
+ {
1107
+ type: "text",
1108
+ text: `✅ Training session started (type: ${session_type ?? "freeform"}, id: ${sid})\n\n${prompt}`,
1109
+ },
1110
+ ],
1111
+ };
1112
+ }
1113
+ case "chat": {
1114
+ if (!message) {
1115
+ return {
1116
+ content: [{ type: "text", text: "Error: message is required for chat" }],
1117
+ isError: true,
1118
+ };
1119
+ }
1120
+ const result = await client.trainingChat(message);
1121
+ return {
1122
+ content: [{ type: "text", text: String(result.response ?? result.message ?? "Received.") }],
1123
+ };
1124
+ }
1125
+ case "status": {
1126
+ const result = await client.trainingStatus();
1127
+ const lines = [
1128
+ "📋 Training Status",
1129
+ `• Active: ${result.active ? "yes" : "no"}`,
1130
+ `• Type: ${String(result.session_type ?? "—")}`,
1131
+ `• Progress: ${String(result.progress ?? "—")}`,
1132
+ `• Items learned: ${String(result.items_learned ?? 0)}`,
1133
+ ];
1134
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1135
+ }
1136
+ case "list_sessions": {
1137
+ const result = await client.trainingSessions();
1138
+ const sessions = result.sessions ?? [];
1139
+ if (sessions.length === 0) {
1140
+ return { content: [{ type: "text", text: "No training sessions found." }] };
1141
+ }
1142
+ const lines = sessions.map((s) => `• [${String(s.status ?? "—")}] ${String(s.session_type ?? "freeform")} — ${String(s.created_at ?? "—")} (id: ${String(s.session_id ?? s.id)})`);
1143
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1144
+ }
1145
+ case "pause": {
1146
+ await client.trainingPause();
1147
+ return {
1148
+ content: [{ type: "text", text: "✅ Training session paused." }],
1149
+ };
1150
+ }
1151
+ case "resume": {
1152
+ const result = await client.trainingResume();
1153
+ const prompt = String(result.prompt ?? result.message ?? "");
1154
+ return {
1155
+ content: [{ type: "text", text: `✅ Training session resumed.\n\n${prompt}` }],
1156
+ };
1157
+ }
1158
+ case "save_chat": {
1159
+ if (!session_id) {
1160
+ return {
1161
+ content: [{ type: "text", text: "Error: session_id is required for save_chat" }],
1162
+ isError: true,
1163
+ };
1164
+ }
1165
+ const result = await client.saveChatToMind(session_id);
1166
+ return {
1167
+ content: [
1168
+ {
1169
+ type: "text",
1170
+ text: `✅ Chat session saved to knowledge graph (${String(result.items_saved ?? result.count ?? 0)} items extracted)`,
1171
+ },
1172
+ ],
1173
+ };
1174
+ }
1175
+ }
1176
+ }
1177
+ catch (err) {
1178
+ return {
1179
+ content: [{ type: "text", text: `Error in mind_train: ${err}` }],
1180
+ isError: true,
1181
+ };
1182
+ }
1183
+ });
1184
+ // ─── mind_social ────────────────────────────────────────
1185
+ // Thoughts, communities, and feed.
1186
+ server.tool("mind_social", "Interact with MIND's social layer — create thoughts (posts), browse the feed, manage communities, and engage with other users' content.", {
1187
+ action: zod_1.z
1188
+ .enum([
1189
+ "create_thought", "get_thought", "delete_thought", "like_thought",
1190
+ "feed", "user_feed", "search_feed",
1191
+ "create_community", "list_communities", "get_community",
1192
+ "join_community", "leave_community",
1193
+ "create_post", "list_posts",
1194
+ ])
1195
+ .describe("Social action — thoughts, feed browsing, community management"),
1196
+ content: zod_1.z.string().optional().describe("Content for thoughts or posts"),
1197
+ thought_id: zod_1.z.string().optional().describe("Thought ID for get/delete/like"),
1198
+ community_id: zod_1.z.string().optional().describe("Community ID for community actions and posts"),
1199
+ post_id: zod_1.z.string().optional().describe("Post ID for post actions"),
1200
+ username: zod_1.z.string().optional().describe("Username for user_feed"),
1201
+ name: zod_1.z.string().optional().describe("Community name for create_community"),
1202
+ description: zod_1.z.string().optional().describe("Community description"),
1203
+ page: zod_1.z.number().optional().describe("Page number for paginated results"),
1204
+ limit: zod_1.z.number().optional().describe("Max items per page"),
1205
+ }, async ({ action, content, thought_id, community_id, post_id, username, name, description, page, limit: lim }) => {
1206
+ try {
1207
+ switch (action) {
1208
+ case "create_thought": {
1209
+ if (!content) {
1210
+ return {
1211
+ content: [{ type: "text", text: "Error: content is required for create_thought" }],
1212
+ isError: true,
1213
+ };
1214
+ }
1215
+ const result = await client.socialCreateThought(content);
1216
+ return {
1217
+ content: [
1218
+ {
1219
+ type: "text",
1220
+ text: `✅ Thought posted (id: ${result.thought_id ?? result.id})`,
1221
+ },
1222
+ ],
1223
+ };
1224
+ }
1225
+ case "get_thought": {
1226
+ if (!thought_id) {
1227
+ return {
1228
+ content: [{ type: "text", text: "Error: thought_id is required for get_thought" }],
1229
+ isError: true,
1230
+ };
1231
+ }
1232
+ const result = await client.socialGetThought(thought_id);
1233
+ const lines = [
1234
+ `@${result.username ?? "—"}: ${result.content}`,
1235
+ `Likes: ${result.likes ?? 0} | Reposts: ${result.reposts ?? 0} | ${result.created_at ?? ""}`,
1236
+ ];
1237
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1238
+ }
1239
+ case "delete_thought": {
1240
+ if (!thought_id) {
1241
+ return {
1242
+ content: [{ type: "text", text: "Error: thought_id is required for delete_thought" }],
1243
+ isError: true,
1244
+ };
1245
+ }
1246
+ await client.socialDeleteThought(thought_id);
1247
+ return {
1248
+ content: [{ type: "text", text: `✅ Deleted thought ${thought_id}` }],
1249
+ };
1250
+ }
1251
+ case "like_thought": {
1252
+ if (!thought_id) {
1253
+ return {
1254
+ content: [{ type: "text", text: "Error: thought_id is required for like_thought" }],
1255
+ isError: true,
1256
+ };
1257
+ }
1258
+ await client.socialLikeThought(thought_id);
1259
+ return {
1260
+ content: [{ type: "text", text: `✅ Liked thought ${thought_id}` }],
1261
+ };
1262
+ }
1263
+ case "feed": {
1264
+ const result = await client.socialFeed(page, lim);
1265
+ const items = result.thoughts ?? [];
1266
+ if (items.length === 0) {
1267
+ return { content: [{ type: "text", text: "Feed is empty." }] };
1268
+ }
1269
+ const lines = items.map((t) => `• @${String(t.username ?? "—")}: ${String(t.content ?? "").slice(0, 120)} (❤ ${String(t.likes ?? 0)}) — id: ${String(t.thought_id ?? t.id)}`);
1270
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1271
+ }
1272
+ case "user_feed": {
1273
+ if (!username) {
1274
+ return {
1275
+ content: [{ type: "text", text: "Error: username is required for user_feed" }],
1276
+ isError: true,
1277
+ };
1278
+ }
1279
+ const result = await client.socialUserFeed(username, page, lim);
1280
+ const items = result.thoughts ?? [];
1281
+ if (items.length === 0) {
1282
+ return { content: [{ type: "text", text: `No thoughts from @${username}.` }] };
1283
+ }
1284
+ const lines = items.map((t) => `• ${String(t.content ?? "").slice(0, 120)} (❤ ${String(t.likes ?? 0)}) — id: ${String(t.thought_id ?? t.id)}`);
1285
+ return { content: [{ type: "text", text: `@${username}'s thoughts:\n${lines.join("\n")}` }] };
1286
+ }
1287
+ case "search_feed": {
1288
+ if (!content) {
1289
+ return {
1290
+ content: [{ type: "text", text: "Error: content (search query) is required for search_feed" }],
1291
+ isError: true,
1292
+ };
1293
+ }
1294
+ const result = await client.socialSearchFeed(content, page, lim);
1295
+ const items = result.thoughts ?? [];
1296
+ if (items.length === 0) {
1297
+ return { content: [{ type: "text", text: `No results for "${content}".` }] };
1298
+ }
1299
+ const lines = items.map((t) => `• @${String(t.username ?? "—")}: ${String(t.content ?? "").slice(0, 120)} — id: ${String(t.thought_id ?? t.id)}`);
1300
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1301
+ }
1302
+ case "create_community": {
1303
+ if (!name) {
1304
+ return {
1305
+ content: [{ type: "text", text: "Error: name is required for create_community" }],
1306
+ isError: true,
1307
+ };
1308
+ }
1309
+ const result = await client.socialCreateCommunity(name, description);
1310
+ return {
1311
+ content: [
1312
+ {
1313
+ type: "text",
1314
+ text: `✅ Community created: "${result.name}" (id: ${result.community_id ?? result.id})`,
1315
+ },
1316
+ ],
1317
+ };
1318
+ }
1319
+ case "list_communities": {
1320
+ const result = await client.socialListCommunities(page, lim);
1321
+ const communities = result.communities ?? [];
1322
+ if (communities.length === 0) {
1323
+ return { content: [{ type: "text", text: "No communities found." }] };
1324
+ }
1325
+ const lines = communities.map((c) => `• ${c.name} — ${c.member_count ?? 0} members (id: ${c.community_id ?? c.id})`);
1326
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1327
+ }
1328
+ case "get_community": {
1329
+ if (!community_id) {
1330
+ return {
1331
+ content: [{ type: "text", text: "Error: community_id is required for get_community" }],
1332
+ isError: true,
1333
+ };
1334
+ }
1335
+ const result = await client.socialGetCommunity(community_id);
1336
+ const lines = [
1337
+ `**${result.name}**`,
1338
+ result.description ?? "",
1339
+ `Members: ${result.member_count ?? 0} | Posts: ${result.post_count ?? 0}`,
1340
+ ];
1341
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1342
+ }
1343
+ case "join_community": {
1344
+ if (!community_id) {
1345
+ return {
1346
+ content: [{ type: "text", text: "Error: community_id is required for join_community" }],
1347
+ isError: true,
1348
+ };
1349
+ }
1350
+ await client.socialJoinCommunity(community_id);
1351
+ return {
1352
+ content: [{ type: "text", text: `✅ Joined community ${community_id}` }],
1353
+ };
1354
+ }
1355
+ case "leave_community": {
1356
+ if (!community_id) {
1357
+ return {
1358
+ content: [{ type: "text", text: "Error: community_id is required for leave_community" }],
1359
+ isError: true,
1360
+ };
1361
+ }
1362
+ await client.socialLeaveCommunity(community_id);
1363
+ return {
1364
+ content: [{ type: "text", text: `✅ Left community ${community_id}` }],
1365
+ };
1366
+ }
1367
+ case "create_post": {
1368
+ if (!community_id || !content) {
1369
+ return {
1370
+ content: [{ type: "text", text: "Error: community_id and content are required for create_post" }],
1371
+ isError: true,
1372
+ };
1373
+ }
1374
+ const result = await client.socialCreatePost(community_id, content);
1375
+ return {
1376
+ content: [
1377
+ {
1378
+ type: "text",
1379
+ text: `✅ Post created in community ${community_id} (id: ${result.post_id ?? result.id})`,
1380
+ },
1381
+ ],
1382
+ };
1383
+ }
1384
+ case "list_posts": {
1385
+ if (!community_id) {
1386
+ return {
1387
+ content: [{ type: "text", text: "Error: community_id is required for list_posts" }],
1388
+ isError: true,
1389
+ };
1390
+ }
1391
+ const result = await client.socialListPosts(community_id, page, lim);
1392
+ const posts = result.posts ?? [];
1393
+ if (posts.length === 0) {
1394
+ return { content: [{ type: "text", text: "No posts in this community." }] };
1395
+ }
1396
+ const lines = posts.map((p) => `• @${p.username ?? "—"}: ${p.content?.slice(0, 120) ?? ""} — id: ${p.post_id ?? p.id}`);
1397
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1398
+ }
1399
+ }
1400
+ }
1401
+ catch (err) {
1402
+ return {
1403
+ content: [{ type: "text", text: `Error in mind_social: ${err}` }],
1404
+ isError: true,
1405
+ };
1406
+ }
1407
+ });
1408
+ // ─── mind_profile ───────────────────────────────────────
1409
+ // Profile, prompts, and model preferences.
1410
+ server.tool("mind_profile", "Manage your MIND profile, AI prompt settings, and model preferences. Update your bio, set custom system prompts for chat and thought generation, and choose your preferred LLM model.", {
1411
+ action: zod_1.z
1412
+ .enum([
1413
+ "get", "update",
1414
+ "get_chat_prompt", "set_chat_prompt",
1415
+ "get_thought_prompt", "set_thought_prompt",
1416
+ "get_model", "set_model", "list_models",
1417
+ ])
1418
+ .describe("Action: get/update profile, get/set chat/thought prompts, get/set/list LLM models"),
1419
+ username: zod_1.z.string().optional().describe("Username for get action (defaults to current user)"),
1420
+ bio: zod_1.z.string().optional().describe("Bio for update action"),
1421
+ display_name: zod_1.z.string().optional().describe("Display name for update action"),
1422
+ prompt: zod_1.z.string().optional().describe("System prompt content for set_chat_prompt/set_thought_prompt"),
1423
+ model_id: zod_1.z.string().optional().describe("Model ID for set_model"),
1424
+ }, async ({ action, username, bio, display_name, prompt, model_id }) => {
1425
+ try {
1426
+ switch (action) {
1427
+ case "get": {
1428
+ const result = await client.profileGet(username);
1429
+ const lines = [
1430
+ `**@${result.username}**`,
1431
+ result.display_name ? `Name: ${result.display_name}` : "",
1432
+ result.bio ? `Bio: ${result.bio}` : "",
1433
+ `Tier: ${result.tier ?? "free"}`,
1434
+ `Joined: ${result.created_at ?? "—"}`,
1435
+ ].filter(Boolean);
1436
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1437
+ }
1438
+ case "update": {
1439
+ const patch = {};
1440
+ if (bio)
1441
+ patch.bio = bio;
1442
+ if (display_name)
1443
+ patch.display_name = display_name;
1444
+ if (username)
1445
+ patch.username = username;
1446
+ const result = await client.profileUpdate(patch);
1447
+ return {
1448
+ content: [{ type: "text", text: `✅ Profile updated: @${result.username}` }],
1449
+ };
1450
+ }
1451
+ case "get_chat_prompt": {
1452
+ const result = await client.getChatPrompt();
1453
+ return {
1454
+ content: [{ type: "text", text: `Chat system prompt:\n\n${result.prompt ?? "No custom prompt set."}` }],
1455
+ };
1456
+ }
1457
+ case "set_chat_prompt": {
1458
+ if (!prompt) {
1459
+ return {
1460
+ content: [{ type: "text", text: "Error: prompt is required for set_chat_prompt" }],
1461
+ isError: true,
1462
+ };
1463
+ }
1464
+ await client.setChatPrompt(prompt);
1465
+ return {
1466
+ content: [{ type: "text", text: "✅ Chat system prompt updated." }],
1467
+ };
1468
+ }
1469
+ case "get_thought_prompt": {
1470
+ const result = await client.getThoughtPrompt();
1471
+ return {
1472
+ content: [{ type: "text", text: `Thought generation prompt:\n\n${result.prompt ?? "No custom prompt set."}` }],
1473
+ };
1474
+ }
1475
+ case "set_thought_prompt": {
1476
+ if (!prompt) {
1477
+ return {
1478
+ content: [{ type: "text", text: "Error: prompt is required for set_thought_prompt" }],
1479
+ isError: true,
1480
+ };
1481
+ }
1482
+ await client.setThoughtPrompt(prompt);
1483
+ return {
1484
+ content: [{ type: "text", text: "✅ Thought generation prompt updated." }],
1485
+ };
1486
+ }
1487
+ case "get_model": {
1488
+ const result = await client.getModel();
1489
+ return {
1490
+ content: [
1491
+ {
1492
+ type: "text",
1493
+ text: `Current model: ${result.model_id ?? result.model ?? "default"} (${result.provider ?? "—"})`,
1494
+ },
1495
+ ],
1496
+ };
1497
+ }
1498
+ case "set_model": {
1499
+ if (!model_id) {
1500
+ return {
1501
+ content: [{ type: "text", text: "Error: model_id is required for set_model" }],
1502
+ isError: true,
1503
+ };
1504
+ }
1505
+ const result = await client.setModel(model_id);
1506
+ return {
1507
+ content: [{ type: "text", text: `✅ Model set to: ${result.model_id ?? model_id}` }],
1508
+ };
1509
+ }
1510
+ case "list_models": {
1511
+ const result = await client.listModels();
1512
+ const models = result.models ?? [];
1513
+ if (models.length === 0) {
1514
+ return { content: [{ type: "text", text: "No models available." }] };
1515
+ }
1516
+ const lines = models.map((m) => `• ${m.name ?? m.model_id} (${m.provider ?? "—"}) — ${m.description ?? ""}${m.is_free ? " [FREE]" : ""}`);
1517
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1518
+ }
1519
+ }
1520
+ }
1521
+ catch (err) {
1522
+ return {
1523
+ content: [{ type: "text", text: `Error in mind_profile: ${err}` }],
1524
+ isError: true,
1525
+ };
1526
+ }
1527
+ });
1528
+ // ─── mind_insights ──────────────────────────────────────
1529
+ // ALE insights and analytics.
1530
+ server.tool("mind_insights", "Access insights from MIND's Autonomous Learning Engine — patterns detected in your knowledge graph, weekly summaries, and proactive intelligence. Also trigger on-demand analysis.", {
1531
+ action: zod_1.z
1532
+ .enum(["list", "unread_count", "view", "feedback", "analyze", "weekly_summary", "context"])
1533
+ .describe("Action: list (recent insights), unread_count, view (mark seen), feedback (rate), analyze (trigger analysis), weekly_summary, context (ALE context)"),
1534
+ insight_id: zod_1.z.string().optional().describe("Insight ID for view/feedback actions"),
1535
+ rating: zod_1.z
1536
+ .enum(["helpful", "not_helpful"])
1537
+ .optional()
1538
+ .describe("Rating for feedback action"),
1539
+ limit: zod_1.z.number().optional().default(10).describe("Max insights to return"),
1540
+ }, async ({ action, insight_id, rating, limit }) => {
1541
+ try {
1542
+ switch (action) {
1543
+ case "list": {
1544
+ const result = await client.insightsList(limit);
1545
+ const insights = result.insights ?? [];
1546
+ if (insights.length === 0) {
1547
+ return { content: [{ type: "text", text: "No insights available." }] };
1548
+ }
1549
+ const lines = insights.map((i) => `• [${i.type ?? "insight"}] ${i.title ?? i.content?.slice(0, 100) ?? "—"} — ${i.created_at ?? ""} (id: ${i.insight_id ?? i.id})`);
1550
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1551
+ }
1552
+ case "unread_count": {
1553
+ const result = await client.insightsUnreadCount();
1554
+ return {
1555
+ content: [{ type: "text", text: `Unread insights: ${result.count ?? 0}` }],
1556
+ };
1557
+ }
1558
+ case "view": {
1559
+ if (!insight_id) {
1560
+ return {
1561
+ content: [{ type: "text", text: "Error: insight_id is required for view" }],
1562
+ isError: true,
1563
+ };
1564
+ }
1565
+ const result = await client.insightsView(insight_id);
1566
+ const lines = [
1567
+ `**${result.title ?? "Insight"}**`,
1568
+ `Type: ${result.type ?? "—"} | Created: ${result.created_at ?? "—"}`,
1569
+ "",
1570
+ result.content ?? "No content.",
1571
+ ];
1572
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1573
+ }
1574
+ case "feedback": {
1575
+ if (!insight_id || !rating) {
1576
+ return {
1577
+ content: [{ type: "text", text: "Error: insight_id and rating are required for feedback" }],
1578
+ isError: true,
1579
+ };
1580
+ }
1581
+ await client.insightsFeedback(insight_id, rating);
1582
+ return {
1583
+ content: [{ type: "text", text: `✅ Feedback recorded for insight ${insight_id}: ${rating}` }],
1584
+ };
1585
+ }
1586
+ case "analyze": {
1587
+ const result = await client.insightsAnalyze();
1588
+ return {
1589
+ content: [
1590
+ {
1591
+ type: "text",
1592
+ text: `✅ Analysis triggered. ${result.message ?? result.status ?? "Processing..."}`,
1593
+ },
1594
+ ],
1595
+ };
1596
+ }
1597
+ case "weekly_summary": {
1598
+ const result = await client.insightsWeeklySummary();
1599
+ return {
1600
+ content: [{ type: "text", text: result.summary ?? "No weekly summary available." }],
1601
+ };
1602
+ }
1603
+ case "context": {
1604
+ const result = await client.insightsContext();
1605
+ return {
1606
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1607
+ };
1608
+ }
1609
+ }
1610
+ }
1611
+ catch (err) {
1612
+ return {
1613
+ content: [{ type: "text", text: `Error in mind_insights: ${err}` }],
1614
+ isError: true,
1615
+ };
1616
+ }
1617
+ });
1618
+ // ─── mind_automate ──────────────────────────────────────
1619
+ // Automations and triggers.
1620
+ server.tool("mind_automate", "Create and manage automations in MIND — scheduled workflows, event triggers, and rules that run automatically. Connect CRM events to actions, schedule recurring tasks, and build custom pipelines.", {
1621
+ action: zod_1.z
1622
+ .enum(["list", "create", "update", "delete", "run_now", "history"])
1623
+ .describe("Action: list/create/update/delete automations, run_now (trigger immediately), history (execution log)"),
1624
+ automation_id: zod_1.z.string().optional().describe("Automation ID for update/delete/run_now/history"),
1625
+ name: zod_1.z.string().optional().describe("Automation name for create/update"),
1626
+ trigger_type: zod_1.z
1627
+ .string()
1628
+ .optional()
1629
+ .describe("Trigger type: schedule, webhook, event"),
1630
+ trigger_config: zod_1.z
1631
+ .string()
1632
+ .optional()
1633
+ .describe("JSON config string for the trigger (e.g. cron expression, event name)"),
1634
+ action_type: zod_1.z.string().optional().describe("Action type to execute when triggered"),
1635
+ action_config: zod_1.z
1636
+ .string()
1637
+ .optional()
1638
+ .describe("JSON config string for the action"),
1639
+ enabled: zod_1.z.boolean().optional().describe("Whether the automation is enabled"),
1640
+ }, async ({ action, automation_id, name, trigger_type, trigger_config, action_type, action_config, enabled }) => {
1641
+ try {
1642
+ switch (action) {
1643
+ case "list": {
1644
+ const result = await client.listAutomations();
1645
+ const automations = result.automations ?? [];
1646
+ if (automations.length === 0) {
1647
+ return { content: [{ type: "text", text: "No automations found." }] };
1648
+ }
1649
+ const lines = automations.map((a) => `• [${a.enabled ? "ON" : "OFF"}] ${a.task} — interval: ${a.interval} (runs: ${a.total_runs}, id: ${a.id})`);
1650
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1651
+ }
1652
+ case "create": {
1653
+ if (!name || !trigger_type || !action_type) {
1654
+ return {
1655
+ content: [{ type: "text", text: "Error: name, trigger_type, and action_type are required for create" }],
1656
+ isError: true,
1657
+ };
1658
+ }
1659
+ const result = await client.createAutomation({
1660
+ name,
1661
+ trigger_type,
1662
+ trigger_config: trigger_config ? JSON.parse(trigger_config) : undefined,
1663
+ action_type,
1664
+ action_config: action_config ? JSON.parse(action_config) : undefined,
1665
+ enabled: enabled ?? true,
1666
+ });
1667
+ return {
1668
+ content: [
1669
+ {
1670
+ type: "text",
1671
+ text: `✅ Automation created: "${result.name}" (id: ${result.automation_id ?? result.id})`,
1672
+ },
1673
+ ],
1674
+ };
1675
+ }
1676
+ case "update": {
1677
+ if (!automation_id) {
1678
+ return {
1679
+ content: [{ type: "text", text: "Error: automation_id is required for update" }],
1680
+ isError: true,
1681
+ };
1682
+ }
1683
+ const patch = {};
1684
+ if (name)
1685
+ patch.name = name;
1686
+ if (trigger_type)
1687
+ patch.trigger_type = trigger_type;
1688
+ if (trigger_config)
1689
+ patch.trigger_config = JSON.parse(trigger_config);
1690
+ if (action_type)
1691
+ patch.action_type = action_type;
1692
+ if (action_config)
1693
+ patch.action_config = JSON.parse(action_config);
1694
+ if (enabled !== undefined)
1695
+ patch.enabled = enabled;
1696
+ const result = await client.updateAutomation(automation_id, patch);
1697
+ return {
1698
+ content: [{ type: "text", text: `✅ Updated automation: "${result.name}"` }],
1699
+ };
1700
+ }
1701
+ case "delete": {
1702
+ if (!automation_id) {
1703
+ return {
1704
+ content: [{ type: "text", text: "Error: automation_id is required for delete" }],
1705
+ isError: true,
1706
+ };
1707
+ }
1708
+ await client.deleteAutomation(automation_id);
1709
+ return {
1710
+ content: [{ type: "text", text: `✅ Deleted automation ${automation_id}` }],
1711
+ };
1712
+ }
1713
+ case "run_now": {
1714
+ if (!automation_id) {
1715
+ return {
1716
+ content: [{ type: "text", text: "Error: automation_id is required for run_now" }],
1717
+ isError: true,
1718
+ };
1719
+ }
1720
+ const result = await client.automationsRunNow(automation_id);
1721
+ return {
1722
+ content: [
1723
+ {
1724
+ type: "text",
1725
+ text: `✅ Automation triggered: ${result.status ?? "running"} (execution_id: ${result.execution_id ?? result.id ?? "—"})`,
1726
+ },
1727
+ ],
1728
+ };
1729
+ }
1730
+ case "history": {
1731
+ if (!automation_id) {
1732
+ return {
1733
+ content: [{ type: "text", text: "Error: automation_id is required for history" }],
1734
+ isError: true,
1735
+ };
1736
+ }
1737
+ const result = await client.automationsHistory(automation_id);
1738
+ const executions = result.executions ?? [];
1739
+ if (executions.length === 0) {
1740
+ return { content: [{ type: "text", text: "No execution history found." }] };
1741
+ }
1742
+ const lines = executions.map((e) => `• [${e.status}] ${e.started_at ?? "—"}${e.completed_at ? ` → ${e.completed_at}` : ""} (id: ${e.execution_id ?? e.id})`);
1743
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1744
+ }
1745
+ }
1746
+ }
1747
+ catch (err) {
1748
+ return {
1749
+ content: [{ type: "text", text: `Error in mind_automate: ${err}` }],
1750
+ isError: true,
1751
+ };
1752
+ }
1753
+ });
1754
+ // ─── mind_notify ────────────────────────────────────────
1755
+ // Notifications management.
1756
+ server.tool("mind_notify", "Read and manage MIND notifications — alerts, reminders, insight notifications, and system messages.", {
1757
+ action: zod_1.z
1758
+ .enum(["list", "mark_read", "mark_all_read", "stats"])
1759
+ .describe("Action: list (view notifications), mark_read (single), mark_all_read (all), stats (overview)"),
1760
+ notification_id: zod_1.z.string().optional().describe("Notification ID for mark_read"),
1761
+ limit: zod_1.z.number().optional().default(20).describe("Max notifications to return"),
1762
+ }, async ({ action, notification_id, limit }) => {
1763
+ try {
1764
+ switch (action) {
1765
+ case "list": {
1766
+ const result = await client.notificationsList(limit);
1767
+ const notifications = result.notifications ?? [];
1768
+ if (notifications.length === 0) {
1769
+ return { content: [{ type: "text", text: "No notifications." }] };
1770
+ }
1771
+ const lines = notifications.map((n) => `• [${n.read ? "read" : "NEW"}] ${n.title ?? n.message ?? "—"} — ${n.created_at ?? ""} (id: ${n.notification_id})`);
1772
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1773
+ }
1774
+ case "mark_read": {
1775
+ if (!notification_id) {
1776
+ return {
1777
+ content: [{ type: "text", text: "Error: notification_id is required for mark_read" }],
1778
+ isError: true,
1779
+ };
1780
+ }
1781
+ await client.notificationsMarkRead(notification_id);
1782
+ return {
1783
+ content: [{ type: "text", text: `✅ Marked notification ${notification_id} as read.` }],
1784
+ };
1785
+ }
1786
+ case "mark_all_read": {
1787
+ const result = await client.notificationsMarkAllRead();
1788
+ return {
1789
+ content: [{ type: "text", text: `✅ Marked ${result.count ?? "all"} notifications as read.` }],
1790
+ };
1791
+ }
1792
+ case "stats": {
1793
+ const result = await client.notificationsStats();
1794
+ const lines = [
1795
+ "🔔 Notification Stats",
1796
+ `• Total: ${result.total ?? 0}`,
1797
+ `• Unread: ${result.unread ?? 0}`,
1798
+ `• Read: ${result.read ?? 0}`,
1799
+ ];
1800
+ return { content: [{ type: "text", text: lines.join("\n") }] };
1801
+ }
1802
+ }
1803
+ }
1804
+ catch (err) {
1805
+ return {
1806
+ content: [{ type: "text", text: `Error in mind_notify: ${err}` }],
1807
+ isError: true,
1808
+ };
1809
+ }
1810
+ });
562
1811
  return server;
563
1812
  }
564
1813
  //# sourceMappingURL=server.js.map