@llmnesia/mcp 0.1.10 → 0.1.13

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/README.md CHANGED
@@ -48,13 +48,39 @@ The installer:
48
48
  1. sets up the native host that bridges the browser extension to your local
49
49
  corpus,
50
50
  2. copies the server into `~/.llmnesia/bin` so it has a permanent home,
51
- 3. sets up the supported desktop AI apps (Claude Code, Claude Desktop, Cursor,
51
+ 3. sets up the supported desktop AI apps (Claude Code, Cursor,
52
52
  and Codex/ChatGPT), and
53
53
  4. registers that copy using the client's own CLI where available, or with an
54
54
  automatic backup before editing its documented user config. It prepares all
55
55
  of those standard config paths, so an app installed later does not require
56
56
  running setup again.
57
57
 
58
+ Claude Desktop on Windows does not provide a supported API for third-party
59
+ installers to add a local desktop extension. LLMnesia therefore leaves any
60
+ existing Claude configuration untouched rather than claiming that Claude has
61
+ been connected.
62
+
63
+ ### Claude Desktop on Windows (current one-time manual step)
64
+
65
+ Until LLMnesia is available in Claude's extension directory, Claude Desktop on
66
+ Windows has one extra, manual step. First run `install` above so the local
67
+ browser bridge and corpus exist. Then download the official LLMnesia
68
+ `llmnesia.mcpb` desktop-extension file from LLMnesia and use Claude Desktop's
69
+ **Settings → Extensions → Install extension** flow to install it. Fully quit
70
+ and reopen Claude Desktop afterwards.
71
+
72
+ This is deliberately separate from the npm command: Claude does not provide a
73
+ supported Windows API for another installer to silently add an `.mcpb`
74
+ extension. The command therefore never edits Claude's internal extension state
75
+ or reports a false success. The packaged extension itself is read-only: it can
76
+ search, list, and read the local corpus but cannot modify it.
77
+
78
+ The future Claude Directory listing is a convenience distribution route, not a
79
+ dependency for the general LLMnesia release. It will replace this one manual
80
+ Claude step with Claude's own in-app install button if Anthropic selects the
81
+ extension. See [`docs/CLAUDE_DESKTOP_RELEASE_PLAN.md`](../docs/CLAUDE_DESKTOP_RELEASE_PLAN.md)
82
+ for the release and directory-submission plan.
83
+
58
84
  The `install` command is the approval to perform those setup steps. It does not
59
85
  interrupt setup with a separate prompt for every detected app, and it never
60
86
  prints existing client configurations or their credentials.
@@ -121,7 +147,7 @@ received data — check it before concluding a chat does not exist.
121
147
  | Client | How `install` wires it |
122
148
  | --- | --- |
123
149
  | Claude Code | Runs `claude mcp add --scope user` with the absolute Node and installed runtime paths when available. Otherwise it writes the documented user-scope `~/.claude.json` entry, so Windows users do not need the `claude` command on PATH. |
124
- | Claude Desktop | Edits `claude_desktop_config.json` at the standard OS-specific path, preparing it in advance if Claude Desktop is installed later. |
150
+ | Claude Desktop | macOS uses the working local JSON registration. On Windows, run `install` for browser sync, then install the official `llmnesia.mcpb` once in Claude Desktop; Claude exposes no supported external installation API for custom desktop extensions. |
125
151
  | Cursor | Edits `~/.cursor/mcp.json`, preparing it in advance if Cursor is installed later. |
126
152
  | Codex / ChatGPT desktop | Runs `codex mcp add` with the absolute runtime paths when available. If the bundled CLI is unavailable, the installer safely edits `~/.codex/config.toml` itself and backs up existing settings first, including preparing it for a later installation. Read-only LLMnesia tools are configured to run without repeated approval prompts; writes still ask. |
127
153
  | Others (Windsurf, Zed, LM Studio, …) | Prints the generic stdio block for you to paste. |
@@ -178,6 +204,23 @@ llmnesia-mcp --version # print the installed version
178
204
 
179
205
  Questions and bug reports: [hello@llmnesia.com](mailto:hello@llmnesia.com).
180
206
 
207
+ ## Privacy Policy
208
+
209
+ The MCP server reads and writes only the LLMnesia corpus stored on the user's
210
+ own computer. It does not upload conversation content, titles, URLs, prompts,
211
+ responses, or search queries to LLMnesia or to any third party, and it makes no
212
+ analytics or advertising requests of its own.
213
+
214
+ The browser extension separately sends limited, non-content product analytics
215
+ to PostHog. Conversation data and MCP searches are excluded. The complete
216
+ policy explains collection, local storage, third-party processing, retention,
217
+ deletion, and contact details:
218
+ [LLMnesia Privacy Policy](https://www.llmnesia.com/privacy-policy).
219
+
220
+ The local MCP corpus remains on the device until the user deletes it. Running
221
+ `uninstall` deliberately leaves that corpus intact so uninstalling the helper
222
+ cannot accidentally destroy the user's history.
223
+
181
224
  ## License
182
225
 
183
226
  MIT — see [LICENSE](./LICENSE).
@@ -38,7 +38,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
38
38
  ));
