@cachly-dev/mcp-server 0.10.115 → 0.10.117

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,11 +22,16 @@
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/136%20MCP%20tools-violet" alt="136 MCP tools" />
25
+ <img src="https://img.shields.io/badge/140%20MCP%20tools-violet" alt="126 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>
29
29
 
30
+ <p align="center">
31
+ <strong><a href="https://cachly.dev/sign-up">⚡ Get your free Brain → cachly.dev</a></strong><br/>
32
+ <sub>Free forever · no credit card · 1-command setup · German servers · GDPR</sub>
33
+ </p>
34
+
30
35
  ---
31
36
 
32
37
  ## The story you already live every day
@@ -286,7 +291,12 @@ MCP tool — bulk-ingests past outcomes the same way `brain_from_git` ingests co
286
291
 
287
292
  ---
288
293
 
289
- ## MCP Tools (136 total)
294
+ ## MCP Tools (140 total)
295
+
296
+ The full tool catalog is generated from `sdk/mcp/src/tools.ts`. Cross-surface
297
+ coverage is tracked in [`../../docs/generated/surface-parity.md`](../../docs/generated/surface-parity.md),
298
+ and pinned OpenAPI/OpenAI/Anthropic/LangChain projections live in
299
+ [`../../docs/generated/tool-specs/`](../../docs/generated/tool-specs/).
290
300
 
291
301
  ### 🧠 Session & Memory (most used)
292
302
 
@@ -14,7 +14,7 @@ const WHATS_NEW = {
14
14
  ` 📖 \`brain_get_pref\` reads back any stored preference (omit key to list all).`,
15
15
  ` ✏️ \`brain_set_pref\` saves a preference to Redis — survives restarts, scoped per Brain instance.`,
16
16
  ` 💡 Known key: \`auto_changelog\` — set to "false" to silence the new-lessons digest at session_start.`,
17
- ` 📊 141 MCP tools`,
17
+ ` 📊 140 MCP tools`,
18
18
  ],
19
19
  '0.10.114': [
20
20
  `📋 **\`brain_changelog\` — weekly knowledge digest in one call**`,
@@ -372,7 +372,6 @@ export const BRAIN_TOOL_NAMES = new Set([
372
372
  // DEPTH gate (hide the tail), never an access wall: the #1 result is always
373
373
  // returned. Usage/limit come from the same authoritative numbers as the Brain
374
374
  // Health bar (GET /instances/:id/memory), cached briefly to avoid per-call latency.
375
- const FREE_TIER_VISIBLE_RECALLS = 3;
376
375
  const UPGRADE_URL = 'https://cachly.dev/billing';
377
376
  const _recallGateCache = new Map();
378
377
  async function getRecallGate(instanceId, apiFetch) {
@@ -383,7 +382,12 @@ async function getRecallGate(instanceId, apiFetch) {
383
382
  const mem = await apiFetch(`/api/v1/instances/${instanceId}/memory`);
384
383
  const limit = mem?.recall_limit ?? -1;
385
384
  const used = mem?.total_recall_count ?? 0;
386
- const gate = { reached: limit > 0 && used >= limit, limit, used };
385
+ const gate = {
386
+ reached: limit > 0 && used >= limit,
387
+ limit,
388
+ used,
389
+ goodwillMessage: mem?.goodwill_message,
390
+ };
387
391
  _recallGateCache.set(instanceId, { gate, expiresAt: Date.now() + 60_000 });
388
392
  return gate;
389
393
  }
@@ -1097,10 +1101,18 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
1097
1101
  .sort((a, b) => b.hybridScore - a.hybridScore);
1098
1102
  // ── Teaser-Gate: free tier over its recall limit hides the long tail ──────
1099
1103
  const recallGate = await getRecallGate(instance_id, apiFetch);
1100
- const gateActive = recallGate.reached && hybridResults.length > FREE_TIER_VISIBLE_RECALLS;
1101
- const visibleCount = gateActive ? FREE_TIER_VISIBLE_RECALLS : 8;
1104
+ // Hard gate: once a free user is over their (monthly, goodwill-adjusted)
1105
+ // recall limit, the long tail is fully withheld until they upgrade or the
1106
+ // month resets. We still show the single highest-value proven lesson below
1107
+ // as a teaser so the tool isn't dead and the value is obvious.
1108
+ const gateActive = recallGate.reached;
1109
+ const visibleCount = gateActive ? 0 : 8;
1102
1110
  // ── Build output ──────────────────────────────────────────────────────────
1103
1111
  const lines = [`🧠 **Smart Recall** for: _"${query}"_\n`];
1112
+ // Warm goodwill note — shown the month a free user is gifted +250 recalls.
1113
+ if (recallGate.goodwillMessage) {
1114
+ lines.push(`${recallGate.goodwillMessage}\n`);
1115
+ }
1104
1116
  // "Brain saved you here" banner — surfaces value inline for proven recalled lessons
1105
1117
  const SORDER = { critical: 0, major: 1, minor: 2 };
1106
1118
  const topLesson = savedHere.sort((a, b) => (SORDER[a.severity] ?? 1) - (SORDER[b.severity] ?? 1))[0];
@@ -1148,7 +1160,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
1148
1160
  // Group by sub-query for multi-topic queries
1149
1161
  if (subQueries.length > 1) {
1150
1162
  const grouped = new Map();
1151
- for (const r of hybridResults.slice(0, gateActive ? FREE_TIER_VISIBLE_RECALLS : 12)) {
1163
+ for (const r of hybridResults.slice(0, gateActive ? 0 : 12)) {
1152
1164
  const sq = r.subQuery ?? query;
1153
1165
  if (!grouped.has(sq))
1154
1166
  grouped.set(sq, []);
@@ -1198,12 +1210,12 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
1198
1210
  lines.push(`> ${preview}${r.content.length > 400 ? '…' : ''}\n`);
1199
1211
  }
1200
1212
  }
1201
- // ── Teaser-Gate footer: sell the withheld tail at the moment of need ──
1213
+ // ── Hard gate footer: over the recall limit, the tail is withheld ──────
1202
1214
  if (gateActive) {
1203
1215
  const withheld = Math.max(0, hybridResults.length - visibleCount);
1204
- if (withheld > 0) {
1205
- lines.push(`🔒 **${withheld} more relevant lesson${withheld !== 1 ? 's' : ''} available** — you've reached your Free recall limit (${recallGate.used}/${recallGate.limit}). Unlock your full Brain → ${UPGRADE_URL}\n`);
1206
- }
1216
+ lines.push(`🔒 **Free recall limit reached** (${recallGate.used}/${recallGate.limit} this month). ` +
1217
+ `${withheld} relevant lesson${withheld !== 1 ? 's' : ''} withheld. ` +
1218
+ `Your limit resets next month, or unlock your full Brain now → ${UPGRADE_URL}\n`);
1207
1219
  }
1208
1220
  }
1209
1221
  else {