@cachly-dev/mcp-server 0.10.108 → 0.10.113

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 CHANGED
@@ -22,7 +22,7 @@
22
22
  <img src="https://img.shields.io/badge/GDPR-EU%20servers-green" alt="GDPR: EU servers" />
23
23
  </a>
24
24
  &nbsp;
25
- <img src="https://img.shields.io/badge/121%20MCP%20tools-violet" alt="121 MCP tools" />
25
+ <img src="https://img.shields.io/badge/136%20MCP%20tools-violet" alt="136 MCP tools" />
26
26
  &nbsp;
27
27
  <img src="https://img.shields.io/badge/License-Apache--2.0-yellow" alt="License: Apache-2.0" />
28
28
  </p>
@@ -246,7 +246,27 @@ npx @cachly-dev/mcp-server@latest learn-git # Auto-learn lessons from recent git
246
246
 
247
247
  ---
248
248
 
249
- ## MCP Tools (120 total)
249
+ ## CI integration — your pipeline teaches the Brain
250
+
251
+ Every CI run is a lesson: a red→green transition is a proven fix, a green→red one is a
252
+ known cause. Ready-to-paste templates live in
253
+ [`src/ci-integration/`](./src/ci-integration/):
254
+
255
+ - **GitHub Actions** — copy [`brain-from-ci-action.yml`](./src/ci-integration/brain-from-ci-action.yml)
256
+ into `.github/workflows/`. It triggers on `workflow_run` (completed) and pushes the
257
+ outcome to your Brain. Requires `CACHLY_JWT` + `CACHLY_BRAIN_INSTANCE_ID` secrets.
258
+ - **GitLab CI** — copy [`brain-from-ci-gitlab.yml`](./src/ci-integration/brain-from-ci-gitlab.yml)
259
+ into your pipeline: two `.post` jobs (`on_success` / `on_failure`) with `allow_failure: true`.
260
+ - **Anything else** — [`push-ci-outcome.mjs`](./src/ci-integration/push-ci-outcome.mjs) is a
261
+ standalone Node.js helper with zero dependencies. It always exits 0 — your CI never
262
+ fails because of a Brain push.
263
+
264
+ Already have months of CI history? Backfill it in one call with the **`brain_from_ci`**
265
+ MCP tool — bulk-ingests past outcomes the same way `brain_from_git` ingests commits.
266
+
267
+ ---
268
+
269
+ ## MCP Tools (136 total)
250
270
 
251
271
  ### 🧠 Session & Memory (most used)
252
272
 
@@ -286,6 +306,7 @@ npx @cachly-dev/mcp-server@latest learn-git # Auto-learn lessons from recent git
286
306
  | **`causal_trace`** | Root-cause analysis through the Causal Knowledge Graph |
287
307
  | **`brain_predict`** / `brain_predict_failures` | Predict likely failures before they happen |
288
308
  | **`brain_from_git`** | Bootstrap people + files + lessons from git history — incremental |
309
+ | **`brain_from_ci`** | Bulk-ingest CI outcomes: red→green becomes a fix lesson + causal `fixes` edge, green→red a `causes` edge — `brain_from_git` for CI logs |
289
310
  | `memory_consolidate` | Detect contradictions, merge duplicates, expire stale lessons |
290
311
  | `ckg_inspect` | Inspect the causal graph around any concept |
291
312
 
@@ -305,7 +326,8 @@ npx @cachly-dev/mcp-server@latest learn-git # Auto-learn lessons from recent git
305
326
  |------|-------------|
306
327
  | `syndicate` / `fedbrain_search` | Contribute to / search the global Knowledge Commons |
307
328
  | `brain_marketplace` / `brain_install` | Browse + install curated Domain Brains (Kubernetes, Auth, DB…) into your Brain |
308
- | `cache_get` / `cache_set` / `semantic_search` / `index_project` | Cache + semantic ops |
329
+ | `cache_get` / `cache_set` / `semantic_search` / `index_project` | Cache + semantic ops — pass `org_id` on `cache_get`/`cache_set` to share the cache org-wide (writes mirror to `org:{org_id}:sem`, reads fall back to it on miss) |
330
+ | `cache_stats` / `cache_org_stats` | Tokenmaxxing ROI: hits, estimated USD saved + monthly projection — per instance or aggregated across your whole org. Zero hits yet? You get a day-1 ROI projection instead. |
309
331
  | `list_instances` / `create_instance` / `delete_instance` | Manage Brain instances |