39
39
 
40
40
  // src/version.ts
41
- var VERSION = true ? "0.1.10" : "0.0.0-dev";
41
+ var VERSION = true ? "0.1.13" : "0.0.0-dev";
42
42
 
43
43
  export {
44
44
  __require,
@@ -15,7 +15,7 @@ import {
15
15
  __commonJS,
16
16
  __require,
17
17
  __toESM
18
- } from "./chunk-LA3BU5ZR.js";
18
+ } from "./chunk-7DAYOGB6.js";
19
19
 
20
20
  // ../node_modules/isexe/windows.js
21
21
  var require_windows = __commonJS({
@@ -3258,12 +3258,20 @@ async function registerClients(options) {
3258
3258
  )
3259
3259
  );
3260
3260
  if (claudeDesktop) {
3261
- results.push(
3262
- await safe(
3263
- "Claude Desktop",
3264
- () => registerJsonClient("Claude Desktop", claudeDesktop, options.serve, options.confirm, now, prepareMissing, false, false)
3265
- )
3266
- );
3261
+ if (osPlatform2 === "win32") {
3262
+ results.push({
3263
+ client: "Claude Desktop",
3264
+ action: "skipped",
3265
+ detail: "Automatic Claude Desktop setup is not available on Windows; existing configuration was left unchanged."
3266
+ });
3267
+ } else {
3268
+ results.push(
3269
+ await safe(
3270
+ "Claude Desktop",
3271
+ () => registerJsonClient("Claude Desktop", claudeDesktop, options.serve, options.confirm, now, prepareMissing, false, false)
3272
+ )
3273
+ );
3274
+ }
3267
3275
  }
3268
3276
  results.push(
3269
3277
  await safe("Cursor", () => registerJsonClient("Cursor", cursor, options.serve, options.confirm, now, prepareMissing))
@@ -3849,7 +3857,7 @@ function summarizeClientRegistrations(results) {
3849
3857
  return { connected, prepared, errors };
3850
3858
  }
3851
3859
  function formatInstallSuccess() {
3852
- return "\nSetup complete.\nFully close and reopen your browser and any desktop AI app you use.\nLLMnesia will be available in each supported desktop AI app you use.\nLLMnesia Settings will confirm when your history is ready.\n";
3860
+ return "\nSetup complete.\nFully close and reopen your browser and any desktop AI app you use.\nLLMnesia will be available in the desktop AI apps connected during setup.\nLLMnesia Settings will confirm when your history is ready.\n";
3853
3861
  }
3854
3862
  async function runInstall(positionals, options, flags) {
3855
3863
  let hadProblems = false;
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire as __llmnesiaCreateRequire } from "node:module";
3
3
  const require = __llmnesiaCreateRequire(import.meta.url);
4
4
  import {
5
5
  VERSION
6
- } from "./chunk-LA3BU5ZR.js";
6
+ } from "./chunk-7DAYOGB6.js";
7
7
 
8
8
  // src/nodeDownload.ts
9
9
  var NODE_DOWNLOAD_URLS = {
@@ -141,7 +141,7 @@ async function bootstrap() {
141
141
  await guideUnsupportedNodeVersion(process.versions.node);
142
142
  return 1;
143
143
  }
144
- const { main } = await import("./cli-VUTW2WGY.js");
144
+ const { main } = await import("./cli-OJM47LQR.js");
145
145
  return main();
146
146
  }
147
147
  bootstrap().then((code) => {
Binary file
package/dist/mcp.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  __commonJS,
14
14
  __export,
15
15
  __toESM
16
- } from "./chunk-LA3BU5ZR.js";
16
+ } from "./chunk-7DAYOGB6.js";
17
17
 
18
18
  // ../node_modules/ajv/dist/compile/codegen/code.js
19
19
  var require_code = __commonJS({
@@ -3211,8 +3211,8 @@ var require_utils = __commonJS({
3211
3211
  }
3212
3212
  return ind;
3213
3213
  }
3214
- function removeDotSegments(path) {
3215
- let input = path;
3214
+ function removeDotSegments(path2) {
3215
+ let input = path2;
3216
3216
  const output = [];
3217
3217
  let nextSlash = -1;
3218
3218
  let len = 0;
@@ -3464,8 +3464,8 @@ var require_schemes = __commonJS({
3464
3464
  wsComponent.secure = void 0;
3465
3465
  }
3466
3466
  if (wsComponent.resourceName) {
3467
- const [path, query] = wsComponent.resourceName.split("?");
3468
- wsComponent.path = path && path !== "/" ? path : void 0;
3467
+ const [path2, query] = wsComponent.resourceName.split("?");
3468
+ wsComponent.path = path2 && path2 !== "/" ? path2 : void 0;
3469
3469
  wsComponent.query = query;
3470
3470
  wsComponent.resourceName = void 0;
3471
3471
  }
@@ -7375,8 +7375,8 @@ function getErrorMap() {
7375
7375
 
7376
7376
  // ../node_modules/zod/v3/helpers/parseUtil.js
7377
7377
  var makeIssue = (params) => {
7378
- const { data, path, errorMaps, issueData } = params;
7379
- const fullPath = [...path, ...issueData.path || []];
7378
+ const { data, path: path2, errorMaps, issueData } = params;
7379
+ const fullPath = [...path2, ...issueData.path || []];
7380
7380
  const fullIssue = {
7381
7381
  ...issueData,
7382
7382
  path: fullPath
@@ -7492,11 +7492,11 @@ var errorUtil;
7492
7492
 
7493
7493
  // ../node_modules/zod/v3/types.js
7494
7494
  var ParseInputLazyPath = class {
7495
- constructor(parent, value, path, key) {
7495
+ constructor(parent, value, path2, key) {
7496
7496
  this._cachedPath = [];
7497
7497
  this.parent = parent;
7498
7498
  this.data = value;
7499
- this._path = path;
7499
+ this._path = path2;
7500
7500
  this._key = key;
7501
7501
  }
7502
7502
  get path() {
@@ -11133,10 +11133,10 @@ function assignProp(target, prop, value) {
11133
11133
  configurable: true
11134
11134
  });
11135
11135
  }
11136
- function getElementAtPath(obj, path) {
11137
- if (!path)
11136
+ function getElementAtPath(obj, path2) {
11137
+ if (!path2)
11138
11138
  return obj;
11139
- return path.reduce((acc, key) => acc?.[key], obj);
11139
+ return path2.reduce((acc, key) => acc?.[key], obj);
11140
11140
  }
11141
11141
  function promiseAllObject(promisesObj) {
11142
11142
  const keys = Object.keys(promisesObj);
@@ -11456,11 +11456,11 @@ function aborted(x, startIndex = 0) {
11456
11456
  }
11457
11457
  return false;
11458
11458
  }
11459
- function prefixIssues(path, issues) {
11459
+ function prefixIssues(path2, issues) {
11460
11460
  return issues.map((iss) => {
11461
11461
  var _a;
11462
11462
  (_a = iss).path ?? (_a.path = []);
11463
- iss.path.unshift(path);
11463
+ iss.path.unshift(path2);
11464
11464
  return iss;
11465
11465
  });
11466
11466
  }
@@ -14871,11 +14871,11 @@ function normalizeObjectSchema(schema) {
14871
14871
  }
14872
14872
  return void 0;
14873
14873
  }
14874
- function getDotPath(path) {
14875
- if (path.length === 0) {
14874
+ function getDotPath(path2) {
14875
+ if (path2.length === 0) {
14876
14876
  return "object root";
14877
14877
  }
14878
- return path.reduce((acc, seg, index) => {
14878
+ return path2.reduce((acc, seg, index) => {
14879
14879
  if (index === 0) {
14880
14880
  return String(seg);
14881
14881
  }
@@ -21131,6 +21131,11 @@ var StdioServerTransport = class {
21131
21131
  }
21132
21132
  };
21133
21133
 
21134
+ // src/mcp.ts
21135
+ import { realpathSync } from "fs";
21136
+ import { fileURLToPath } from "url";
21137
+ import path from "path";
21138
+
21134
21139
  // src/saveSchema.ts
21135
21140
  import { createHash } from "crypto";
21136
21141
  var saveMessageSchema = external_exports.object({
@@ -21360,6 +21365,51 @@ var CompanionService = class _CompanionService {
21360
21365
  function noop() {
21361
21366
  }
21362
21367
 
21368
+ // src/lazyResource.ts
21369
+ var ResourcePreparingError = class extends Error {
21370
+ constructor() {
21371
+ super("Resource is still preparing");
21372
+ this.name = "ResourcePreparingError";
21373
+ }
21374
+ };
21375
+ var LazyResource = class {
21376
+ constructor(open) {
21377
+ this.open = open;
21378
+ }
21379
+ open;
21380
+ resource = null;
21381
+ failure;
21382
+ completion = null;
21383
+ start() {
21384
+ if (this.completion) return;
21385
+ this.completion = Promise.resolve().then(() => this.open()).then(
21386
+ (resource) => {
21387
+ this.resource = resource;
21388
+ },
21389
+ (error2) => {
21390
+ this.failure = error2;
21391
+ }
21392
+ );
21393
+ }
21394
+ async get(waitMs) {
21395
+ this.start();
21396
+ if (this.resource) return this.resource;
21397
+ let timeout;
21398
+ await Promise.race([
21399
+ this.completion,
21400
+ new Promise((resolve) => {
21401
+ timeout = setTimeout(resolve, waitMs);
21402
+ })
21403
+ ]);
21404
+ if (timeout) clearTimeout(timeout);
21405
+ if (this.resource) return this.resource;
21406
+ if (this.failure) {
21407
+ throw this.failure;
21408
+ }
21409
+ throw new ResourcePreparingError();
21410
+ }
21411
+ };
21412
+
21363
21413
  // src/mcp.ts
21364
21414
  function jsonResult(payload) {
21365
21415
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
@@ -21387,13 +21437,25 @@ function parseDate(value) {
21387
21437
  }
21388
21438
  async function runServe() {
21389
21439
  const root = resolveCorpusDir(process.env.LLMNESIA_CORPUS_DIR);
21390
- const service = await CompanionService.open(root, {
21391
- // stdout is the MCP JSON-RPC channel, so diagnostics go to stderr.
21392
- onDrainError: (error2) => process.stderr.write(
21393
- `llmnesia: inbox drain failed, serving the existing index: ${error2 instanceof Error ? error2.message : String(error2)}
21440
+ const service = new LazyResource(
21441
+ () => CompanionService.open(root, {
21442
+ // stdout is the MCP JSON-RPC channel, so diagnostics go to stderr.
21443
+ onDrainError: (error2) => process.stderr.write(
21444
+ `llmnesia: inbox drain failed, serving the existing index: ${error2 instanceof Error ? error2.message : String(error2)}
21394
21445
  `
21395
- )
21396
- });
21446
+ )
21447
+ })
21448
+ );
21449
+ const withService = async (operation) => {
21450
+ try {
21451
+ return await operation(await service.get(5e3));
21452
+ } catch (err) {
21453
+ if (err instanceof ResourcePreparingError) {
21454
+ return errorResult("LLMnesia is still preparing the local conversation index. Retry this tool shortly.");
21455
+ }
21456
+ return errorResult(`LLMnesia could not open the local conversation index: ${err instanceof Error ? err.message : String(err)}`);
21457
+ }
21458
+ };
21397
21459
  const server = new McpServer(
21398
21460
  { name: "llmnesia", version: VERSION },
21399
21461
  {
@@ -21423,7 +21485,7 @@ async function runServe() {
21423
21485
  openWorldHint: false
21424
21486
  }
21425
21487
  },
21426
- async (args) => {
21488
+ async (args) => withService(async (service2) => {
21427
21489
  const filters = {
21428
21490
  platform: args.platform,
21429
21491
  title: args.title,
@@ -21432,8 +21494,8 @@ async function runServe() {
21432
21494
  limit: args.limit,
21433
21495
  matchMode: args.match_mode
21434
21496
  };
21435
- const hits = await service.search(args.query, filters);
21436
- const status = await service.corpusStatus({ refresh: false });
21497
+ const hits = await service2.search(args.query, filters);
21498
+ const status = await service2.corpusStatus({ refresh: false });
21437
21499
  return jsonResult({
21438
21500
  count: hits.length,
21439
21501
  corpus: corpusField(status),
@@ -21450,7 +21512,7 @@ async function runServe() {
21450
21512
  messageCount: h.messageCount
21451
21513
  }))
21452
21514
  });
21453
- }
21515
+ })
21454
21516
  );
21455
21517
  server.registerTool(
21456
21518
  "get_conversation",
@@ -21467,8 +21529,8 @@ async function runServe() {
21467
21529
  openWorldHint: false
21468
21530
  }
21469
21531
  },
21470
- async (args) => {
21471
- const record2 = await service.getConversation(args.id);
21532
+ async (args) => withService(async (service2) => {
21533
+ const record2 = await service2.getConversation(args.id);
21472
21534
  if (!record2) {
21473
21535
  return errorResult(`No conversation found with id '${args.id}'.`);
21474
21536
  }
@@ -21481,7 +21543,7 @@ async function runServe() {
21481
21543
  text: m.formattedText ?? m.text
21482
21544
  }))
21483
21545
  });
21484
- }
21546
+ })
21485
21547
  );
21486
21548
  server.registerTool(
21487
21549
  "list_recent",
@@ -21498,9 +21560,9 @@ async function runServe() {
21498
21560
  openWorldHint: false
21499
21561
  }
21500
21562
  },
21501
- async (args) => {
21502
- const entries = await service.listRecent(args.limit ?? 10);
21503
- const status = await service.corpusStatus({ refresh: false });
21563
+ async (args) => withService(async (service2) => {
21564
+ const entries = await service2.listRecent(args.limit ?? 10);
21565
+ const status = await service2.corpusStatus({ refresh: false });
21504
21566
  return jsonResult({
21505
21567
  count: entries.length,
21506
21568
  corpus: corpusField(status),
@@ -21514,7 +21576,7 @@ async function runServe() {
21514
21576
  summary: e.summary ?? e.preview
21515
21577
  }))
21516
21578
  });
21517
- }
21579
+ })
21518
21580
  );
21519
21581
  server.registerTool(
21520
21582
  "list_conversations",
@@ -21532,9 +21594,9 @@ async function runServe() {
21532
21594
  openWorldHint: false
21533
21595
  }
21534
21596
  },
21535
- async (args) => {
21536
- const entries = await service.listConversations(args.limit ?? 10, args.sort ?? "recent");
21537
- const status = await service.corpusStatus({ refresh: false });
21597
+ async (args) => withService(async (service2) => {
21598
+ const entries = await service2.listConversations(args.limit ?? 10, args.sort ?? "recent");
21599
+ const status = await service2.corpusStatus({ refresh: false });
21538
21600
  return jsonResult({
21539
21601
  count: entries.length,
21540
21602
  sort: args.sort ?? "recent",
@@ -21550,7 +21612,7 @@ async function runServe() {
21550
21612
  summary: e.summary ?? e.preview
21551
21613
  }))
21552
21614
  });
21553
- }
21615
+ })
21554
21616
  );
21555
21617
  server.registerTool(
21556
21618
  "corpus_status",
@@ -21565,39 +21627,49 @@ async function runServe() {
21565
21627
  openWorldHint: false
21566
21628
  }
21567
21629
  },
21568
- async () => {
21569
- const status = await service.corpusStatus();
21630
+ async () => withService(async (service2) => {
21631
+ const status = await service2.corpusStatus();
21570
21632
  return jsonResult(status);
21571
- }
21572
- );
21573
- server.registerTool(
21574
- "save_conversation",
21575
- {
21576
- title: "Save conversation",
21577
- description: "Add or update a conversation in the user's local corpus. Provide platform, title, and the messages; identity is keyed on docId (or platform:sourceId), so re-saving the same conversation updates it in place.",
21578
- inputSchema: saveConversationSchema.shape,
21579
- annotations: {
21580
- readOnlyHint: false,
21581
- destructiveHint: false,
21582
- idempotentHint: false,
21583
- openWorldHint: false
21584
- }
21585
- },
21586
- async (args) => {
21587
- try {
21588
- const result = await service.saveConversation(args);
21589
- return jsonResult(result);
21590
- } catch (err) {
21591
- return errorResult(`save_conversation failed: ${err instanceof Error ? err.message : String(err)}`);
21592
- }
21593
- }
21633
+ })
21594
21634
  );
21635
+ if (process.env.LLMNESIA_READ_ONLY !== "1") {
21636
+ server.registerTool(
21637
+ "save_conversation",
21638
+ {
21639
+ title: "Save conversation",
21640
+ description: "Add or update a conversation in the user's local corpus. Provide platform, title, and the messages; identity is keyed on docId (or platform:sourceId), so re-saving the same conversation updates it in place.",
21641
+ inputSchema: saveConversationSchema.shape,
21642
+ annotations: {
21643
+ readOnlyHint: false,
21644
+ destructiveHint: false,
21645
+ idempotentHint: false,
21646
+ openWorldHint: false
21647
+ }
21648
+ },
21649
+ async (args) => withService(async (service2) => {
21650
+ try {
21651
+ const result = await service2.saveConversation(args);
21652
+ return jsonResult(result);
21653
+ } catch (err) {
21654
+ return errorResult(`save_conversation failed: ${err instanceof Error ? err.message : String(err)}`);
21655
+ }
21656
+ })
21657
+ );
21658
+ }
21659
+ server.server.oninitialized = () => service.start();
21595
21660
  const transport = new StdioServerTransport();
21596
21661
  await server.connect(transport);
21597
- process.stderr.write(`llmnesia MCP server ready (corpus: ${root})
21662
+ process.stderr.write(`llmnesia MCP protocol ready; waiting for client initialization (${root})
21598
21663
  `);
21599
21664
  }
21600
- var isMain = import.meta.url === `file://${process.argv[1]}`;
21665
+ var isMain = (() => {
21666
+ if (!process.argv[1]) return false;
21667
+ try {
21668
+ return realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1]);
21669
+ } catch {
21670
+ return path.resolve(fileURLToPath(import.meta.url)) === path.resolve(process.argv[1]);
21671
+ }
21672
+ })();
21601
21673
  if (isMain) {
21602
21674
  runServe().catch((err) => {
21603
21675
  process.stderr.write(`Fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmnesia/mcp",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "comment:mcpName": "The MCP Registry's ownership marker: it must equal server.json's `name`, and the namespace must match how you authenticate with mcp-publisher. `com.llmnesia/...` requires DNS auth (a TXT record on llmnesia.com) — see docs/MCP_INSTALLER_BOARD.md.",
@@ -39,12 +39,14 @@
39
39
  "access": "public"
40
40
  },
41
41
  "scripts": {
42
- "build": "tsup",
42
+ "build": "tsup && npm run build:mcpb",
43
+ "build:mcpb": "node scripts/build-mcpb.mjs",
43
44
  "prepack": "npm run build",
44
45
  "dev": "tsx src/cli.ts",
45
46
  "mcp": "tsx src/mcp.ts",
46
47
  "typecheck": "tsc --noEmit",
47
- "test": "vitest run"
48
+ "test": "vitest run",
49
+ "test:mcpb": "node scripts/smoke-mcpb.mjs"
48
50
  },
49
51
  "comment:deps": "This package publishes with ZERO runtime dependencies — everything is bundled into dist by tsup (see noExternal in tsup.config.ts). That is not just an optimisation: `install` copies dist/ to ~/.llmnesia/bin so MCP clients can spawn it by absolute path, and nothing puts a node_modules beside that copy, so any unbundled import would fail there with ERR_MODULE_NOT_FOUND. Listing them as runtime deps would also be false comfort — npm would install them next to the package, not next to the copy that actually runs. The workspace packages additionally must not appear in the install graph at all: shared-types does not exist on the registry, and the published claude-code-host is an older build without the exports this package needs.",
50
52
  "devDependencies": {
@@ -52,6 +54,7 @@
52
54
  "@llmnesia/shared-types": "*",
53
55
  "@modelcontextprotocol/sdk": "^1.29.0",
54
56
  "@types/node": "^22.13.0",
57
+ "adm-zip": "^0.5.18",
55
58
  "chokidar": "^4.0.3",
56
59
  "cross-spawn": "^7.0.6",
57
60
  "fast-uri": "^3.1.5",
package/server.json CHANGED
@@ -3,13 +3,13 @@
3
3
  "name": "com.llmnesia/mcp",
4
4
  "title": "LLMnesia",
5
5
  "description": "Search your AI chat history from Claude, Cursor, Codex, and other MCP clients.",
6
- "version": "0.1.3",
6
+ "version": "0.1.13",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "registryBaseUrl": "https://registry.npmjs.org",
11
11
  "identifier": "@llmnesia/mcp",
12
- "version": "0.1.3",
12
+ "version": "0.1.13",
13
13
  "transport": {
14
14
  "type": "stdio"
15
15
  }