context-vault 2.4.0 → 2.4.2

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-vault/core",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "type": "module",
5
5
  "description": "Shared core: capture, index, retrieve, tools, and utilities for context-vault",
6
6
  "main": "src/index.js",
@@ -21,16 +21,18 @@
21
21
  "./core/frontmatter": "./src/core/frontmatter.js",
22
22
  "./core/status": "./src/core/status.js"
23
23
  },
24
- "files": ["src/"],
24
+ "files": [
25
+ "src/"
26
+ ],
25
27
  "license": "MIT",
26
- "engines": { "node": ">=20" },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
27
31
  "author": "Felix Hellstrom",
28
- "repository": { "type": "git", "url": "git+https://github.com/fellanH/context-mcp.git", "directory": "packages/core" },
29
- "homepage": "https://github.com/fellanH/context-mcp",
30
- "dependencies": {
31
- "@huggingface/transformers": "^3.0.0",
32
- "@modelcontextprotocol/sdk": "^1.26.0",
33
- "better-sqlite3": "^12.6.2",
34
- "sqlite-vec": "^0.1.0"
35
- }
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/fellanH/context-mcp.git",
35
+ "directory": "packages/core"
36
+ },
37
+ "homepage": "https://github.com/fellanH/context-mcp"
36
38
  }
@@ -4,7 +4,7 @@
4
4
  * Resolution chain (highest priority last):
5
5
  * 1. Convention defaults
6
6
  * 2. Config file (~/.context-mcp/config.json)
7
- * 3. Environment variables (CONTEXT_MCP_*)
7
+ * 3. Environment variables (CONTEXT_VAULT_* or CONTEXT_MCP_*)
8
8
  * 4. CLI arguments
9
9
  */
10
10
 
