memax-cli 0.1.0-alpha.5 → 0.1.0-alpha.50

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.
Files changed (185) hide show
  1. package/assets/skills/memax-memory/SKILL.md +173 -0
  2. package/dist/commands/agent-sessions.d.ts +62 -0
  3. package/dist/commands/agent-sessions.d.ts.map +1 -0
  4. package/dist/commands/agent-sessions.js +1447 -0
  5. package/dist/commands/agent-sessions.js.map +1 -0
  6. package/dist/commands/agent-sessions.test.d.ts +2 -0
  7. package/dist/commands/agent-sessions.test.d.ts.map +1 -0
  8. package/dist/commands/agent-sessions.test.js +255 -0
  9. package/dist/commands/agent-sessions.test.js.map +1 -0
  10. package/dist/commands/agents.d.ts +3 -0
  11. package/dist/commands/agents.d.ts.map +1 -0
  12. package/dist/commands/agents.js +36 -0
  13. package/dist/commands/agents.js.map +1 -0
  14. package/dist/commands/ask.d.ts +15 -0
  15. package/dist/commands/ask.d.ts.map +1 -0
  16. package/dist/commands/ask.js +483 -0
  17. package/dist/commands/ask.js.map +1 -0
  18. package/dist/commands/auth.d.ts +7 -0
  19. package/dist/commands/auth.d.ts.map +1 -1
  20. package/dist/commands/auth.js +99 -8
  21. package/dist/commands/auth.js.map +1 -1
  22. package/dist/commands/capture.d.ts +19 -0
  23. package/dist/commands/capture.d.ts.map +1 -0
  24. package/dist/commands/capture.js +69 -0
  25. package/dist/commands/capture.js.map +1 -0
  26. package/dist/commands/config.d.ts +2 -0
  27. package/dist/commands/config.d.ts.map +1 -1
  28. package/dist/commands/config.js +13 -0
  29. package/dist/commands/config.js.map +1 -1
  30. package/dist/commands/delete.d.ts +3 -1
  31. package/dist/commands/delete.d.ts.map +1 -1
  32. package/dist/commands/delete.js +30 -5
  33. package/dist/commands/delete.js.map +1 -1
  34. package/dist/commands/dreams.d.ts +22 -0
  35. package/dist/commands/dreams.d.ts.map +1 -0
  36. package/dist/commands/dreams.js +235 -0
  37. package/dist/commands/dreams.js.map +1 -0
  38. package/dist/commands/dreams.test.d.ts +2 -0
  39. package/dist/commands/dreams.test.d.ts.map +1 -0
  40. package/dist/commands/dreams.test.js +39 -0
  41. package/dist/commands/dreams.test.js.map +1 -0
  42. package/dist/commands/hook.d.ts +2 -0
  43. package/dist/commands/hook.d.ts.map +1 -1
  44. package/dist/commands/hook.js +25 -103
  45. package/dist/commands/hook.js.map +1 -1
  46. package/dist/commands/hub.d.ts +37 -0
  47. package/dist/commands/hub.d.ts.map +1 -0
  48. package/dist/commands/hub.js +347 -0
  49. package/dist/commands/hub.js.map +1 -0
  50. package/dist/commands/hub.test.d.ts +2 -0
  51. package/dist/commands/hub.test.d.ts.map +1 -0
  52. package/dist/commands/hub.test.js +62 -0
  53. package/dist/commands/hub.test.js.map +1 -0
  54. package/dist/commands/list.d.ts +9 -2
  55. package/dist/commands/list.d.ts.map +1 -1
  56. package/dist/commands/list.js +118 -9
  57. package/dist/commands/list.js.map +1 -1
  58. package/dist/commands/list.test.d.ts +2 -0
  59. package/dist/commands/list.test.d.ts.map +1 -0
  60. package/dist/commands/list.test.js +20 -0
  61. package/dist/commands/list.test.js.map +1 -0
  62. package/dist/commands/login.d.ts +7 -1
  63. package/dist/commands/login.d.ts.map +1 -1
  64. package/dist/commands/login.js +85 -22
  65. package/dist/commands/login.js.map +1 -1
  66. package/dist/commands/mcp.d.ts.map +1 -1
  67. package/dist/commands/mcp.js +427 -60
  68. package/dist/commands/mcp.js.map +1 -1
  69. package/dist/commands/push.d.ts +7 -2
  70. package/dist/commands/push.d.ts.map +1 -1
  71. package/dist/commands/push.js +80 -12
  72. package/dist/commands/push.js.map +1 -1
  73. package/dist/commands/recall.d.ts +11 -1
  74. package/dist/commands/recall.d.ts.map +1 -1
  75. package/dist/commands/recall.js +228 -41
  76. package/dist/commands/recall.js.map +1 -1
  77. package/dist/commands/recall.test.d.ts +2 -0
  78. package/dist/commands/recall.test.d.ts.map +1 -0
  79. package/dist/commands/recall.test.js +31 -0
  80. package/dist/commands/recall.test.js.map +1 -0
  81. package/dist/commands/setup-hooks.d.ts +13 -0
  82. package/dist/commands/setup-hooks.d.ts.map +1 -0
  83. package/dist/commands/setup-hooks.js +193 -0
  84. package/dist/commands/setup-hooks.js.map +1 -0
  85. package/dist/commands/setup-instructions.d.ts +21 -0
  86. package/dist/commands/setup-instructions.d.ts.map +1 -0
  87. package/dist/commands/setup-instructions.js +172 -0
  88. package/dist/commands/setup-instructions.js.map +1 -0
  89. package/dist/commands/setup-mcp.d.ts +40 -0
  90. package/dist/commands/setup-mcp.d.ts.map +1 -0
  91. package/dist/commands/setup-mcp.js +414 -0
  92. package/dist/commands/setup-mcp.js.map +1 -0
  93. package/dist/commands/setup-types.d.ts +33 -0
  94. package/dist/commands/setup-types.d.ts.map +1 -0
  95. package/dist/commands/setup-types.js +60 -0
  96. package/dist/commands/setup-types.js.map +1 -0
  97. package/dist/commands/setup.d.ts +13 -1
  98. package/dist/commands/setup.d.ts.map +1 -1
  99. package/dist/commands/setup.js +289 -313
  100. package/dist/commands/setup.js.map +1 -1
  101. package/dist/commands/show.d.ts +5 -1
  102. package/dist/commands/show.d.ts.map +1 -1
  103. package/dist/commands/show.js +36 -14
  104. package/dist/commands/show.js.map +1 -1
  105. package/dist/commands/sync.d.ts +47 -3
  106. package/dist/commands/sync.d.ts.map +1 -1
  107. package/dist/commands/sync.js +1351 -135
  108. package/dist/commands/sync.js.map +1 -1
  109. package/dist/commands/sync.test.d.ts +2 -0
  110. package/dist/commands/sync.test.d.ts.map +1 -0
  111. package/dist/commands/sync.test.js +130 -0
  112. package/dist/commands/sync.test.js.map +1 -0
  113. package/dist/commands/topic.d.ts +32 -0
  114. package/dist/commands/topic.d.ts.map +1 -0
  115. package/dist/commands/topic.js +265 -0
  116. package/dist/commands/topic.js.map +1 -0
  117. package/dist/commands/topic.test.d.ts +2 -0
  118. package/dist/commands/topic.test.d.ts.map +1 -0
  119. package/dist/commands/topic.test.js +114 -0
  120. package/dist/commands/topic.test.js.map +1 -0
  121. package/dist/index.js +35 -125
  122. package/dist/index.js.map +1 -1
  123. package/dist/lib/client.d.ts +10 -0
  124. package/dist/lib/client.d.ts.map +1 -0
  125. package/dist/lib/client.js +104 -0
  126. package/dist/lib/client.js.map +1 -0
  127. package/dist/lib/client.test.d.ts +2 -0
  128. package/dist/lib/client.test.d.ts.map +1 -0
  129. package/dist/lib/client.test.js +44 -0
  130. package/dist/lib/client.test.js.map +1 -0
  131. package/dist/lib/config.d.ts +43 -0
  132. package/dist/lib/config.d.ts.map +1 -1
  133. package/dist/lib/config.js +72 -1
  134. package/dist/lib/config.js.map +1 -1
  135. package/dist/lib/credentials.d.ts +3 -0
  136. package/dist/lib/credentials.d.ts.map +1 -1
  137. package/dist/lib/credentials.js +24 -2
  138. package/dist/lib/credentials.js.map +1 -1
  139. package/dist/lib/hubs.d.ts +7 -0
  140. package/dist/lib/hubs.d.ts.map +1 -0
  141. package/dist/lib/hubs.js +33 -0
  142. package/dist/lib/hubs.js.map +1 -0
  143. package/dist/lib/hubs.test.d.ts +2 -0
  144. package/dist/lib/hubs.test.d.ts.map +1 -0
  145. package/dist/lib/hubs.test.js +58 -0
  146. package/dist/lib/hubs.test.js.map +1 -0
  147. package/dist/lib/project-context.d.ts +56 -0
  148. package/dist/lib/project-context.d.ts.map +1 -0
  149. package/dist/lib/project-context.js +225 -0
  150. package/dist/lib/project-context.js.map +1 -0
  151. package/dist/lib/project-context.test.d.ts +2 -0
  152. package/dist/lib/project-context.test.d.ts.map +1 -0
  153. package/dist/lib/project-context.test.js +75 -0
  154. package/dist/lib/project-context.test.js.map +1 -0
  155. package/dist/lib/prompt.d.ts +7 -0
  156. package/dist/lib/prompt.d.ts.map +1 -0
  157. package/dist/lib/prompt.js +41 -0
  158. package/dist/lib/prompt.js.map +1 -0
  159. package/dist/lib/trash.d.ts +6 -0
  160. package/dist/lib/trash.d.ts.map +1 -0
  161. package/dist/lib/trash.js +28 -0
  162. package/dist/lib/trash.js.map +1 -0
  163. package/package.json +17 -13
  164. package/.vscode/mcp.json +0 -8
  165. package/dist/lib/api.d.ts +0 -4
  166. package/dist/lib/api.d.ts.map +0 -1
  167. package/dist/lib/api.js +0 -95
  168. package/dist/lib/api.js.map +0 -1
  169. package/src/commands/auth.ts +0 -92
  170. package/src/commands/config.ts +0 -27
  171. package/src/commands/delete.ts +0 -20
  172. package/src/commands/hook.ts +0 -243
  173. package/src/commands/list.ts +0 -38
  174. package/src/commands/login.ts +0 -162
  175. package/src/commands/mcp.ts +0 -357
  176. package/src/commands/push.ts +0 -82
  177. package/src/commands/recall.ts +0 -163
  178. package/src/commands/setup.ts +0 -682
  179. package/src/commands/show.ts +0 -35
  180. package/src/commands/sync.ts +0 -403
  181. package/src/index.ts +0 -192
  182. package/src/lib/api.ts +0 -110
  183. package/src/lib/config.ts +0 -61
  184. package/src/lib/credentials.ts +0 -42
  185. package/tsconfig.json +0 -9
