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