@llmnesia/mcp 0.2.5 → 0.2.7

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.
@@ -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.2.5" : "0.0.0-dev";
41
+ var VERSION = true ? "0.2.7" : "0.0.0-dev";
42
42
 
43
43
  export {
44
44
  __require,
@@ -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-BDR4JVMF.js";
6
+ } from "./chunk-CMQHGLAD.js";
7
7
 
8
8
  // src/config.ts
9
9
  import { readFileSync } from "fs";
@@ -13,14 +13,22 @@ var CORPUS_FORMAT_VERSION = 2;
13
13
  function nativeHostConfigPath() {
14
14
  return join(homedir(), ".llmnesia", "config.json");
15
15
  }
16
- function readNativeHostCorpusRoot() {
16
+ function readNativeHostConfig() {
17
17
  try {
18
18
  const parsed = JSON.parse(readFileSync(nativeHostConfigPath(), "utf8"));
19
- return typeof parsed.corpusRoot === "string" ? parsed.corpusRoot : void 0;
19
+ return parsed && typeof parsed === "object" ? parsed : void 0;
20
20
  } catch {
21
21
  return void 0;
22
22
  }
23
23
  }
24
+ function readNativeHostCorpusRoot() {
25
+ const root = readNativeHostConfig()?.corpusRoot;
26
+ return typeof root === "string" ? root : void 0;
27
+ }
28
+ function readNativeHostViewerExtensionId() {
29
+ const id = readNativeHostConfig()?.viewerExtensionId;
30
+ return typeof id === "string" ? id : void 0;
31
+ }
24
32
  function resolveCorpusDir(explicit) {
25
33
  const raw = explicit ?? process.env.LLMNESIA_CORPUS_DIR ?? readNativeHostCorpusRoot() ?? "~/.llmnesia/corpus";
26
34
  return expandHome(raw);
@@ -39,7 +47,7 @@ function expandHome(p) {
39
47
  import { join as join2 } from "path";
40
48
  import { readdir } from "fs/promises";
41
49
  import { createHash } from "crypto";
42
- var INDEX_FORMAT_VERSION = 3;
50
+ var INDEX_FORMAT_VERSION = 4;
43
51
  function indexDbFilename(version) {
44
52
  return version === 1 ? "llmnesia.db" : `llmnesia-v${version}.db`;
45
53
  }
@@ -200,6 +208,8 @@ function canonicalConversationDoc(c) {
200
208
  assignIfDefined(out, "origin", c.origin);
201
209
  assignIfDefined(out, "accountId", c.accountId);
202
210
  assignIfDefined(out, "accountLabel", c.accountLabel);
211
+ if (c.models && c.models.length > 0) out.models = [...c.models];
212
+ assignIfDefined(out, "modelMetadataUpdatedAt", c.modelMetadataUpdatedAt);
203
213
  if (c.summary) {
204
214
  out.summary = {
205
215
  text: c.summary.text,
@@ -219,6 +229,7 @@ function canonicalMessageDoc(m) {
219
229
  text: m.text
220
230
  };
221
231
  assignIfDefined(out, "formattedText", m.formattedText);
232
+ assignIfDefined(out, "model", m.model);
222
233
  out.createdAt = m.createdAt;
223
234
  out.updatedAt = m.updatedAt;
224
235
  out.contentHash = m.contentHash;
@@ -896,6 +907,9 @@ function coerceMessage(docId, value) {
896
907
  if (typeof m.formattedText === "string") {
897
908
  message.formattedText = m.formattedText;
898
909
  }
910
+ if (typeof m.model === "string" && m.model.trim()) {
911
+ message.model = m.model.trim();
912
+ }
899
913
  if (typeof m.platformMessageId === "string") {
900
914
  message.platformMessageId = m.platformMessageId;
901
915
  } else if (m.platformMessageId === null) {
@@ -1000,7 +1014,8 @@ CREATE TABLE IF NOT EXISTS conversations (
1000
1014
  preview TEXT NOT NULL,
1001
1015
  pinned INTEGER NOT NULL,
1002
1016
  accountId TEXT,
1003
- accountLabel TEXT
1017
+ accountLabel TEXT,
1018
+ models TEXT
1004
1019
  );
1005
1020
  CREATE INDEX IF NOT EXISTS idx_conversations_platform ON conversations(platform);
1006
1021
  CREATE INDEX IF NOT EXISTS idx_conversations_createdAt ON conversations(createdAt);
@@ -1074,8 +1089,8 @@ var SearchIndex = class {
1074
1089
  deleteConversation: this.db.prepare("DELETE FROM conversations WHERE docId = ?"),
1075
1090
  insertConversation: this.db.prepare(
1076
1091
  `INSERT INTO conversations
1077
- (docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned, accountId, accountLabel)
1078
- VALUES (@docId, @platform, @title, @url, @createdAt, @updatedAt, @messageCount, @preview, @pinned, @accountId, @accountLabel)`
1092
+ (docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned, accountId, accountLabel, models)
1093
+ VALUES (@docId, @platform, @title, @url, @createdAt, @updatedAt, @messageCount, @preview, @pinned, @accountId, @accountLabel, @models)`
1079
1094
  ),
1080
1095
  deleteMemoryFts: this.db.prepare("DELETE FROM memories_fts WHERE memoryId = ?"),
1081
1096
  insertMemoryFts: this.db.prepare(
@@ -1119,14 +1134,16 @@ var SearchIndex = class {
1119
1134
  const orderBy = sort === "oldest" ? "createdAt ASC, updatedAt ASC" : sort === "newest" ? "createdAt DESC, updatedAt DESC" : "updatedAt DESC, createdAt DESC";
1120
1135
  const rows = this.db.prepare(
1121
1136
  `SELECT docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned,
1122
- accountId, accountLabel
1137
+ accountId, accountLabel, models
1123
1138
  FROM conversations ORDER BY ${orderBy} LIMIT ?`
1124
1139
  ).all(limit);
1125
1140
  return rows.map((r) => {
1126
- const { accountId, accountLabel, ...rest } = r;
1141
+ const { accountId, accountLabel, models, ...rest } = r;
1127
1142
  const entry = { ...rest, pinned: r.pinned === 1 };
1128
1143
  if (accountId) entry.accountId = accountId;
1129
1144
  if (accountLabel) entry.accountLabel = accountLabel;
1145
+ const parsedModels = parseModels(models);
1146
+ if (parsedModels.length > 0) entry.models = parsedModels;
1130
1147
  return entry;
1131
1148
  });
1132
1149
  }
@@ -1213,7 +1230,8 @@ var SearchIndex = class {
1213
1230
  preview: conversation.preview ?? "",
1214
1231
  pinned: conversation.pinned ? 1 : 0,
1215
1232
  accountId: conversation.accountId ?? null,
1216
- accountLabel: conversation.accountLabel ?? null
1233
+ accountLabel: conversation.accountLabel ?? null,
1234
+ models: conversation.models?.length ? JSON.stringify(conversation.models) : null
1217
1235
  });
1218
1236
  }
1219
1237
  insertFtsRow(docId, msgIndex, role, text) {
@@ -1278,7 +1296,7 @@ var SearchIndex = class {
1278
1296
  const sql = `
1279
1297
  SELECT
1280
1298
  c.docId, c.platform, c.title, c.url, c.createdAt, c.updatedAt,
1281
- c.messageCount, c.preview, c.pinned, c.accountId, c.accountLabel,
1299
+ c.messageCount, c.preview, c.pinned, c.accountId, c.accountLabel, c.models,
1282
1300
  m.msgIndex AS msgIndex, m.role AS role,
1283
1301
  bm25(messages_fts) AS bm25
1284
1302
  FROM messages_fts
@@ -1314,6 +1332,8 @@ var SearchIndex = class {
1314
1332
  };
1315
1333
  if (row.accountId) hit.accountId = row.accountId;
1316
1334
  if (row.accountLabel) hit.accountLabel = row.accountLabel;
1335
+ const models = parseModels(row.models);
1336
+ if (models.length > 0) hit.models = models;
1317
1337
  hits.push(hit);
1318
1338
  if (hits.length >= limit) {
1319
1339
  break;
@@ -1394,6 +1414,15 @@ function normalizeMatchRole(role) {
1394
1414
  }
1395
1415
  return role === "assistant" || role === "user" || role === "system" ? role : "unknown";
1396
1416
  }
1417
+ function parseModels(value) {
1418
+ if (!value) return [];
1419
+ try {
1420
+ const parsed = JSON.parse(value);
1421
+ return Array.isArray(parsed) ? parsed.filter((model) => typeof model === "string" && model.trim().length > 0) : [];
1422
+ } catch {
1423
+ return [];
1424
+ }
1425
+ }
1397
1426
 
1398
1427
  // src/storageMaintenance.ts
1399
1428
  import { promises as fs4 } from "fs";
@@ -2063,6 +2092,7 @@ function describeOutcome(outcome) {
2063
2092
  }
2064
2093
 
2065
2094
  export {
2095
+ readNativeHostViewerExtensionId,
2066
2096
  resolveCorpusDir,
2067
2097
  staleIndexFiles,
2068
2098
  Corpus,
@@ -17,13 +17,13 @@ import {
17
17
  runtimeBinDir,
18
18
  staleIndexFiles,
19
19
  uninstallRuntime
20
- } from "./chunk-MTPXE734.js";
20
+ } from "./chunk-O34A5U2L.js";
21
21
  import {
22
22
  VERSION,
23
23
  __commonJS,
24
24
  __require,
25
25
  __toESM
26
- } from "./chunk-BDR4JVMF.js";
26
+ } from "./chunk-CMQHGLAD.js";
27
27
 
28
28
  // ../node_modules/isexe/windows.js
29
29
  var require_windows = __commonJS({
@@ -687,6 +687,7 @@ async function installNativeHost({ ids = [], corpus, codexHome, force = false, q
687
687
  }
688
688
  const allIds = [.../* @__PURE__ */ new Set([STORE_EXTENSION_ID, ...ids])];
689
689
  const allowedOrigins = allIds.map((id) => `chrome-extension://${id}/`);
690
+ const viewerExtensionId = ids[0] ?? STORE_EXTENSION_ID;
690
691
  if (await supportedBrowserCount(isWindows2) === 0) {
691
692
  throw new Error(
692
693
  "LLMnesia couldn't find Chrome, Brave, Edge, or Chromium. Open your browser once so it creates a profile, then retry. Safari and Firefox are not supported yet. Nothing was installed."
@@ -720,7 +721,7 @@ async function installNativeHost({ ids = [], corpus, codexHome, force = false, q
720
721
  corpusRootChanged = false;
721
722
  await writeFile(
722
723
  configPath,
723
- `${JSON.stringify({ ...existing, corpusRoot: existingRoot, codexHome: resolvedCodexHome }, null, 2)}
724
+ `${JSON.stringify({ ...existing, corpusRoot: existingRoot, codexHome: resolvedCodexHome, viewerExtensionId }, null, 2)}
724
725
  `,
725
726
  { encoding: "utf8", mode: 384 }
726
727
  );
@@ -732,7 +733,7 @@ async function installNativeHost({ ids = [], corpus, codexHome, force = false, q
732
733
  } else {
733
734
  await writeFile(
734
735
  configPath,
735
- `${JSON.stringify({ ...existing ?? {}, corpusRoot, codexHome: resolvedCodexHome }, null, 2)}
736
+ `${JSON.stringify({ ...existing ?? {}, corpusRoot, codexHome: resolvedCodexHome, viewerExtensionId }, null, 2)}
736
737
  `,
737
738
  { encoding: "utf8", mode: 384 }
738
739
  );
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-BDR4JVMF.js";
6
+ } from "./chunk-CMQHGLAD.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-OXKBAUBE.js");
144
+ const { main } = await import("./cli-XQUMZ3BU.js");
145
145
  return main();
146
146
  }
147
147
  bootstrap().then((code) => {
Binary file
package/dist/mcp.js CHANGED
@@ -8,16 +8,17 @@ import {
8
8
  drainInbox,
9
9
  openSearchIndex,
10
10
  pendingInboxFiles,
11
+ readNativeHostViewerExtensionId,
11
12
  resolveCorpusDir,
12
13
  runAutomaticMaintenance,
13
14
  scheduleSelfUpdate
14
- } from "./chunk-MTPXE734.js";
15
+ } from "./chunk-O34A5U2L.js";
15
16
  import {
16
17
  VERSION,
17
18
  __commonJS,
18
19
  __export,
19
20
  __toESM
20
- } from "./chunk-BDR4JVMF.js";
21
+ } from "./chunk-CMQHGLAD.js";
21
22
 
22
23
  // ../node_modules/ajv/dist/compile/codegen/code.js
23
24
  var require_code = __commonJS({
@@ -21677,7 +21678,27 @@ var LazyResource = class {
21677
21678
  function jsonResult(payload) {
21678
21679
  return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
21679
21680
  }
21680
- var SOURCE_LINK_INSTRUCTION = "When answering from these conversations, always include a Sources section with a clickable Markdown link to every original chat you relied on whose `url` is non-empty. Do this automatically; do not wait for the user to ask for links.";
21681
+ var SOURCE_LINK_INSTRUCTION = "When answering from these conversations, always include a Sources section with a clickable Markdown link to every chat you relied on. Link its `sourceUrl`: this is the original chat URL when available, otherwise an HTTPS hand-off that opens the local LLMnesia Viewer without sending the conversation id to the website. Do this automatically; do not wait for the user to ask for links.";
21682
+ var STORE_EXTENSION_ID = "leekfgbdojiaabifbjbbgiiclannjdkf";
21683
+ var EXTENSION_ID_RE = /^[a-p]{32}$/;
21684
+ var VIEWER_HANDOFF_URL = "https://llmnesia.com/open";
21685
+ function viewerExtensionId() {
21686
+ const configured = process.env.LLMNESIA_VIEWER_EXTENSION_ID?.trim() ?? readNativeHostViewerExtensionId();
21687
+ return configured && EXTENSION_ID_RE.test(configured) ? configured : STORE_EXTENSION_ID;
21688
+ }
21689
+ function viewerSourceUrl(docId, extensionId) {
21690
+ const fragment = new URLSearchParams({ docId, extensionId });
21691
+ return `${VIEWER_HANDOFF_URL}#${fragment.toString()}`;
21692
+ }
21693
+ function sourceLinks(docId, originalUrl) {
21694
+ const extensionId = viewerExtensionId();
21695
+ const localViewerUrl = `chrome-extension://${extensionId}/viewer.html?docId=${encodeURIComponent(docId)}`;
21696
+ return originalUrl ? { viewerUrl: localViewerUrl, sourceUrl: originalUrl, sourceKind: "original" } : {
21697
+ viewerUrl: localViewerUrl,
21698
+ sourceUrl: viewerSourceUrl(docId, extensionId),
21699
+ sourceKind: "viewer"
21700
+ };
21701
+ }
21681
21702
  function sourcedJsonResult(payload) {
21682
21703
  return jsonResult({ responseInstruction: SOURCE_LINK_INSTRUCTION, ...payload });
21683
21704
  }
@@ -21743,14 +21764,14 @@ async function runServe() {
21743
21764
  const server = new McpServer(
21744
21765
  { name: "llmnesia", version: VERSION },
21745
21766
  {
21746
- instructions: "LLMnesia is the user's searchable archive of past AI chats. Whenever the user asks about 'my chats', 'my conversations', or anything they previously said, discussed, decided, or worked on, use LLMnesia before built-in task/thread lists, local file scans, or memory, unless they explicitly ask only about Codex tasks. Use list_conversations with sort='oldest' for their earliest chat, search_conversations to find relevant prior chats, get_conversation to read a full transcript, and list_recent to see what they worked on lately. Search and list results carry a `corpus` block saying when the corpus last received data; if a chat the user expects is missing, check corpus_status before concluding it does not exist. Whenever you answer using LLMnesia, always include a Sources section with clickable links to the original chats you used when their `url` fields are non-empty; never wait for the user to ask."
21767
+ instructions: "LLMnesia is the user's searchable archive of past AI chats. Whenever the user asks about 'my chats', 'my conversations', or anything they previously said, discussed, decided, or worked on, use LLMnesia before built-in task/thread lists, local file scans, or memory, unless they explicitly ask only about Codex tasks. Use list_conversations with sort='oldest' for their earliest chat, search_conversations to find relevant prior chats, get_conversation to read a full transcript, and list_recent to see what they worked on lately. Search and list results carry a `corpus` block saying when the corpus last received data; if a chat the user expects is missing, check corpus_status before concluding it does not exist. Whenever you answer using LLMnesia, always include a Sources section with clickable links to the chats you used. Link each result's `sourceUrl`, which is its original URL when available or a clickable HTTPS hand-off to its local LLMnesia Viewer otherwise; never wait for the user to ask."
21747
21768
  }
21748
21769
  );
21749
21770
  server.registerTool(
21750
21771
  "search_conversations",
21751
21772
  {
21752
21773
  title: "Search conversations",
21753
- description: "Full-text search across the user's past AI conversations. Call this whenever the user asks what they said, thought, discussed, decided, or worked on previously \u2014 even if the question doesn't say 'search' \u2014 rather than answering from conversation memory alone or claiming no record exists. Returns matching conversations with a highlighted snippet, ranked by relevance. Defaults to recall-first matching (any term); pass match_mode to answer questions where a wrong hit matters, such as whether or how often something was discussed. Every result includes its original-chat URL when available; always link the chats used in the answer.",
21774
+ description: "Full-text search across the user's past AI conversations. Call this whenever the user asks what they said, thought, discussed, decided, or worked on previously \u2014 even if the question doesn't say 'search' \u2014 rather than answering from conversation memory alone or claiming no record exists. Returns matching conversations with a highlighted snippet, ranked by relevance. Defaults to recall-first matching (any term); pass match_mode to answer questions where a wrong hit matters, such as whether or how often something was discussed. Every result includes `sourceUrl`: the original chat URL when available, otherwise a clickable HTTPS hand-off to its local LLMnesia Viewer. Always link the chats used in the answer.",
21754
21775
  inputSchema: {
21755
21776
  query: external_exports.string().describe("Search terms (natural words; FTS operators are not needed)."),
21756
21777
  match_mode: external_exports.enum(["any", "all", "phrase"]).optional().describe(
@@ -21789,6 +21810,7 @@ async function runServe() {
21789
21810
  title: h.title,
21790
21811
  platform: h.platform,
21791
21812
  url: h.url,
21813
+ ...sourceLinks(h.docId, h.url),
21792
21814
  createdAt: h.createdAt,
21793
21815
  score: Number(h.score.toFixed(4)),
21794
21816
  snippet: h.snippet,
@@ -21798,6 +21820,7 @@ async function runServe() {
21798
21820
  };
21799
21821
  if (h.accountId) entry.accountId = h.accountId;
21800
21822
  if (h.accountLabel) entry.accountLabel = h.accountLabel;
21823
+ if (h.models?.length) entry.models = h.models;
21801
21824
  return entry;
21802
21825
  })
21803
21826
  });
@@ -21807,7 +21830,7 @@ async function runServe() {
21807
21830
  "get_conversation",
21808
21831
  {
21809
21832
  title: "Get conversation",
21810
- description: "Return the full transcript of one conversation by its id (the `id` from search results). The conversation includes its original-chat URL when available; always link it in an answer based on this transcript.",
21833
+ description: "Return the full transcript of one conversation by its id (the `id` from search results). The conversation includes `sourceUrl`: its original-chat URL when available, otherwise a clickable HTTPS hand-off to its local LLMnesia Viewer. Always link it in an answer based on this transcript.",
21811
21834
  inputSchema: {
21812
21835
  id: external_exports.string().describe("The conversation id (docId), e.g. 'claude:abc-123'.")
21813
21836
  },
@@ -21824,10 +21847,14 @@ async function runServe() {
21824
21847
  return errorResult(`No conversation found with id '${args.id}'.`);
21825
21848
  }
21826
21849
  return sourcedJsonResult({
21827
- conversation: record2.conversation,
21850
+ conversation: {
21851
+ ...record2.conversation,
21852
+ ...sourceLinks(record2.conversation.docId, record2.conversation.url)
21853
+ },
21828
21854
  messages: record2.messages.map((m) => ({
21829
21855
  index: m.msgIndex,
21830
21856
  role: m.role,
21857
+ ...m.model ? { model: m.model } : {},
21831
21858
  // Prefer the block-formatted copy; fall back to the search-collapsed text.
21832
21859
  text: m.formattedText ?? m.text
21833
21860
  }))
@@ -21838,7 +21865,7 @@ async function runServe() {
21838
21865
  "list_recent",
21839
21866
  {
21840
21867
  title: "List recent conversations",
21841
- description: "List the user's most recently updated conversations (title + summary + original-chat URL), newest first. Always link the chats used in the answer.",
21868
+ description: "List the user's most recently updated conversations (title + summary + source URL), newest first. `sourceUrl` is the original chat URL when available, otherwise a clickable HTTPS hand-off to its local LLMnesia Viewer. Always link the chats used in the answer.",
21842
21869
  inputSchema: {
21843
21870
  limit: external_exports.number().int().min(1).max(100).optional().describe("How many to return (default 10).")
21844
21871
  },
@@ -21861,6 +21888,7 @@ async function runServe() {
21861
21888
  title: e.title,
21862
21889
  platform: e.platform,
21863
21890
  url: e.url,
21891
+ ...sourceLinks(e.docId, e.url),
21864
21892
  updatedAt: e.updatedAt,
21865
21893
  messageCount: e.messageCount,
21866
21894
  pinned: e.pinned,
@@ -21868,6 +21896,7 @@ async function runServe() {
21868
21896
  };
21869
21897
  if (e.accountId) entry.accountId = e.accountId;
21870
21898
  if (e.accountLabel) entry.accountLabel = e.accountLabel;
21899
+ if (e.models?.length) entry.models = e.models;
21871
21900
  return entry;
21872
21901
  })
21873
21902
  });
@@ -21877,7 +21906,7 @@ async function runServe() {
21877
21906
  "list_conversations",
21878
21907
  {
21879
21908
  title: "List conversations by date",
21880
- description: "List conversation metadata in chronological order. Use sort='oldest' for the user's earliest or oldest chat, sort='newest' for most recently created chats, and sort='recent' for most recently updated chats. This is the complete corpus chronology, so do not scan LLMnesia's private files with shell commands. Entries include original-chat URLs when available; always link the chats used in the answer.",
21909
+ description: "List conversation metadata in chronological order. Use sort='oldest' for the user's earliest or oldest chat, sort='newest' for most recently created chats, and sort='recent' for most recently updated chats. This is the complete corpus chronology, so do not scan LLMnesia's private files with shell commands. Entries include `sourceUrl`: the original chat URL when available, otherwise a clickable HTTPS hand-off to the local LLMnesia Viewer. Always link the chats used in the answer.",
21881
21910
  inputSchema: {
21882
21911
  sort: external_exports.enum(["recent", "oldest", "newest"]).optional().describe("Chronology: recent (default, updated), oldest (created), or newest (created)."),
21883
21912
  limit: external_exports.number().int().min(1).max(100).optional().describe("How many to return (default 10).")
@@ -21902,6 +21931,7 @@ async function runServe() {
21902
21931
  title: e.title,
21903
21932
  platform: e.platform,
21904
21933
  url: e.url,
21934
+ ...sourceLinks(e.docId, e.url),
21905
21935
  createdAt: e.createdAt,
21906
21936
  updatedAt: e.updatedAt,
21907
21937
  messageCount: e.messageCount,
@@ -21910,6 +21940,7 @@ async function runServe() {
21910
21940
  };
21911
21941
  if (e.accountId) entry.accountId = e.accountId;
21912
21942
  if (e.accountLabel) entry.accountLabel = e.accountLabel;
21943
+ if (e.models?.length) entry.models = e.models;
21913
21944
  return entry;
21914
21945
  })
21915
21946
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmnesia/mcp",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
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.",
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.2.5",
6
+ "version": "0.2.7",
7
7
  "packages": [
8
8
  {
9
9
  "registryType": "npm",
10
10
  "registryBaseUrl": "https://registry.npmjs.org",
11
11
  "identifier": "@llmnesia/mcp",
12
- "version": "0.2.5",
12
+ "version": "0.2.7",
13
13
  "transport": {
14
14
  "type": "stdio"
15
15
  }