brains-mcp 1.69.1 → 1.70.0
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/bin/brains.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// GH #730 (local-first phase 3a): stdio launcher for the `brains` bin entry
|
|
3
|
+
// and the MCPB bundle's mcp_config.command. Not compiled by tsc (it lives
|
|
4
|
+
// outside src/, tsconfig's rootDir) so it can run standalone with zero
|
|
5
|
+
// resolution steps before the real server (dist/index.js) loads.
|
|
6
|
+
//
|
|
7
|
+
// A host launching this via MCPB always wants stdio, not the HTTP server
|
|
8
|
+
// dist/index.js defaults to — set BRAINS_TRANSPORT before importing it.
|
|
9
|
+
process.env.BRAINS_TRANSPORT ??= "stdio";
|
|
10
|
+
process.env.STORAGE_BACKEND ??= "local";
|
|
11
|
+
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { dirname, join } from "node:path";
|
|
14
|
+
|
|
15
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
await import(join(here, "..", "dist", "index.js"));
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type SearchIndexSyncStats } from "../search/sqliteIndex.js";
|
|
2
|
+
/**
|
|
3
|
+
* GH #643 (local-first phase 0): pull a cloud wiki down to a local WIKI_DIR.
|
|
4
|
+
*
|
|
5
|
+
* Two halves, kept separate so each is independently testable:
|
|
6
|
+
* - fetchExportZip: talks to the cloud instance's async export job
|
|
7
|
+
* (POST /api/v1/export -> GET /api/v1/export/download), never the MCP
|
|
8
|
+
* export_wiki inline zipData path (base64-overflows around 769 pages, #328).
|
|
9
|
+
* - hydrateLocalWikiFromZip: unpacks the zip into a local WIKI_DIR via the
|
|
10
|
+
* existing AdmZip-backed importWikiZip.runImportFromBuffer, then syncs the
|
|
11
|
+
* local SQLite search index so search works with no separate step.
|
|
12
|
+
*/
|
|
13
|
+
export interface ExportJob {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
jobId: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface JobStatus {
|
|
19
|
+
status: "queued" | "running" | "done" | "failed";
|
|
20
|
+
error?: string;
|
|
21
|
+
progress?: {
|
|
22
|
+
processed: number;
|
|
23
|
+
total: number;
|
|
24
|
+
phase: string;
|
|
25
|
+
};
|
|
26
|
+
result?: {
|
|
27
|
+
pageCount: number;
|
|
28
|
+
skippedCount: number;
|
|
29
|
+
generatedAt: string;
|
|
30
|
+
downloadUrl: string;
|
|
31
|
+
fileName: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface FetchExportOptions {
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
apiKey: string;
|
|
37
|
+
folder?: string;
|
|
38
|
+
tags?: string[];
|
|
39
|
+
since?: string;
|
|
40
|
+
includeSystem?: boolean;
|
|
41
|
+
/** Injectable for tests; defaults to the global fetch. */
|
|
42
|
+
fetchImpl?: typeof fetch;
|
|
43
|
+
pollIntervalMs?: number;
|
|
44
|
+
timeoutMs?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface ExportedZip {
|
|
47
|
+
buffer: Buffer;
|
|
48
|
+
pageCount: number;
|
|
49
|
+
skippedCount: number;
|
|
50
|
+
generatedAt: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function fetchExportZip(opts: FetchExportOptions): Promise<ExportedZip>;
|
|
53
|
+
export interface HydrateLocalWikiOptions {
|
|
54
|
+
/**
|
|
55
|
+
* How to handle a page that already exists locally with different content.
|
|
56
|
+
* Defaults to "skip" — a local edit is never silently clobbered (GH #643 AC5).
|
|
57
|
+
* Pass "overwrite" only when the caller has explicitly opted into replacing
|
|
58
|
+
* local state with the cloud copy.
|
|
59
|
+
*/
|
|
60
|
+
conflictStrategy?: "skip" | "overwrite" | "merge";
|
|
61
|
+
includeSystem?: boolean;
|
|
62
|
+
onProgress?: (processed: number, total: number, phase: string) => void;
|
|
63
|
+
}
|
|
64
|
+
export interface HydrateLocalWikiResult {
|
|
65
|
+
created: number;
|
|
66
|
+
updated: number;
|
|
67
|
+
skipped: number;
|
|
68
|
+
errors: Array<{
|
|
69
|
+
path: string;
|
|
70
|
+
reason: string;
|
|
71
|
+
}>;
|
|
72
|
+
warnings: Array<{
|
|
73
|
+
path: string;
|
|
74
|
+
reason: string;
|
|
75
|
+
}>;
|
|
76
|
+
/** Non-system page count reported by the source export job. */
|
|
77
|
+
expectedPageCount: number;
|
|
78
|
+
/** Of the zip's own pages, how many now exist on disk in WIKI_DIR. */
|
|
79
|
+
hydratedPageCount: number;
|
|
80
|
+
/** Zip page names that are still missing locally after hydration (should be empty). */
|
|
81
|
+
missingPages: string[];
|
|
82
|
+
index: SearchIndexSyncStats;
|
|
83
|
+
}
|
|
84
|
+
export declare function hydrateLocalWikiFromZip(wikiDir: string, zip: ExportedZip, opts?: HydrateLocalWikiOptions): Promise<HydrateLocalWikiResult>;
|
|
85
|
+
//# sourceMappingURL=hydrateWiki.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrateWiki.d.ts","sourceRoot":"","sources":["../../src/tools/hydrateWiki.ts"],"names":[],"mappings":"AAGA,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE3F;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,MAAM,CAAC,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0DnF;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;IAClD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxE;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAID,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,sBAAsB,CAAC,CAqCjC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import AdmZip from "adm-zip";
|
|
2
|
+
import { LocalClient } from "../storage/client.js";
|
|
3
|
+
import { runImportFromBuffer, isValidWikiFilename } from "./importWikiZip.js";
|
|
4
|
+
import { getSqliteSearchIndex } from "../search/sqliteIndex.js";
|
|
5
|
+
export async function fetchExportZip(opts) {
|
|
6
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
7
|
+
const baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
8
|
+
const params = new URLSearchParams();
|
|
9
|
+
if (opts.folder)
|
|
10
|
+
params.set("folder", opts.folder);
|
|
11
|
+
if (opts.tags?.length)
|
|
12
|
+
params.set("tags", opts.tags.join(","));
|
|
13
|
+
if (opts.since)
|
|
14
|
+
params.set("since", opts.since);
|
|
15
|
+
if (opts.includeSystem)
|
|
16
|
+
params.set("includeSystem", "true");
|
|
17
|
+
const createRes = await fetchImpl(`${baseUrl}/api/v1/export/download?${params}`, {
|
|
18
|
+
headers: { "x-api-key": opts.apiKey },
|
|
19
|
+
});
|
|
20
|
+
const created = (await createRes.json());
|
|
21
|
+
if (!createRes.ok || !created.ok) {
|
|
22
|
+
throw new Error(`hydrateWiki: export create failed: ${createRes.status} ${created.error ?? JSON.stringify(created)}`);
|
|
23
|
+
}
|
|
24
|
+
const timeoutMs = opts.timeoutMs ?? 15 * 60_000;
|
|
25
|
+
const pollIntervalMs = opts.pollIntervalMs ?? 2000;
|
|
26
|
+
const deadline = Date.now() + timeoutMs;
|
|
27
|
+
let job;
|
|
28
|
+
for (;;) {
|
|
29
|
+
if (Date.now() > deadline) {
|
|
30
|
+
throw new Error("hydrateWiki: export job timed out");
|
|
31
|
+
}
|
|
32
|
+
const pollRes = await fetchImpl(`${baseUrl}/api/v1/jobs/${created.jobId}`, {
|
|
33
|
+
headers: { "x-api-key": opts.apiKey },
|
|
34
|
+
});
|
|
35
|
+
const body = (await pollRes.json());
|
|
36
|
+
if (!pollRes.ok || !body.ok) {
|
|
37
|
+
throw new Error(`hydrateWiki: job poll failed: ${pollRes.status}`);
|
|
38
|
+
}
|
|
39
|
+
job = body.job;
|
|
40
|
+
if (job.status === "done")
|
|
41
|
+
break;
|
|
42
|
+
if (job.status === "failed") {
|
|
43
|
+
throw new Error(`hydrateWiki: export job failed: ${job.error ?? "unknown error"}`);
|
|
44
|
+
}
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
46
|
+
}
|
|
47
|
+
if (!job.result) {
|
|
48
|
+
throw new Error("hydrateWiki: export job reported done with no result");
|
|
49
|
+
}
|
|
50
|
+
const downloadRes = await fetchImpl(`${baseUrl}${job.result.downloadUrl}`, {
|
|
51
|
+
headers: { "x-api-key": opts.apiKey },
|
|
52
|
+
});
|
|
53
|
+
if (!downloadRes.ok) {
|
|
54
|
+
throw new Error(`hydrateWiki: export download failed: ${downloadRes.status}`);
|
|
55
|
+
}
|
|
56
|
+
const arrayBuffer = await downloadRes.arrayBuffer();
|
|
57
|
+
return {
|
|
58
|
+
buffer: Buffer.from(arrayBuffer),
|
|
59
|
+
pageCount: job.result.pageCount,
|
|
60
|
+
skippedCount: job.result.skippedCount,
|
|
61
|
+
generatedAt: job.result.generatedAt,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const SYSTEM_FILES = new Set(["index.md", "log.md"]);
|
|
65
|
+
export async function hydrateLocalWikiFromZip(wikiDir, zip, opts = {}) {
|
|
66
|
+
const drive = new LocalClient(wikiDir);
|
|
67
|
+
await drive.verifyAccess();
|
|
68
|
+
const includeSystem = opts.includeSystem ?? false;
|
|
69
|
+
const admZip = new AdmZip(zip.buffer);
|
|
70
|
+
const zipPageNames = admZip
|
|
71
|
+
.getEntries()
|
|
72
|
+
.filter((e) => !e.isDirectory)
|
|
73
|
+
.map((e) => e.entryName.replace(/\\/g, "/"))
|
|
74
|
+
.filter((name) => name !== "export-index.json")
|
|
75
|
+
.filter((name) => includeSystem || !SYSTEM_FILES.has(name))
|
|
76
|
+
.filter((name) => isValidWikiFilename(name));
|
|
77
|
+
const importResult = await runImportFromBuffer(drive, zip.buffer, {
|
|
78
|
+
conflictStrategy: opts.conflictStrategy ?? "skip",
|
|
79
|
+
includeSystem,
|
|
80
|
+
onProgress: opts.onProgress,
|
|
81
|
+
});
|
|
82
|
+
const index = getSqliteSearchIndex(wikiDir);
|
|
83
|
+
const indexStats = await index.syncNow(drive);
|
|
84
|
+
const localNames = new Set((await drive.listFiles()).map((f) => f.name));
|
|
85
|
+
const missingPages = zipPageNames.filter((name) => !localNames.has(name));
|
|
86
|
+
return {
|
|
87
|
+
created: importResult.created,
|
|
88
|
+
updated: importResult.updated,
|
|
89
|
+
skipped: importResult.skipped,
|
|
90
|
+
errors: importResult.errors,
|
|
91
|
+
warnings: importResult.warnings,
|
|
92
|
+
expectedPageCount: zip.pageCount,
|
|
93
|
+
hydratedPageCount: zipPageNames.length - missingPages.length,
|
|
94
|
+
missingPages,
|
|
95
|
+
index: indexStats,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=hydrateWiki.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrateWiki.js","sourceRoot":"","sources":["../../src/tools/hydrateWiki.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brains-mcp",
|
|
3
3
|
"mcpName": "io.github.spacecowboyian/brains",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.70.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/spacecowboyian/brains.git"
|
|
@@ -9,9 +9,13 @@
|
|
|
9
9
|
"description": "Personal wiki and memory MCP server for AI assistants — store, search, and recall structured notes from Claude and ChatGPT.",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
|
+
"bin": {
|
|
13
|
+
"brains": "bin/brains.js"
|
|
14
|
+
},
|
|
12
15
|
"files": [
|
|
13
16
|
"dist",
|
|
14
17
|
"!dist/editor",
|
|
18
|
+
"bin",
|
|
15
19
|
"README.md"
|
|
16
20
|
],
|
|
17
21
|
"scripts": {
|
|
@@ -34,6 +38,7 @@
|
|
|
34
38
|
"commitlint": "commitlint --edit",
|
|
35
39
|
"release": "semantic-release",
|
|
36
40
|
"release:dry": "semantic-release --dry-run --no-ci",
|
|
41
|
+
"build:mcpb": "npm run build && node scripts/build-mcpb.mjs",
|
|
37
42
|
"prepare": "husky",
|
|
38
43
|
"bench:convomem": "tsx benchmark/convomem/run.ts",
|
|
39
44
|
"bench:locomo": "tsx benchmark/locomo/run.ts",
|
|
@@ -64,6 +69,7 @@
|
|
|
64
69
|
}
|
|
65
70
|
},
|
|
66
71
|
"devDependencies": {
|
|
72
|
+
"@anthropic-ai/mcpb": "^2.1.2",
|
|
67
73
|
"@commitlint/cli": "^20.5.0",
|
|
68
74
|
"@commitlint/config-conventional": "^20.5.0",
|
|
69
75
|
"@semantic-release/changelog": "^6.0.3",
|