mind-palace-graph 0.3.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/INSTALL.md +387 -0
- package/README.md +602 -0
- package/dist/api.d.ts +682 -0
- package/dist/api.js +660 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +95 -0
- package/dist/cli.js +856 -0
- package/dist/cli.js.map +1 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.js +199 -0
- package/dist/format.js.map +1 -0
- package/dist/fuzzy.d.ts +45 -0
- package/dist/fuzzy.js +150 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +528 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +24 -0
- package/dist/mcp-server.js +187 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mind-palace.d.ts +148 -0
- package/dist/mind-palace.js +780 -0
- package/dist/mind-palace.js.map +1 -0
- package/dist/nodes.d.ts +57 -0
- package/dist/nodes.js +220 -0
- package/dist/nodes.js.map +1 -0
- package/dist/pagination.d.ts +41 -0
- package/dist/pagination.js +63 -0
- package/dist/pagination.js.map +1 -0
- package/dist/palace-format.d.ts +30 -0
- package/dist/palace-format.js +146 -0
- package/dist/palace-format.js.map +1 -0
- package/dist/rg.d.ts +34 -0
- package/dist/rg.js +288 -0
- package/dist/rg.js.map +1 -0
- package/dist/sources.d.ts +87 -0
- package/dist/sources.js +457 -0
- package/dist/sources.js.map +1 -0
- package/dist/tokens.d.ts +35 -0
- package/dist/tokens.js +95 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/mpg-context/SKILL.md +556 -0
- package/skills/mpg-context/references/anti-patterns.md +133 -0
- package/skills/mpg-context/references/integration.md +123 -0
- package/skills/mpg-context/references/mind-palace.md +217 -0
- package/skills/mpg-context/references/multi-agent.md +147 -0
- package/skills/mpg-context/references/sources.md +120 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Minimal MCP server for mpg.
|
|
4
|
+
*
|
|
5
|
+
* Exposes mpg as an MCP-compatible tool server. Drop this into
|
|
6
|
+
* Claude Desktop, Cline, Windsurf, or any MCP client.
|
|
7
|
+
*
|
|
8
|
+
* Tools: mpg_search, mpg_stash, mpg_list_stashes, mpg_get_stash,
|
|
9
|
+
* mpg_drop_stash, mpg_discover (--ls)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node mcp-server.js
|
|
13
|
+
* # or from the repo root:
|
|
14
|
+
* npx tsx mcp-server.ts
|
|
15
|
+
*
|
|
16
|
+
* Configuration (Claude Desktop mcp.json):
|
|
17
|
+
* {
|
|
18
|
+
* "mpg": {
|
|
19
|
+
* "command": "node",
|
|
20
|
+
* "args": ["path/to/mcp-server.js"]
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
import { search, stash, listStashes, getStash, dropStash } from "./api.js";
|
|
25
|
+
// Re-use the tool definitions from api.ts for MCP tool listing.
|
|
26
|
+
import { claudeTools } from "./api.js";
|
|
27
|
+
const log = (...args) => process.stderr.write(`[mpg-mcp] ${args.join(" ")}\n`);
|
|
28
|
+
async function handleRequest(req) {
|
|
29
|
+
switch (req.method) {
|
|
30
|
+
case "initialize":
|
|
31
|
+
return {
|
|
32
|
+
jsonrpc: "2.0",
|
|
33
|
+
id: req.id,
|
|
34
|
+
result: {
|
|
35
|
+
protocolVersion: "2024-11-05",
|
|
36
|
+
capabilities: { tools: {} },
|
|
37
|
+
serverInfo: { name: "mpg", version: "0.3.0" },
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
case "notifications/initialized":
|
|
41
|
+
return { jsonrpc: "2.0", result: {} };
|
|
42
|
+
case "tools/list":
|
|
43
|
+
return {
|
|
44
|
+
jsonrpc: "2.0",
|
|
45
|
+
id: req.id,
|
|
46
|
+
result: { tools: claudeTools.map((t) => t.function) },
|
|
47
|
+
};
|
|
48
|
+
case "tools/call": {
|
|
49
|
+
const params = req.params;
|
|
50
|
+
if (!params) {
|
|
51
|
+
return { jsonrpc: "2.0", id: req.id, error: { code: -32602, message: "Missing params" } };
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const result = await callTool(params.name, params.arguments ?? {});
|
|
55
|
+
return {
|
|
56
|
+
jsonrpc: "2.0",
|
|
57
|
+
id: req.id,
|
|
58
|
+
result: { content: [{ type: "text", text: result }] },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return {
|
|
63
|
+
jsonrpc: "2.0",
|
|
64
|
+
id: req.id,
|
|
65
|
+
error: { code: -32000, message: err.message },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
default:
|
|
70
|
+
return { jsonrpc: "2.0", id: req.id, error: { code: -32601, message: `Unknown method: ${req.method}` } };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function callTool(name, args) {
|
|
74
|
+
log(`tool call: ${name}`, JSON.stringify(args).slice(0, 200));
|
|
75
|
+
switch (name) {
|
|
76
|
+
case "mpg_search": {
|
|
77
|
+
const result = await search({
|
|
78
|
+
pattern: args.pattern,
|
|
79
|
+
in: args.in,
|
|
80
|
+
cmd: args.cmd,
|
|
81
|
+
url: args.url,
|
|
82
|
+
before: args.before,
|
|
83
|
+
after: args.after,
|
|
84
|
+
maxNodes: args.max_nodes,
|
|
85
|
+
maxTokens: args.max_tokens,
|
|
86
|
+
effort: args.effort,
|
|
87
|
+
strategy: args.strategy,
|
|
88
|
+
from: args.from,
|
|
89
|
+
compose: args.compose,
|
|
90
|
+
page: args.page,
|
|
91
|
+
pageSize: args.page_size,
|
|
92
|
+
});
|
|
93
|
+
return JSON.stringify(result, null, 2);
|
|
94
|
+
}
|
|
95
|
+
case "mpg_stash": {
|
|
96
|
+
// Run a search and stash the result in one call.
|
|
97
|
+
if (!args.pattern)
|
|
98
|
+
throw new Error("mpg_stash requires a pattern to search for.");
|
|
99
|
+
const searchResult = await search({
|
|
100
|
+
pattern: args.pattern,
|
|
101
|
+
in: args.in,
|
|
102
|
+
before: args.before,
|
|
103
|
+
after: args.after,
|
|
104
|
+
maxNodes: args.max_nodes,
|
|
105
|
+
effort: args.effort,
|
|
106
|
+
});
|
|
107
|
+
const stashResult = await stash(searchResult, {
|
|
108
|
+
name: args.name,
|
|
109
|
+
note: args.note ?? "",
|
|
110
|
+
tags: args.tags,
|
|
111
|
+
replace: args.replace,
|
|
112
|
+
palacePath: args.palace_path,
|
|
113
|
+
});
|
|
114
|
+
return JSON.stringify({ search: { total_nodes: searchResult.total_nodes, total_tokens: searchResult.total_tokens }, stash: stashResult }, null, 2);
|
|
115
|
+
}
|
|
116
|
+
case "mpg_list_stashes": {
|
|
117
|
+
const result = listStashes(args.palace_path, args.tag_filter);
|
|
118
|
+
return JSON.stringify(result.map((s) => ({
|
|
119
|
+
name: s.name,
|
|
120
|
+
note: s.note,
|
|
121
|
+
tags: s.tags,
|
|
122
|
+
nodes_count: s.nodes.length,
|
|
123
|
+
sources_count: s.sources.length,
|
|
124
|
+
relations_count: s.relations.length,
|
|
125
|
+
updated_at: s.updated_at,
|
|
126
|
+
expires_at: s.expires_at,
|
|
127
|
+
})), null, 2);
|
|
128
|
+
}
|
|
129
|
+
case "mpg_get_stash": {
|
|
130
|
+
const result = getStash(args.name, args.palace_path);
|
|
131
|
+
if (!result)
|
|
132
|
+
throw new Error(`No such stash: ${args.name}`);
|
|
133
|
+
// Default to the card view (no nodes block) — what an agent
|
|
134
|
+
// almost always wants. Pass `with_nodes: true` to recover the
|
|
135
|
+
// legacy full-content dump.
|
|
136
|
+
const withNodes = args.with_nodes === true;
|
|
137
|
+
if (!withNodes) {
|
|
138
|
+
const { nodes: _drop, ...card } = result;
|
|
139
|
+
return JSON.stringify({
|
|
140
|
+
...card,
|
|
141
|
+
view: "card",
|
|
142
|
+
nodes_count: result.nodes.length,
|
|
143
|
+
hint: "Pass with_nodes:true to dump the captured nodes block.",
|
|
144
|
+
}, null, 2);
|
|
145
|
+
}
|
|
146
|
+
return JSON.stringify({ ...result, view: "full" }, null, 2);
|
|
147
|
+
}
|
|
148
|
+
case "mpg_drop_stash": {
|
|
149
|
+
const ok = dropStash(args.name, args.palace_path);
|
|
150
|
+
return JSON.stringify({ dropped: ok, name: args.name });
|
|
151
|
+
}
|
|
152
|
+
default:
|
|
153
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ─── Read JSON-RPC from stdin, write to stdout ──────────────────────
|
|
157
|
+
let buffer = "";
|
|
158
|
+
process.stdin.setEncoding("utf8");
|
|
159
|
+
process.stdin.on("data", (chunk) => {
|
|
160
|
+
buffer += chunk;
|
|
161
|
+
// Process complete JSON-RPC messages (separated by newlines)
|
|
162
|
+
const lines = buffer.split("\n");
|
|
163
|
+
buffer = lines.pop();
|
|
164
|
+
for (const line of lines) {
|
|
165
|
+
if (!line.trim())
|
|
166
|
+
continue;
|
|
167
|
+
handleMessage(line);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
process.stdin.on("end", () => {
|
|
171
|
+
if (buffer.trim())
|
|
172
|
+
handleMessage(buffer);
|
|
173
|
+
});
|
|
174
|
+
async function handleMessage(line) {
|
|
175
|
+
let req;
|
|
176
|
+
try {
|
|
177
|
+
req = JSON.parse(line);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
log("invalid JSON:", line.slice(0, 100));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const resp = await handleRequest(req);
|
|
184
|
+
process.stdout.write(JSON.stringify(resp) + "\n");
|
|
185
|
+
}
|
|
186
|
+
log("MCP server started. Waiting for requests on stdin...");
|
|
187
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mind Palace — the LLM's instantiable short-term memory.
|
|
3
|
+
*
|
|
4
|
+
* The metaphor: an LLM harness doing multi-step investigation needs
|
|
5
|
+
* named, addressable memory slots it can write to, read from, and
|
|
6
|
+
* compose. The mind palace provides exactly that.
|
|
7
|
+
*
|
|
8
|
+
* --mp-stash <name> <note> instantiate a slot: run the search,
|
|
9
|
+
* stash the result, output as normal
|
|
10
|
+
* --mp-from <name> read from a slot as search input
|
|
11
|
+
* (re-runs the search fresh, scoped to
|
|
12
|
+
* the stashed file paths)
|
|
13
|
+
* --mp-compose <a> <b> ... read from multiple slots at once
|
|
14
|
+
* --mp-list [--tag t] inspect: what slots exist
|
|
15
|
+
* --mp-get <name> inspect: full contents of a slot
|
|
16
|
+
* --mp-drop <name> destroy: free a slot
|
|
17
|
+
*
|
|
18
|
+
* Storage: a JSON file (default `./.mpg/mind-palace.json`, project-
|
|
19
|
+
* scoped). Use `--mp-path` to point at a different file for isolated
|
|
20
|
+
* sessions. The LLM can have multiple palaces (one per task) just by
|
|
21
|
+
* pointing `--mp-path` at different files.
|
|
22
|
+
*/
|
|
23
|
+
import type { Node, Source } from "./types.js";
|
|
24
|
+
export declare const PALACE_VERSION = 1;
|
|
25
|
+
export declare const DEFAULT_PALACE_FILENAME = "mind-palace.json";
|
|
26
|
+
export declare const DEFAULT_PALACE_DIR = ".mpg";
|
|
27
|
+
/** A stashed collection of nodes plus the metadata of the search that produced them. */
|
|
28
|
+
export interface Stash {
|
|
29
|
+
name: string;
|
|
30
|
+
note: string;
|
|
31
|
+
tags: string[];
|
|
32
|
+
created_at: string;
|
|
33
|
+
updated_at: string;
|
|
34
|
+
/** ISO timestamp when this stash auto-expires, or null. */
|
|
35
|
+
expires_at: string | null;
|
|
36
|
+
search: {
|
|
37
|
+
pattern: string;
|
|
38
|
+
effort: string;
|
|
39
|
+
sources_count: number;
|
|
40
|
+
};
|
|
41
|
+
/** Source paths involved in the original search (for context). */
|
|
42
|
+
sources: string[];
|
|
43
|
+
/** The stashed nodes (subset of full Node: source + location + matched text snapshot). */
|
|
44
|
+
nodes: StashedNode[];
|
|
45
|
+
/** Source file paths (filesystem paths only, no cmd/url/stdin). */
|
|
46
|
+
file_paths: string[];
|
|
47
|
+
/** Relationships to other stashes. */
|
|
48
|
+
relations: StashRelation[];
|
|
49
|
+
}
|
|
50
|
+
/** A directed edge between two stashes. */
|
|
51
|
+
export interface StashRelation {
|
|
52
|
+
target: string;
|
|
53
|
+
type: string;
|
|
54
|
+
note: string;
|
|
55
|
+
created_at: string;
|
|
56
|
+
}
|
|
57
|
+
/** A compact, stash-friendly representation of a Node. */
|
|
58
|
+
export interface StashedNode {
|
|
59
|
+
source: string;
|
|
60
|
+
/** Canonical filesystem path, or null if source is not a file. */
|
|
61
|
+
file_path: string | null;
|
|
62
|
+
source_type: string;
|
|
63
|
+
match_line: number;
|
|
64
|
+
start_line: number;
|
|
65
|
+
end_line: number;
|
|
66
|
+
/** Snapshot of the match line and its context, so the stash is self-contained. */
|
|
67
|
+
context_before: string[];
|
|
68
|
+
match_text: string;
|
|
69
|
+
context_after: string[];
|
|
70
|
+
tokens: number;
|
|
71
|
+
}
|
|
72
|
+
export interface Palace {
|
|
73
|
+
version: number;
|
|
74
|
+
stashes: Record<string, Stash>;
|
|
75
|
+
}
|
|
76
|
+
/** Walk up from `start` looking for a mind-palace.json. Returns null if none found. */
|
|
77
|
+
export declare function findExistingPalace(start?: string): string | null;
|
|
78
|
+
/** Resolve the default palace path: env override, then git root, then
|
|
79
|
+
* nearest existing palace walking up, then CWD/.mpg/.
|
|
80
|
+
* This ensures the mind palace is project-scoped by default — even
|
|
81
|
+
* when invoked from a deep subdirectory. */
|
|
82
|
+
export declare function defaultPalacePath(): string;
|
|
83
|
+
export declare function loadPalace(path: string): Palace;
|
|
84
|
+
export declare function savePalace(path: string, palace: Palace): void;
|
|
85
|
+
/** Convert full Node objects into the compact StashedNode form. */
|
|
86
|
+
export declare function stashNodes(nodes: Node[]): StashedNode[];
|
|
87
|
+
/** Reverse: turn StashedNodes back into Sources (unique file paths). */
|
|
88
|
+
export declare function stashToSources(stash: Stash): Source[];
|
|
89
|
+
/** Add or merge a stash into the palace. Merge dedupes by (source, match_line). */
|
|
90
|
+
export declare function addStash(palace: Palace, name: string, note: string, nodes: Node[], meta: Stash["search"], sources: string[], tags?: string[], options?: {
|
|
91
|
+
replace?: boolean;
|
|
92
|
+
locations?: boolean;
|
|
93
|
+
ttl?: string;
|
|
94
|
+
}): {
|
|
95
|
+
stash: Stash;
|
|
96
|
+
action: "created" | "replaced" | "merged";
|
|
97
|
+
};
|
|
98
|
+
export declare function getStash(palace: Palace, name: string): Stash | null;
|
|
99
|
+
export declare function dropStash(palace: Palace, name: string): boolean;
|
|
100
|
+
export declare function listStashes(palace: Palace, tagFilter?: string[]): Stash[];
|
|
101
|
+
/** Compose multiple stashes into a single set of unique Sources. */
|
|
102
|
+
export declare function composeToSources(palace: Palace, names: string[]): Source[];
|
|
103
|
+
/** Set difference: files in `a` but not in any of `b`. */
|
|
104
|
+
export declare function exceptToSources(palace: Palace, a: string, b: string[]): Source[];
|
|
105
|
+
/** Set intersection: files in ALL of the given stashes. */
|
|
106
|
+
export declare function intersectToSources(palace: Palace, names: string[]): Source[];
|
|
107
|
+
/** Lightweight stash: only (source, line, match_text), no context buffers. */
|
|
108
|
+
export declare function stashNodesLocations(nodes: Node[]): StashedNode[];
|
|
109
|
+
/** Parse a human-readable duration into milliseconds.
|
|
110
|
+
* Accepts: "30s", "10m", "2h", "7d", "14d", or bare number (ms). */
|
|
111
|
+
export declare function parseDuration(s: string): number;
|
|
112
|
+
/** Format an ISO timestamp as a relative time string for display. */
|
|
113
|
+
export declare function formatRelativeTime(iso: string): string;
|
|
114
|
+
/** Compute an expiry timestamp from now + duration. */
|
|
115
|
+
export declare function expiryFromNow(duration: string): string;
|
|
116
|
+
export interface PruneResult {
|
|
117
|
+
removed: number;
|
|
118
|
+
names: string[];
|
|
119
|
+
dry_run: boolean;
|
|
120
|
+
}
|
|
121
|
+
/** Remove stashes whose updated_at is older than `duration`. */
|
|
122
|
+
export declare function pruneOlderThan(palace: Palace, duration: string, dryRun?: boolean): PruneResult;
|
|
123
|
+
/** Remove stashes whose expires_at is in the past. */
|
|
124
|
+
export declare function pruneExpired(palace: Palace, dryRun?: boolean): PruneResult;
|
|
125
|
+
/** Keep the N most recently updated stashes, remove the rest. */
|
|
126
|
+
export declare function pruneKeep(palace: Palace, n: number, dryRun?: boolean): PruneResult;
|
|
127
|
+
/** Remove all stashes with the given tag. */
|
|
128
|
+
export declare function pruneTag(palace: Palace, tag: string, dryRun?: boolean): PruneResult;
|
|
129
|
+
/** Remove all stashes. Requires explicit confirmation. */
|
|
130
|
+
export declare function pruneAll(palace: Palace, confirmed: boolean, dryRun?: boolean): PruneResult;
|
|
131
|
+
/** Add a directed relationship from `from` stash to `to` stash. */
|
|
132
|
+
export declare function addRelation(palace: Palace, from: string, to: string, type: string, note: string): StashRelation;
|
|
133
|
+
/** Remove a relationship from `from` to `to`. */
|
|
134
|
+
export declare function removeRelation(palace: Palace, from: string, to: string): boolean;
|
|
135
|
+
/** Get all stashes related to `name` (both outbound and inbound edges). */
|
|
136
|
+
export declare function getRelated(palace: Palace, name: string): Array<{
|
|
137
|
+
stash: Stash;
|
|
138
|
+
direction: "outbound" | "inbound";
|
|
139
|
+
relation: StashRelation;
|
|
140
|
+
}>;
|
|
141
|
+
/** Traverse the relationship graph from `name` up to `maxDepth` levels. */
|
|
142
|
+
export declare function traversalGraph(palace: Palace, name: string, maxDepth: number): Array<{
|
|
143
|
+
stash: Stash;
|
|
144
|
+
depth: number;
|
|
145
|
+
direction: "outbound" | "inbound";
|
|
146
|
+
via: string;
|
|
147
|
+
relation: StashRelation;
|
|
148
|
+
}>;
|