@cachly-dev/mcp-server 0.10.122 → 0.10.123
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 +31 -15
- package/dist/src/ambient-hooks.d.ts +11 -2
- package/dist/src/ambient-hooks.js +11 -2
- package/dist/src/ambient-hooks.js.map +1 -1
- package/dist/src/ambient-ledger.js +2 -2
- package/dist/src/ambient-ledger.js.map +1 -1
- package/dist/src/ambient-memory.js +2 -2
- package/dist/src/ambient-memory.js.map +1 -1
- package/dist/src/auth.js +2 -1
- package/dist/src/auth.js.map +1 -1
- package/dist/src/brain-export.d.ts +40 -0
- package/dist/src/brain-export.js +89 -0
- package/dist/src/brain-export.js.map +1 -0
- package/dist/src/cachly-url.d.ts +68 -0
- package/dist/src/cachly-url.js +21 -0
- package/dist/src/cachly-url.js.map +1 -0
- package/dist/src/credentials.d.ts +37 -0
- package/dist/src/credentials.js +85 -0
- package/dist/src/credentials.js.map +1 -0
- package/dist/src/doctor.js +2 -1
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/first-recall-proof.d.ts +19 -0
- package/dist/src/first-recall-proof.js +41 -0
- package/dist/src/first-recall-proof.js.map +1 -0
- package/dist/src/handlers/advanced.js +13 -29
- package/dist/src/handlers/advanced.js.map +1 -1
- package/dist/src/handlers/brain.js +132 -41
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/handlers/cache.js +3 -2
- package/dist/src/handlers/cache.js.map +1 -1
- package/dist/src/handlers/fedbrain.js +15 -4
- package/dist/src/handlers/fedbrain.js.map +1 -1
- package/dist/src/handlers/share.js +4 -3
- package/dist/src/handlers/share.js.map +1 -1
- package/dist/src/handlers/team.js +2 -1
- package/dist/src/handlers/team.js.map +1 -1
- package/dist/src/index.d.ts +32 -2
- package/dist/src/index.js +301 -75
- package/dist/src/index.js.map +1 -1
- package/dist/src/kostprobe.d.ts +25 -0
- package/dist/src/kostprobe.js +125 -0
- package/dist/src/kostprobe.js.map +1 -0
- package/dist/src/telemetry-types.d.ts +1 -1
- package/dist/src/tools.d.ts +0 -99
- package/dist/src/tools.js +0 -110
- package/dist/src/tools.js.map +1 -1
- package/dist/src/toolspecs.d.ts +1 -1
- package/dist/src/toolspecs.js +1 -1
- package/dist/src/upgrade-nudge.d.ts +15 -0
- package/dist/src/upgrade-nudge.js +29 -0
- package/dist/src/upgrade-nudge.js.map +1 -0
- package/glama.json +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.js +1 -1
- package/server.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { calculateConfidence, confidenceBadge, STRUCTURED_TEMPLATES, CONFIDENCE_WARN_VALUE, CONFIDENCE_STALE_VALUE, CONFIDENCE_WARN_DAYS } from '../confidence.js';
|
|
3
4
|
import { ckgSlug, extractProblemConcept, ckgUpsertNode, ckgUpdateEdge, ckgUpsertPersonNode, ckgUpsertFileNode, ckgRecordCollaboration, ckgUpsertServiceNode } from '../ckg.js';
|
|
4
5
|
import { safeJsonParse, scanKeys } from '../utils.js';
|
|
@@ -6,15 +7,47 @@ import { getRole, ROLE_BADGE, getScopes, lessonVisibleToScope, reviewModeEnabled
|
|
|
6
7
|
import { keywordSearch, tokenize, splitMultiQuery, levenshtein, indexVocab as _indexVocab } from '../search.js';
|
|
7
8
|
import { rerankByQuality, qualityMultiplier, extractLessonQuality } from '../rerank.js';
|
|
8
9
|
import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
|
|
10
|
+
import { upgradeNudge } from '../upgrade-nudge.js';
|
|
11
|
+
import { cachlyUrl } from '../cachly-url.js';
|
|
9
12
|
// ── Changelog (shown once per version in session_start) ──────────────────────
|
|
10
|
-
|
|
13
|
+
// Resolve the package version at runtime from package.json so the session briefing
|
|
14
|
+
// `version` field always matches the published npm version. A hardcoded constant
|
|
15
|
+
// silently drifted (0.10.119 vs published 0.10.122), making new-feature adoption
|
|
16
|
+
// impossible to track. Paths cover both prod (dist/handlers/brain.js → ../../../) and
|
|
17
|
+
// dev (src/handlers/brain.ts → ../../../). Falls back to a literal if resolution fails.
|
|
18
|
+
const CURRENT_VERSION = (() => {
|
|
19
|
+
try {
|
|
20
|
+
const req = createRequire(import.meta.url);
|
|
21
|
+
for (const rel of ['../../../package.json', '../../package.json']) {
|
|
22
|
+
try {
|
|
23
|
+
const pkg = req(rel);
|
|
24
|
+
if (pkg.name === '@cachly-dev/mcp-server' && pkg.version)
|
|
25
|
+
return pkg.version;
|
|
26
|
+
}
|
|
27
|
+
catch { /* try next candidate */ }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch { /* fall through to literal */ }
|
|
31
|
+
return '0.10.100';
|
|
32
|
+
})();
|
|
33
|
+
// Resolve the total MCP tools count at runtime from generated capabilities.
|
|
34
|
+
// This count is shown in session_start's What's-New briefing for the current version.
|
|
35
|
+
// Falls back silently per CONTRACT: better to skip the count than show a wrong number.
|
|
36
|
+
const getTotalMcpTools = () => {
|
|
37
|
+
try {
|
|
38
|
+
const req = createRequire(import.meta.url);
|
|
39
|
+
const caps = req('../../../CACHLY_CAPABILITIES.json');
|
|
40
|
+
return caps.mcp?.total_tools ?? null;
|
|
41
|
+
}
|
|
42
|
+
catch { /* fail silently */ }
|
|
43
|
+
return null;
|
|
44
|
+
};
|
|
11
45
|
const WHATS_NEW = {
|
|
12
46
|
'0.10.119': [
|
|
13
47
|
`🔍 **Explainable briefings — provenance in every warning**`,
|
|
14
48
|
` 📎 \`/briefing\` warnings now carry \`outcome\`, \`author\`, \`learned_at\` and \`matched_on\` (the context tokens that triggered the warning) — editors can show WHY a fix hint fired, not just what it claims.`,
|
|
15
49
|
` 🧰 VS Code 0.12.0 uses this: severity + confidence in the toast, full lesson card with provenance, "Not helpful" per-file suppression, reviewable CLS auto-learns.`,
|
|
16
50
|
` 🧹 CI docs now describe exactly what ships: scan mode uses the REST \`/scan\` endpoint, the GitLab template covers learn/scan/confirm.`,
|
|
17
|
-
` 📊 126 MCP tools`,
|
|
18
51
|
],
|
|
19
52
|
'0.10.115': [
|
|
20
53
|
`🔧 **\`brain_get_pref\` + \`brain_set_pref\` — persistent Brain preferences**`,
|
|
@@ -332,7 +365,7 @@ const WHATS_NEW = {
|
|
|
332
365
|
`✅ Build: 0 errors, 0 warnings · 379 tests green`,
|
|
333
366
|
],
|
|
334
367
|
'0.10.57': [
|
|
335
|
-
`🆕 **What's new in v${
|
|
368
|
+
`🆕 **What's new in v${CURRENT_VERSION}:**`,
|
|
336
369
|
` 🔧 **Critical fix** — corrected the npm bin/main entry path (\`dist/src/index.js\`); 0.10.50–0.10.52 shipped a broken entry point`,
|
|
337
370
|
` 🔧 Version hygiene — synced package.json, server.json, lockfile, MCP_VERSION; \`latest\` now points forward again`,
|
|
338
371
|
` ✅ Accurate tool count (95) across README, server.json, CLI banners`,
|
|
@@ -379,8 +412,18 @@ export const BRAIN_TOOL_NAMES = new Set([
|
|
|
379
412
|
// DEPTH gate (hide the tail), never an access wall: the #1 result is always
|
|
380
413
|
// returned. Usage/limit come from the same authoritative numbers as the Brain
|
|
381
414
|
// Health bar (GET /instances/:id/memory), cached briefly to avoid per-call latency.
|
|
382
|
-
const UPGRADE_URL = '
|
|
415
|
+
const UPGRADE_URL = cachlyUrl('/billing', 'upgrade');
|
|
383
416
|
const _recallGateCache = new Map();
|
|
417
|
+
/**
|
|
418
|
+
* Instances whose notice has already been shown in this process.
|
|
419
|
+
*
|
|
420
|
+
* Once per PROCESS, not once per call: the MCP server lives for the length of
|
|
421
|
+
* the editor session, so this is exactly "once per session". Without it the
|
|
422
|
+
* notice would repeat on every session_start — and with Ambient Recall that is
|
|
423
|
+
* every prompt. That is the nagging the upgrade nudge was built to avoid, and
|
|
424
|
+
* a line that appears every time stops being read within a day.
|
|
425
|
+
*/
|
|
426
|
+
const _noticeGezeigt = new Set();
|
|
384
427
|
// ── Recall quota: ONE unit per recall CALL ───────────────────────────────────
|
|
385
428
|
// The gate above reads a monthly counter that this function writes. It counts
|
|
386
429
|
// calls, not lessons.
|
|
@@ -421,6 +464,7 @@ async function getRecallGate(instanceId, apiFetch) {
|
|
|
421
464
|
limit,
|
|
422
465
|
used,
|
|
423
466
|
goodwillMessage: mem?.goodwill_message,
|
|
467
|
+
notice: mem?.notice,
|
|
424
468
|
};
|
|
425
469
|
_recallGateCache.set(instanceId, { gate, expiresAt: Date.now() + 60_000 });
|
|
426
470
|
return gate;
|
|
@@ -1462,6 +1506,24 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
1462
1506
|
const timeStr = h > 0 ? `${h}h${m > 0 ? ` ${m}m` : ''}` : `${m}m`;
|
|
1463
1507
|
lines.push(`⏱️ **Brain saved you ~${timeStr} total** (time not re-researching known fixes)`, '');
|
|
1464
1508
|
}
|
|
1509
|
+
// Upgrade nudge — surfaces the free-tier quota BEFORE the wall, once
|
|
1510
|
+
// per session and right next to the value it just proved.
|
|
1511
|
+
const recallGate = await getRecallGate(instance_id, apiFetch);
|
|
1512
|
+
const nudge = upgradeNudge({ used: recallGate.used, limit: recallGate.limit, savedMins: timeSavedMins });
|
|
1513
|
+
if (nudge)
|
|
1514
|
+
lines.push(nudge, '');
|
|
1515
|
+
// Notice from the API — the only channel that reaches a WORKING account.
|
|
1516
|
+
// Everything else we can say today requires denying the user something
|
|
1517
|
+
// first (the 402 goodwill text arrived because it was an error), and most
|
|
1518
|
+
// accounts have no email address on file.
|
|
1519
|
+
//
|
|
1520
|
+
// Once per process, so once per editor session. Repeating it would put it
|
|
1521
|
+
// in front of the user on every prompt via Ambient Recall, and a line
|
|
1522
|
+
// that appears every time stops being read within a day.
|
|
1523
|
+
if (recallGate.notice && !_noticeGezeigt.has(instance_id)) {
|
|
1524
|
+
_noticeGezeigt.add(instance_id);
|
|
1525
|
+
lines.push(recallGate.notice, '');
|
|
1526
|
+
}
|
|
1465
1527
|
// ── Welcome-back digest (gap ≥ 7 days) ──────────────────────────────────
|
|
1466
1528
|
// When the user has been away a week or more, lead with a short "what
|
|
1467
1529
|
// happened while you were gone" digest. All data is already loaded above
|
|
@@ -1491,11 +1553,16 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
1491
1553
|
// ── What's New (shown once per version update) ──────────────────────────
|
|
1492
1554
|
try {
|
|
1493
1555
|
const seenVersion = await redis.get('cachly:mcp:version:last_seen');
|
|
1494
|
-
if (seenVersion !==
|
|
1495
|
-
await redis.set('cachly:mcp:version:last_seen',
|
|
1496
|
-
const changelog = WHATS_NEW[
|
|
1556
|
+
if (seenVersion !== CURRENT_VERSION) {
|
|
1557
|
+
await redis.set('cachly:mcp:version:last_seen', CURRENT_VERSION, 'EX', 365 * 86400);
|
|
1558
|
+
const changelog = WHATS_NEW[CURRENT_VERSION];
|
|
1497
1559
|
if (changelog) {
|
|
1498
1560
|
lines.push(...changelog, '');
|
|
1561
|
+
// For current version, append dynamic tool count if available
|
|
1562
|
+
const toolCount = getTotalMcpTools();
|
|
1563
|
+
if (toolCount) {
|
|
1564
|
+
lines.push(`📊 ${toolCount} MCP tools`, '');
|
|
1565
|
+
}
|
|
1499
1566
|
}
|
|
1500
1567
|
}
|
|
1501
1568
|
}
|
|
@@ -2356,33 +2423,12 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2356
2423
|
await redis.expire(key, 90 * 86400);
|
|
2357
2424
|
autoLearned.push(topic);
|
|
2358
2425
|
}
|
|
2359
|
-
// Also store a lesson per changed file area if files were changed
|
|
2360
|
-
if (files_changed.length > 0) {
|
|
2361
|
-
const areas = [...new Set(files_changed.map(f => f.split('/').slice(0, 2).join('/')))].slice(0, 3);
|
|
2362
|
-
for (const area of areas) {
|
|
2363
|
-
const slug = area.replace(/[^a-z0-9]/gi, '-').toLowerCase().replace(/-+/g, '-').slice(0, 30);
|
|
2364
|
-
const topic = `auto:changed:${slug}`;
|
|
2365
|
-
const key = `cachly:lesson:best:${topic}`;
|
|
2366
|
-
const lesson = {
|
|
2367
|
-
topic,
|
|
2368
|
-
outcome: 'success',
|
|
2369
|
-
what_worked: `Files changed in ${area}: ${files_changed.filter(f => f.startsWith(area.split('/')[0])).slice(0, 5).join(', ')}`,
|
|
2370
|
-
context: summary.slice(0, 200),
|
|
2371
|
-
severity: 'minor',
|
|
2372
|
-
ts: now.toISOString(),
|
|
2373
|
-
recall_count: 0,
|
|
2374
|
-
auto_learned: true,
|
|
2375
|
-
version: 2,
|
|
2376
|
-
};
|
|
2377
|
-
await redis.set(key, JSON.stringify(lesson));
|
|
2378
|
-
await redis.expire(key, 90 * 86400);
|
|
2379
|
-
autoLearned.push(topic);
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
2426
|
}
|
|
2383
2427
|
catch { /* auto-learn errors must never break session_end */ }
|
|
2384
2428
|
// ── 🌿 Ambient Git Learning ────────────────────────────────────────────────
|
|
2385
2429
|
// Read git commits since session start → auto-learn each meaningful commit.
|
|
2430
|
+
// The commit BODY (%b) carries the reasoning — what was measured, what the
|
|
2431
|
+
// cause was, what trap it avoided. The subject (%s) alone is just a heading.
|
|
2386
2432
|
const ambientLearned = [];
|
|
2387
2433
|
if (workspace_path) {
|
|
2388
2434
|
try {
|
|
@@ -2396,13 +2442,56 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2396
2442
|
} })()
|
|
2397
2443
|
: '';
|
|
2398
2444
|
const sinceArg = sessionStartTs ? `--since="${sessionStartTs}"` : '--since="1 hour ago"';
|
|
2399
|
-
|
|
2445
|
+
// '|||ENDE' terminates one commit's record. A commit body can contain
|
|
2446
|
+
// blank lines and newlines of its own, so splitting the raw output on
|
|
2447
|
+
// '\n' would tear a single multi-line body apart into several fake
|
|
2448
|
+
// "commits" — splitting on the marker keeps each body intact.
|
|
2449
|
+
const gitOut = execSync(`git -C "${workspace_path}" log ${sinceArg} --oneline --format="%H|||%s|||%b|||%ai|||ENDE"`, { timeout: 5000, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
2400
2450
|
if (gitOut) {
|
|
2401
2451
|
const commitActionRe = /\b(fix|add|remove|refactor|migrate|update|resolve|implement|improve|optimize|configure|create|delete|disable|enable|debug|patch|upgrade|build|rewrite|deploy|feat|chore|docs|test|perf|ci)\b/i;
|
|
2402
|
-
|
|
2403
|
-
|
|
2452
|
+
const commitBlocks = gitOut.split('|||ENDE').map(b => b.trim()).filter(Boolean);
|
|
2453
|
+
for (const block of commitBlocks.slice(0, 10)) {
|
|
2454
|
+
const [hash, msg, rawBody, dateStr] = block.split('|||');
|
|
2455
|
+
// Files touched together in one commit are recorded as co-occurs
|
|
2456
|
+
// edges between file nodes in the graph ("who touches A usually
|
|
2457
|
+
// touches B") — that is independent of whether the commit message
|
|
2458
|
+
// itself is lesson-worthy, so it runs for every recent commit.
|
|
2459
|
+
if (hash) {
|
|
2460
|
+
try {
|
|
2461
|
+
// '--root' matters for a repo's very first commit: without it,
|
|
2462
|
+
// diff-tree has no parent to compare against and silently
|
|
2463
|
+
// reports zero changed files for that commit.
|
|
2464
|
+
const nameOut = execSync(`git -C "${workspace_path}" diff-tree --no-commit-id --name-only -r --root "${hash}"`, { timeout: 5000, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
2465
|
+
// Pairing is quadratic, so the cap decides the cost — and this
|
|
2466
|
+
// runs inside session_end, which must stay quick. At 12 files
|
|
2467
|
+
// that is 66 pairs; at 25 it would be 300, times up to ten
|
|
2468
|
+
// commits. Each file node is upserted ONCE up front instead of
|
|
2469
|
+
// once per pair: with 12 files that is 12 upserts rather than
|
|
2470
|
+
// 132, and it turns ~530 round-trips into ~144.
|
|
2471
|
+
const CO_OCCUR_MAX_FILES = 12;
|
|
2472
|
+
const changedFiles = nameOut
|
|
2473
|
+
? nameOut.split('\n').map(f => f.trim()).filter(Boolean).slice(0, CO_OCCUR_MAX_FILES)
|
|
2474
|
+
: [];
|
|
2475
|
+
const fileIds = [];
|
|
2476
|
+
for (const f of changedFiles)
|
|
2477
|
+
fileIds.push(await ckgUpsertFileNode(redis, f));
|
|
2478
|
+
for (let i = 0; i < fileIds.length; i++) {
|
|
2479
|
+
for (let j = i + 1; j < fileIds.length; j++) {
|
|
2480
|
+
await ckgUpdateEdge(redis, fileIds[i], 'co-occurs', fileIds[j], true);
|
|
2481
|
+
await ckgUpdateEdge(redis, fileIds[j], 'co-occurs', fileIds[i], true);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
catch { /* file co-occurrence is best-effort */ }
|
|
2486
|
+
}
|
|
2404
2487
|
if (!msg || !commitActionRe.test(msg))
|
|
2405
2488
|
continue;
|
|
2489
|
+
// A heading alone is not a lesson. Without a substantial body —
|
|
2490
|
+
// the why, the measurement, the trap — nothing gets stored: better
|
|
2491
|
+
// no entry than one that fills space and says nothing.
|
|
2492
|
+
const body = (rawBody ?? '').trim();
|
|
2493
|
+
if (body.length < 120)
|
|
2494
|
+
continue;
|
|
2406
2495
|
const slug = msg
|
|
2407
2496
|
.toLowerCase().replace(/^(fix|feat|chore|docs|test|ci|perf|refactor|build|revert)[:(\s]/i, '')
|
|
2408
2497
|
.replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40);
|
|
@@ -2416,7 +2505,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2416
2505
|
const commitLesson = {
|
|
2417
2506
|
topic,
|
|
2418
2507
|
outcome: 'success',
|
|
2419
|
-
what_worked: msg.slice(0,
|
|
2508
|
+
what_worked: `${msg}\n\n${body.slice(0, 1200)}`,
|
|
2420
2509
|
context: `Auto-learned from git commit ${(hash ?? '').slice(0, 7)} at ${dateStr ?? ''} in ${workspace_path}`,
|
|
2421
2510
|
severity: 'minor',
|
|
2422
2511
|
ts: now.toISOString(),
|
|
@@ -3349,7 +3438,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3349
3438
|
cachly: {
|
|
3350
3439
|
command: 'npx',
|
|
3351
3440
|
args: ['@cachly-dev/mcp-server@latest'],
|
|
3352
|
-
env: {
|
|
3441
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3353
3442
|
},
|
|
3354
3443
|
},
|
|
3355
3444
|
}, null, 2),
|
|
@@ -3364,7 +3453,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3364
3453
|
cachly: {
|
|
3365
3454
|
command: 'npx',
|
|
3366
3455
|
args: ['@cachly-dev/mcp-server@latest'],
|
|
3367
|
-
env: {
|
|
3456
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3368
3457
|
},
|
|
3369
3458
|
},
|
|
3370
3459
|
}, null, 2),
|
|
@@ -3379,7 +3468,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3379
3468
|
cachly: {
|
|
3380
3469
|
command: 'npx',
|
|
3381
3470
|
args: ['@cachly-dev/mcp-server@latest'],
|
|
3382
|
-
env: {
|
|
3471
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3383
3472
|
},
|
|
3384
3473
|
},
|
|
3385
3474
|
}, null, 2),
|
|
@@ -3395,7 +3484,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3395
3484
|
type: 'stdio',
|
|
3396
3485
|
command: 'npx',
|
|
3397
3486
|
args: ['@cachly-dev/mcp-server@latest'],
|
|
3398
|
-
env: {
|
|
3487
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3399
3488
|
},
|
|
3400
3489
|
},
|
|
3401
3490
|
}, null, 2),
|
|
@@ -3410,7 +3499,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3410
3499
|
cachly: {
|
|
3411
3500
|
command: 'npx',
|
|
3412
3501
|
args: ['@cachly-dev/mcp-server@latest'],
|
|
3413
|
-
env: {
|
|
3502
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3414
3503
|
},
|
|
3415
3504
|
},
|
|
3416
3505
|
}, null, 2),
|
|
@@ -3424,7 +3513,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3424
3513
|
context_servers: {
|
|
3425
3514
|
cachly: {
|
|
3426
3515
|
command: { path: 'npx', args: ['@cachly-dev/mcp-server@latest'] },
|
|
3427
|
-
env: {
|
|
3516
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3428
3517
|
},
|
|
3429
3518
|
},
|
|
3430
3519
|
}, null, 2),
|
|
@@ -3439,7 +3528,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3439
3528
|
{
|
|
3440
3529
|
name: 'cachly',
|
|
3441
3530
|
command: 'npx @cachly-dev/mcp-server@latest',
|
|
3442
|
-
env: {
|
|
3531
|
+
env: { CACHLY_JWT: '<cky_live_...>', CACHLY_BRAIN_INSTANCE_ID: instance_id },
|
|
3443
3532
|
},
|
|
3444
3533
|
],
|
|
3445
3534
|
}, null, 2),
|
|
@@ -3452,6 +3541,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
3452
3541
|
``,
|
|
3453
3542
|
`**Your Brain ID:** \`${instance_id}\``,
|
|
3454
3543
|
``,
|
|
3544
|
+
`Replace \`<cky_live_...>\` below with your own API key (get one at https://cachly.dev/setup-ai) — the Brain ID alone does not authenticate you.`,
|
|
3545
|
+
``,
|
|
3455
3546
|
`This Brain ID is model-agnostic. Every lesson you've learned, every Memory Crystal you've distilled,`,
|
|
3456
3547
|
`and every prediction from your Causal Knowledge Graph is accessible from **any MCP-compatible AI client**.`,
|
|
3457
3548
|
``,
|