compendium-mcp 0.2.0 → 0.5.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/README.md +34 -33
- package/npm/lib/platform.js +54 -2
- package/package.json +8 -6
package/README.md
CHANGED
|
@@ -101,9 +101,9 @@ Single MCP tool: **`compendium`**. Choose the operation with `action`:
|
|
|
101
101
|
|
|
102
102
|
| `action` | Purpose | Main fields |
|
|
103
103
|
|----------|---------|-------------|
|
|
104
|
-
| `filter` | Strip ANSI, boilerplate, whitespace; densify JSON; keep/drop regexes | `text`, `filter` |
|
|
105
|
-
| `compress` | Dense representation of text/code/logs | `text`, `compress` |
|
|
106
|
-
| `compress_output` | Domain-aware stdout/stderr scrub (git, cargo, npm, docker, …) | `text`, `output` |
|
|
104
|
+
| `filter` | Strip ANSI, boilerplate, whitespace; densify JSON; keep/drop regexes | `text`, `filter` — not for cargo/npm dumps (`compress_output`) |
|
|
105
|
+
| `compress` | Dense representation of text/code/logs | `text`, `compress` — soft inputs under ~1000 chars bypass unless `force` |
|
|
106
|
+
| `compress_output` | Domain-aware stdout/stderr scrub (git, cargo, npm, docker, …) | `text`, `output` — prefer when CLI domain is known |
|
|
107
107
|
| `summarize` | Hierarchical summary (conversation / file tree / outline) | `text`, `summarize` |
|
|
108
108
|
| `summarize_smart` | Local-SLM dense summary (heuristic fallback if unset/fails) | `text`, `smart?`, `summarize?` |
|
|
109
109
|
| `filter_relevant` | Query-aware keep of relevant lines (local SLM + heuristic fallback) | `text`, `query`, `smart?` |
|
|
@@ -111,20 +111,20 @@ Single MCP tool: **`compendium`**. Choose the operation with `action`:
|
|
|
111
111
|
| `chunk` | Split into `cmp://` chunks (session-cached) | `text`, `chunk` |
|
|
112
112
|
| `resolve` | Fetch chunk content by id | `id` (+ optional `map` / `text`) |
|
|
113
113
|
| `count_tokens` | Measure tokens | `text` |
|
|
114
|
-
| `stats` | Session savings + latency/bypass/backend telemetry | `reset?` |
|
|
114
|
+
| `stats` | Session savings + latency/bypass/backend telemetry | `reset?` — see playbook `stats-debug` |
|
|
115
115
|
| `cache_store` | Park bulky payload outside the prompt | `text`, `cache` |
|
|
116
116
|
| `cache_get` | Retrieve by key | `key` |
|
|
117
117
|
| `cache_invalidate` | Drop one key or clear cache | `key?` |
|
|
118
|
-
| `sanitize` | Redact secrets + neutralize IPI phrases | `text`, `sanitize?` |
|
|
119
|
-
| `rerank` | BM25 (+ optional loopback embeddings) rank candidates / chunks | `query`, `items` or `text` or chunk `map`, `rerank?` |
|
|
118
|
+
| `sanitize` | Redact secrets + neutralize IPI phrases | `text`, `sanitize?` — or `sanitize_input` |
|
|
119
|
+
| `rerank` | BM25 (+ optional loopback embeddings + opt-in SLM cross-encoder) rank candidates / chunks | `query`, `items` or `text` or chunk `map`, `rerank?` |
|
|
120
120
|
| `brief` | Scan a workspace; pack a structured starter briefing + cache key | `query`, `brief?` (`root`, caps), optional `text` hint |
|
|
121
|
-
| `catalog` | Short action (+ playbook) ads; prefer before guessing | _(none)_ |
|
|
121
|
+
| `catalog` | Short action (+ playbook) ads; prefer before guessing | _(none)_ — call first when unsure |
|
|
122
122
|
| `help` | Usage notes for one action (default **compressed**; `force: true` → full) | `id`, `force?` |
|
|
123
123
|
| `playbooks` | List playbook ads | _(none)_ |
|
|
124
124
|
| `playbook` | Load one playbook body | `id` |
|
|
125
125
|
| `pack` | Zip text/files into a bounded archive | `text` or `items`, `pack?` |
|
|
126
126
|
| `unpack` | Unpack zip with size caps into chunks (never runs scripts) | `text` or `key`, `pack?` |
|
|
127
|
-
| `llm_status` | Probe configured local LLM (models; `force` = chat ping) | `force?` |
|
|
127
|
+
| `llm_status` | Probe configured local LLM (models; `force` = chat ping) | `force?` — when smart/hybrid unexpectedly heuristic |
|
|
128
128
|
|
|
129
129
|
### Progressive disclosure (skills)
|
|
130
130
|
|
|
@@ -162,22 +162,24 @@ Response envelope: `{ "ok": true, "action": "filter", "result_json": "{...}" }`.
|
|
|
162
162
|
assets/ # brand mark (SVG/PNG); baked into MCP icons via data URI
|
|
163
163
|
docs/ # architecture notes
|
|
164
164
|
examples/ # sample MCP tool-call JSON payloads
|
|
165
|
+
testdata/ # eval fixtures (noisy logs, cargo fail, …)
|
|
165
166
|
src/
|
|
166
167
|
main.rs # CLI: stdio | http
|
|
167
168
|
lib.rs
|
|
168
169
|
brand.rs # SEP-973 icons for serverInfo + tool
|
|
169
170
|
config.rs # COMPENDIUM_* env config
|
|
170
|
-
server
|
|
171
|
+
server/ # MCP tool + resources + action handlers (rmcp)
|
|
171
172
|
http.rs # Streamable HTTP/SSE (feature = "http")
|
|
172
173
|
pipeline/
|
|
174
|
+
brief/ # workspace brief (walk / window / pack / synthesize)
|
|
173
175
|
tokens.rs # heuristic or tiktoken BPE (feature = "real-tokens")
|
|
174
176
|
filter.rs
|
|
175
177
|
compress.rs
|
|
176
178
|
summarize.rs
|
|
177
179
|
smart.rs # summarize_smart + filter_relevant
|
|
178
|
-
local_llm.rs # OpenAI-compatible local SLM client
|
|
180
|
+
local_llm.rs # OpenAI-compatible local SLM client (+ embed cache)
|
|
179
181
|
chunk.rs # chunk + resolve
|
|
180
|
-
cache.rs # session key/value cache (+ optional disk)
|
|
182
|
+
cache.rs # session key/value cache (+ optional disk / embed vectors)
|
|
181
183
|
catalog.rs # action ads + help (progressive disclosure)
|
|
182
184
|
playbook.rs # bundled / dir playbooks
|
|
183
185
|
pack.rs # zip pack/unpack with size caps
|
|
@@ -188,6 +190,7 @@ playbooks/ # embedded skill-md playbooks
|
|
|
188
190
|
tests/
|
|
189
191
|
integration.rs
|
|
190
192
|
e2e_smoke.rs # spawns binary, MCP handshake, tools + resources
|
|
193
|
+
eval_regression.rs # B1 heuristic quality + latency smoke
|
|
191
194
|
CHANGELOG.md
|
|
192
195
|
REPORT.md # design essay + Shipped/Next/Deferred roadmap
|
|
193
196
|
```
|
|
@@ -269,6 +272,8 @@ Point an MCP streamable-HTTP client at that URL (e.g. `StreamableHttpClientTrans
|
|
|
269
272
|
| `COMPENDIUM_LOCAL_LLM_MODEL` | `Qwen3-4B-GGUF` | Model id on that server (Ollama: e.g. `qwen:latest`) |
|
|
270
273
|
| `COMPENDIUM_LOCAL_EMBED_MODEL` | _(same as chat)_ | Embeddings model for hybrid `rerank` / `brief` (e.g. `nomic-embed-text`) |
|
|
271
274
|
| `COMPENDIUM_HYBRID_ALPHA` | `0.55` | BM25 weight in hybrid score (0–1); remainder is embedding cosine |
|
|
275
|
+
| `COMPENDIUM_RERANK_CROSS_ENCODER` | _(off)_ | When `1`/`true`, `rerank` SLM-rescores top-N after BM25/hybrid |
|
|
276
|
+
| `COMPENDIUM_CROSS_ENCODER_TOP_N` | `16` | Candidates passed to cross-encoder (clamped 4–64) |
|
|
272
277
|
| `COMPENDIUM_AUDIT_PATH` | _(unset)_ | Append-only JSONL audit log (action metadata only; no payloads) |
|
|
273
278
|
| `COMPENDIUM_LOCAL_LLM_API_KEY` | _(unset)_ | Optional bearer token for locked loopback servers |
|
|
274
279
|
| `COMPENDIUM_LOCAL_LLM_TIMEOUT_SECS` | `120` | HTTP timeout (first model load can be slow) |
|
|
@@ -285,17 +290,17 @@ Point an MCP streamable-HTTP client at that URL (e.g. `StreamableHttpClientTrans
|
|
|
285
290
|
|
|
286
291
|
## Example tool calls
|
|
287
292
|
|
|
293
|
+
All calls use the single tool **`compendium`** with an `action` field.
|
|
294
|
+
|
|
288
295
|
**Filter noisy terminal output**
|
|
289
296
|
|
|
290
297
|
```json
|
|
291
298
|
{
|
|
292
|
-
"
|
|
293
|
-
"
|
|
294
|
-
|
|
295
|
-
"
|
|
296
|
-
|
|
297
|
-
"keep_patterns": ["ERROR|WARN"]
|
|
298
|
-
}
|
|
299
|
+
"action": "filter",
|
|
300
|
+
"text": "\u001b[31mERROR\u001b[0m boom\n\n\nINFO ok",
|
|
301
|
+
"filter": {
|
|
302
|
+
"strip_ansi": true,
|
|
303
|
+
"keep_patterns": ["ERROR|WARN"]
|
|
299
304
|
}
|
|
300
305
|
}
|
|
301
306
|
```
|
|
@@ -304,13 +309,11 @@ Point an MCP streamable-HTTP client at that URL (e.g. `StreamableHttpClientTrans
|
|
|
304
309
|
|
|
305
310
|
```json
|
|
306
311
|
{
|
|
307
|
-
"
|
|
308
|
-
"
|
|
309
|
-
|
|
310
|
-
"
|
|
311
|
-
|
|
312
|
-
"max_tokens": 512
|
|
313
|
-
}
|
|
312
|
+
"action": "compress",
|
|
313
|
+
"text": "...",
|
|
314
|
+
"compress": {
|
|
315
|
+
"content_type": "log",
|
|
316
|
+
"max_tokens": 512
|
|
314
317
|
}
|
|
315
318
|
}
|
|
316
319
|
```
|
|
@@ -319,14 +322,12 @@ Point an MCP streamable-HTTP client at that URL (e.g. `StreamableHttpClientTrans
|
|
|
319
322
|
|
|
320
323
|
```json
|
|
321
324
|
{
|
|
322
|
-
"
|
|
323
|
-
"
|
|
324
|
-
|
|
325
|
-
"
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
"overlap_tokens": 40
|
|
329
|
-
}
|
|
325
|
+
"action": "chunk",
|
|
326
|
+
"text": "... huge file ...",
|
|
327
|
+
"chunk": {
|
|
328
|
+
"source": "file:///path/to/doc.md",
|
|
329
|
+
"chunk_tokens": 400,
|
|
330
|
+
"overlap_tokens": 40
|
|
330
331
|
}
|
|
331
332
|
}
|
|
332
333
|
```
|
package/npm/lib/platform.js
CHANGED
|
@@ -7,10 +7,13 @@
|
|
|
7
7
|
* 1. Prefer optionalDependency platform packages (esbuild-style) — offline, fast.
|
|
8
8
|
* 2. Fall back to downloading the matching GitHub Release asset into a local cache.
|
|
9
9
|
* 3. Dev override: COMPENDIUM_BINARY or ./target/release/compendium.
|
|
10
|
+
* 4. Force key: COMPENDIUM_PLATFORM (e.g. linux-x64-musl).
|
|
10
11
|
*/
|
|
11
12
|
|
|
13
|
+
const fs = require('fs');
|
|
12
14
|
const os = require('os');
|
|
13
15
|
const path = require('path');
|
|
16
|
+
const { execSync } = require('child_process');
|
|
14
17
|
|
|
15
18
|
/** @typedef {{ pkg: string, asset: string, rustTarget: string }} PlatformSpec */
|
|
16
19
|
|
|
@@ -31,6 +34,11 @@ const PLATFORMS = {
|
|
|
31
34
|
asset: 'compendium-linux-x64',
|
|
32
35
|
rustTarget: 'x86_64-unknown-linux-gnu',
|
|
33
36
|
},
|
|
37
|
+
'linux-x64-musl': {
|
|
38
|
+
pkg: 'compendium-mcp-linux-x64-musl',
|
|
39
|
+
asset: 'compendium-linux-x64-musl',
|
|
40
|
+
rustTarget: 'x86_64-unknown-linux-musl',
|
|
41
|
+
},
|
|
34
42
|
'linux-arm64': {
|
|
35
43
|
pkg: 'compendium-mcp-linux-arm64',
|
|
36
44
|
asset: 'compendium-linux-arm64',
|
|
@@ -41,6 +49,11 @@ const PLATFORMS = {
|
|
|
41
49
|
asset: 'compendium-win32-x64.exe',
|
|
42
50
|
rustTarget: 'x86_64-pc-windows-msvc',
|
|
43
51
|
},
|
|
52
|
+
'win32-arm64': {
|
|
53
|
+
pkg: 'compendium-mcp-win32-arm64',
|
|
54
|
+
asset: 'compendium-win32-arm64.exe',
|
|
55
|
+
rustTarget: 'aarch64-pc-windows-msvc',
|
|
56
|
+
},
|
|
44
57
|
};
|
|
45
58
|
|
|
46
59
|
function packageVersion() {
|
|
@@ -56,15 +69,51 @@ function githubRepo() {
|
|
|
56
69
|
);
|
|
57
70
|
}
|
|
58
71
|
|
|
72
|
+
/** Best-effort musl detection (Alpine / static libc). Default is glibc. */
|
|
73
|
+
function isLinuxMusl() {
|
|
74
|
+
if (process.platform !== 'linux') return false;
|
|
75
|
+
try {
|
|
76
|
+
if (typeof process.report?.getReport === 'function') {
|
|
77
|
+
const report = process.report.getReport();
|
|
78
|
+
if (report?.header?.glibcVersionRuntime) return false;
|
|
79
|
+
}
|
|
80
|
+
} catch (_) {
|
|
81
|
+
/* ignore */
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
if (fs.existsSync('/etc/alpine-release')) return true;
|
|
85
|
+
} catch (_) {
|
|
86
|
+
/* ignore */
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const out = execSync('ldd --version 2>&1 || true', {
|
|
90
|
+
encoding: 'utf8',
|
|
91
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
92
|
+
});
|
|
93
|
+
if (/musl/i.test(out)) return true;
|
|
94
|
+
} catch (_) {
|
|
95
|
+
/* ignore */
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
59
100
|
/**
|
|
60
101
|
* Normalize Node's process.platform + process.arch into our key.
|
|
102
|
+
* Override with COMPENDIUM_PLATFORM when needed (e.g. linux-x64-musl).
|
|
61
103
|
* @returns {string}
|
|
62
104
|
*/
|
|
63
105
|
function platformKey() {
|
|
106
|
+
const forced = (process.env.COMPENDIUM_PLATFORM || '').trim();
|
|
107
|
+
if (forced) return forced;
|
|
108
|
+
|
|
64
109
|
const platform = process.platform;
|
|
65
110
|
let arch = process.arch;
|
|
66
111
|
// Rosetta / rare aliases
|
|
67
112
|
if (arch === 'ia32') arch = 'x64';
|
|
113
|
+
|
|
114
|
+
if (platform === 'linux' && arch === 'x64' && isLinuxMusl()) {
|
|
115
|
+
return 'linux-x64-musl';
|
|
116
|
+
}
|
|
68
117
|
return `${platform}-${arch}`;
|
|
69
118
|
}
|
|
70
119
|
|
|
@@ -78,7 +127,7 @@ function currentPlatform() {
|
|
|
78
127
|
const supported = Object.keys(PLATFORMS).join(', ');
|
|
79
128
|
throw new Error(
|
|
80
129
|
`Unsupported platform "${key}". Supported: ${supported}.\n` +
|
|
81
|
-
`Set COMPENDIUM_BINARY to a local build, or open an issue for this target.`
|
|
130
|
+
`Set COMPENDIUM_BINARY to a local build, COMPENDIUM_PLATFORM to a known key, or open an issue for this target.`
|
|
82
131
|
);
|
|
83
132
|
}
|
|
84
133
|
return spec;
|
|
@@ -89,7 +138,9 @@ function currentPlatform() {
|
|
|
89
138
|
* @param {PlatformSpec} [spec]
|
|
90
139
|
*/
|
|
91
140
|
function binaryName(spec = currentPlatform()) {
|
|
92
|
-
return process.platform === 'win32'
|
|
141
|
+
return process.platform === 'win32' || spec.asset.endsWith('.exe')
|
|
142
|
+
? 'compendium.exe'
|
|
143
|
+
: 'compendium';
|
|
93
144
|
}
|
|
94
145
|
|
|
95
146
|
/**
|
|
@@ -112,4 +163,5 @@ module.exports = {
|
|
|
112
163
|
currentPlatform,
|
|
113
164
|
binaryName,
|
|
114
165
|
cacheDir,
|
|
166
|
+
isLinuxMusl,
|
|
115
167
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "compendium-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "MCP server that compresses, summarizes, and filters context to minimize LLM token usage",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -38,11 +38,13 @@
|
|
|
38
38
|
"prepare": "node npm/scripts/link-bins.js"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
|
-
"compendium-mcp-darwin-arm64": "0.
|
|
42
|
-
"compendium-mcp-darwin-x64": "0.
|
|
43
|
-
"compendium-mcp-linux-x64": "0.
|
|
44
|
-
"compendium-mcp-linux-
|
|
45
|
-
"compendium-mcp-
|
|
41
|
+
"compendium-mcp-darwin-arm64": "0.5.0",
|
|
42
|
+
"compendium-mcp-darwin-x64": "0.5.0",
|
|
43
|
+
"compendium-mcp-linux-x64": "0.5.0",
|
|
44
|
+
"compendium-mcp-linux-x64-musl": "0.5.0",
|
|
45
|
+
"compendium-mcp-linux-arm64": "0.5.0",
|
|
46
|
+
"compendium-mcp-win32-x64": "0.5.0",
|
|
47
|
+
"compendium-mcp-win32-arm64": "0.5.0"
|
|
46
48
|
},
|
|
47
49
|
"preferUnplugged": true
|
|
48
50
|
}
|