@@ -1,14 +1,56 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
- import { apiGet, apiPost } from "../lib/api.js";
5
- function createServer() {
4
+ import { getClient, setClientAgent } from "../lib/client.js";
5
+ import { getActiveHubID } from "../lib/config.js";
6
+ import { findHubMatch, getHubReference, PERSONAL_HUB_ALIAS, } from "../lib/hubs.js";
7
+ const listMemoriesInputSchema = {
8
+ type: "object",
9
+ properties: {
10
+ limit: {
11
+ type: "number",
12
+ description: "Max results to return (default 20, max 50)",
13
+ },
14
+ cursor: {
15
+ type: "string",
16
+ description: "Pagination cursor from previous response (omit for first page)",
17
+ },
18
+ sort: {
19
+ type: "string",
20
+ description: "Sort by: newest (default) or relevant",
21
+ },
22
+ hub_id: {
23
+ type: "string",
24
+ description: 'Optional hub ID, slug, or "personal" to filter results.',
25
+ },
26
+ topic_id: {
27
+ type: "string",
28
+ description: "Optional topic ID (UUID) to filter results.",
29
+ },
30
+ },
31
+ };
32
+ function memoryClassification(memory) {
33
+ return [memory.kind, memory.stability].filter(Boolean).join("/");
34
+ }
35
+ function memberDisplayName(member) {
36
+ return member.user_name || member.user_email || member.user_id;
37
+ }
38
+ async function resolveHubReference(ref) {
39
+ const hubs = await getClient().hubs.list();
40
+ const hubRef = ref ?? getActiveHubID() ?? PERSONAL_HUB_ALIAS;
41
+ const match = findHubMatch(hubs, hubRef);
42
+ if (!match) {
43
+ throw new Error("Hub not found or not accessible. Use memax_hubs to list available hubs.");
44
+ }
45
+ return match.hub.id;
46
+ }
47
+ function createServer(agentId = "") {
6
48
  const server = new Server({ name: "memax", version: "0.0.1" }, { capabilities: { tools: {} } });
7
49
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
8
50
  tools: [
9
51
  {
10
52
  name: "memax_recall",
11
- description: "Search the user's Memax knowledge base with a natural language query. " +
53
+ description: "Search every hub the current token can access with a natural language query. " +
12
54
  "Returns relevant memories ranked by relevance. Use this when you need " +
13
55
  "background information about the project, team processes, or past decisions.",
14
56
  inputSchema: {
@@ -20,11 +62,19 @@ function createServer() {
20
62
  },
21
63
  limit: {
22
64
  type: "number",
23
- description: "Max results to return (default 5)",
65
+ description: "Max results to return (default 10)",
66
+ },
67
+ topic_id: {
68
+ type: "string",
69
+ description: "Restrict results to memories in this topic (UUID).",
24
70
  },
25
- category: {
71
+ hub_id: {
26
72
  type: "string",
27
- description: "Filter by category prefix (e.g. 'core', 'decisions', 'process')",
73
+ description: "Hub ID, slug, or 'personal'. Boosts ranking for this hub.",
74
+ },
75
+ project_context: {
76
+ type: "object",
77
+ description: "Current project context for relevance boosting. Keys: repo (git remote URL), project (short name).",
28
78
  },
29
79
  },
30
80
  required: ["query"],
@@ -33,7 +83,7 @@ function createServer() {
33
83
  {
34
84
  name: "memax_push",
35
85
  description: "Save a piece of knowledge to the user's Memax knowledge base. " +
36
- "Auto-categorized by AI if no category is provided.",
86
+ "Memax classifies it automatically for retrieval.",
37
87
  inputSchema: {
38
88
  type: "object",
39
89
  properties: {
@@ -45,49 +95,131 @@ function createServer() {
45
95
  type: "string",
46
96
  description: "Optional title (auto-generated if omitted)",
47
97
  },
48
- category: {
98
+ hint: {
49
99
  type: "string",
50
- description: "Category (e.g. 'decisions/adr', 'core/architecture'). Auto-detected if omitted.",
100
+ description: "Context hint to help AI process this memory (e.g. 'This is my resume', 'Meeting notes from product review'). Improves classification, summarization, and retrieval.",
51
101
  },
52
102
  tags: {
53
103
  type: "array",
54
104
  items: { type: "string" },
55
105
  description: "Tags for the memory",
56
106
  },
107
+ initiation_type: {
108
+ type: "string",
109
+ description: "How this save was initiated: human_direct, human_requested_agent, agent_proactive, agent_automatic, import, or unknown.",
110
+ },
111
+ project_context: {
112
+ type: "object",
113
+ description: "Project context (auto-detected by CLI). Keys: repo (git remote URL), project (short name), branch.",
114
+ },
115
+ hub_id: {
116
+ type: "string",
117
+ description: "Target hub ID. Required when pushing into a team hub.",
118
+ },
119
+ hub_reason: {
120
+ type: "string",
121
+ description: "Why this belongs in the shared hub. Required when hub_id targets a team hub.",
122
+ },
57
123
  },
58
124
  required: ["content"],
59
125
  },
60
126
  },
61
127
  {
62
128
  name: "memax_get",
63
- description: "Get the full content of a specific note by ID. " +
129
+ description: "Get the full content of a specific memory by ID. " +
64
130
  "Use this after memax_recall to read the complete content of a relevant memory.",
65
131
  inputSchema: {
66
132
  type: "object",
67
133
  properties: {
68
134
  id: {
69
135
  type: "string",
70
- description: "The note ID (from memax_recall or memax_search results)",
136
+ description: "The memory ID (from memax_recall or memax_list results)",
71
137
  },
72
138
  },
73
139
  required: ["id"],
74
140
  },
75
141
  },
76
142
  {
77
- name: "memax_search",
78
- description: "List notes filtered by category or tags. " +
79
- "For browsing and structured lookups, not semantic search. " +
80
- "Use memax_recall for natural language queries instead.",
143
+ name: "memax_list",
144
+ description: "List memories with pagination. Use cursor from the previous response for the next page. Returns total count.",
145
+ inputSchema: listMemoriesInputSchema,
146
+ },
147
+ {
148
+ name: "memax_hubs",
149
+ description: "List hubs the current user can access, including hub IDs, slugs, roles, and memory counts.",
150
+ inputSchema: {
151
+ type: "object",
152
+ properties: {},
153
+ },
154
+ },
155
+ {
156
+ name: "memax_hub_members",
157
+ description: 'List members for a hub. Requires hub_id (hub ID, slug, or "personal").',
81
158
  inputSchema: {
82
159
  type: "object",
83
160
  properties: {
84
- category: {
161
+ hub_id: {
85
162
  type: "string",
86
- description: "Filter by category prefix",
163
+ description: 'Hub ID, slug, or "personal".',
87
164
  },
88
- limit: {
89
- type: "number",
90
- description: "Max results to return (default 10)",
165
+ },
166
+ required: ["hub_id"],
167
+ },
168
+ },
169
+ {
170
+ name: "memax_forget",
171
+ description: "Delete a memory from the user's Memax knowledge base by ID. " +
172
+ "Use this to remove outdated, incorrect, or duplicate memories.",
173
+ inputSchema: {
174
+ type: "object",
175
+ properties: {
176
+ id: {
177
+ type: "string",
178
+ description: "The memory ID to delete (from memax_recall or memax_list results)",
179
+ },
180
+ },
181
+ required: ["id"],
182
+ },
183
+ },
184
+ {
185
+ name: "memax_capture",
186
+ description: "Capture key decisions, learnings, and context from this session. " +
187
+ "Call at the end of a significant work session to save what was accomplished " +
188
+ "and what should be remembered. Each fact is extracted and stored as a separate searchable memory.",
189
+ inputSchema: {
190
+ type: "object",
191
+ properties: {
192
+ summary: {
193
+ type: "string",
194
+ description: "Brief summary of what was accomplished in this session",
195
+ },
196
+ decisions: {
197
+ type: "array",
198
+ items: { type: "string" },
199
+ description: "Key decisions made (e.g., 'Chose PostgreSQL over MongoDB')",
200
+ },
201
+ learnings: {
202
+ type: "array",
203
+ items: { type: "string" },
204
+ description: "Things learned (e.g., 'pg_trgm is language-agnostic')",
205
+ },
206
+ },
207
+ required: ["summary"],
208
+ },
209
+ },
210
+ {
211
+ name: "memax_topics",
212
+ description: "Browse the user's knowledge topics. Without topic_id: returns full topic tree with memory counts. With topic_id: returns memories in that topic.",
213
+ inputSchema: {
214
+ type: "object",
215
+ properties: {
216
+ topic_id: {
217
+ type: "string",
218
+ description: "Topic ID to browse. Omit for full tree.",
219
+ },
220
+ hub_id: {
221
+ type: "string",
222
+ description: "Hub ID to scope topics.",
91
223
  },
92
224
  },
93
225
  },
@@ -100,25 +232,41 @@ function createServer() {
100
232
  case "memax_recall": {
101
233
  const typedArgs = args;
102
234
  try {
103
- const result = await apiPost("/v1/recall", {
104
- query: typedArgs.query,
105
- limit: typedArgs.limit ?? 5,
106
- category: typedArgs.category ?? "",
235
+ let hubId = getActiveHubID() || undefined;
236
+ if (typedArgs.hub_id) {
237
+ try {
238
+ hubId = await resolveHubReference(typedArgs.hub_id);
239
+ }
240
+ catch {
241
+ // Invalid hub ref — fall back to active hub (hub_id is a ranking boost, not a gate)
242
+ }
243
+ }
244
+ const result = await getClient().recall(typedArgs.query, {
245
+ limit: typedArgs.limit ?? 10,
246
+ topicId: typedArgs.topic_id,
107
247
  source: "mcp",
108
- working_dir: process.cwd(),
248
+ workingDir: process.cwd(),
249
+ projectContext: typedArgs.project_context,
250
+ hubId,
109
251
  });
110
- const notes = result.notes ?? [];
111
- if (notes.length === 0) {
252
+ const memories = result.memories ?? [];
253
+ if (memories.length === 0) {
112
254
  return {
113
255
  content: [{ type: "text", text: "No results found." }],
114
256
  };
115
257
  }
116
- const formatted = notes
117
- .map((n, i) => {
118
- const score = (n.relevance_score * 100).toFixed(0);
119
- const heading = n.heading_chain ? ` — ${n.heading_chain}` : "";
120
- return (`[${i + 1}] ${n.title} [${n.category}, ${score}%, ${n.age}] (id: ${n.id})${heading}\n` +
121
- n.chunk_content);
258
+ const formatted = memories
259
+ .map((m, i) => {
260
+ const score = (m.relevance_score * 100).toFixed(0);
261
+ const heading = m.heading_chain ? ` — ${m.heading_chain}` : "";
262
+ const parts = [
263
+ `[${i + 1}] ${m.title} [${memoryClassification(m)}, ${score}%, ${m.age}] (id: ${m.id})${heading}`,
264
+ ];
265
+ if (m.summary) {
266
+ parts.push(`Summary: ${m.summary}`);
267
+ }
268
+ parts.push(`Relevant excerpt:\n${m.chunk_content}`);
269
+ return parts.join("\n");
122
270
  })
123
271
  .join("\n\n");
124
272
  return { content: [{ type: "text", text: formatted }] };
@@ -138,18 +286,22 @@ function createServer() {
138
286
  case "memax_push": {
139
287
  const typedArgs = args;
140
288
  try {
141
- const note = await apiPost("/v1/notes", {
142
- content: typedArgs.content,
289
+ const memory = await getClient().push(typedArgs.content, {
143
290
  title: typedArgs.title ?? "",
144
- category: typedArgs.category ?? "",
291
+ hint: typedArgs.hint ?? "",
145
292
  tags: typedArgs.tags ?? [],
146
293
  source: "mcp",
294
+ sourceAgent: agentId,
295
+ initiationType: typedArgs.initiation_type ?? undefined,
296
+ projectContext: typedArgs.project_context,
297
+ hubId: typedArgs.hub_id,
298
+ hubReason: typedArgs.hub_reason,
147
299
  });
148
300
  return {
149
301
  content: [
150
302
  {
151
303
  type: "text",
152
- text: `Saved: ${note.title} (id: ${note.id})`,
304
+ text: `Saved: ${memory.title} (id: ${memory.id})`,
153
305
  },
154
306
  ],
155
307
  };
@@ -169,21 +321,21 @@ function createServer() {
169
321
  case "memax_get": {
170
322
  const typedArgs = args;
171
323
  try {
172
- const note = await apiGet(`/v1/notes/${typedArgs.id}`);
324
+ const memory = await getClient().memories.get(typedArgs.id);
173
325
  const parts = [
174
- `# ${note.title}`,
175
- `Category: ${note.category} | Source: ${note.source} | Created: ${note.created_at}`,
326
+ `# ${memory.title}`,
327
+ `Classification: ${memoryClassification(memory)} | Source: ${memory.source} | Created: ${memory.created_at}`,
176
328
  ];
177
- if (note.tags?.length > 0) {
178
- parts.push(`Tags: ${note.tags.join(", ")}`);
329
+ if (memory.tags?.length > 0) {
330
+ parts.push(`Tags: ${memory.tags.join(", ")}`);
179
331
  }
180
- if (note.source_path) {
181
- parts.push(`Source: ${note.source_path}`);
332
+ if (memory.source_path) {
333
+ parts.push(`Source: ${memory.source_path}`);
182
334
  }
183
- if (note.summary) {
184
- parts.push(`\n## Summary\n${note.summary}`);
335
+ if (memory.summary) {
336
+ parts.push(`\n## Summary\n${memory.summary}`);
185
337
  }
186
- parts.push(`\n## Content\n${note.content}`);
338
+ parts.push(`\n## Content\n${memory.content}`);
187
339
  return {
188
340
  content: [{ type: "text", text: parts.join("\n") }],
189
341
  };
@@ -200,23 +352,41 @@ function createServer() {
200
352
  };
201
353
  }
202
354
  }
203
- case "memax_search": {
355
+ case "memax_list": {
204
356
  const typedArgs = args;
205
357
  try {
206
- const notes = (await apiGet("/v1/notes")) ?? [];
207
- let filtered = notes;
208
- if (typedArgs.category) {
209
- filtered = notes.filter((n) => n.category.startsWith(typedArgs.category));
358
+ let hubId;
359
+ if (typedArgs.hub_id) {
360
+ hubId = await resolveHubReference(typedArgs.hub_id);
210
361
  }
211
- const limited = filtered.slice(0, typedArgs.limit ?? 10);
212
- if (limited.length === 0) {
362
+ const res = await getClient().memories.list({
363
+ limit: typedArgs.limit ?? 20,
364
+ cursor: typedArgs.cursor,
365
+ sort: typedArgs.sort,
366
+ hubId,
367
+ topicId: typedArgs.topic_id,
368
+ });
369
+ const memories = res.memories ?? [];
370
+ const total = res.total ?? 0;
371
+ const nextCursor = res.next_cursor ?? "";
372
+ const hasMore = res.has_more ?? false;
373
+ if (memories.length === 0) {
213
374
  return {
214
- content: [{ type: "text", text: "No notes found." }],
375
+ content: [
376
+ {
377
+ type: "text",
378
+ text: `No memories found. (${total} total in workspace)`,
379
+ },
380
+ ],
215
381
  };
216
382
  }
217
- const formatted = limited
218
- .map((n) => `- ${n.title} [${n.category}] — ${n.source} (id: ${n.id})`)
383
+ let formatted = memories
384
+ .map((m) => `- ${m.title} [${memoryClassification(m)}] — ${m.source} (id: ${m.id})`)
219
385
  .join("\n");
386
+ formatted += `\n\nShowing ${memories.length} of ${total} total.`;
387
+ if (hasMore) {
388
+ formatted += ` More available — pass cursor: "${nextCursor}" to get next page.`;
389
+ }
220
390
  return { content: [{ type: "text", text: formatted }] };
221
391
  }
222
392
  catch (err) {
@@ -224,7 +394,202 @@ function createServer() {
224
394
  content: [
225
395
  {
226
396
  type: "text",
227
- text: `Search failed: ${err.message}`,
397
+ text: `List failed: ${err.message}`,
398
+ },
399
+ ],
400
+ isError: true,
401
+ };
402
+ }
403
+ }
404
+ case "memax_hubs": {
405
+ try {
406
+ const hubs = await getClient().hubs.list();
407
+ if (hubs.length === 0) {
408
+ return {
409
+ content: [{ type: "text", text: "No hubs found." }],
410
+ };
411
+ }
412
+ const activeHubID = getActiveHubID();
413
+ const text = hubs
414
+ .map(({ hub, role, memory_count }) => {
415
+ const active = hub.id === activeHubID ? " active" : "";
416
+ return `- **${hub.name}** (${hub.hub_type}, ${role}${active}) ref: ${getHubReference(hub)} id: ${hub.id} memories: ${memory_count}`;
417
+ })
418
+ .join("\n");
419
+ return { content: [{ type: "text", text }] };
420
+ }
421
+ catch (err) {
422
+ return {
423
+ content: [
424
+ {
425
+ type: "text",
426
+ text: `Hubs failed: ${err.message}`,
427
+ },
428
+ ],
429
+ isError: true,
430
+ };
431
+ }
432
+ }
433
+ case "memax_hub_members": {
434
+ const typedArgs = args;
435
+ try {
436
+ const hubID = await resolveHubReference(typedArgs.hub_id);
437
+ const result = await getClient().hubs.get(hubID);
438
+ const members = result.members ?? [];
439
+ let text = `## ${result.hub.name} members\n\n`;
440
+ if (members.length === 0) {
441
+ text += "No members found.";
442
+ }
443
+ else {
444
+ text += members
445
+ .map((member) => {
446
+ const email = member.user_email
447
+ ? ` <${member.user_email}>`
448
+ : "";
449
+ return `- **${memberDisplayName(member)}**${email} [${member.role}] joined: ${member.joined_at}`;
450
+ })
451
+ .join("\n");
452
+ }
453
+ return { content: [{ type: "text", text }] };
454
+ }
455
+ catch (err) {
456
+ return {
457
+ content: [
458
+ {
459
+ type: "text",
460
+ text: `Hub members failed: ${err.message}`,
461
+ },
462
+ ],
463
+ isError: true,
464
+ };
465
+ }
466
+ }
467
+ case "memax_forget": {
468
+ const typedArgs = args;
469
+ if (!typedArgs.id) {
470
+ return {
471
+ content: [
472
+ { type: "text", text: "Memory ID is required." },
473
+ ],
474
+ isError: true,
475
+ };
476
+ }
477
+ try {
478
+ await getClient().memories.delete(typedArgs.id);
479
+ return {
480
+ content: [
481
+ {
482
+ type: "text",
483
+ text: `Forgotten: ${typedArgs.id}`,
484
+ },
485
+ ],
486
+ };
487
+ }
488
+ catch (err) {
489
+ return {
490
+ content: [
491
+ {
492
+ type: "text",
493
+ text: `Forget failed: ${err.message}`,
494
+ },
495
+ ],
496
+ isError: true,
497
+ };
498
+ }
499
+ }
500
+ case "memax_capture": {
501
+ const typedArgs = args;
502
+ if (!typedArgs.summary) {
503
+ return {
504
+ content: [{ type: "text", text: "Summary is required." }],
505
+ isError: true,
506
+ };
507
+ }
508
+ // Build structured content for the extraction pipeline
509
+ let content = `## Session Summary\n${typedArgs.summary}\n`;
510
+ if (typedArgs.decisions?.length) {
511
+ content += `\n## Decisions Made\n${typedArgs.decisions.map((d) => `- ${d}`).join("\n")}\n`;
512
+ }
513
+ if (typedArgs.learnings?.length) {
514
+ content += `\n## Learnings\n${typedArgs.learnings.map((l) => `- ${l}`).join("\n")}\n`;
515
+ }
516
+ try {
517
+ const memory = await getClient().push(content, {
518
+ title: `Session capture — ${new Date().toLocaleDateString()}`,
519
+ contentType: "transcript",
520
+ source: "mcp/capture",
521
+ sourceAgent: agentId,
522
+ initiationType: "agent_automatic",
523
+ });
524
+ return {
525
+ content: [
526
+ {
527
+ type: "text",
528
+ text: `Session captured (id: ${memory.id}). Key facts will be extracted and stored as separate memories.`,
529
+ },
530
+ ],
531
+ };
532
+ }
533
+ catch (err) {
534
+ return {
535
+ content: [
536
+ {
537
+ type: "text",
538
+ text: `Capture failed: ${err.message}`,
539
+ },
540
+ ],
541
+ isError: true,
542
+ };
543
+ }
544
+ }
545
+ case "memax_topics": {
546
+ const typedArgs = args;
547
+ try {
548
+ if (typedArgs.topic_id) {
549
+ // Browse specific topic's memories
550
+ const res = await getClient().topics.listMemories(typedArgs.topic_id);
551
+ const topic = await getClient().topics.get(typedArgs.topic_id);
552
+ const memories = res.memories ?? [];
553
+ let text = `## ${topic.name} (${memories.length} memories)\n\n`;
554
+ for (const [i, m] of memories.entries()) {
555
+ text += `${i + 1}. **${m.title}** [${memoryClassification(m)}] (id: ${m.id})\n`;
556
+ if (m.summary)
557
+ text += ` ${m.summary}\n`;
558
+ }
559
+ if (memories.length === 0)
560
+ text += "No memories in this topic yet.\n";
561
+ return { content: [{ type: "text", text }] };
562
+ }
563
+ // Full topic tree
564
+ const res = await getClient().topics.list(typedArgs.hub_id);
565
+ const topics = res.topics ?? [];
566
+ let text = "## Topics\n\n";
567
+ if (topics.length === 0) {
568
+ text +=
569
+ "No topics yet. Push memories and run a dream cycle to auto-organize.\n";
570
+ }
571
+ else {
572
+ for (const t of topics) {
573
+ const indent = t.parent_id ? " " : "";
574
+ text += `${indent}- **${t.name}** (${t.memory_count} memories) [id: ${t.id}]\n`;
575
+ if (t.description)
576
+ text += `${indent} ${t.description}\n`;
577
+ for (const child of t.children) {
578
+ text += ` - **${child.name}** (${child.memory_count} memories) [id: ${child.id}]\n`;
579
+ }
580
+ }
581
+ }
582
+ if (res.unassigned_count > 0) {
583
+ text += `\nšŸ“„ **Inbox**: ${res.unassigned_count} unassigned memories\n`;
584
+ }
585
+ return { content: [{ type: "text", text }] };
586
+ }
587
+ catch (err) {
588
+ return {
589
+ content: [
590
+ {
591
+ type: "text",
592
+ text: `Topics failed: ${err.message}`,
228
593
  },
229
594
  ],
230
595
  isError: true,
@@ -240,8 +605,9 @@ function createServer() {
240
605
  });
241
606
  return server;
242
607
  }
243
- async function mcpServeCommand() {
244
- const server = createServer();
608
+ async function mcpServeCommand(options) {
609
+ setClientAgent(options.agent);
610
+ const server = createServer(options.agent ?? "");
245
611
  const transport = new StdioServerTransport();
246
612
  await server.connect(transport);
247
613
  // Keep the process alive — some agent launchers close stdin early
@@ -261,6 +627,7 @@ export function registerMcpCommand(program) {
261
627
  mcp
262
628
  .command("serve")
263
629
  .description("Start MCP server on stdio")
630
+ .option("--agent <name>", "Agent identity (e.g., claude-code, cursor)")
264
631
  .action(mcpServeCommand);
265
632
  }
266
633
  //# sourceMappingURL=mcp.js.map