@@ -29,7 +29,7 @@ export function resolveConfig() {
29
29
  const cliArgs = parseArgs(process.argv);
30
30
 
31
31
  // 1. Convention defaults
32
- const dataDir = resolve(cliArgs.dataDir || process.env.CONTEXT_MCP_DATA_DIR || join(HOME, ".context-mcp"));
32
+ const dataDir = resolve(cliArgs.dataDir || process.env.CONTEXT_VAULT_DATA_DIR || process.env.CONTEXT_MCP_DATA_DIR || join(HOME, ".context-mcp"));
33
33
  const config = {
34
34
  vaultDir: join(HOME, "vault"),
35
35
  dataDir,
@@ -51,16 +51,16 @@ export function resolveConfig() {
51
51
  if (fc.eventDecayDays) config.eventDecayDays = fc.eventDecayDays;
52
52
  config.resolvedFrom = "config file";
53
53
  } catch (e) {
54
- throw new Error(`[context-mcp] Invalid config at ${configPath}: ${e.message}`);
54
+ throw new Error(`[context-vault] Invalid config at ${configPath}: ${e.message}`);
55
55
  }
56
56
  }
57
57
  config.configPath = configPath;
58
58
 
59
- // 3. Environment variable overrides
60
- if (process.env.CONTEXT_MCP_VAULT_DIR) { config.vaultDir = process.env.CONTEXT_MCP_VAULT_DIR; config.resolvedFrom = "env"; }
61
- if (process.env.CONTEXT_MCP_DB_PATH) { config.dbPath = process.env.CONTEXT_MCP_DB_PATH; config.resolvedFrom = "env"; }
62
- if (process.env.CONTEXT_MCP_DEV_DIR) { config.devDir = process.env.CONTEXT_MCP_DEV_DIR; config.resolvedFrom = "env"; }
63
- if (process.env.CONTEXT_MCP_EVENT_DECAY_DAYS) { config.eventDecayDays = Number(process.env.CONTEXT_MCP_EVENT_DECAY_DAYS); config.resolvedFrom = "env"; }
59
+ // 3. Environment variable overrides (CONTEXT_VAULT_* takes priority over CONTEXT_MCP_*)
60
+ if (process.env.CONTEXT_VAULT_VAULT_DIR || process.env.CONTEXT_MCP_VAULT_DIR) { config.vaultDir = process.env.CONTEXT_VAULT_VAULT_DIR || process.env.CONTEXT_MCP_VAULT_DIR; config.resolvedFrom = "env"; }
61
+ if (process.env.CONTEXT_VAULT_DB_PATH || process.env.CONTEXT_MCP_DB_PATH) { config.dbPath = process.env.CONTEXT_VAULT_DB_PATH || process.env.CONTEXT_MCP_DB_PATH; config.resolvedFrom = "env"; }
62
+ if (process.env.CONTEXT_VAULT_DEV_DIR || process.env.CONTEXT_MCP_DEV_DIR) { config.devDir = process.env.CONTEXT_VAULT_DEV_DIR || process.env.CONTEXT_MCP_DEV_DIR; config.resolvedFrom = "env"; }
63
+ if (process.env.CONTEXT_VAULT_EVENT_DECAY_DAYS || process.env.CONTEXT_MCP_EVENT_DECAY_DAYS) { config.eventDecayDays = Number(process.env.CONTEXT_VAULT_EVENT_DECAY_DAYS || process.env.CONTEXT_MCP_EVENT_DECAY_DAYS); config.resolvedFrom = "env"; }
64
64
 
65
65
  // 4. CLI arg overrides (highest priority)
66
66
  if (cliArgs.vaultDir) { config.vaultDir = cliArgs.vaultDir; config.resolvedFrom = "CLI args"; }
@@ -136,11 +136,7 @@ export async function initDatabase(dbPath) {
136
136
  try {
137
137
  sqliteVec.load(db);
138
138
  } catch (e) {
139
- console.error(`[context-mcp] Failed to load sqlite-vec native module.`);
140
- console.error(`[context-mcp] This usually means prebuilt binaries aren't available for your platform.`);
141
- console.error(`[context-mcp] Try: npm rebuild sqlite-vec`);
142
- console.error(`[context-mcp] Error: ${e.message}`);
143
- throw e;
139
+ throw new NativeModuleError(e);
144
140
  }
145
141
  return db;
146
142
  }
@@ -150,7 +146,7 @@ export async function initDatabase(dbPath) {
150
146
 
151
147
  // Enforce fresh-DB-only — old schemas get a full rebuild (with backup)
152
148
  if (version > 0 && version < 5) {
153
- console.error(`[context-mcp] Schema v${version} is outdated. Rebuilding database...`);
149
+ console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
154
150
 
155
151
  // Backup old DB before destroying it
156
152
  const backupPath = `${dbPath}.v${version}.backup`;
@@ -158,10 +154,10 @@ export async function initDatabase(dbPath) {
158
154
  db.close();
159
155
  if (existsSync(dbPath)) {
160
156
  copyFileSync(dbPath, backupPath);
161
- console.error(`[context-mcp] Backed up old database to: ${backupPath}`);
157
+ console.error(`[context-vault] Backed up old database to: ${backupPath}`);
162
158
  }
163
159
  } catch (backupErr) {
164
- console.error(`[context-mcp] Warning: could not backup old database: ${backupErr.message}`);
160
+ console.error(`[context-vault] Warning: could not backup old database: ${backupErr.message}`);
165
161
  }
166
162
 
167
163
  unlinkSync(dbPath);
@@ -222,7 +218,7 @@ export function prepareStatements(db) {
222
218
  } catch (e) {
223
219
  throw new Error(
224
220
  `Failed to prepare database statements. The database may be corrupted.\n` +
225
- `Try deleting and rebuilding: rm "${db.name}" && context-mcp reindex\n` +
221
+ `Try deleting and rebuilding: rm "${db.name}" && context-vault reindex\n` +
226
222
  `Original error: ${e.message}`
227
223
  );
228
224
  }
@@ -5,17 +5,10 @@
5
5
  * disk issues), semantic search is disabled but FTS still works.
6
6
  */
7
7
 
8
- import { pipeline, env } from "@huggingface/transformers";
9
8
  import { join } from "node:path";
10
9
  import { homedir } from "node:os";
11
10
  import { mkdirSync } from "node:fs";
12
11
 
13
- // Redirect model cache to ~/.context-mcp/models/ so it works when the
14
- // package is installed globally in a root-owned directory (e.g. /usr/lib/node_modules/).
15
- const modelCacheDir = join(homedir(), ".context-mcp", "models");
16
- mkdirSync(modelCacheDir, { recursive: true });
17
- env.cacheDir = modelCacheDir;
18
-
19
12
  let extractor = null;
20
13
 
21
14
  /** @type {null | true | false} null = unknown, true = working, false = failed */
@@ -26,14 +19,25 @@ async function ensurePipeline() {
26
19
  if (extractor) return extractor;
27
20
 
28
21
  try {
29
- console.error("[context-mcp] Loading embedding model (first run may download ~22MB)...");
22
+ // Dynamic import @huggingface/transformers is optional (its transitive
23
+ // dep `sharp` can fail to install on some platforms). When missing, the
24
+ // server still works with full-text search only.
25
+ const { pipeline, env } = await import("@huggingface/transformers");
26
+
27
+ // Redirect model cache to ~/.context-mcp/models/ so it works when the
28
+ // package is installed globally in a root-owned directory (e.g. /usr/lib/node_modules/).
29
+ const modelCacheDir = join(homedir(), ".context-mcp", "models");
30
+ mkdirSync(modelCacheDir, { recursive: true });
31
+ env.cacheDir = modelCacheDir;
32
+
33
+ console.error("[context-vault] Loading embedding model (first run may download ~22MB)...");
30
34
  extractor = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
31
35
  embedAvailable = true;
32
36
  return extractor;
33
37
  } catch (e) {
34
38
  embedAvailable = false;
35
- console.error(`[context-mcp] Failed to load embedding model: ${e.message}`);
36
- console.error(`[context-mcp] Semantic search disabled. Full-text search still works.`);
39
+ console.error(`[context-vault] Failed to load embedding model: ${e.message}`);
40
+ console.error(`[context-vault] Semantic search disabled. Full-text search still works.`);
37
41
  return null;
38
42
  }
39
43
  }
@@ -16,6 +16,7 @@ import { gatherVaultStatus } from "../core/status.js";
16
16
  import { categoryFor } from "../core/categories.js";
17
17
  import { normalizeKind } from "../core/files.js";
18
18
  import { ok, err, ensureVaultExists, ensureValidKind } from "./helpers.js";
19
+ import { isEmbedAvailable } from "../index/embed.js";
19
20
 
20
21
  /**
21
22
  * Register all MCP tools on the server.
@@ -23,10 +24,37 @@ import { ok, err, ensureVaultExists, ensureValidKind } from "./helpers.js";
23
24
  * @param {import("@modelcontextprotocol/sdk/server/mcp.js").McpServer} server
24
25
  * @param {{ db, config, stmts, embed, insertVec, deleteVec }} ctx
25
26
  */
27
+ const TOOL_TIMEOUT_MS = 60_000;
28
+
26
29
  export function registerTools(server, ctx) {
27
30
  const { config } = ctx;
28
31
  const userId = ctx.userId !== undefined ? ctx.userId : undefined;
29
32
 
33
+ // ─── Tool wrapper: tracks in-flight ops for graceful shutdown + timeout ────
34
+
35
+ function tracked(handler) {
36
+ return async (...args) => {
37
+ if (ctx.activeOps) ctx.activeOps.count++;
38
+ let timer;
39
+ try {
40
+ return await Promise.race([
41
+ Promise.resolve(handler(...args)),
42
+ new Promise((_, reject) => {
43
+ timer = setTimeout(() => reject(new Error("TOOL_TIMEOUT")), TOOL_TIMEOUT_MS);
44
+ }),
45
+ ]);
46
+ } catch (e) {
47
+ if (e.message === "TOOL_TIMEOUT") {
48
+ return err("Tool timed out after 60s. Try a simpler query or run `context-vault reindex` first.", "TIMEOUT");
49
+ }
50
+ throw e;
51
+ } finally {
52
+ clearTimeout(timer);
53
+ if (ctx.activeOps) ctx.activeOps.count--;
54
+ }
55
+ };
56
+ }
57
+
30
58
  // ─── Auto-Reindex (runs once per session, on first tool call) ──────────────
31
59
 
32
60
  // In hosted mode, skip reindex — DB is always in sync via writeEntry→indexEntry
@@ -44,14 +72,14 @@ export function registerTools(server, ctx) {
44
72
  reindexDone = true;
45
73
  const total = stats.added + stats.updated + stats.removed;
46
74
  if (total > 0) {
47
- console.error(`[context-mcp] Auto-reindex: +${stats.added} ~${stats.updated} -${stats.removed} (${stats.unchanged} unchanged)`);
75
+ console.error(`[context-vault] Auto-reindex: +${stats.added} ~${stats.updated} -${stats.removed} (${stats.unchanged} unchanged)`);
48
76
  }
49
77
  })
50
78
  .catch((e) => {
51
79
  reindexAttempts++;
52
- console.error(`[context-mcp] Auto-reindex failed (attempt ${reindexAttempts}/${MAX_REINDEX_ATTEMPTS}): ${e.message}`);
80
+ console.error(`[context-vault] Auto-reindex failed (attempt ${reindexAttempts}/${MAX_REINDEX_ATTEMPTS}): ${e.message}`);
53
81
  if (reindexAttempts >= MAX_REINDEX_ATTEMPTS) {
54
- console.error(`[context-mcp] Giving up on auto-reindex. Run \`context-mcp reindex\` manually to diagnose.`);
82
+ console.error(`[context-vault] Giving up on auto-reindex. Run \`context-vault reindex\` manually to diagnose.`);
55
83
  reindexDone = true;
56
84
  reindexFailed = true;
57
85
  } else {
@@ -76,7 +104,7 @@ export function registerTools(server, ctx) {
76
104
  until: z.string().optional().describe("ISO date, return entries created before this"),
77
105
  limit: z.number().optional().describe("Max results to return (default 10)"),
78
106
  },
79
- async ({ query, kind, category, identity_key, tags, since, until, limit }) => {
107
+ tracked(async ({ query, kind, category, identity_key, tags, since, until, limit }) => {
80
108
  const hasQuery = query?.trim();
81
109
  const hasFilters = kind || category || tags?.length || since || until || identity_key;
82
110
  if (!hasQuery && !hasFilters) return err("Required: query or at least one filter (kind, category, tags, since, until, identity_key)", "INVALID_INPUT");
@@ -175,7 +203,8 @@ export function registerTools(server, ctx) {
175
203
  }
176
204
 
177
205
  const lines = [];
178
- if (reindexFailed) lines.push(`> **Warning:** Auto-reindex failed. Results may be stale. Run \`context-mcp reindex\` to fix.\n`);
206
+ if (reindexFailed) lines.push(`> **Warning:** Auto-reindex failed. Results may be stale. Run \`context-vault reindex\` to fix.\n`);
207
+ if (hasQuery && isEmbedAvailable() === false) lines.push(`> **Note:** Semantic search unavailable — results ranked by keyword match only. Run \`context-vault setup\` to download the embedding model.\n`);
179
208
  const heading = hasQuery ? `Results for "${query}"` : "Filtered entries";
180
209
  lines.push(`## ${heading} (${filtered.length} matches)\n`);
181
210
  for (let i = 0; i < filtered.length; i++) {
@@ -192,7 +221,7 @@ export function registerTools(server, ctx) {
192
221
  lines.push(`_Showing events from last ${config.eventDecayDays || 30} days. Use since/until for custom range._`);
193
222
  }
194
223
  return ok(lines.join("\n"));
195
- }
224
+ })
196
225
  );
197
226
 
198
227
  // ─── save_context (write / update) ────────────────────────────────────────
@@ -212,7 +241,7 @@ export function registerTools(server, ctx) {
212
241
  identity_key: z.string().optional().describe("Required for entity kinds (contact, project, tool, source). The unique identifier for this entity."),
213
242
  expires_at: z.string().optional().describe("ISO date for TTL expiry"),
214
243
  },
215
- async ({ id, kind, title, body, tags, meta, folder, source, identity_key, expires_at }) => {
244
+ tracked(async ({ id, kind, title, body, tags, meta, folder, source, identity_key, expires_at }) => {
216
245
  const vaultErr = ensureVaultExists(config);
217
246
  if (vaultErr) return vaultErr;
218
247
 
@@ -264,6 +293,17 @@ export function registerTools(server, ctx) {
264
293
  return err(`Entity kind "${kind}" requires identity_key`, "MISSING_IDENTITY_KEY");
265
294
  }
266
295
 
296
+ // Hosted tier limit enforcement (skipped in local mode — no checkLimits on ctx)
297
+ if (ctx.checkLimits) {
298
+ const usage = ctx.checkLimits();
299
+ if (usage.entryCount >= usage.maxEntries) {
300
+ return err(`Entry limit reached (${usage.maxEntries}). Upgrade to Pro for unlimited entries.`, "LIMIT_EXCEEDED");
301
+ }
302
+ if (usage.storageMb >= usage.maxStorageMb) {
303
+ return err(`Storage limit reached (${usage.maxStorageMb} MB). Upgrade to Pro for more storage.`, "LIMIT_EXCEEDED");
304
+ }
305
+ }
306
+
267
307
  await ensureIndexed();
268
308
 
269
309
  const mergedMeta = { ...(meta || {}) };
@@ -277,7 +317,7 @@ export function registerTools(server, ctx) {
277
317
  if (tags?.length) parts.push(` tags: ${tags.join(", ")}`);
278
318
  parts.push("", "_Use this id to update or delete later._");
279
319
  return ok(parts.join("\n"));
280
- }
320
+ })
281
321
  );
282
322
 
283
323
  // ─── list_context (browse) ────────────────────────────────────────────────
@@ -294,7 +334,7 @@ export function registerTools(server, ctx) {
294
334
  limit: z.number().optional().describe("Max results to return (default 20, max 100)"),
295
335
  offset: z.number().optional().describe("Skip first N results for pagination"),
296
336
  },
297
- async ({ kind, category, tags, since, until, limit, offset }) => {
337
+ tracked(async ({ kind, category, tags, since, until, limit, offset }) => {
298
338
  await ensureIndexed();
299
339
 
300
340
  const clauses = [];
@@ -342,7 +382,9 @@ export function registerTools(server, ctx) {
342
382
 
343
383
  if (!filtered.length) return ok("No entries found matching the given filters.");
344
384
 
345
- const lines = [`## Vault Entries (${filtered.length} shown, ${total} total)\n`];
385
+ const lines = [];
386
+ if (reindexFailed) lines.push(`> **Warning:** Auto-reindex failed. Results may be stale. Run \`context-vault reindex\` to fix.\n`);
387
+ lines.push(`## Vault Entries (${filtered.length} shown, ${total} total)\n`);
346
388
  for (const r of filtered) {
347
389
  const entryTags = r.tags ? JSON.parse(r.tags) : [];
348
390
  const tagStr = entryTags.length ? entryTags.join(", ") : "none";
@@ -355,7 +397,7 @@ export function registerTools(server, ctx) {
355
397
  }
356
398
 
357
399
  return ok(lines.join("\n"));
358
- }
400
+ })
359
401
  );
360
402
 
361
403
  // ─── delete_context (remove) ──────────────────────────────────────────────
@@ -366,7 +408,7 @@ export function registerTools(server, ctx) {
366
408
  {
367
409
  id: z.string().describe("The entry ULID to delete"),
368
410
  },
369
- async ({ id }) => {
411
+ tracked(async ({ id }) => {
370
412
  if (!id?.trim()) return err("Required: id (non-empty string)", "INVALID_INPUT");
371
413
  await ensureIndexed();
372
414
 
@@ -393,7 +435,7 @@ export function registerTools(server, ctx) {
393
435
  ctx.stmts.deleteEntry.run(id);
394
436
 
395
437
  return ok(`Deleted ${entry.kind}: ${entry.title || "(untitled)"} [${id}]`);
396
- }
438
+ })
397
439
  );
398
440
 
399
441
  // ─── submit_feedback (bug/feature reports) ────────────────────────────────
@@ -407,7 +449,7 @@ export function registerTools(server, ctx) {
407
449
  body: z.string().describe("Detailed description"),
408
450
  severity: z.enum(["low", "medium", "high"]).optional().describe("Severity level (default: medium)"),
409
451
  },
410
- async ({ type, title, body, severity }) => {
452
+ tracked(async ({ type, title, body, severity }) => {
411
453
  const vaultErr = ensureVaultExists(config);
412
454
  if (vaultErr) return vaultErr;
413
455
 
@@ -430,7 +472,7 @@ export function registerTools(server, ctx) {
430
472
 
431
473
  const relPath = entry.filePath ? entry.filePath.replace(config.vaultDir + "/", "") : entry.filePath;
432
474
  return ok(`Feedback submitted: ${type} [${effectiveSeverity}] → ${relPath}\n id: ${entry.id}\n title: ${title}`);
433
- }
475
+ })
434
476
  );
435
477
 
436
478
  // ─── context_status (diagnostics) ──────────────────────────────────────────
@@ -446,7 +488,7 @@ export function registerTools(server, ctx) {
446
488
  const healthIcon = hasIssues ? "⚠" : "✓";
447
489
 
448
490
  const lines = [
449
- `## ${healthIcon} Vault Status`,
491
+ `## ${healthIcon} Vault Status (connected)`,
450
492
  ``,
451
493
  `Vault: ${config.vaultDir} (${config.vaultDirExists ? status.fileCount + " files" : "missing"})`,
452
494
  `Database: ${config.dbPath} (${status.dbSize})`,
@@ -501,9 +543,9 @@ export function registerTools(server, ctx) {
501
543
 
502
544
  // Suggested actions
503
545
  const actions = [];
504
- if (status.stalePaths) actions.push("- Run `context-mcp reindex` to fix stale paths");
505
- if (status.embeddingStatus?.missing > 0) actions.push("- Run `context-mcp reindex` to generate missing embeddings");
506
- if (!config.vaultDirExists) actions.push("- Run `context-mcp setup` to create the vault directory");
546
+ if (status.stalePaths) actions.push("- Run `context-vault reindex` to fix stale paths");
547
+ if (status.embeddingStatus?.missing > 0) actions.push("- Run `context-vault reindex` to generate missing embeddings");
548
+ if (!config.vaultDirExists) actions.push("- Run `context-vault setup` to create the vault directory");
507
549
  if (status.kindCounts.length === 0 && config.vaultDirExists) actions.push("- Use `save_context` to add your first entry");
508
550
 
509
551
  if (actions.length) {
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "context-vault",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "type": "module",
5
5
  "description": "Persistent memory for AI agents — saves and searches knowledge across sessions",
6
6
  "bin": {
7
+ "context-vault": "bin/cli.js",
7
8
  "context-mcp": "bin/cli.js"
8
9
  },
9
10
  "main": "src/server/index.js",
@@ -19,19 +20,44 @@
19
20
  "bin/",
20
21
  "src/",
21
22
  "scripts/",
22
- "ui/",
23
23
  "README.md",
24
24
  "LICENSE"
25
25
  ],
26
26
  "license": "MIT",
27
- "engines": { "node": ">=20" },
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
28
30
  "author": "Felix Hellstrom",
29
- "repository": { "type": "git", "url": "git+https://github.com/fellanH/context-mcp.git" },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/fellanH/context-mcp.git"
34
+ },
30
35
  "homepage": "https://github.com/fellanH/context-mcp",
31
- "bugs": { "url": "https://github.com/fellanH/context-mcp/issues" },
32
- "keywords": ["mcp", "model-context-protocol", "ai", "knowledge-base", "knowledge-management", "vault", "rag", "sqlite", "embeddings", "claude", "cursor", "cline", "windsurf"],
33
- "bundledDependencies": ["@context-vault/core"],
36
+ "bugs": {
37
+ "url": "https://github.com/fellanH/context-mcp/issues"
38
+ },
39
+ "keywords": [
40
+ "mcp",
41
+ "model-context-protocol",
42
+ "ai",
43
+ "knowledge-base",
44
+ "knowledge-management",
45
+ "vault",
46
+ "rag",
47
+ "sqlite",
48
+ "embeddings",
49
+ "claude",
50
+ "cursor",
51
+ "cline",
52
+ "windsurf"
53
+ ],
54
+ "bundledDependencies": [
55
+ "@context-vault/core"
56
+ ],
34
57
  "dependencies": {
35
- "@context-vault/core": "^2.4.0"
58
+ "@context-vault/core": "^2.4.2",
59
+ "@modelcontextprotocol/sdk": "^1.26.0",
60
+ "better-sqlite3": "^12.6.2",
61
+ "sqlite-vec": "^0.1.0"
36
62
  }
37
63
  }