@llmnesia/mcp 0.2.5 → 0.2.6
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/{chunk-MTPXE734.js → chunk-HL5QE57W.js} +12 -3
- package/dist/{chunk-BDR4JVMF.js → chunk-YRK2DRGG.js} +1 -1
- package/dist/{cli-OXKBAUBE.js → cli-DRB4DVH3.js} +5 -4
- package/dist/cli.js +2 -2
- package/dist/llmnesia.mcpb +0 -0
- package/dist/mcp.js +29 -9
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -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-
|
|
6
|
+
} from "./chunk-YRK2DRGG.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
|
|
16
|
+
function readNativeHostConfig() {
|
|
17
17
|
try {
|
|
18
18
|
const parsed = JSON.parse(readFileSync(nativeHostConfigPath(), "utf8"));
|
|
19
|
-
return typeof parsed
|
|
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);
|
|
@@ -2063,6 +2071,7 @@ function describeOutcome(outcome) {
|
|
|
2063
2071
|
}
|
|
2064
2072
|
|
|
2065
2073
|
export {
|
|
2074
|
+
readNativeHostViewerExtensionId,
|
|
2066
2075
|
resolveCorpusDir,
|
|
2067
2076
|
staleIndexFiles,
|
|
2068
2077
|
Corpus,
|
|
@@ -17,13 +17,13 @@ import {
|
|
|
17
17
|
runtimeBinDir,
|
|
18
18
|
staleIndexFiles,
|
|
19
19
|
uninstallRuntime
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-HL5QE57W.js";
|
|
21
21
|
import {
|
|
22
22
|
VERSION,
|
|
23
23
|
__commonJS,
|
|
24
24
|
__require,
|
|
25
25
|
__toESM
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YRK2DRGG.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-
|
|
6
|
+
} from "./chunk-YRK2DRGG.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-
|
|
144
|
+
const { main } = await import("./cli-DRB4DVH3.js");
|
|
145
145
|
return main();
|
|
146
146
|
}
|
|
147
147
|
bootstrap().then((code) => {
|
package/dist/llmnesia.mcpb
CHANGED
|
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-
|
|
15
|
+
} from "./chunk-HL5QE57W.js";
|
|
15
16
|
import {
|
|
16
17
|
VERSION,
|
|
17
18
|
__commonJS,
|
|
18
19
|
__export,
|
|
19
20
|
__toESM
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-YRK2DRGG.js";
|
|
21
22
|
|
|
22
23
|
// ../node_modules/ajv/dist/compile/codegen/code.js
|
|
23
24
|
var require_code = __commonJS({
|
|
@@ -21677,7 +21678,20 @@ 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
|
|
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 its local LLMnesia Viewer URL. 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
|
+
function viewerExtensionId() {
|
|
21685
|
+
const configured = process.env.LLMNESIA_VIEWER_EXTENSION_ID?.trim() ?? readNativeHostViewerExtensionId();
|
|
21686
|
+
return configured && EXTENSION_ID_RE.test(configured) ? configured : STORE_EXTENSION_ID;
|
|
21687
|
+
}
|
|
21688
|
+
function viewerUrl(docId) {
|
|
21689
|
+
return `chrome-extension://${viewerExtensionId()}/viewer.html?docId=${encodeURIComponent(docId)}`;
|
|
21690
|
+
}
|
|
21691
|
+
function sourceLinks(docId, originalUrl) {
|
|
21692
|
+
const localViewerUrl = viewerUrl(docId);
|
|
21693
|
+
return originalUrl ? { viewerUrl: localViewerUrl, sourceUrl: originalUrl, sourceKind: "original" } : { viewerUrl: localViewerUrl, sourceUrl: localViewerUrl, sourceKind: "viewer" };
|
|
21694
|
+
}
|
|
21681
21695
|
function sourcedJsonResult(payload) {
|
|
21682
21696
|
return jsonResult({ responseInstruction: SOURCE_LINK_INSTRUCTION, ...payload });
|
|
21683
21697
|
}
|
|
@@ -21743,14 +21757,14 @@ async function runServe() {
|
|
|
21743
21757
|
const server = new McpServer(
|
|
21744
21758
|
{ name: "llmnesia", version: VERSION },
|
|
21745
21759
|
{
|
|
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
|
|
21760
|
+
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 its local LLMnesia Viewer URL otherwise; never wait for the user to ask."
|
|
21747
21761
|
}
|
|
21748
21762
|
);
|
|
21749
21763
|
server.registerTool(
|
|
21750
21764
|
"search_conversations",
|
|
21751
21765
|
{
|
|
21752
21766
|
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
|
|
21767
|
+
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 its local LLMnesia Viewer URL. Always link the chats used in the answer.",
|
|
21754
21768
|
inputSchema: {
|
|
21755
21769
|
query: external_exports.string().describe("Search terms (natural words; FTS operators are not needed)."),
|
|
21756
21770
|
match_mode: external_exports.enum(["any", "all", "phrase"]).optional().describe(
|
|
@@ -21789,6 +21803,7 @@ async function runServe() {
|
|
|
21789
21803
|
title: h.title,
|
|
21790
21804
|
platform: h.platform,
|
|
21791
21805
|
url: h.url,
|
|
21806
|
+
...sourceLinks(h.docId, h.url),
|
|
21792
21807
|
createdAt: h.createdAt,
|
|
21793
21808
|
score: Number(h.score.toFixed(4)),
|
|
21794
21809
|
snippet: h.snippet,
|
|
@@ -21807,7 +21822,7 @@ async function runServe() {
|
|
|
21807
21822
|
"get_conversation",
|
|
21808
21823
|
{
|
|
21809
21824
|
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
|
|
21825
|
+
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 its local LLMnesia Viewer URL. Always link it in an answer based on this transcript.",
|
|
21811
21826
|
inputSchema: {
|
|
21812
21827
|
id: external_exports.string().describe("The conversation id (docId), e.g. 'claude:abc-123'.")
|
|
21813
21828
|
},
|
|
@@ -21824,7 +21839,10 @@ async function runServe() {
|
|
|
21824
21839
|
return errorResult(`No conversation found with id '${args.id}'.`);
|
|
21825
21840
|
}
|
|
21826
21841
|
return sourcedJsonResult({
|
|
21827
|
-
conversation:
|
|
21842
|
+
conversation: {
|
|
21843
|
+
...record2.conversation,
|
|
21844
|
+
...sourceLinks(record2.conversation.docId, record2.conversation.url)
|
|
21845
|
+
},
|
|
21828
21846
|
messages: record2.messages.map((m) => ({
|
|
21829
21847
|
index: m.msgIndex,
|
|
21830
21848
|
role: m.role,
|
|
@@ -21838,7 +21856,7 @@ async function runServe() {
|
|
|
21838
21856
|
"list_recent",
|
|
21839
21857
|
{
|
|
21840
21858
|
title: "List recent conversations",
|
|
21841
|
-
description: "List the user's most recently updated conversations (title + summary +
|
|
21859
|
+
description: "List the user's most recently updated conversations (title + summary + source URL), newest first. `sourceUrl` is the original chat URL when available, otherwise its local LLMnesia Viewer URL. Always link the chats used in the answer.",
|
|
21842
21860
|
inputSchema: {
|
|
21843
21861
|
limit: external_exports.number().int().min(1).max(100).optional().describe("How many to return (default 10).")
|
|
21844
21862
|
},
|
|
@@ -21861,6 +21879,7 @@ async function runServe() {
|
|
|
21861
21879
|
title: e.title,
|
|
21862
21880
|
platform: e.platform,
|
|
21863
21881
|
url: e.url,
|
|
21882
|
+
...sourceLinks(e.docId, e.url),
|
|
21864
21883
|
updatedAt: e.updatedAt,
|
|
21865
21884
|
messageCount: e.messageCount,
|
|
21866
21885
|
pinned: e.pinned,
|
|
@@ -21877,7 +21896,7 @@ async function runServe() {
|
|
|
21877
21896
|
"list_conversations",
|
|
21878
21897
|
{
|
|
21879
21898
|
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
|
|
21899
|
+
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 the local LLMnesia Viewer URL. Always link the chats used in the answer.",
|
|
21881
21900
|
inputSchema: {
|
|
21882
21901
|
sort: external_exports.enum(["recent", "oldest", "newest"]).optional().describe("Chronology: recent (default, updated), oldest (created), or newest (created)."),
|
|
21883
21902
|
limit: external_exports.number().int().min(1).max(100).optional().describe("How many to return (default 10).")
|
|
@@ -21902,6 +21921,7 @@ async function runServe() {
|
|
|
21902
21921
|
title: e.title,
|
|
21903
21922
|
platform: e.platform,
|
|
21904
21923
|
url: e.url,
|
|
21924
|
+
...sourceLinks(e.docId, e.url),
|
|
21905
21925
|
createdAt: e.createdAt,
|
|
21906
21926
|
updatedAt: e.updatedAt,
|
|
21907
21927
|
messageCount: e.messageCount,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llmnesia/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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.
|
|
6
|
+
"version": "0.2.6",
|
|
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.
|
|
12
|
+
"version": "0.2.6",
|
|
13
13
|
"transport": {
|
|
14
14
|
"type": "stdio"
|
|
15
15
|
}
|