310
332
  | `roadmap_add` / `roadmap_next` | Persistent project roadmap stored in the Brain |
311
333
 
@@ -0,0 +1,21 @@
1
+ /** Bumped whenever the hook script changes so installers can upgrade old hooks. */
2
+ export declare const BRAIN_WATCH_HOOK_VERSION = "v1";
3
+ export type BrainWatchHookResult = 'written' | 'upgraded' | 'appended' | 'unchanged' | 'skipped-no-git';
4
+ /**
5
+ * Idempotently install/upgrade the brain_watch post-commit hook in `projectDir`.
6
+ * Never throws — returns a status string the caller can report. Safe to run
7
+ * repeatedly; a second call with the same version returns 'unchanged'.
8
+ */
9
+ export declare function installBrainWatchHook(projectDir: string, instanceId: string, apiKey?: string): Promise<{
10
+ result: BrainWatchHookResult;
11
+ hookPath: string;
12
+ }>;
13
+ /**
14
+ * Build the `.git/hooks/post-commit` shell script for brain_watch.
15
+ * Uses curl (not Node) so it works without npx. Runs in the background and
16
+ * always exits 0 — never blocks a commit.
17
+ *
18
+ * @param instanceId Cachly Brain instance to learn into.
19
+ * @param apiKey Optional cky_… key; if absent, the script reads $CACHLY_JWT from env.
20
+ */
21
+ export declare function buildBrainWatchHook(instanceId: string, apiKey?: string): string;
@@ -0,0 +1,86 @@
1
+ // Ambient git post-commit hook builder for Brain auto-learning.
2
+ //
3
+ // Installs a .git/hooks/post-commit script that POSTs the commit data
4
+ // directly to the cachly API via curl — no Node required at hook runtime,
5
+ // so it works even without npx or the MCP server installed locally.
6
+ //
7
+ // Safety contract:
8
+ // • exit 0 is ALWAYS the last line — the hook never blocks a commit.
9
+ // • All network calls run in the background (&) with 2>/dev/null.
10
+ // • Commit message / sha / files are never interpolated into JS source;
11
+ // they're passed as shell variables in the JSON body (curl --data-raw).
12
+ import { existsSync } from 'node:fs';
13
+ import { readFile, writeFile, chmod, mkdir } from 'node:fs/promises';
14
+ import { resolve } from 'node:path';
15
+ /** Bumped whenever the hook script changes so installers can upgrade old hooks. */
16
+ export const BRAIN_WATCH_HOOK_VERSION = 'v1';
17
+ /**
18
+ * Matches any previously-installed cachly brain_watch block (from its marker
19
+ * comment down to the trailing `exit 0`), optionally including a shebang.
20
+ * Used to upgrade old hooks in place rather than duplicating them.
21
+ */
22
+ const BRAIN_WATCH_BLOCK_RE = /(?:#!\/bin\/sh\n)?# cachly brain_watch[\s\S]*?\nexit 0\n?/;
23
+ /**
24
+ * Idempotently install/upgrade the brain_watch post-commit hook in `projectDir`.
25
+ * Never throws — returns a status string the caller can report. Safe to run
26
+ * repeatedly; a second call with the same version returns 'unchanged'.
27
+ */
28
+ export async function installBrainWatchHook(projectDir, instanceId, apiKey) {
29
+ if (!existsSync(resolve(projectDir, '.git'))) {
30
+ return { result: 'skipped-no-git', hookPath: '' };
31
+ }
32
+ const hookDir = resolve(projectDir, '.git', 'hooks');
33
+ const hookPath = resolve(hookDir, 'post-commit');
34
+ await mkdir(hookDir, { recursive: true });
35
+ const script = buildBrainWatchHook(instanceId, apiKey);
36
+ let existing = '';
37
+ try {
38
+ existing = await readFile(hookPath, 'utf-8');
39
+ }
40
+ catch { /* no existing hook */ }
41
+ if (!existing) {
42
+ await writeFile(hookPath, script + '\n', 'utf-8');
43
+ await chmod(hookPath, 0o755).catch(() => { });
44
+ return { result: 'written', hookPath };
45
+ }
46
+ if (existing.includes(`cachly brain_watch — Auto-Learn ${BRAIN_WATCH_HOOK_VERSION}`)) {
47
+ return { result: 'unchanged', hookPath };
48
+ }
49
+ if (BRAIN_WATCH_BLOCK_RE.test(existing)) {
50
+ const replaced = existing.replace(BRAIN_WATCH_BLOCK_RE, script);
51
+ await writeFile(hookPath, replaced.endsWith('\n') ? replaced : replaced + '\n', 'utf-8');
52
+ await chmod(hookPath, 0o755).catch(() => { });
53
+ return { result: 'upgraded', hookPath };
54
+ }
55
+ // Foreign hook with no brain_watch block → append ours.
56
+ await writeFile(hookPath, existing.trimEnd() + '\n\n' + script + '\n', 'utf-8');
57
+ await chmod(hookPath, 0o755).catch(() => { });
58
+ return { result: 'appended', hookPath };
59
+ }
60
+ /**
61
+ * Build the `.git/hooks/post-commit` shell script for brain_watch.
62
+ * Uses curl (not Node) so it works without npx. Runs in the background and
63
+ * always exits 0 — never blocks a commit.
64
+ *
65
+ * @param instanceId Cachly Brain instance to learn into.
66
+ * @param apiKey Optional cky_… key; if absent, the script reads $CACHLY_JWT from env.
67
+ */
68
+ export function buildBrainWatchHook(instanceId, apiKey) {
69
+ return [
70
+ `#!/bin/sh`,
71
+ `# cachly brain_watch — Auto-Learn ${BRAIN_WATCH_HOOK_VERSION}`,
72
+ `# Silently teaches your Brain after every commit — no manual brain_from_git needed.`,
73
+ ...(apiKey ? [`CACHLY_JWT="${apiKey}"`] : []),
74
+ `_BW_SHA=$(git rev-parse HEAD 2>/dev/null || echo "")`,
75
+ `_BW_MSG=$(git log -1 --pretty=%B 2>/dev/null | head -1 | cut -c1-200)`,
76
+ `_BW_FILES=$(git diff-tree --no-commit-id -r --name-only HEAD 2>/dev/null | tr '\\n' '\\t' | sed 's/\\t$//')`,
77
+ `(curl -s -o /dev/null -m 8 \\`,
78
+ ` -X POST "https://api.cachly.dev/api/v1/instances/${instanceId}/learn" \\`,
79
+ ` -H "Authorization: Bearer \${CACHLY_JWT}" \\`,
80
+ ` -H "Content-Type: application/json" \\`,
81
+ ` --data-raw "{\\"message\\":\\"$(echo "$_BW_MSG" | sed 's/"/\\\\"/g')\\",\\"sha\\":\\"$_BW_SHA\\",\\"files\\":[$(echo "$_BW_FILES" | tr '\\t' '\\n' | grep -v '^$' | sed 's/.*/\\"&\\"/' | tr '\\n' ',' | sed 's/,$//')],\\"source\\":\\"brain_watch\\"}" \\`,
82
+ `) 2>/dev/null &`,
83
+ `exit 0`,
84
+ ].join('\n');
85
+ }
86
+ //# sourceMappingURL=brain-watch-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-watch-hook.js","sourceRoot":"","sources":["../../src/brain-watch-hook.ts"],"names":[],"mappings":"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"}
@@ -7,8 +7,43 @@ import { keywordSearch, tokenize, splitMultiQuery, levenshtein, indexVocab as _i
7
7
  import { rerankByQuality } from '../rerank.js';
8
8
  import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
9
9
  // ── Changelog (shown once per version in session_start) ──────────────────────
10
- const MCP_VERSION = '0.10.108';
10
+ const MCP_VERSION = '0.10.113';
11
11
  const WHATS_NEW = {
12
+ '0.10.113': [
13
+ `📈 **Week-over-week savings trend in \`cache_stats\`**`,
14
+ ` 📅 \`cache_stats\` now shows **7-day hits** + **WoW trend %** (e.g. \`+23.0% vs prev week\`) so ROI momentum is visible, not just the cumulative total.`,
15
+ ` ⬇️ Goes red (📉) on drops, green (📈) on growth — first week always shows +100% (new).`,
16
+ ` 🔧 Backed by new \`CountHitsInWindow\` repo method + \`hits_last_7d\`, \`hits_prev_7d\`, \`week_over_week_pct\` fields in \`SavingsEstimate\`.`,
17
+ ` 📊 137 MCP tools`,
18
+ ],
19
+ '0.10.112': [
20
+ `⚙️ **Configurable cost_per_call_usd — accurate ROI for any LLM**`,
21
+ ` 💡 New \`set_cost_per_call\` tool: set your real per-call cost (claude-opus-4.8 → $0.02, gpt-5.5 → $0.015, claude-sonnet-4.6 → $0.009, claude-haiku-4.5 → $0.001) so savings estimates in \`cache_stats\` reflect your actual bill.`,
22
+ ` 🔧 New API: \`PUT /api/v1/instances/:id/cost-per-call\` — persisted per instance, used by \`cache_stats\`, org savings, and SSE analytics stream.`,
23
+ ` 📊 137 MCP tools`,
24
+ ],
25
+ '0.10.111': [
26
+ `🏢 **Org-wide ROI + GitLab CI — the CFO number, aggregated**`,
27
+ ` 💰 \`cache_org_stats\` now shows **org-wide Tokenmaxxing ROI**: total savings summed across every instance in your org, monthly projection, top-5 instances by savings. One number for the whole team.`,
28
+ ` 🔌 Backed by new API endpoint \`GET /api/v1/orgs/:id/savings\` (org members only)`,
29
+ ` 🦊 GitLab CI integration: \`brain-from-ci-gitlab.yml\` — two \`.post\` jobs (on_success/on_failure), same helper script, pipeline never fails because of Brain push`,
30
+ ` 🛠️ GitHub Action template fixed: \`secrets.*\` in job-level \`if\` is invalid — guard removed (helper script skips cleanly on missing secrets)`,
31
+ ` 📊 136 MCP tools`,
32
+ ],
33
+ '0.10.110': [
34
+ `🏢 **Zero friction: ROI-Projektor, Org-Shared-Cache, CI ready-to-paste**`,
35
+ ` 📈 \`cache_stats\` — zero-hit projection calculator: shows expected monthly savings for 5/10/20-dev teams before a single cache hit lands. ROI visible from day 1.`,
36
+ ` 🏢 New \`cache_org_stats\` — shared org-level cache stats across multiple instances. Convention-based (\`org:{id}:sem\`), zero API changes needed.`,
37
+ ` 🔗 \`cache_set\`/\`cache_get\` now accept optional \`org_id\` — write to personal + org namespace, fall back to org on miss. Fully backwards-compatible.`,
38
+ ` 📋 Copy-paste CI integration: \`brain-from-ci-action.yml\` → Brain self-calibrates confidence on every GitHub Actions run. No config beyond two repo secrets.`,
39
+ ` 📊 136 MCP tools`,
40
+ ],
41
+ '0.10.109': [
42
+ `💰 **Tokenmaxxing ROI + Closed-loop CI learning**`,
43
+ ` 📊 \`cache_stats\` now shows a **Tokenmaxxing ROI** section — total tokens saved, monthly cost projection, and top 3 most-cached prompts. Finally a number you can show the CFO.`,
44
+ ` 🔄 New \`brain_from_ci\` — bulk-ingest CI history into the Brain (red→green = learned fix, green→red = CKG causal edge). The brain_from_git equivalent for CI. Bootstrap the Brain from your CI logs in one call.`,
45
+ ` 📊 134 MCP tools`,
46
+ ],
12
47
  '0.10.108': [
13
48
  `🧠 **Focused briefing + trustworthy autopilot**`,
14
49
  ` 🎯 New \`session_start_summary\` — top-N focused briefing by topic. Scores lessons by relevance × confidence + recall_count + severity + recency. Use it for a quick pre-brief without loading the full Brain.`,