@codemem/mcp 0.30.0-alpha.2 → 0.30.0-alpha.4

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/index.js CHANGED
@@ -6,6 +6,44 @@ import { MemoryStore, VERSION, dedupeOrderedIds, projectMatchesFilter, resolveDb
6
6
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
8
  import { z } from "zod";
9
+ //#region src/memory-access.ts
10
+ function getMemoryForMcp(store, memoryId, filters) {
11
+ return store.timeline(null, memoryId, 0, 0, filters ?? null).find((row) => row.id === memoryId) ?? null;
12
+ }
13
+ function getManyForMcp(store, ids, filters) {
14
+ if (ids.length === 0) return [];
15
+ const results = [];
16
+ for (const id of ids) {
17
+ const item = getMemoryForMcp(store, id, filters);
18
+ if (item) results.push(item);
19
+ }
20
+ return results;
21
+ }
22
+ function forgetMemoryForMcp(store, memoryId, filters) {
23
+ if (!getMemoryForMcp(store, memoryId, filters)) return false;
24
+ store.forget(memoryId);
25
+ return true;
26
+ }
27
+ function rememberMemoryForMcp(store, input, context = {}) {
28
+ return store.db.transaction(() => {
29
+ const now = context.now?.() ?? (/* @__PURE__ */ new Date()).toISOString();
30
+ const user = context.user ?? process.env.USER ?? "unknown";
31
+ const cwd = context.cwd ?? process.cwd();
32
+ const project = input.project ?? context.envProject ?? null;
33
+ const sessionInfo = store.db.prepare(`INSERT INTO sessions(started_at, ended_at, cwd, project, user, tool_version, metadata_json)
34
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(now, now, cwd, project, user, "mcp-ts", toJson({ mcp: true }));
35
+ const sessionId = Number(sessionInfo.lastInsertRowid);
36
+ const memId = store.remember(sessionId, input.kind, input.title, input.body, input.confidence);
37
+ if (!getMemoryForMcp(store, memId)) throw new Error("unauthorized_scope");
38
+ store.db.prepare("UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?").run(context.now?.() ?? (/* @__PURE__ */ new Date()).toISOString(), toJson({ mcp: true }), sessionId);
39
+ return {
40
+ memId,
41
+ title: input.title,
42
+ body: input.body
43
+ };
44
+ })();
45
+ }
46
+ //#endregion
9
47
  //#region src/project-scope.ts
10
48
  function resolveDefaultProject() {
11
49
  return process.env.CODEMEM_PROJECT?.trim() || resolveProject(process.cwd());
@@ -21,6 +59,9 @@ function buildFilters(raw, defaultProject = resolveDefaultProject()) {
21
59
  for (const key of [
22
60
  "kind",
23
61
  "visibility",
62
+ "scope_id",
63
+ "include_scope_ids",
64
+ "exclude_scope_ids",
24
65
  "include_visibility",
25
66
  "exclude_visibility",
26
67
  "include_workspace_ids",
@@ -65,9 +106,15 @@ var MEMORY_KINDS = {
65
106
  decision: "A design or architecture decision",
66
107
  exploration: "An experiment or investigation (may not have shipped)"
67
108
  };
109
+ var scopeFilterSchema = {
110
+ scope_id: z.string().optional().describe("Filter by a single sharing domain scope_id"),
111
+ include_scope_ids: z.array(z.string()).optional().describe("Sharing domain scope_ids to include"),
112
+ exclude_scope_ids: z.array(z.string()).optional().describe("Sharing domain scope_ids to exclude")
113
+ };
68
114
  var filterSchema = {
69
115
  kind: z.string().optional().describe("Filter by memory kind"),
70
116
  project: z.string().optional().describe("Filter by project scope (matches sessions.project)"),
117
+ ...scopeFilterSchema,
71
118
  visibility: z.array(z.string()).optional(),
72
119
  include_visibility: z.array(z.string()).optional(),
73
120
  exclude_visibility: z.array(z.string()).optional(),
@@ -101,23 +148,6 @@ function errorContent(message) {
101
148
  text: JSON.stringify({ error: message })
102
149
  }] };
103
150
  }
104
- /** ISO timestamp. */
105
- function nowIso() {
106
- return (/* @__PURE__ */ new Date()).toISOString();
107
- }
108
- /**
109
- * Fetch multiple memory items by ID. Returns items in ID order, skipping
110
- * missing IDs. Implemented directly since MemoryStore doesn't have getMany.
111
- */
112
- function getMany(store, ids) {
113
- if (ids.length === 0) return [];
114
- const results = [];
115
- for (const id of ids) {
116
- const item = store.get(id);
117
- if (item) results.push(item);
118
- }
119
- return results;
120
- }
121
151
  /** Default viewer host/port for health checks. */
122
152
  var VIEWER_HOST = process.env.CODEMEM_VIEWER_HOST ?? "127.0.0.1";
123
153
  var VIEWER_PORT = process.env.CODEMEM_VIEWER_PORT ?? "38888";
@@ -256,11 +286,11 @@ async function main() {
256
286
  depth_before: z.number().int().min(0).default(3).describe("Timeline items before"),
257
287
  depth_after: z.number().int().min(0).default(3).describe("Timeline items after"),
258
288
  include_observations: z.boolean().default(false).describe("Include full observation details"),
259
- project: z.string().optional().describe("Project scope filter")
289
+ ...filterSchema
260
290
  }, async (args) => {
261
291
  try {
262
- const resolvedProject = args.project !== void 0 ? args.project.trim() || null : defaultProject || null;
263
- const filters = resolvedProject ? { project: resolvedProject } : void 0;
292
+ const filters = buildFilters(args, args.project !== void 0 && !args.project.trim() ? null : defaultProject);
293
+ const resolvedProject = filters?.project ?? null;
264
294
  const { ordered: orderedIds, invalid: invalidIds } = dedupeOrderedIds(args.ids);
265
295
  const errors = [];
266
296
  if (invalidIds.length > 0) errors.push({
@@ -271,6 +301,7 @@ async function main() {
271
301
  });
272
302
  const missingNotFound = [];
273
303
  const missingProjectMismatch = [];
304
+ const missingFilterMismatch = [];
274
305
  const anchors = [];
275
306
  const timelineItems = [];
276
307
  const timelineSeen = /* @__PURE__ */ new Set();
@@ -295,8 +326,13 @@ async function main() {
295
326
  missingProjectMismatch.push(memoryId);
296
327
  continue;
297
328
  }
298
- anchors.push(item);
299
329
  const expanded = store.timeline(null, memoryId, args.depth_before, args.depth_after, filters);
330
+ const anchor = expanded.find((expandedItem) => expandedItem.id === memoryId);
331
+ if (!anchor) {
332
+ missingFilterMismatch.push(memoryId);
333
+ continue;
334
+ }
335
+ anchors.push(anchor);
300
336
  for (const expandedItem of expanded) {
301
337
  const expandedId = expandedItem.id;
302
338
  if (expandedId <= 0 || timelineSeen.has(expandedId)) continue;
@@ -316,6 +352,12 @@ async function main() {
316
352
  message: "some requested ids are outside the requested project scope",
317
353
  ids: missingProjectMismatch
318
354
  });
355
+ if (missingFilterMismatch.length > 0) errors.push({
356
+ code: "FILTER_MISMATCH",
357
+ field: "filters",
358
+ message: "some requested ids are outside the requested filters",
359
+ ids: missingFilterMismatch
360
+ });
319
361
  let observations = [];
320
362
  if (args.include_observations) {
321
363
  const observationSeen = /* @__PURE__ */ new Set();
@@ -324,13 +366,13 @@ async function main() {
324
366
  observationSeen.add(item.id);
325
367
  observationIds.push(item.id);
326
368
  }
327
- observations = getMany(store, observationIds);
369
+ observations = getManyForMcp(store, observationIds, filters);
328
370
  }
329
371
  return jsonContent({
330
372
  anchors,
331
373
  timeline: timelineItems,
332
374
  observations,
333
- missing_ids: orderedIds.filter((memoryId) => missingNotFound.includes(memoryId) || missingProjectMismatch.includes(memoryId)),
375
+ missing_ids: orderedIds.filter((memoryId) => missingNotFound.includes(memoryId) || missingProjectMismatch.includes(memoryId) || missingFilterMismatch.includes(memoryId)),
334
376
  errors,
335
377
  metadata: {
336
378
  project: resolvedProject,
@@ -344,18 +386,24 @@ async function main() {
344
386
  return errorContent(err instanceof Error ? err.message : String(err));
345
387
  }
346
388
  });
347
- server.tool("memory_get", "Fetch a single memory item by ID.", { memory_id: z.number().int().describe("Memory ID") }, async (args) => {
389
+ server.tool("memory_get", "Fetch a single memory item by ID.", {
390
+ memory_id: z.number().int().describe("Memory ID"),
391
+ ...filterSchema
392
+ }, async (args) => {
348
393
  try {
349
- const item = store.get(args.memory_id);
394
+ const item = getMemoryForMcp(store, args.memory_id, buildFilters(args, null));
350
395
  if (!item) return errorContent("not_found");
351
396
  return jsonContent(item);
352
397
  } catch (err) {
353
398
  return errorContent(err instanceof Error ? err.message : String(err));
354
399
  }
355
400
  });
356
- server.tool("memory_get_observations", "Fetch multiple memory items by their IDs.", { ids: z.array(z.number().int()).max(200).describe("Memory IDs to fetch") }, async (args) => {
401
+ server.tool("memory_get_observations", "Fetch multiple memory items by their IDs.", {
402
+ ids: z.array(z.number().int()).max(200).describe("Memory IDs to fetch"),
403
+ ...filterSchema
404
+ }, async (args) => {
357
405
  try {
358
- return jsonContent({ items: getMany(store, args.ids) });
406
+ return jsonContent({ items: getManyForMcp(store, args.ids, buildFilters(args, null)) });
359
407
  } catch (err) {
360
408
  return errorContent(err instanceof Error ? err.message : String(err));
361
409
  }
@@ -405,22 +453,7 @@ async function main() {
405
453
  project: z.string().optional().describe("Project identifier")
406
454
  }, async (args) => {
407
455
  try {
408
- const result = store.db.transaction(() => {
409
- const now = nowIso();
410
- const user = process.env.USER ?? "unknown";
411
- const cwd = process.cwd();
412
- const project = args.project ?? process.env.CODEMEM_PROJECT ?? null;
413
- const sessionInfo = store.db.prepare(`INSERT INTO sessions(started_at, ended_at, cwd, project, user, tool_version, metadata_json)
414
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(now, now, cwd, project, user, "mcp-ts", toJson({ mcp: true }));
415
- const sessionId = Number(sessionInfo.lastInsertRowid);
416
- const memId = store.remember(sessionId, args.kind, args.title, args.body, args.confidence);
417
- store.db.prepare("UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?").run(nowIso(), toJson({ mcp: true }), sessionId);
418
- return {
419
- memId,
420
- title: args.title,
421
- body: args.body
422
- };
423
- })();
456
+ const result = rememberMemoryForMcp(store, args, { envProject: process.env.CODEMEM_PROJECT ?? null });
424
457
  try {
425
458
  await storeVectors(store.db, result.memId, result.title, result.body);
426
459
  } catch {}
@@ -429,9 +462,12 @@ async function main() {
429
462
  return errorContent(err instanceof Error ? err.message : String(err));
430
463
  }
431
464
  });
432
- server.tool("memory_forget", "Soft-delete a memory item. Use for incorrect or sensitive data.", { memory_id: z.number().int().describe("Memory ID to forget") }, async (args) => {
465
+ server.tool("memory_forget", "Soft-delete a memory item. Use for incorrect or sensitive data.", {
466
+ memory_id: z.number().int().describe("Memory ID to forget"),
467
+ ...filterSchema
468
+ }, async (args) => {
433
469
  try {
434
- store.forget(args.memory_id);
470
+ if (!forgetMemoryForMcp(store, args.memory_id, buildFilters(args, null))) return errorContent("not_found");
435
471
  return jsonContent({ status: "ok" });
436
472
  } catch (err) {
437
473
  return errorContent(err instanceof Error ? err.message : String(err));
@@ -457,6 +493,9 @@ async function main() {
457
493
  "session_id",
458
494
  "since",
459
495
  "project",
496
+ "scope_id",
497
+ "include_scope_ids",
498
+ "exclude_scope_ids",
460
499
  "include_actor_ids",
461
500
  "exclude_actor_ids",
462
501
  "include_visibility",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/project-scope.ts","../src/index.ts"],"sourcesContent":["import { type MemoryFilters, resolveProject } from \"@codemem/core\";\n\nexport function resolveDefaultProject(): string | null {\n\tconst project = process.env.CODEMEM_PROJECT?.trim();\n\treturn project || resolveProject(process.cwd());\n}\n\nexport function buildFilters(\n\traw: Record<string, unknown>,\n\tdefaultProject = resolveDefaultProject(),\n): MemoryFilters | undefined {\n\tconst filters: MemoryFilters = {};\n\tlet hasAny = false;\n\n\tconst explicitProject = typeof raw.project === \"string\" ? raw.project.trim() : undefined;\n\tconst resolvedProject = explicitProject || defaultProject || undefined;\n\tif (resolvedProject) {\n\t\tfilters.project = resolvedProject;\n\t\thasAny = true;\n\t}\n\n\tfor (const key of [\n\t\t\"kind\",\n\t\t\"visibility\",\n\t\t\"include_visibility\",\n\t\t\"exclude_visibility\",\n\t\t\"include_workspace_ids\",\n\t\t\"exclude_workspace_ids\",\n\t\t\"include_workspace_kinds\",\n\t\t\"exclude_workspace_kinds\",\n\t\t\"include_actor_ids\",\n\t\t\"exclude_actor_ids\",\n\t\t\"include_trust_states\",\n\t\t\"exclude_trust_states\",\n\t\t\"ownership_scope\",\n\t\t\"personal_first\",\n\t\t\"trust_bias\",\n\t\t\"widen_shared_when_weak\",\n\t\t\"widen_shared_min_personal_results\",\n\t\t\"widen_shared_min_personal_score\",\n\t] as const) {\n\t\tconst val = raw[key];\n\t\tif (val !== undefined && val !== null) {\n\t\t\t(filters as Record<string, unknown>)[key] = val;\n\t\t\thasAny = true;\n\t\t}\n\t}\n\n\treturn hasAny ? filters : undefined;\n}\n","#!/usr/bin/env node\n\n/**\n * @codemem/mcp — MCP stdio server.\n *\n * Runs as a separate process spawned by the host (OpenCode/Claude).\n * Owns its own better-sqlite3 connection. Communicates via stdio JSON-RPC.\n *\n * Port of codemem/mcp_server.py — all 13 tools.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tdedupeOrderedIds,\n\ttype MemoryItemResponse,\n\ttype MemoryResult,\n\tMemoryStore,\n\tprojectMatchesFilter,\n\tresolveDbPath,\n\tstoreVectors,\n\ttoJson,\n\tVERSION,\n} from \"@codemem/core\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { buildFilters, resolveDefaultProject } from \"./project-scope.js\";\n\n// ---------------------------------------------------------------------------\n// Static data\n// ---------------------------------------------------------------------------\n\nconst MEMORY_KINDS: Record<string, string> = {\n\tdiscovery: \"Something learned about the codebase, architecture, or tools\",\n\tchange: \"A code change that was made\",\n\tfeature: \"A new feature that was implemented\",\n\tbugfix: \"A bug that was found and fixed\",\n\trefactor: \"Code that was refactored or restructured\",\n\tdecision: \"A design or architecture decision\",\n\texploration: \"An experiment or investigation (may not have shipped)\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared zod filter schema (spread into each tool that accepts filters)\n// ---------------------------------------------------------------------------\n\nconst filterSchema = {\n\tkind: z.string().optional().describe(\"Filter by memory kind\"),\n\tproject: z.string().optional().describe(\"Filter by project scope (matches sessions.project)\"),\n\tvisibility: z.array(z.string()).optional(),\n\tinclude_visibility: z.array(z.string()).optional(),\n\texclude_visibility: z.array(z.string()).optional(),\n\tinclude_workspace_ids: z.array(z.string()).optional(),\n\texclude_workspace_ids: z.array(z.string()).optional(),\n\tinclude_workspace_kinds: z.array(z.string()).optional(),\n\texclude_workspace_kinds: z.array(z.string()).optional(),\n\tinclude_actor_ids: z.array(z.string()).optional(),\n\texclude_actor_ids: z.array(z.string()).optional(),\n\tinclude_trust_states: z.array(z.string()).optional(),\n\texclude_trust_states: z.array(z.string()).optional(),\n\townership_scope: z.string().optional(),\n\tpersonal_first: z.union([z.boolean(), z.string()]).optional(),\n\ttrust_bias: z.string().optional(),\n\twiden_shared_when_weak: z.union([z.boolean(), z.string()]).optional(),\n\twiden_shared_min_personal_results: z.number().int().optional(),\n\twiden_shared_min_personal_score: z.number().optional(),\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst defaultProject = resolveDefaultProject();\n\n/** Wrap a JSON result into the MCP text content envelope. */\nfunction jsonContent(data: unknown) {\n\treturn { content: [{ type: \"text\" as const, text: JSON.stringify(data) }] };\n}\n\n/** Wrap an error message into the MCP text content envelope. */\nfunction errorContent(message: string) {\n\treturn { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }] };\n}\n\n/** ISO timestamp. */\nfunction nowIso(): string {\n\treturn new Date().toISOString();\n}\n\n/**\n * Fetch multiple memory items by ID. Returns items in ID order, skipping\n * missing IDs. Implemented directly since MemoryStore doesn't have getMany.\n */\nfunction getMany(store: MemoryStore, ids: number[]): MemoryItemResponse[] {\n\tif (ids.length === 0) return [];\n\tconst results: MemoryItemResponse[] = [];\n\tfor (const id of ids) {\n\t\tconst item = store.get(id);\n\t\tif (item) results.push(item);\n\t}\n\treturn results;\n}\n\n// ---------------------------------------------------------------------------\n// Viewer autostart\n// ---------------------------------------------------------------------------\n\n/** Default viewer host/port for health checks. */\nconst VIEWER_HOST = process.env.CODEMEM_VIEWER_HOST ?? \"127.0.0.1\";\nconst VIEWER_PORT = process.env.CODEMEM_VIEWER_PORT ?? \"38888\";\n\n/** Resolve the `codemem` CLI binary path. Checks package-local paths first, then PATH. */\nfunction resolveCliPath(): string | null {\n\t// When installed via npm/npx, the MCP server and CLI share node_modules.\n\t// Walk up from this file to find the CLI's bin entry.\n\tconst candidates: string[] = [];\n\tconst selfDir = dirname(import.meta.dirname ?? \".\");\n\t// Monorepo dev: sibling package\n\tcandidates.push(join(selfDir, \"..\", \"cli\", \"dist\", \"index.js\"));\n\t// npm install: node_modules/.bin/codemem\n\tcandidates.push(join(selfDir, \"..\", \".bin\", \"codemem\"));\n\t// npm install: deeper node_modules\n\tcandidates.push(join(selfDir, \"..\", \"..\", \".bin\", \"codemem\"));\n\tfor (const p of candidates) {\n\t\tif (existsSync(p)) return p;\n\t}\n\t// Fall back to PATH\n\treturn \"codemem\";\n}\n\n/** Check if the viewer is already running. */\nasync function isViewerHealthy(): Promise<boolean> {\n\ttry {\n\t\tconst url = `http://${VIEWER_HOST}:${VIEWER_PORT}/api/health`;\n\t\tconst response = await fetch(url, { signal: AbortSignal.timeout(2_000) });\n\t\treturn response.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Attempt to start the viewer server as a detached background process.\n * Best-effort: failures are logged to stderr but never block MCP startup.\n */\nasync function ensureViewer(): Promise<void> {\n\tif (process.env.CODEMEM_VIEWER === \"0\" || process.env.CODEMEM_VIEWER_AUTO === \"0\") return;\n\n\tif (await isViewerHealthy()) return;\n\n\tconst cli = resolveCliPath();\n\tif (!cli) return;\n\n\ttry {\n\t\t// If the resolved path is a .js file, run it with node.\n\t\t// Otherwise it's a bin script that can run directly.\n\t\tconst isJsFile = cli.endsWith(\".js\");\n\t\tconst cmd = isJsFile ? process.execPath : cli;\n\t\tconst args = isJsFile ? [cli, \"serve\", \"start\"] : [\"serve\", \"start\"];\n\t\t// Pass non-default host/port so the spawned viewer matches what we health-check.\n\t\tif (VIEWER_HOST !== \"127.0.0.1\") args.push(\"--host\", VIEWER_HOST);\n\t\tif (VIEWER_PORT !== \"38888\") args.push(\"--port\", VIEWER_PORT);\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tdetached: true,\n\t\t\tstdio: \"ignore\",\n\t\t\tenv: { ...process.env, CODEMEM_PLUGIN_IGNORE: \"1\" },\n\t\t});\n\t\tchild.on(\"error\", () => {}); // swallow — best effort\n\t\tchild.unref();\n\n\t\t// Brief health check loop — don't block for long\n\t\tfor (let i = 0; i < 5; i++) {\n\t\t\tawait new Promise((r) => setTimeout(r, 1_000));\n\t\t\tif (await isViewerHealthy()) return;\n\t\t}\n\t} catch {\n\t\t// Best effort — MCP server continues regardless\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Server bootstrap\n// ---------------------------------------------------------------------------\n\nasync function main() {\n\tconst dbPath = resolveDbPath();\n\tconst store = new MemoryStore(dbPath);\n\n\t// Auto-start viewer in background (belt and suspenders with any hook-based start)\n\tensureViewer().catch(() => {});\n\n\tconst server = new McpServer({ name: \"codemem\", version: VERSION });\n\n\t// -------------------------------------------------------------------\n\t// 1. memory_search\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_search\",\n\t\t\"Search memories by text query. Returns full body text for each match.\",\n\t\t{\n\t\t\tquery: z.string().describe(\"Search query\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(5).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.search(args.query, args.limit, filters);\n\t\t\t\treturn jsonContent({\n\t\t\t\t\titems: items.map((m: MemoryResult) => ({\n\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\ttitle: m.title,\n\t\t\t\t\t\tkind: m.kind,\n\t\t\t\t\t\tbody: m.body_text,\n\t\t\t\t\t\tconfidence: m.confidence,\n\t\t\t\t\t\tscore: m.score,\n\t\t\t\t\t\tsession_id: m.session_id,\n\t\t\t\t\t\tmetadata: m.metadata,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 2. memory_search_index\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_search_index\",\n\t\t\"Search memories by text query. Returns compact index entries (no body) for browsing.\",\n\t\t{\n\t\t\tquery: z.string().describe(\"Search query\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(8).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.search(args.query, args.limit, filters);\n\t\t\t\treturn jsonContent({\n\t\t\t\t\titems: items.map((m: MemoryResult) => ({\n\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\tkind: m.kind,\n\t\t\t\t\t\ttitle: m.title,\n\t\t\t\t\t\tscore: m.score,\n\t\t\t\t\t\tcreated_at: m.created_at,\n\t\t\t\t\t\tsession_id: m.session_id,\n\t\t\t\t\t\tmetadata: m.metadata,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 3. memory_timeline\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_timeline\",\n\t\t\"Get a chronological window of memories around an anchor (by ID or query).\",\n\t\t{\n\t\t\tquery: z.string().optional().describe(\"Search query to find anchor\"),\n\t\t\tmemory_id: z.number().int().optional().describe(\"Anchor memory ID\"),\n\t\t\tdepth_before: z.number().int().min(0).default(3).describe(\"Items before anchor\"),\n\t\t\tdepth_after: z.number().int().min(0).default(3).describe(\"Items after anchor\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.timeline(\n\t\t\t\t\targs.query ?? null,\n\t\t\t\t\targs.memory_id ?? null,\n\t\t\t\t\targs.depth_before,\n\t\t\t\t\targs.depth_after,\n\t\t\t\t\tfilters,\n\t\t\t\t);\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 4. memory_explain\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_explain\",\n\t\t\"Explain search results with detailed scoring breakdown.\",\n\t\t{\n\t\t\tquery: z.string().optional().describe(\"Search query\"),\n\t\t\tids: z.array(z.number().int()).max(200).optional().describe(\"Specific memory IDs to explain\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(10).describe(\"Max results\"),\n\t\t\tinclude_pack_context: z.boolean().default(false).describe(\"Include formatted pack context\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst result = store.explain(args.query ?? null, args.ids ?? null, args.limit, filters, {\n\t\t\t\t\tincludePackContext: args.include_pack_context,\n\t\t\t\t});\n\t\t\t\treturn jsonContent(result);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 5. memory_expand\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_expand\",\n\t\t\"Fetch memories by ID with surrounding timeline context.\",\n\t\t{\n\t\t\tids: z\n\t\t\t\t.array(z.union([z.number(), z.string()]))\n\t\t\t\t.max(200)\n\t\t\t\t.describe(\"Memory IDs to expand\"),\n\t\t\tdepth_before: z.number().int().min(0).default(3).describe(\"Timeline items before\"),\n\t\t\tdepth_after: z.number().int().min(0).default(3).describe(\"Timeline items after\"),\n\t\t\tinclude_observations: z.boolean().default(false).describe(\"Include full observation details\"),\n\t\t\tproject: z.string().optional().describe(\"Project scope filter\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\t// Python: project if project is not None else default_project\n\t\t\t\t// Explicit \"\" clears project scoping; only fall back to default when undefined.\n\t\t\t\tconst resolvedProject =\n\t\t\t\t\targs.project !== undefined ? args.project.trim() || null : defaultProject || null;\n\t\t\t\tconst filters = resolvedProject ? { project: resolvedProject } : undefined;\n\t\t\t\tconst { ordered: orderedIds, invalid: invalidIds } = dedupeOrderedIds(args.ids);\n\t\t\t\tconst errors: Array<Record<string, unknown>> = [];\n\n\t\t\t\tif (invalidIds.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"INVALID_ARGUMENT\",\n\t\t\t\t\t\tfield: \"ids\",\n\t\t\t\t\t\tmessage: \"some ids are not valid integers\",\n\t\t\t\t\t\tids: invalidIds,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst missingNotFound: number[] = [];\n\t\t\t\tconst missingProjectMismatch: number[] = [];\n\t\t\t\tconst anchors: MemoryItemResponse[] = [];\n\t\t\t\tconst timelineItems: MemoryItemResponse[] = [];\n\t\t\t\tconst timelineSeen = new Set<number>();\n\t\t\t\tconst sessionProjects = new Map<number, string | null>();\n\n\t\t\t\tfor (const memoryId of orderedIds) {\n\t\t\t\t\tconst item = store.get(memoryId);\n\t\t\t\t\tif (!item?.active) {\n\t\t\t\t\t\tmissingNotFound.push(memoryId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst sessionId = item.session_id;\n\t\t\t\t\tif (resolvedProject && sessionId > 0) {\n\t\t\t\t\t\tif (!sessionProjects.has(sessionId)) {\n\t\t\t\t\t\t\tconst row = store.db\n\t\t\t\t\t\t\t\t.prepare(\"SELECT project FROM sessions WHERE id = ? LIMIT 1\")\n\t\t\t\t\t\t\t\t.get(sessionId) as { project: string | null } | undefined;\n\t\t\t\t\t\t\tsessionProjects.set(sessionId, typeof row?.project === \"string\" ? row.project : null);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!projectMatchesFilter(resolvedProject, sessionProjects.get(sessionId) ?? null)) {\n\t\t\t\t\t\t\tmissingProjectMismatch.push(memoryId);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (resolvedProject && sessionId <= 0) {\n\t\t\t\t\t\tmissingProjectMismatch.push(memoryId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tanchors.push(item);\n\n\t\t\t\t\tconst expanded = store.timeline(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tmemoryId,\n\t\t\t\t\t\targs.depth_before,\n\t\t\t\t\t\targs.depth_after,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t);\n\t\t\t\t\tfor (const expandedItem of expanded) {\n\t\t\t\t\t\tconst expandedId = expandedItem.id;\n\t\t\t\t\t\tif (expandedId <= 0 || timelineSeen.has(expandedId)) continue;\n\t\t\t\t\t\ttimelineSeen.add(expandedId);\n\t\t\t\t\t\ttimelineItems.push(expandedItem);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (missingNotFound.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\t\tfield: \"ids\",\n\t\t\t\t\t\tmessage: \"some requested ids were not found\",\n\t\t\t\t\t\tids: missingNotFound,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (missingProjectMismatch.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"PROJECT_MISMATCH\",\n\t\t\t\t\t\tfield: \"project\",\n\t\t\t\t\t\tmessage: \"some requested ids are outside the requested project scope\",\n\t\t\t\t\t\tids: missingProjectMismatch,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Collect full observations if requested\n\t\t\t\tlet observations: MemoryItemResponse[] = [];\n\t\t\t\tif (args.include_observations) {\n\t\t\t\t\tconst observationSeen = new Set<number>();\n\t\t\t\t\tconst observationIds: number[] = [];\n\t\t\t\t\tfor (const item of [...anchors, ...timelineItems]) {\n\t\t\t\t\t\tif (item.id > 0 && !observationSeen.has(item.id)) {\n\t\t\t\t\t\t\tobservationSeen.add(item.id);\n\t\t\t\t\t\t\tobservationIds.push(item.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tobservations = getMany(store, observationIds);\n\t\t\t\t}\n\n\t\t\t\treturn jsonContent({\n\t\t\t\t\tanchors,\n\t\t\t\t\ttimeline: timelineItems,\n\t\t\t\t\tobservations,\n\t\t\t\t\tmissing_ids: orderedIds.filter(\n\t\t\t\t\t\t(memoryId: number) =>\n\t\t\t\t\t\t\tmissingNotFound.includes(memoryId) || missingProjectMismatch.includes(memoryId),\n\t\t\t\t\t),\n\t\t\t\t\terrors,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tproject: resolvedProject,\n\t\t\t\t\t\trequested_ids_count: orderedIds.length,\n\t\t\t\t\t\treturned_anchor_count: anchors.length,\n\t\t\t\t\t\ttimeline_count: timelineItems.length,\n\t\t\t\t\t\tinclude_observations: args.include_observations,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 6. memory_get\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_get\",\n\t\t\"Fetch a single memory item by ID.\",\n\t\t{\n\t\t\tmemory_id: z.number().int().describe(\"Memory ID\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst item = store.get(args.memory_id);\n\t\t\t\tif (!item) return errorContent(\"not_found\");\n\t\t\t\treturn jsonContent(item);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 7. memory_get_observations\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_get_observations\",\n\t\t\"Fetch multiple memory items by their IDs.\",\n\t\t{\n\t\t\tids: z.array(z.number().int()).max(200).describe(\"Memory IDs to fetch\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst items = getMany(store, args.ids);\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 8. memory_recent\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_recent\",\n\t\t\"Return recent memories, newest first.\",\n\t\t{\n\t\t\tlimit: z.number().int().min(1).max(100).default(8).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.recent(args.limit, filters);\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 9. memory_pack\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_pack\",\n\t\t\"Build a formatted memory pack from search results — quick one-shot context block.\",\n\t\t{\n\t\t\tcontext: z.string().describe(\"Context description to search for\"),\n\t\t\tlimit: z.number().int().min(1).max(50).optional().describe(\"Max items to include\"),\n\t\t\tcompact: z\n\t\t\t\t.boolean()\n\t\t\t\t.optional()\n\t\t\t\t.describe(\n\t\t\t\t\t\"When true, render a scannable index of all items with full detail only for the top N (default 3). Saves tokens when broad overview matters more than per-item detail.\",\n\t\t\t\t),\n\t\t\tcompact_detail_count: z\n\t\t\t\t.number()\n\t\t\t\t.int()\n\t\t\t\t.min(0)\n\t\t\t\t.max(50)\n\t\t\t\t.optional()\n\t\t\t\t.describe(\"Number of items to show in full detail in compact mode (default 3)\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst renderOptions =\n\t\t\t\t\targs.compact || args.compact_detail_count != null\n\t\t\t\t\t\t? { compact: args.compact ?? true, compactDetailCount: args.compact_detail_count }\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst result = await store.buildMemoryPackAsync(\n\t\t\t\t\targs.context,\n\t\t\t\t\targs.limit ?? undefined,\n\t\t\t\t\tnull,\n\t\t\t\t\tfilters,\n\t\t\t\t\trenderOptions,\n\t\t\t\t);\n\t\t\t\treturn jsonContent(result);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 10. memory_remember\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_remember\",\n\t\t\"Create a new memory. Use for milestones, decisions, and notable facts.\",\n\t\t{\n\t\t\tkind: z\n\t\t\t\t.enum([\"discovery\", \"change\", \"feature\", \"bugfix\", \"refactor\", \"decision\", \"exploration\"])\n\t\t\t\t.describe(\"Memory kind\"),\n\t\t\ttitle: z.string().describe(\"Short title\"),\n\t\t\tbody: z.string().describe(\"Body text (high-signal content)\"),\n\t\t\tconfidence: z.number().min(0).max(1).default(0.5).describe(\"Confidence 0-1\"),\n\t\t\tproject: z.string().optional().describe(\"Project identifier\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\t// Create a transient session + memory in a transaction for atomicity.\n\t\t\t\t// TS store doesn't have startSession/endSession yet, so\n\t\t\t\t// we insert the session row directly. Wrapped in transaction to\n\t\t\t\t// prevent orphaned sessions if remember() fails.\n\t\t\t\tconst result = store.db.transaction(() => {\n\t\t\t\t\tconst now = nowIso();\n\t\t\t\t\tconst user = process.env.USER ?? \"unknown\";\n\t\t\t\t\tconst cwd = process.cwd();\n\t\t\t\t\tconst project = args.project ?? process.env.CODEMEM_PROJECT ?? null;\n\n\t\t\t\t\tconst sessionInfo = store.db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t`INSERT INTO sessions(started_at, ended_at, cwd, project, user, tool_version, metadata_json)\n\t\t\t\t\t\t\t VALUES (?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.run(now, now, cwd, project, user, \"mcp-ts\", toJson({ mcp: true }));\n\t\t\t\t\tconst sessionId = Number(sessionInfo.lastInsertRowid);\n\n\t\t\t\t\tconst memId = store.remember(\n\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\targs.kind,\n\t\t\t\t\t\targs.title,\n\t\t\t\t\t\targs.body,\n\t\t\t\t\t\targs.confidence,\n\t\t\t\t\t);\n\n\t\t\t\t\t// End the session\n\t\t\t\t\tstore.db\n\t\t\t\t\t\t.prepare(\"UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?\")\n\t\t\t\t\t\t.run(nowIso(), toJson({ mcp: true }), sessionId);\n\n\t\t\t\t\treturn { memId, title: args.title, body: args.body };\n\t\t\t\t})();\n\n\t\t\t\ttry {\n\t\t\t\t\tawait storeVectors(store.db, result.memId, result.title, result.body);\n\t\t\t\t} catch {\n\t\t\t\t\t// Non-fatal — memory writes should succeed even if embeddings are unavailable\n\t\t\t\t}\n\n\t\t\t\treturn jsonContent({ id: result.memId });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 11. memory_forget\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_forget\",\n\t\t\"Soft-delete a memory item. Use for incorrect or sensitive data.\",\n\t\t{\n\t\t\tmemory_id: z.number().int().describe(\"Memory ID to forget\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tstore.forget(args.memory_id);\n\t\t\t\treturn jsonContent({ status: \"ok\" });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 12. memory_schema\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_schema\",\n\t\t\"Return the memory schema — kinds, fields, and available filters.\",\n\t\t{},\n\t\tasync () => {\n\t\t\treturn jsonContent({\n\t\t\t\tkinds: Object.keys(MEMORY_KINDS),\n\t\t\t\tkind_descriptions: MEMORY_KINDS,\n\t\t\t\tfields: {\n\t\t\t\t\ttitle: \"short text\",\n\t\t\t\t\tbody: \"long text\",\n\t\t\t\t\tsubtitle: \"short text\",\n\t\t\t\t\tfacts: \"list<string>\",\n\t\t\t\t\tnarrative: \"long text\",\n\t\t\t\t\tconcepts: \"list<string>\",\n\t\t\t\t\tfiles_read: \"list<string>\",\n\t\t\t\t\tfiles_modified: \"list<string>\",\n\t\t\t\t\tprompt_number: \"int\",\n\t\t\t\t},\n\t\t\t\tfilters: [\n\t\t\t\t\t\"kind\",\n\t\t\t\t\t\"session_id\",\n\t\t\t\t\t\"since\",\n\t\t\t\t\t\"project\",\n\t\t\t\t\t\"include_actor_ids\",\n\t\t\t\t\t\"exclude_actor_ids\",\n\t\t\t\t\t\"include_visibility\",\n\t\t\t\t\t\"exclude_visibility\",\n\t\t\t\t\t\"include_workspace_ids\",\n\t\t\t\t\t\"exclude_workspace_ids\",\n\t\t\t\t\t\"include_workspace_kinds\",\n\t\t\t\t\t\"exclude_workspace_kinds\",\n\t\t\t\t],\n\t\t\t});\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 13. memory_learn\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_learn\",\n\t\t\"Learn how to use codemem memory tools. Call this first if unfamiliar.\",\n\t\t{},\n\t\tasync () => {\n\t\t\treturn jsonContent({\n\t\t\t\tintro: \"Use this tool when you're new to codemem or unsure when to recall/persist.\",\n\t\t\t\tclient_hint: \"If you are unfamiliar with codemem, call memory.learn first.\",\n\t\t\t\trecall: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Start of a task or when the user references prior work.\",\n\t\t\t\t\t\t\"When you need background context, decisions, or recent changes.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Use memory.search_index to get compact candidates.\",\n\t\t\t\t\t\t\"Use memory.timeline to expand around a promising memory.\",\n\t\t\t\t\t\t\"Use memory.get_observations for full details only when needed.\",\n\t\t\t\t\t\t\"Use memory.pack for quick one-shot context blocks.\",\n\t\t\t\t\t\t\"Use the project filter unless the user requests cross-project context.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t'memory.search_index(\"billing cache bug\", limit=5)',\n\t\t\t\t\t\t\"memory.timeline(memory_id=123)\",\n\t\t\t\t\t\t\"memory.get_observations([123, 456])\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tpersistence: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Milestones (task done, key decision, new facts learned).\",\n\t\t\t\t\t\t\"Notable regressions or follow-ups that should be remembered.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Use memory.remember with kind decision/discovery/change/exploration.\",\n\t\t\t\t\t\t\"Keep titles short and bodies high-signal.\",\n\t\t\t\t\t\t\"ALWAYS pass the project parameter if known.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t'memory.remember(kind=\"decision\", title=\"Switch to async cache\", body=\"...why...\", project=\"my-service\")',\n\t\t\t\t\t\t'memory.remember(kind=\"change\", title=\"Fixed retry loop\", body=\"...impact...\", project=\"my-service\")',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tforget: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Accidental or sensitive data stored in memory items.\",\n\t\t\t\t\t\t\"Obsolete or incorrect items that should no longer surface.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Call memory.forget(id) to mark the item inactive.\",\n\t\t\t\t\t\t\"Prefer forgetting over overwriting to preserve auditability.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\"memory.forget(123)\"],\n\t\t\t\t},\n\t\t\t\tprompt_hint:\n\t\t\t\t\t\"At task start: call memory.search_index; during work: memory.timeline + memory.get_observations; at milestones: memory.remember.\",\n\t\t\t\trecommended_system_prompt: [\n\t\t\t\t\t\"Trigger policy (1-liner): If the user references prior work or starts a task,\",\n\t\t\t\t\t\"immediately call memory.search_index; then use memory.timeline + memory.get_observations;\",\n\t\t\t\t\t\"at milestones, call memory.remember; use memory.forget for incorrect/sensitive items.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"System prompt:\",\n\t\t\t\t\t\"You have access to codemem MCP tools. If unfamiliar, call memory.learn first.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Recall:\",\n\t\t\t\t\t\"- Start of any task: call memory.search_index with a concise task query.\",\n\t\t\t\t\t'- If prior work is referenced (\"as before\", \"last time\", \"we already did…\", \"regression\"),',\n\t\t\t\t\t\" call memory.search_index or memory.timeline.\",\n\t\t\t\t\t\"- Use memory.get_observations only after filtering IDs.\",\n\t\t\t\t\t\"- Prefer project-scoped queries unless the user asks for cross-project.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Persistence:\",\n\t\t\t\t\t\"- On milestones (task done, key decision, new facts learned), call memory.remember.\",\n\t\t\t\t\t\"- Use kind=decision for tradeoffs, kind=change for outcomes, kind=discovery/exploration for useful findings.\",\n\t\t\t\t\t\"- Keep titles short and bodies high-signal.\",\n\t\t\t\t\t\"- ALWAYS pass the project parameter if known.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Safety:\",\n\t\t\t\t\t\"- Use memory.forget(id) for incorrect or sensitive items.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Examples:\",\n\t\t\t\t\t'- memory.search_index(\"billing cache bug\")',\n\t\t\t\t\t\"- memory.timeline(memory_id=123)\",\n\t\t\t\t\t\"- memory.get_observations([123, 456])\",\n\t\t\t\t\t'- memory.remember(kind=\"decision\", title=\"Use async cache\", body=\"Chose async cache to avoid lock contention in X.\", project=\"my-service\")',\n\t\t\t\t\t'- memory.remember(kind=\"change\", title=\"Fixed retry loop\", body=\"Root cause was Y; added guard in Z.\", project=\"my-service\")',\n\t\t\t\t\t\"- memory.forget(123)\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// Connect and handle shutdown\n\t// -------------------------------------------------------------------\n\tconst transport = new StdioServerTransport();\n\n\tconst shutdown = () => {\n\t\ttry {\n\t\t\tstore.close();\n\t\t} catch {\n\t\t\t// Best effort — process is exiting\n\t\t}\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n\n\tawait server.connect(transport);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"codemem MCP server failed to start:\", err);\n\tprocess.exit(1);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/memory-access.ts","../src/project-scope.ts","../src/index.ts"],"sourcesContent":["import {\n\ttype MemoryFilters,\n\ttype MemoryItemResponse,\n\ttype MemoryStore,\n\ttoJson,\n} from \"@codemem/core\";\n\nexport function getMemoryForMcp(\n\tstore: MemoryStore,\n\tmemoryId: number,\n\tfilters?: MemoryFilters,\n): MemoryItemResponse | null {\n\tconst rows = store.timeline(null, memoryId, 0, 0, filters ?? null);\n\treturn rows.find((row) => row.id === memoryId) ?? null;\n}\n\nexport function getManyForMcp(\n\tstore: MemoryStore,\n\tids: number[],\n\tfilters?: MemoryFilters,\n): MemoryItemResponse[] {\n\tif (ids.length === 0) return [];\n\tconst results: MemoryItemResponse[] = [];\n\tfor (const id of ids) {\n\t\tconst item = getMemoryForMcp(store, id, filters);\n\t\tif (item) results.push(item);\n\t}\n\treturn results;\n}\n\nexport function forgetMemoryForMcp(\n\tstore: MemoryStore,\n\tmemoryId: number,\n\tfilters?: MemoryFilters,\n): boolean {\n\tconst item = getMemoryForMcp(store, memoryId, filters);\n\tif (!item) return false;\n\tstore.forget(memoryId);\n\treturn true;\n}\n\nexport interface RememberMemoryForMcpInput {\n\tkind: string;\n\ttitle: string;\n\tbody: string;\n\tconfidence: number;\n\tproject?: string | null;\n}\n\nexport interface RememberMemoryForMcpContext {\n\tcwd?: string;\n\tuser?: string;\n\tenvProject?: string | null;\n\tnow?: () => string;\n}\n\nexport function rememberMemoryForMcp(\n\tstore: MemoryStore,\n\tinput: RememberMemoryForMcpInput,\n\tcontext: RememberMemoryForMcpContext = {},\n): { memId: number; title: string; body: string } {\n\treturn store.db.transaction(() => {\n\t\tconst now = context.now?.() ?? new Date().toISOString();\n\t\tconst user = context.user ?? process.env.USER ?? \"unknown\";\n\t\tconst cwd = context.cwd ?? process.cwd();\n\t\tconst project = input.project ?? context.envProject ?? null;\n\n\t\tconst sessionInfo = store.db\n\t\t\t.prepare(\n\t\t\t\t`INSERT INTO sessions(started_at, ended_at, cwd, project, user, tool_version, metadata_json)\n\t\t\t\t VALUES (?, ?, ?, ?, ?, ?, ?)`,\n\t\t\t)\n\t\t\t.run(now, now, cwd, project, user, \"mcp-ts\", toJson({ mcp: true }));\n\t\tconst sessionId = Number(sessionInfo.lastInsertRowid);\n\n\t\tconst memId = store.remember(sessionId, input.kind, input.title, input.body, input.confidence);\n\t\tif (!getMemoryForMcp(store, memId)) {\n\t\t\tthrow new Error(\"unauthorized_scope\");\n\t\t}\n\n\t\tstore.db\n\t\t\t.prepare(\"UPDATE sessions SET ended_at = ?, metadata_json = ? WHERE id = ?\")\n\t\t\t.run(context.now?.() ?? new Date().toISOString(), toJson({ mcp: true }), sessionId);\n\n\t\treturn { memId, title: input.title, body: input.body };\n\t})();\n}\n","import { type MemoryFilters, resolveProject } from \"@codemem/core\";\n\nexport function resolveDefaultProject(): string | null {\n\tconst project = process.env.CODEMEM_PROJECT?.trim();\n\treturn project || resolveProject(process.cwd());\n}\n\nexport function buildFilters(\n\traw: Record<string, unknown>,\n\tdefaultProject = resolveDefaultProject(),\n): MemoryFilters | undefined {\n\tconst filters: MemoryFilters = {};\n\tlet hasAny = false;\n\n\tconst explicitProject = typeof raw.project === \"string\" ? raw.project.trim() : undefined;\n\tconst resolvedProject = explicitProject || defaultProject || undefined;\n\tif (resolvedProject) {\n\t\tfilters.project = resolvedProject;\n\t\thasAny = true;\n\t}\n\n\tfor (const key of [\n\t\t\"kind\",\n\t\t\"visibility\",\n\t\t\"scope_id\",\n\t\t\"include_scope_ids\",\n\t\t\"exclude_scope_ids\",\n\t\t\"include_visibility\",\n\t\t\"exclude_visibility\",\n\t\t\"include_workspace_ids\",\n\t\t\"exclude_workspace_ids\",\n\t\t\"include_workspace_kinds\",\n\t\t\"exclude_workspace_kinds\",\n\t\t\"include_actor_ids\",\n\t\t\"exclude_actor_ids\",\n\t\t\"include_trust_states\",\n\t\t\"exclude_trust_states\",\n\t\t\"ownership_scope\",\n\t\t\"personal_first\",\n\t\t\"trust_bias\",\n\t\t\"widen_shared_when_weak\",\n\t\t\"widen_shared_min_personal_results\",\n\t\t\"widen_shared_min_personal_score\",\n\t] as const) {\n\t\tconst val = raw[key];\n\t\tif (val !== undefined && val !== null) {\n\t\t\t(filters as Record<string, unknown>)[key] = val;\n\t\t\thasAny = true;\n\t\t}\n\t}\n\n\treturn hasAny ? filters : undefined;\n}\n","#!/usr/bin/env node\n\n/**\n * @codemem/mcp — MCP stdio server.\n *\n * Runs as a separate process spawned by the host (OpenCode/Claude).\n * Owns its own better-sqlite3 connection. Communicates via stdio JSON-RPC.\n *\n * Port of codemem/mcp_server.py — all 13 tools.\n */\n\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tdedupeOrderedIds,\n\ttype MemoryItemResponse,\n\ttype MemoryResult,\n\tMemoryStore,\n\tprojectMatchesFilter,\n\tresolveDbPath,\n\tstoreVectors,\n\tVERSION,\n} from \"@codemem/core\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport {\n\tforgetMemoryForMcp,\n\tgetManyForMcp,\n\tgetMemoryForMcp,\n\trememberMemoryForMcp,\n} from \"./memory-access.js\";\nimport { buildFilters, resolveDefaultProject } from \"./project-scope.js\";\n\n// ---------------------------------------------------------------------------\n// Static data\n// ---------------------------------------------------------------------------\n\nconst MEMORY_KINDS: Record<string, string> = {\n\tdiscovery: \"Something learned about the codebase, architecture, or tools\",\n\tchange: \"A code change that was made\",\n\tfeature: \"A new feature that was implemented\",\n\tbugfix: \"A bug that was found and fixed\",\n\trefactor: \"Code that was refactored or restructured\",\n\tdecision: \"A design or architecture decision\",\n\texploration: \"An experiment or investigation (may not have shipped)\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared zod filter schema (spread into each tool that accepts filters)\n// ---------------------------------------------------------------------------\n\nconst scopeFilterSchema = {\n\tscope_id: z.string().optional().describe(\"Filter by a single sharing domain scope_id\"),\n\tinclude_scope_ids: z.array(z.string()).optional().describe(\"Sharing domain scope_ids to include\"),\n\texclude_scope_ids: z.array(z.string()).optional().describe(\"Sharing domain scope_ids to exclude\"),\n};\n\nconst filterSchema = {\n\tkind: z.string().optional().describe(\"Filter by memory kind\"),\n\tproject: z.string().optional().describe(\"Filter by project scope (matches sessions.project)\"),\n\t...scopeFilterSchema,\n\tvisibility: z.array(z.string()).optional(),\n\tinclude_visibility: z.array(z.string()).optional(),\n\texclude_visibility: z.array(z.string()).optional(),\n\tinclude_workspace_ids: z.array(z.string()).optional(),\n\texclude_workspace_ids: z.array(z.string()).optional(),\n\tinclude_workspace_kinds: z.array(z.string()).optional(),\n\texclude_workspace_kinds: z.array(z.string()).optional(),\n\tinclude_actor_ids: z.array(z.string()).optional(),\n\texclude_actor_ids: z.array(z.string()).optional(),\n\tinclude_trust_states: z.array(z.string()).optional(),\n\texclude_trust_states: z.array(z.string()).optional(),\n\townership_scope: z.string().optional(),\n\tpersonal_first: z.union([z.boolean(), z.string()]).optional(),\n\ttrust_bias: z.string().optional(),\n\twiden_shared_when_weak: z.union([z.boolean(), z.string()]).optional(),\n\twiden_shared_min_personal_results: z.number().int().optional(),\n\twiden_shared_min_personal_score: z.number().optional(),\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst defaultProject = resolveDefaultProject();\n\n/** Wrap a JSON result into the MCP text content envelope. */\nfunction jsonContent(data: unknown) {\n\treturn { content: [{ type: \"text\" as const, text: JSON.stringify(data) }] };\n}\n\n/** Wrap an error message into the MCP text content envelope. */\nfunction errorContent(message: string) {\n\treturn { content: [{ type: \"text\" as const, text: JSON.stringify({ error: message }) }] };\n}\n\n// ---------------------------------------------------------------------------\n// Viewer autostart\n// ---------------------------------------------------------------------------\n\n/** Default viewer host/port for health checks. */\nconst VIEWER_HOST = process.env.CODEMEM_VIEWER_HOST ?? \"127.0.0.1\";\nconst VIEWER_PORT = process.env.CODEMEM_VIEWER_PORT ?? \"38888\";\n\n/** Resolve the `codemem` CLI binary path. Checks package-local paths first, then PATH. */\nfunction resolveCliPath(): string | null {\n\t// When installed via npm/npx, the MCP server and CLI share node_modules.\n\t// Walk up from this file to find the CLI's bin entry.\n\tconst candidates: string[] = [];\n\tconst selfDir = dirname(import.meta.dirname ?? \".\");\n\t// Monorepo dev: sibling package\n\tcandidates.push(join(selfDir, \"..\", \"cli\", \"dist\", \"index.js\"));\n\t// npm install: node_modules/.bin/codemem\n\tcandidates.push(join(selfDir, \"..\", \".bin\", \"codemem\"));\n\t// npm install: deeper node_modules\n\tcandidates.push(join(selfDir, \"..\", \"..\", \".bin\", \"codemem\"));\n\tfor (const p of candidates) {\n\t\tif (existsSync(p)) return p;\n\t}\n\t// Fall back to PATH\n\treturn \"codemem\";\n}\n\n/** Check if the viewer is already running. */\nasync function isViewerHealthy(): Promise<boolean> {\n\ttry {\n\t\tconst url = `http://${VIEWER_HOST}:${VIEWER_PORT}/api/health`;\n\t\tconst response = await fetch(url, { signal: AbortSignal.timeout(2_000) });\n\t\treturn response.ok;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Attempt to start the viewer server as a detached background process.\n * Best-effort: failures are logged to stderr but never block MCP startup.\n */\nasync function ensureViewer(): Promise<void> {\n\tif (process.env.CODEMEM_VIEWER === \"0\" || process.env.CODEMEM_VIEWER_AUTO === \"0\") return;\n\n\tif (await isViewerHealthy()) return;\n\n\tconst cli = resolveCliPath();\n\tif (!cli) return;\n\n\ttry {\n\t\t// If the resolved path is a .js file, run it with node.\n\t\t// Otherwise it's a bin script that can run directly.\n\t\tconst isJsFile = cli.endsWith(\".js\");\n\t\tconst cmd = isJsFile ? process.execPath : cli;\n\t\tconst args = isJsFile ? [cli, \"serve\", \"start\"] : [\"serve\", \"start\"];\n\t\t// Pass non-default host/port so the spawned viewer matches what we health-check.\n\t\tif (VIEWER_HOST !== \"127.0.0.1\") args.push(\"--host\", VIEWER_HOST);\n\t\tif (VIEWER_PORT !== \"38888\") args.push(\"--port\", VIEWER_PORT);\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tdetached: true,\n\t\t\tstdio: \"ignore\",\n\t\t\tenv: { ...process.env, CODEMEM_PLUGIN_IGNORE: \"1\" },\n\t\t});\n\t\tchild.on(\"error\", () => {}); // swallow — best effort\n\t\tchild.unref();\n\n\t\t// Brief health check loop — don't block for long\n\t\tfor (let i = 0; i < 5; i++) {\n\t\t\tawait new Promise((r) => setTimeout(r, 1_000));\n\t\t\tif (await isViewerHealthy()) return;\n\t\t}\n\t} catch {\n\t\t// Best effort — MCP server continues regardless\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Server bootstrap\n// ---------------------------------------------------------------------------\n\nasync function main() {\n\tconst dbPath = resolveDbPath();\n\tconst store = new MemoryStore(dbPath);\n\n\t// Auto-start viewer in background (belt and suspenders with any hook-based start)\n\tensureViewer().catch(() => {});\n\n\tconst server = new McpServer({ name: \"codemem\", version: VERSION });\n\n\t// -------------------------------------------------------------------\n\t// 1. memory_search\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_search\",\n\t\t\"Search memories by text query. Returns full body text for each match.\",\n\t\t{\n\t\t\tquery: z.string().describe(\"Search query\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(5).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.search(args.query, args.limit, filters);\n\t\t\t\treturn jsonContent({\n\t\t\t\t\titems: items.map((m: MemoryResult) => ({\n\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\ttitle: m.title,\n\t\t\t\t\t\tkind: m.kind,\n\t\t\t\t\t\tbody: m.body_text,\n\t\t\t\t\t\tconfidence: m.confidence,\n\t\t\t\t\t\tscore: m.score,\n\t\t\t\t\t\tsession_id: m.session_id,\n\t\t\t\t\t\tmetadata: m.metadata,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 2. memory_search_index\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_search_index\",\n\t\t\"Search memories by text query. Returns compact index entries (no body) for browsing.\",\n\t\t{\n\t\t\tquery: z.string().describe(\"Search query\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(8).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.search(args.query, args.limit, filters);\n\t\t\t\treturn jsonContent({\n\t\t\t\t\titems: items.map((m: MemoryResult) => ({\n\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\tkind: m.kind,\n\t\t\t\t\t\ttitle: m.title,\n\t\t\t\t\t\tscore: m.score,\n\t\t\t\t\t\tcreated_at: m.created_at,\n\t\t\t\t\t\tsession_id: m.session_id,\n\t\t\t\t\t\tmetadata: m.metadata,\n\t\t\t\t\t})),\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 3. memory_timeline\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_timeline\",\n\t\t\"Get a chronological window of memories around an anchor (by ID or query).\",\n\t\t{\n\t\t\tquery: z.string().optional().describe(\"Search query to find anchor\"),\n\t\t\tmemory_id: z.number().int().optional().describe(\"Anchor memory ID\"),\n\t\t\tdepth_before: z.number().int().min(0).default(3).describe(\"Items before anchor\"),\n\t\t\tdepth_after: z.number().int().min(0).default(3).describe(\"Items after anchor\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.timeline(\n\t\t\t\t\targs.query ?? null,\n\t\t\t\t\targs.memory_id ?? null,\n\t\t\t\t\targs.depth_before,\n\t\t\t\t\targs.depth_after,\n\t\t\t\t\tfilters,\n\t\t\t\t);\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 4. memory_explain\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_explain\",\n\t\t\"Explain search results with detailed scoring breakdown.\",\n\t\t{\n\t\t\tquery: z.string().optional().describe(\"Search query\"),\n\t\t\tids: z.array(z.number().int()).max(200).optional().describe(\"Specific memory IDs to explain\"),\n\t\t\tlimit: z.number().int().min(1).max(50).default(10).describe(\"Max results\"),\n\t\t\tinclude_pack_context: z.boolean().default(false).describe(\"Include formatted pack context\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst result = store.explain(args.query ?? null, args.ids ?? null, args.limit, filters, {\n\t\t\t\t\tincludePackContext: args.include_pack_context,\n\t\t\t\t});\n\t\t\t\treturn jsonContent(result);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 5. memory_expand\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_expand\",\n\t\t\"Fetch memories by ID with surrounding timeline context.\",\n\t\t{\n\t\t\tids: z\n\t\t\t\t.array(z.union([z.number(), z.string()]))\n\t\t\t\t.max(200)\n\t\t\t\t.describe(\"Memory IDs to expand\"),\n\t\t\tdepth_before: z.number().int().min(0).default(3).describe(\"Timeline items before\"),\n\t\t\tdepth_after: z.number().int().min(0).default(3).describe(\"Timeline items after\"),\n\t\t\tinclude_observations: z.boolean().default(false).describe(\"Include full observation details\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\t// Python: project if project is not None else default_project\n\t\t\t\t// Explicit \"\" clears project scoping; only fall back to default when undefined.\n\t\t\t\tconst filterDefaultProject =\n\t\t\t\t\targs.project !== undefined && !args.project.trim() ? null : defaultProject;\n\t\t\t\tconst filters = buildFilters(args, filterDefaultProject);\n\t\t\t\tconst resolvedProject = filters?.project ?? null;\n\t\t\t\tconst { ordered: orderedIds, invalid: invalidIds } = dedupeOrderedIds(args.ids);\n\t\t\t\tconst errors: Array<Record<string, unknown>> = [];\n\n\t\t\t\tif (invalidIds.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"INVALID_ARGUMENT\",\n\t\t\t\t\t\tfield: \"ids\",\n\t\t\t\t\t\tmessage: \"some ids are not valid integers\",\n\t\t\t\t\t\tids: invalidIds,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst missingNotFound: number[] = [];\n\t\t\t\tconst missingProjectMismatch: number[] = [];\n\t\t\t\tconst missingFilterMismatch: number[] = [];\n\t\t\t\tconst anchors: MemoryItemResponse[] = [];\n\t\t\t\tconst timelineItems: MemoryItemResponse[] = [];\n\t\t\t\tconst timelineSeen = new Set<number>();\n\t\t\t\tconst sessionProjects = new Map<number, string | null>();\n\n\t\t\t\tfor (const memoryId of orderedIds) {\n\t\t\t\t\tconst item = store.get(memoryId);\n\t\t\t\t\tif (!item?.active) {\n\t\t\t\t\t\tmissingNotFound.push(memoryId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst sessionId = item.session_id;\n\t\t\t\t\tif (resolvedProject && sessionId > 0) {\n\t\t\t\t\t\tif (!sessionProjects.has(sessionId)) {\n\t\t\t\t\t\t\tconst row = store.db\n\t\t\t\t\t\t\t\t.prepare(\"SELECT project FROM sessions WHERE id = ? LIMIT 1\")\n\t\t\t\t\t\t\t\t.get(sessionId) as { project: string | null } | undefined;\n\t\t\t\t\t\t\tsessionProjects.set(sessionId, typeof row?.project === \"string\" ? row.project : null);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!projectMatchesFilter(resolvedProject, sessionProjects.get(sessionId) ?? null)) {\n\t\t\t\t\t\t\tmissingProjectMismatch.push(memoryId);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (resolvedProject && sessionId <= 0) {\n\t\t\t\t\t\tmissingProjectMismatch.push(memoryId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst expanded = store.timeline(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tmemoryId,\n\t\t\t\t\t\targs.depth_before,\n\t\t\t\t\t\targs.depth_after,\n\t\t\t\t\t\tfilters,\n\t\t\t\t\t);\n\t\t\t\t\tconst anchor = expanded.find((expandedItem) => expandedItem.id === memoryId);\n\t\t\t\t\tif (!anchor) {\n\t\t\t\t\t\tmissingFilterMismatch.push(memoryId);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tanchors.push(anchor);\n\t\t\t\t\tfor (const expandedItem of expanded) {\n\t\t\t\t\t\tconst expandedId = expandedItem.id;\n\t\t\t\t\t\tif (expandedId <= 0 || timelineSeen.has(expandedId)) continue;\n\t\t\t\t\t\ttimelineSeen.add(expandedId);\n\t\t\t\t\t\ttimelineItems.push(expandedItem);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (missingNotFound.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\t\tfield: \"ids\",\n\t\t\t\t\t\tmessage: \"some requested ids were not found\",\n\t\t\t\t\t\tids: missingNotFound,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (missingProjectMismatch.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"PROJECT_MISMATCH\",\n\t\t\t\t\t\tfield: \"project\",\n\t\t\t\t\t\tmessage: \"some requested ids are outside the requested project scope\",\n\t\t\t\t\t\tids: missingProjectMismatch,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (missingFilterMismatch.length > 0) {\n\t\t\t\t\terrors.push({\n\t\t\t\t\t\tcode: \"FILTER_MISMATCH\",\n\t\t\t\t\t\tfield: \"filters\",\n\t\t\t\t\t\tmessage: \"some requested ids are outside the requested filters\",\n\t\t\t\t\t\tids: missingFilterMismatch,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Collect full observations if requested\n\t\t\t\tlet observations: MemoryItemResponse[] = [];\n\t\t\t\tif (args.include_observations) {\n\t\t\t\t\tconst observationSeen = new Set<number>();\n\t\t\t\t\tconst observationIds: number[] = [];\n\t\t\t\t\tfor (const item of [...anchors, ...timelineItems]) {\n\t\t\t\t\t\tif (item.id > 0 && !observationSeen.has(item.id)) {\n\t\t\t\t\t\t\tobservationSeen.add(item.id);\n\t\t\t\t\t\t\tobservationIds.push(item.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tobservations = getManyForMcp(store, observationIds, filters);\n\t\t\t\t}\n\n\t\t\t\treturn jsonContent({\n\t\t\t\t\tanchors,\n\t\t\t\t\ttimeline: timelineItems,\n\t\t\t\t\tobservations,\n\t\t\t\t\tmissing_ids: orderedIds.filter(\n\t\t\t\t\t\t(memoryId: number) =>\n\t\t\t\t\t\t\tmissingNotFound.includes(memoryId) ||\n\t\t\t\t\t\t\tmissingProjectMismatch.includes(memoryId) ||\n\t\t\t\t\t\t\tmissingFilterMismatch.includes(memoryId),\n\t\t\t\t\t),\n\t\t\t\t\terrors,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tproject: resolvedProject,\n\t\t\t\t\t\trequested_ids_count: orderedIds.length,\n\t\t\t\t\t\treturned_anchor_count: anchors.length,\n\t\t\t\t\t\ttimeline_count: timelineItems.length,\n\t\t\t\t\t\tinclude_observations: args.include_observations,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 6. memory_get\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_get\",\n\t\t\"Fetch a single memory item by ID.\",\n\t\t{\n\t\t\tmemory_id: z.number().int().describe(\"Memory ID\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst item = getMemoryForMcp(store, args.memory_id, buildFilters(args, null));\n\t\t\t\tif (!item) return errorContent(\"not_found\");\n\t\t\t\treturn jsonContent(item);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 7. memory_get_observations\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_get_observations\",\n\t\t\"Fetch multiple memory items by their IDs.\",\n\t\t{\n\t\t\tids: z.array(z.number().int()).max(200).describe(\"Memory IDs to fetch\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst items = getManyForMcp(store, args.ids, buildFilters(args, null));\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 8. memory_recent\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_recent\",\n\t\t\"Return recent memories, newest first.\",\n\t\t{\n\t\t\tlimit: z.number().int().min(1).max(100).default(8).describe(\"Max results\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst items = store.recent(args.limit, filters);\n\t\t\t\treturn jsonContent({ items });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 9. memory_pack\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_pack\",\n\t\t\"Build a formatted memory pack from search results — quick one-shot context block.\",\n\t\t{\n\t\t\tcontext: z.string().describe(\"Context description to search for\"),\n\t\t\tlimit: z.number().int().min(1).max(50).optional().describe(\"Max items to include\"),\n\t\t\tcompact: z\n\t\t\t\t.boolean()\n\t\t\t\t.optional()\n\t\t\t\t.describe(\n\t\t\t\t\t\"When true, render a scannable index of all items with full detail only for the top N (default 3). Saves tokens when broad overview matters more than per-item detail.\",\n\t\t\t\t),\n\t\t\tcompact_detail_count: z\n\t\t\t\t.number()\n\t\t\t\t.int()\n\t\t\t\t.min(0)\n\t\t\t\t.max(50)\n\t\t\t\t.optional()\n\t\t\t\t.describe(\"Number of items to show in full detail in compact mode (default 3)\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst filters = buildFilters(args);\n\t\t\t\tconst renderOptions =\n\t\t\t\t\targs.compact || args.compact_detail_count != null\n\t\t\t\t\t\t? { compact: args.compact ?? true, compactDetailCount: args.compact_detail_count }\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst result = await store.buildMemoryPackAsync(\n\t\t\t\t\targs.context,\n\t\t\t\t\targs.limit ?? undefined,\n\t\t\t\t\tnull,\n\t\t\t\t\tfilters,\n\t\t\t\t\trenderOptions,\n\t\t\t\t);\n\t\t\t\treturn jsonContent(result);\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 10. memory_remember\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_remember\",\n\t\t\"Create a new memory. Use for milestones, decisions, and notable facts.\",\n\t\t{\n\t\t\tkind: z\n\t\t\t\t.enum([\"discovery\", \"change\", \"feature\", \"bugfix\", \"refactor\", \"decision\", \"exploration\"])\n\t\t\t\t.describe(\"Memory kind\"),\n\t\t\ttitle: z.string().describe(\"Short title\"),\n\t\t\tbody: z.string().describe(\"Body text (high-signal content)\"),\n\t\t\tconfidence: z.number().min(0).max(1).default(0.5).describe(\"Confidence 0-1\"),\n\t\t\tproject: z.string().optional().describe(\"Project identifier\"),\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tconst result = rememberMemoryForMcp(store, args, {\n\t\t\t\t\tenvProject: process.env.CODEMEM_PROJECT ?? null,\n\t\t\t\t});\n\n\t\t\t\ttry {\n\t\t\t\t\tawait storeVectors(store.db, result.memId, result.title, result.body);\n\t\t\t\t} catch {\n\t\t\t\t\t// Non-fatal — memory writes should succeed even if embeddings are unavailable\n\t\t\t\t}\n\n\t\t\t\treturn jsonContent({ id: result.memId });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 11. memory_forget\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_forget\",\n\t\t\"Soft-delete a memory item. Use for incorrect or sensitive data.\",\n\t\t{\n\t\t\tmemory_id: z.number().int().describe(\"Memory ID to forget\"),\n\t\t\t...filterSchema,\n\t\t},\n\t\tasync (args) => {\n\t\t\ttry {\n\t\t\t\tif (!forgetMemoryForMcp(store, args.memory_id, buildFilters(args, null))) {\n\t\t\t\t\treturn errorContent(\"not_found\");\n\t\t\t\t}\n\t\t\t\treturn jsonContent({ status: \"ok\" });\n\t\t\t} catch (err) {\n\t\t\t\treturn errorContent(err instanceof Error ? err.message : String(err));\n\t\t\t}\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 12. memory_schema\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_schema\",\n\t\t\"Return the memory schema — kinds, fields, and available filters.\",\n\t\t{},\n\t\tasync () => {\n\t\t\treturn jsonContent({\n\t\t\t\tkinds: Object.keys(MEMORY_KINDS),\n\t\t\t\tkind_descriptions: MEMORY_KINDS,\n\t\t\t\tfields: {\n\t\t\t\t\ttitle: \"short text\",\n\t\t\t\t\tbody: \"long text\",\n\t\t\t\t\tsubtitle: \"short text\",\n\t\t\t\t\tfacts: \"list<string>\",\n\t\t\t\t\tnarrative: \"long text\",\n\t\t\t\t\tconcepts: \"list<string>\",\n\t\t\t\t\tfiles_read: \"list<string>\",\n\t\t\t\t\tfiles_modified: \"list<string>\",\n\t\t\t\t\tprompt_number: \"int\",\n\t\t\t\t},\n\t\t\t\tfilters: [\n\t\t\t\t\t\"kind\",\n\t\t\t\t\t\"session_id\",\n\t\t\t\t\t\"since\",\n\t\t\t\t\t\"project\",\n\t\t\t\t\t\"scope_id\",\n\t\t\t\t\t\"include_scope_ids\",\n\t\t\t\t\t\"exclude_scope_ids\",\n\t\t\t\t\t\"include_actor_ids\",\n\t\t\t\t\t\"exclude_actor_ids\",\n\t\t\t\t\t\"include_visibility\",\n\t\t\t\t\t\"exclude_visibility\",\n\t\t\t\t\t\"include_workspace_ids\",\n\t\t\t\t\t\"exclude_workspace_ids\",\n\t\t\t\t\t\"include_workspace_kinds\",\n\t\t\t\t\t\"exclude_workspace_kinds\",\n\t\t\t\t],\n\t\t\t});\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// 13. memory_learn\n\t// -------------------------------------------------------------------\n\tserver.tool(\n\t\t\"memory_learn\",\n\t\t\"Learn how to use codemem memory tools. Call this first if unfamiliar.\",\n\t\t{},\n\t\tasync () => {\n\t\t\treturn jsonContent({\n\t\t\t\tintro: \"Use this tool when you're new to codemem or unsure when to recall/persist.\",\n\t\t\t\tclient_hint: \"If you are unfamiliar with codemem, call memory.learn first.\",\n\t\t\t\trecall: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Start of a task or when the user references prior work.\",\n\t\t\t\t\t\t\"When you need background context, decisions, or recent changes.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Use memory.search_index to get compact candidates.\",\n\t\t\t\t\t\t\"Use memory.timeline to expand around a promising memory.\",\n\t\t\t\t\t\t\"Use memory.get_observations for full details only when needed.\",\n\t\t\t\t\t\t\"Use memory.pack for quick one-shot context blocks.\",\n\t\t\t\t\t\t\"Use the project filter unless the user requests cross-project context.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t'memory.search_index(\"billing cache bug\", limit=5)',\n\t\t\t\t\t\t\"memory.timeline(memory_id=123)\",\n\t\t\t\t\t\t\"memory.get_observations([123, 456])\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tpersistence: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Milestones (task done, key decision, new facts learned).\",\n\t\t\t\t\t\t\"Notable regressions or follow-ups that should be remembered.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Use memory.remember with kind decision/discovery/change/exploration.\",\n\t\t\t\t\t\t\"Keep titles short and bodies high-signal.\",\n\t\t\t\t\t\t\"ALWAYS pass the project parameter if known.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t'memory.remember(kind=\"decision\", title=\"Switch to async cache\", body=\"...why...\", project=\"my-service\")',\n\t\t\t\t\t\t'memory.remember(kind=\"change\", title=\"Fixed retry loop\", body=\"...impact...\", project=\"my-service\")',\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tforget: {\n\t\t\t\t\twhen: [\n\t\t\t\t\t\t\"Accidental or sensitive data stored in memory items.\",\n\t\t\t\t\t\t\"Obsolete or incorrect items that should no longer surface.\",\n\t\t\t\t\t],\n\t\t\t\t\thow: [\n\t\t\t\t\t\t\"Call memory.forget(id) to mark the item inactive.\",\n\t\t\t\t\t\t\"Prefer forgetting over overwriting to preserve auditability.\",\n\t\t\t\t\t],\n\t\t\t\t\texamples: [\"memory.forget(123)\"],\n\t\t\t\t},\n\t\t\t\tprompt_hint:\n\t\t\t\t\t\"At task start: call memory.search_index; during work: memory.timeline + memory.get_observations; at milestones: memory.remember.\",\n\t\t\t\trecommended_system_prompt: [\n\t\t\t\t\t\"Trigger policy (1-liner): If the user references prior work or starts a task,\",\n\t\t\t\t\t\"immediately call memory.search_index; then use memory.timeline + memory.get_observations;\",\n\t\t\t\t\t\"at milestones, call memory.remember; use memory.forget for incorrect/sensitive items.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"System prompt:\",\n\t\t\t\t\t\"You have access to codemem MCP tools. If unfamiliar, call memory.learn first.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Recall:\",\n\t\t\t\t\t\"- Start of any task: call memory.search_index with a concise task query.\",\n\t\t\t\t\t'- If prior work is referenced (\"as before\", \"last time\", \"we already did…\", \"regression\"),',\n\t\t\t\t\t\" call memory.search_index or memory.timeline.\",\n\t\t\t\t\t\"- Use memory.get_observations only after filtering IDs.\",\n\t\t\t\t\t\"- Prefer project-scoped queries unless the user asks for cross-project.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Persistence:\",\n\t\t\t\t\t\"- On milestones (task done, key decision, new facts learned), call memory.remember.\",\n\t\t\t\t\t\"- Use kind=decision for tradeoffs, kind=change for outcomes, kind=discovery/exploration for useful findings.\",\n\t\t\t\t\t\"- Keep titles short and bodies high-signal.\",\n\t\t\t\t\t\"- ALWAYS pass the project parameter if known.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Safety:\",\n\t\t\t\t\t\"- Use memory.forget(id) for incorrect or sensitive items.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Examples:\",\n\t\t\t\t\t'- memory.search_index(\"billing cache bug\")',\n\t\t\t\t\t\"- memory.timeline(memory_id=123)\",\n\t\t\t\t\t\"- memory.get_observations([123, 456])\",\n\t\t\t\t\t'- memory.remember(kind=\"decision\", title=\"Use async cache\", body=\"Chose async cache to avoid lock contention in X.\", project=\"my-service\")',\n\t\t\t\t\t'- memory.remember(kind=\"change\", title=\"Fixed retry loop\", body=\"Root cause was Y; added guard in Z.\", project=\"my-service\")',\n\t\t\t\t\t\"- memory.forget(123)\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t});\n\t\t},\n\t);\n\n\t// -------------------------------------------------------------------\n\t// Connect and handle shutdown\n\t// -------------------------------------------------------------------\n\tconst transport = new StdioServerTransport();\n\n\tconst shutdown = () => {\n\t\ttry {\n\t\t\tstore.close();\n\t\t} catch {\n\t\t\t// Best effort — process is exiting\n\t\t}\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n\n\tawait server.connect(transport);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"codemem MCP server failed to start:\", err);\n\tprocess.exit(1);\n});\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type MemoryFilters, type MemoryItemResponse, type MemoryStore } from "@codemem/core";
2
+ export declare function getMemoryForMcp(store: MemoryStore, memoryId: number, filters?: MemoryFilters): MemoryItemResponse | null;
3
+ export declare function getManyForMcp(store: MemoryStore, ids: number[], filters?: MemoryFilters): MemoryItemResponse[];
4
+ export declare function forgetMemoryForMcp(store: MemoryStore, memoryId: number, filters?: MemoryFilters): boolean;
5
+ export interface RememberMemoryForMcpInput {
6
+ kind: string;
7
+ title: string;
8
+ body: string;
9
+ confidence: number;
10
+ project?: string | null;
11
+ }
12
+ export interface RememberMemoryForMcpContext {
13
+ cwd?: string;
14
+ user?: string;
15
+ envProject?: string | null;
16
+ now?: () => string;
17
+ }
18
+ export declare function rememberMemoryForMcp(store: MemoryStore, input: RememberMemoryForMcpInput, context?: RememberMemoryForMcpContext): {
19
+ memId: number;
20
+ title: string;
21
+ body: string;
22
+ };
23
+ //# sourceMappingURL=memory-access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-access.d.ts","sourceRoot":"","sources":["../src/memory-access.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAEhB,MAAM,eAAe,CAAC;AAEvB,wBAAgB,eAAe,CAC9B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GACrB,kBAAkB,GAAG,IAAI,CAG3B;AAED,wBAAgB,aAAa,CAC5B,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,aAAa,GACrB,kBAAkB,EAAE,CAQtB;AAED,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GACrB,OAAO,CAKT;AAED,MAAM,WAAW,yBAAyB;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,yBAAyB,EAChC,OAAO,GAAE,2BAAgC,GACvC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA0BhD"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-scope.d.ts","sourceRoot":"","sources":["../src/project-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,eAAe,CAAC;AAEnE,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,YAAY,CAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,cAAc,gBAA0B,GACtC,aAAa,GAAG,SAAS,CAuC3B"}
1
+ {"version":3,"file":"project-scope.d.ts","sourceRoot":"","sources":["../src/project-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,eAAe,CAAC;AAEnE,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAGrD;AAED,wBAAgB,YAAY,CAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,cAAc,gBAA0B,GACtC,aAAa,GAAG,SAAS,CA0C3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemem/mcp",
3
- "version": "0.30.0-alpha.2",
3
+ "version": "0.30.0-alpha.4",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  "dependencies": {
20
20
  "@modelcontextprotocol/sdk": "^1.29.0",
21
21
  "zod": "^4.4.2",
22
- "@codemem/core": "^0.30.0-alpha.2"
22
+ "@codemem/core": "^0.30.0-alpha.4"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^25.6.0",