@cachly-dev/mcp-server 0.10.113 → 0.10.114
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 +28 -8
- package/dist/src/handlers/brain.js +85 -2
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/tools.d.ts +25 -0
- package/dist/src/tools.js +17 -0
- package/dist/src/tools.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -101,6 +101,26 @@ Like what you see? Make it permanent in the next step.
|
|
|
101
101
|
|
|
102
102
|
---
|
|
103
103
|
|
|
104
|
+
## Brain-first — Semantic Cache as Proof-Point
|
|
105
|
+
|
|
106
|
+
cachly is not a semantic cache with a brain bolt-on. The Brain is the product. The
|
|
107
|
+
Semantic Cache is the **proof-point** — it shows ROI in dollars from day one, with zero
|
|
108
|
+
trust required. It opens the door. The Brain is why teams never leave.
|
|
109
|
+
|
|
110
|
+
| | Wedge — Land | Moat — Retain |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| **Feature** | Semantic Cache | AI Brain (Lessons, Recall, Team-Sharing) |
|
|
113
|
+
| **Value** | Measurable cost savings from day one | Compounding team intelligence |
|
|
114
|
+
| **Metric** | Cache-hit rate, $/month saved | Lessons retained, WoW trend, recall quality |
|
|
115
|
+
| **Analogy** | Datadog APM (surfaces the problem) | Stripe (becomes critical infrastructure) |
|
|
116
|
+
|
|
117
|
+
**The org-level advantage:** Brain lessons and cache hits are shared across the whole
|
|
118
|
+
team — one person's fix becomes every agent's reflex. Anthropic Projects Memory is
|
|
119
|
+
per-user and model-locked. cachly is team-wide and model-neutral. That's the structural
|
|
120
|
+
moat no first-party tool can build.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
104
124
|
## Setup — one command
|
|
105
125
|
|
|
106
126
|
```bash
|
|
@@ -229,7 +249,7 @@ causal_trace(problem="auth breaks after restart")
|
|
|
229
249
|
npx @cachly-dev/mcp-server@latest autopilot # One command — signs in, configures every editor, bootstraps from git
|
|
230
250
|
npx @cachly-dev/mcp-server@latest demo # Preview your Brain (no account needed)
|
|
231
251
|
npx @cachly-dev/mcp-server@latest bench # Recall quality vs flat-file memory (no auth required)
|
|
232
|
-
npx @cachly-dev/mcp-server@latest
|
|
252
|
+
npx @cachly-dev/mcp-server@latest autosetup # Interactive variant — pick editors yourself
|
|
233
253
|
npx @cachly-dev/mcp-server@latest health # Check token, API, editors, git hook
|
|
234
254
|
npx @cachly-dev/mcp-server@latest digest # Weekly Brain summary — shareable
|
|
235
255
|
npx @cachly-dev/mcp-server@latest share # Generate a shareable stats card + tweet
|
|
@@ -378,17 +398,17 @@ following. Manual snippets are in the **Manual Setup** section below.
|
|
|
378
398
|
| **Cline** | ✅ detected via VS Code | `.vscode/mcp.json` | — | Shares config with Copilot; restart VS Code |
|
|
379
399
|
| **Continue.dev** | ✅ detected via `.continue/` | `.continue/config.json` | — | Uses `modelContextProtocolServers` key |
|
|
380
400
|
| **Zed** | ✅ detected via `.zed/` | `.zed/settings.json` | — | Uses `context_servers` key |
|
|
381
|
-
| **Windsurf (global)** | `
|
|
382
|
-
| **Any other MCP client** | `
|
|
401
|
+
| **Windsurf (global)** | `autosetup --editor windsurf` | `~/.windsurf/mcp.json` | ✅ | Pass `--editor` to target global config |
|
|
402
|
+
| **Any other MCP client** | `autosetup --editor claude` | `.mcp.json` | — | Standard `mcpServers` stdio format |
|
|
383
403
|
|
|
384
404
|
**Which sign-in path each editor uses:**
|
|
385
405
|
|
|
386
406
|
| Scenario | Path |
|
|
387
407
|
|---|---|
|
|
388
|
-
| `
|
|
389
|
-
| `
|
|
408
|
+
| `autosetup` from a real terminal (TTY) | OAuth device-flow → browser click → API key saved automatically |
|
|
409
|
+
| `autosetup` from VSCode task / CI (non-TTY) | Auto-detects non-interactive, opens browser with step-by-step guide, prints `CACHLY_JWT=... autosetup` instruction |
|
|
390
410
|
| First tool call from Claude Code (no JWT yet) | Inline device-flow: MCP returns URL + code, browser opens automatically, next call proceeds |
|
|
391
|
-
| `CACHLY_JWT=cky_live_xxx npx ...
|
|
411
|
+
| `CACHLY_JWT=cky_live_xxx npx ... autosetup` | Skips auth step entirely, uses provided key |
|
|
392
412
|
|
|
393
413
|
> **Tip — fastest per-project setup from inside Claude Code:**
|
|
394
414
|
> ```
|
|
@@ -480,12 +500,12 @@ private backend instead of `api.cachly.dev`:
|
|
|
480
500
|
npx @cachly-dev/mcp-server@latest autopilot --api-url https://cachly.mycorp.internal
|
|
481
501
|
|
|
482
502
|
# Or non-interactively
|
|
483
|
-
npx @cachly-dev/mcp-server@latest
|
|
503
|
+
npx @cachly-dev/mcp-server@latest autosetup \
|
|
484
504
|
--instance-id <uuid> --api-key <cky_live_...> \
|
|
485
505
|
--api-url https://cachly.mycorp.internal
|
|
486
506
|
```
|
|
487
507
|
|
|
488
|
-
`
|
|
508
|
+
`autosetup` bakes `CACHLY_API_URL` into the editor config **only** when it differs
|
|
489
509
|
from the default cloud — so default installs stay clean, and self-hosted installs
|
|
490
510
|
keep talking to your backend on every editor launch. All data stays in your infra.
|
|
491
511
|
|
|
@@ -7,8 +7,15 @@ 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.
|
|
10
|
+
const MCP_VERSION = '0.10.114';
|
|
11
11
|
const WHATS_NEW = {
|
|
12
|
+
'0.10.114': [
|
|
13
|
+
`📋 **\`brain_changelog\` — weekly knowledge digest in one call**`,
|
|
14
|
+
` 📅 Generates a grouped Markdown changelog of lessons learned in the last N days.`,
|
|
15
|
+
` 👥 Grouped by topic category, annotated with author, recall count, and confidence — paste directly into standup or Slack.`,
|
|
16
|
+
` ⚙️ Params: \`days\` (default 7), \`max_lessons\` (default 30), \`include_failures\` (default true).`,
|
|
17
|
+
` 📊 138 MCP tools`,
|
|
18
|
+
],
|
|
12
19
|
'0.10.113': [
|
|
13
20
|
`📈 **Week-over-week savings trend in \`cache_stats\`**`,
|
|
14
21
|
` 📅 \`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.`,
|
|
@@ -348,7 +355,7 @@ export const BRAIN_TOOL_NAMES = new Set([
|
|
|
348
355
|
'session_start', 'session_start_summary', 'session_end', 'session_ping', 'session_handoff', 'auto_learn_session',
|
|
349
356
|
'brain_who_knows', 'brain_file_map', 'team_expertise_map',
|
|
350
357
|
'skill_gaps', 'brain_coverage', 'brain_metrics', 'brain_service_map',
|
|
351
|
-
'brain_collab_pairs', 'brain_portability',
|
|
358
|
+
'brain_collab_pairs', 'brain_portability', 'brain_changelog',
|
|
352
359
|
]);
|
|
353
360
|
// ── Free-tier Teaser-Gate ──────────────────────────────────────────────────
|
|
354
361
|
// When a Free-tier Brain crosses its recall limit, smart_recall still delivers
|
|
@@ -3265,6 +3272,82 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3265
3272
|
lines.push(`---`, ``, `### What travels with you`, ``, `| Data | Model-neutral? |`, `|------|---------------|`, `| Lessons (learn_from_attempts) | ✅ Full access in all clients |`, `| Memory Crystals (memory_crystalize) | ✅ Included in every session_start |`, `| Causal Knowledge Graph (brain_predict) | ✅ Same graph, same predictions |`, `| Team lessons (team_learn, team_confirm) | ✅ Team is per-Brain, not per-model |`, `| Domain Brain Marketplace installs | ✅ Installed once, available everywhere |`, `| Session handoffs (session_handoff) | ✅ Cross-client continuity |`, ``, `---`, ``, `### One-command setup for any new client`, ``, '```bash', `npx @cachly-dev/mcp-server@latest autopilot`, '```', ``, `Autopilot detects all installed editors and writes the config for each — with your \`${instance_id}\` Brain ID pre-filled.`, ``, `---`, `_Docs: cachly.dev/docs/model-neutral • Your Brain, Any Model_`);
|
|
3266
3273
|
return lines.join('\n');
|
|
3267
3274
|
}
|
|
3275
|
+
// ── brain_changelog ───────────────────────────────────────────────────────
|
|
3276
|
+
// Generates a human-readable Markdown changelog of recent lessons.
|
|
3277
|
+
// Useful for weekly standups, sprint reviews, or async team updates.
|
|
3278
|
+
case 'brain_changelog': {
|
|
3279
|
+
const { instance_id, days = 7, max_lessons = 30, include_failures = true, } = args;
|
|
3280
|
+
const redis = await getConnection(instance_id);
|
|
3281
|
+
const cutoff = Date.now() - Number(days) * 86_400_000;
|
|
3282
|
+
// Scan all lessons and collect recent ones.
|
|
3283
|
+
const keys = await scanKeys(redis, 'cachly:lesson:best:*', { max: 4000, timeoutMs: 4000 });
|
|
3284
|
+
const recent = [];
|
|
3285
|
+
for (const k of keys) {
|
|
3286
|
+
const raw = await redis.get(k).catch(() => null);
|
|
3287
|
+
if (!raw)
|
|
3288
|
+
continue;
|
|
3289
|
+
const lesson = safeJsonParse(raw, {});
|
|
3290
|
+
const ts = lesson.ts ? new Date(lesson.ts).getTime() : 0;
|
|
3291
|
+
if (ts < cutoff)
|
|
3292
|
+
continue;
|
|
3293
|
+
if (!include_failures && lesson.outcome === 'failure')
|
|
3294
|
+
continue;
|
|
3295
|
+
const topic = k.replace('cachly:lesson:best:', '');
|
|
3296
|
+
recent.push({ ...lesson, topic });
|
|
3297
|
+
}
|
|
3298
|
+
// Sort by timestamp desc, cap at max_lessons.
|
|
3299
|
+
recent.sort((a, b) => {
|
|
3300
|
+
const ta = a.ts ? new Date(a.ts).getTime() : 0;
|
|
3301
|
+
const tb = b.ts ? new Date(b.ts).getTime() : 0;
|
|
3302
|
+
return tb - ta;
|
|
3303
|
+
});
|
|
3304
|
+
const lessons = recent.slice(0, Number(max_lessons));
|
|
3305
|
+
if (lessons.length === 0) {
|
|
3306
|
+
return [
|
|
3307
|
+
`## 📋 Brain Changelog — last ${days} day${Number(days) !== 1 ? 's' : ''}`,
|
|
3308
|
+
``,
|
|
3309
|
+
`_No new lessons learned in this window. Your Brain already knows everything it knows — add new lessons with \`learn_from_attempts\`._`,
|
|
3310
|
+
].join('\n');
|
|
3311
|
+
}
|
|
3312
|
+
// Group by category (topic prefix before first ':').
|
|
3313
|
+
const groups = new Map();
|
|
3314
|
+
for (const l of lessons) {
|
|
3315
|
+
const cat = l.topic.includes(':') ? l.topic.split(':')[0] : 'general';
|
|
3316
|
+
const arr = groups.get(cat) ?? [];
|
|
3317
|
+
arr.push(l);
|
|
3318
|
+
groups.set(cat, arr);
|
|
3319
|
+
}
|
|
3320
|
+
const severityEmoji = (s) => s === 'critical' ? '🚨' : s === 'major' ? '⚠️' : s === 'minor' ? '💡' : '✨';
|
|
3321
|
+
const outcomeEmoji = (o) => o === 'failure' ? '❌' : o === 'partial' ? '🔶' : '✅';
|
|
3322
|
+
const dateStr = new Date().toISOString().slice(0, 10);
|
|
3323
|
+
const lines = [
|
|
3324
|
+
`## 📋 Brain Changelog — ${dateStr} (last ${days} day${Number(days) !== 1 ? 's' : ''})`,
|
|
3325
|
+
``,
|
|
3326
|
+
`_${lessons.length} lesson${lessons.length !== 1 ? 's' : ''} learned across ${groups.size} topic area${groups.size !== 1 ? 's' : ''}_`,
|
|
3327
|
+
``,
|
|
3328
|
+
];
|
|
3329
|
+
for (const [cat, catLessons] of Array.from(groups.entries()).sort((a, b) => b[1].length - a[1].length)) {
|
|
3330
|
+
lines.push(`### ${cat}`);
|
|
3331
|
+
lines.push('');
|
|
3332
|
+
for (const l of catLessons) {
|
|
3333
|
+
const icon = l.outcome === 'failure' ? outcomeEmoji(l.outcome) : severityEmoji(l.severity);
|
|
3334
|
+
const body = l.outcome === 'failure' ? l.what_failed : l.what_worked;
|
|
3335
|
+
const meta = [];
|
|
3336
|
+
if (l.author)
|
|
3337
|
+
meta.push(`by **${l.author}**`);
|
|
3338
|
+
if (l.recall_count)
|
|
3339
|
+
meta.push(`${l.recall_count} recall${l.recall_count !== 1 ? 's' : ''}`);
|
|
3340
|
+
if (l.confidence !== undefined)
|
|
3341
|
+
meta.push(`${Math.round(l.confidence * 100)}% confidence`);
|
|
3342
|
+
lines.push(`- ${icon} **${l.topic}**${body ? ` — ${body}` : ''}`);
|
|
3343
|
+
if (meta.length)
|
|
3344
|
+
lines.push(` _${meta.join(' · ')}_`);
|
|
3345
|
+
}
|
|
3346
|
+
lines.push('');
|
|
3347
|
+
}
|
|
3348
|
+
lines.push('---', `_Generated from Brain \`${instance_id}\` · Share this in your standup or Slack_`);
|
|
3349
|
+
return lines.join('\n');
|
|
3350
|
+
}
|
|
3268
3351
|
// ── sync_file_changes ─────────────────────────────────────────────────────
|
|
3269
3352
|
default:
|
|
3270
3353
|
return null;
|