@cachly-dev/mcp-server 0.7.1 → 0.8.1
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/dist/index.js +90 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +122 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cachly-dev/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"mcpName": "io.github.cachly-dev/mcp-server",
|
|
5
5
|
"description": "AI memory brain for Claude Code, Cursor, Copilot & Windsurf — persistent sessions, lessons learned, semantic search, team brain. 51 MCP tools.",
|
|
6
6
|
"type": "module",
|
package/src/index.ts
CHANGED
|
@@ -55,7 +55,7 @@ import { Redis } from 'ioredis';
|
|
|
55
55
|
const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
|
|
56
56
|
const JWT = process.env.CACHLY_JWT ?? '';
|
|
57
57
|
const EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
|
|
58
|
-
const CURRENT_VERSION = '0.
|
|
58
|
+
const CURRENT_VERSION = '0.8.1';
|
|
59
59
|
/**
|
|
60
60
|
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
61
61
|
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
@@ -3494,7 +3494,8 @@ const TOOLS = [
|
|
|
3494
3494
|
'The lesson is immediately searchable by any other AI using syndicate_search. ' +
|
|
3495
3495
|
'This is how individual knowledge becomes collective intelligence. ' +
|
|
3496
3496
|
'Call this AFTER every learn_from_attempts that is worth sharing universally ' +
|
|
3497
|
-
'(critical bugs, deployment gotchas, architecture discoveries).'
|
|
3497
|
+
'(critical bugs, deployment gotchas, architecture discoveries). ' +
|
|
3498
|
+
'Use scope="org" to keep the lesson private to your organisation.',
|
|
3498
3499
|
inputSchema: {
|
|
3499
3500
|
type: 'object',
|
|
3500
3501
|
properties: {
|
|
@@ -3504,6 +3505,7 @@ const TOOLS = [
|
|
|
3504
3505
|
what_failed: { type: 'string', description: 'What failed or was wrong — helps others avoid the same trap.' },
|
|
3505
3506
|
severity: { type: 'string', enum: ['critical', 'major', 'minor'], description: 'How severe the issue was (default: minor)' },
|
|
3506
3507
|
tags: { type: 'array', items: { type: 'string' }, description: 'Up to 10 keywords for better discoverability' },
|
|
3508
|
+
scope: { type: 'string', enum: ['public', 'org'], description: 'Visibility: "public" = global commons (default), "org" = private to your org only' },
|
|
3507
3509
|
},
|
|
3508
3510
|
required: ['topic', 'what_worked'],
|
|
3509
3511
|
},
|
|
@@ -3521,6 +3523,7 @@ const TOOLS = [
|
|
|
3521
3523
|
properties: {
|
|
3522
3524
|
q: { type: 'string', description: 'Free-text search query (leave empty for most recent lessons)' },
|
|
3523
3525
|
category: { type: 'string', description: 'Filter by category prefix: "fix", "deploy", "debug", "infra", "api", "web"' },
|
|
3526
|
+
scope: { type: 'string', enum: ['public', 'org'], description: '"public" = global commons (default), "org" = public + your org-private lessons' },
|
|
3524
3527
|
limit: { type: 'number', description: 'Max results to return (default: 20, max: 50)' },
|
|
3525
3528
|
},
|
|
3526
3529
|
required: [],
|
|
@@ -3530,7 +3533,7 @@ const TOOLS = [
|
|
|
3530
3533
|
name: 'syndicate_stats',
|
|
3531
3534
|
description:
|
|
3532
3535
|
'Show the health of the global Knowledge Commons: total lessons, total confirms, ' +
|
|
3533
|
-
'top categories, most-trusted lessons,
|
|
3536
|
+
'top categories, most-trusted lessons, growth in the last 7 days, and top contributors (anonymous scores). ' +
|
|
3534
3537
|
'Use for weekly reviews or to explore what the community knows.',
|
|
3535
3538
|
inputSchema: {
|
|
3536
3539
|
type: 'object',
|
|
@@ -3538,6 +3541,21 @@ const TOOLS = [
|
|
|
3538
3541
|
required: [],
|
|
3539
3542
|
},
|
|
3540
3543
|
},
|
|
3544
|
+
{
|
|
3545
|
+
name: 'syndicate_trending',
|
|
3546
|
+
description:
|
|
3547
|
+
'Show the TRENDING lessons in the global Knowledge Commons — those with the fastest confirmation velocity ' +
|
|
3548
|
+
'in the last 7 days (confirm_count / age_in_days). ' +
|
|
3549
|
+
'Use this at the start of a session or weekly review to see what the community is actively validating. ' +
|
|
3550
|
+
'Lessons need at least 2 independent confirms to appear here.',
|
|
3551
|
+
inputSchema: {
|
|
3552
|
+
type: 'object',
|
|
3553
|
+
properties: {
|
|
3554
|
+
limit: { type: 'number', description: 'Max results (default: 10, max: 50)' },
|
|
3555
|
+
},
|
|
3556
|
+
required: [],
|
|
3557
|
+
},
|
|
3558
|
+
},
|
|
3541
3559
|
] as const;
|
|
3542
3560
|
|
|
3543
3561
|
// ── Handlers ──────────────────────────────────────────────────────────────────
|
|
@@ -5315,6 +5333,25 @@ async function handleTool(name: string, args: Record<string, unknown>): Promise<
|
|
|
5315
5333
|
}
|
|
5316
5334
|
} catch { /* non-critical */ }
|
|
5317
5335
|
|
|
5336
|
+
// ── 🌍 Knowledge Commons — community stats banner ───────────────────────
|
|
5337
|
+
// Fetch syndication stats and show a 1-liner: total lessons + confirms + weekly growth.
|
|
5338
|
+
// Non-fatal: never blocks session start if the API call fails.
|
|
5339
|
+
try {
|
|
5340
|
+
const commonsStats = await apiFetch<{
|
|
5341
|
+
total_lessons: number;
|
|
5342
|
+
total_confirms: number;
|
|
5343
|
+
added_last_7_days: number;
|
|
5344
|
+
}>('/api/v1/syndication/stats');
|
|
5345
|
+
if (commonsStats.total_lessons > 0) {
|
|
5346
|
+
lines.push(
|
|
5347
|
+
`🌍 **Commons:** ${commonsStats.total_lessons.toLocaleString()} lessons · ` +
|
|
5348
|
+
`${commonsStats.total_confirms.toLocaleString()} confirms · ` +
|
|
5349
|
+
`+${commonsStats.added_last_7_days} this week`,
|
|
5350
|
+
);
|
|
5351
|
+
lines.push('');
|
|
5352
|
+
}
|
|
5353
|
+
} catch { /* non-critical — never block session start */ }
|
|
5354
|
+
|
|
5318
5355
|
return lines.join('\n');
|
|
5319
5356
|
}
|
|
5320
5357
|
|
|
@@ -7607,28 +7644,35 @@ smart_recall(
|
|
|
7607
7644
|
|
|
7608
7645
|
// ── v0.7 Knowledge Syndication: syndicate ────────────────────────────────
|
|
7609
7646
|
case 'syndicate': {
|
|
7610
|
-
const { topic, outcome = 'success', what_worked, what_failed = '', severity = 'minor', tags = [] } = args as {
|
|
7611
|
-
topic: string; outcome?: string; what_worked: string; what_failed?: string; severity?: string; tags?: string[];
|
|
7647
|
+
const { topic, outcome = 'success', what_worked, what_failed = '', severity = 'minor', tags = [], scope = 'public' } = args as {
|
|
7648
|
+
topic: string; outcome?: string; what_worked: string; what_failed?: string; severity?: string; tags?: string[]; scope?: string;
|
|
7612
7649
|
};
|
|
7613
7650
|
|
|
7614
7651
|
if (!topic || !what_worked) {
|
|
7615
7652
|
throw new McpError(ErrorCode.InvalidParams, 'topic and what_worked are required');
|
|
7616
7653
|
}
|
|
7617
7654
|
|
|
7618
|
-
const body = { topic, outcome, what_worked, what_failed, severity, tags };
|
|
7619
|
-
const res = await apiFetch<{ id: string; topic: string; outcome: string; message: string }>(
|
|
7655
|
+
const body = { topic, outcome, what_worked, what_failed, severity, tags, scope };
|
|
7656
|
+
const res = await apiFetch<{ id: string; topic: string; outcome: string; message: string; deduped?: boolean }>(
|
|
7620
7657
|
'/api/v1/syndication/contribute',
|
|
7621
7658
|
{ method: 'POST', body: JSON.stringify(body) }
|
|
7622
7659
|
);
|
|
7623
7660
|
|
|
7661
|
+
const scopeLabel = scope === 'org' ? '🏢 org-private' : '🌐 global commons';
|
|
7662
|
+
const dedupNote = res.deduped
|
|
7663
|
+
? `\n> ♻️ Duplicate detected — trust score incremented for the existing lesson.`
|
|
7664
|
+
: '';
|
|
7665
|
+
|
|
7624
7666
|
return [
|
|
7625
|
-
|
|
7667
|
+
`${scope === 'org' ? '🏢' : '🌐'} **Lesson syndicated to the ${scope === 'org' ? 'org Knowledge Commons' : 'global Knowledge Commons'}**${dedupNote}`,
|
|
7626
7668
|
``,
|
|
7627
7669
|
`**ID:** \`${res.id}\``,
|
|
7628
|
-
`**Topic:** \`${res.topic}\` · **Outcome:** ${res.outcome}`,
|
|
7670
|
+
`**Topic:** \`${res.topic}\` · **Outcome:** ${res.outcome} · **Scope:** ${scopeLabel}`,
|
|
7629
7671
|
``,
|
|
7630
|
-
|
|
7631
|
-
|
|
7672
|
+
scope === 'org'
|
|
7673
|
+
? `This lesson is visible only within your organisation. Use \`syndicate_search(scope="org")\` to find it.`
|
|
7674
|
+
: `Your lesson is now searchable by every AI brain in the network.`,
|
|
7675
|
+
`When another instance confirms it works, its trust score rises — and so does your contributor reputation.`,
|
|
7632
7676
|
``,
|
|
7633
7677
|
`**Tip:** Use \`syndicate_search(q="${topic}")\` to see all community lessons on this topic.`,
|
|
7634
7678
|
].join('\n');
|
|
@@ -7636,11 +7680,12 @@ smart_recall(
|
|
|
7636
7680
|
|
|
7637
7681
|
// ── v0.7 Knowledge Syndication: syndicate_search ─────────────────────────
|
|
7638
7682
|
case 'syndicate_search': {
|
|
7639
|
-
const { q = '', limit = 20, category = '' } = args as { q?: string; limit?: number; category?: string };
|
|
7683
|
+
const { q = '', limit = 20, category = '', scope = '' } = args as { q?: string; limit?: number; category?: string; scope?: string };
|
|
7640
7684
|
|
|
7641
7685
|
const params = new URLSearchParams();
|
|
7642
7686
|
if (q) params.set('q', q);
|
|
7643
7687
|
if (category) params.set('category', category);
|
|
7688
|
+
if (scope) params.set('scope', scope);
|
|
7644
7689
|
params.set('limit', String(Math.min(Math.max(1, limit), 50)));
|
|
7645
7690
|
|
|
7646
7691
|
const res = await apiFetch<{ results: Array<{
|
|
@@ -7739,9 +7784,74 @@ smart_recall(
|
|
|
7739
7784
|
`**Contribute:** \`syndicate(topic="...", what_worked="...")\` | **Search:** \`syndicate_search(q="your problem")\``,
|
|
7740
7785
|
);
|
|
7741
7786
|
|
|
7787
|
+
// Top contributors (anonymous scores)
|
|
7788
|
+
if ((res as any).top_contributors?.length) {
|
|
7789
|
+
lines.push(``, `### 🏅 Top Contributors (anonymous)`);
|
|
7790
|
+
for (const c of (res as any).top_contributors) {
|
|
7791
|
+
lines.push(`- Trust **${c.trust_score}** · ${c.lessons_count} lesson${c.lessons_count === 1 ? '' : 's'} · ${c.confirms_received} confirms received`);
|
|
7792
|
+
}
|
|
7793
|
+
}
|
|
7794
|
+
|
|
7742
7795
|
return lines.join('\n');
|
|
7743
7796
|
}
|
|
7744
7797
|
|
|
7798
|
+
// ── v0.8 Knowledge Syndication: syndicate_trending ───────────────────────
|
|
7799
|
+
case 'syndicate_trending': {
|
|
7800
|
+
const { limit = 10 } = args as { limit?: number };
|
|
7801
|
+
|
|
7802
|
+
const params = new URLSearchParams({ limit: String(Math.min(Math.max(1, limit), 50)) });
|
|
7803
|
+
const res = await apiFetch<{ results: Array<{
|
|
7804
|
+
id: string; topic: string; category: string; outcome: string;
|
|
7805
|
+
what_worked: string; what_failed: string; severity: string;
|
|
7806
|
+
confirm_count: number; trend_score: number; created_at: string;
|
|
7807
|
+
}>; count: number }>(`/api/v1/syndication/trending?${params}`);
|
|
7808
|
+
|
|
7809
|
+
if (!res.results || res.results.length === 0) {
|
|
7810
|
+
return [
|
|
7811
|
+
`## 📈 Trending in the Knowledge Commons`,
|
|
7812
|
+
``,
|
|
7813
|
+
`No trending lessons yet (need at least 2 confirms in the last 7 days).`,
|
|
7814
|
+
``,
|
|
7815
|
+
`Contribute and confirm lessons to see them trend: \`syndicate(topic="...", what_worked="...")\``,
|
|
7816
|
+
].join('\n');
|
|
7817
|
+
}
|
|
7818
|
+
|
|
7819
|
+
const outcomeIcon = (o: string) => o === 'success' ? '✅' : o === 'failure' ? '❌' : '⚠️';
|
|
7820
|
+
const severityLabel = (s: string) => s === 'critical' ? '🔴' : s === 'major' ? '🟡' : '🟢';
|
|
7821
|
+
const confirmBar = (n: number) => {
|
|
7822
|
+
const filled = Math.min(10, Math.round(n / 5));
|
|
7823
|
+
return '█'.repeat(filled) + '░'.repeat(10 - filled) + ` ×${n}`;
|
|
7824
|
+
};
|
|
7825
|
+
const trendBar = (score: number) => {
|
|
7826
|
+
const filled = Math.min(10, Math.round(score * 2));
|
|
7827
|
+
return '▲'.repeat(filled) + '△'.repeat(10 - filled) + ` ${score.toFixed(2)}/day`;
|
|
7828
|
+
};
|
|
7829
|
+
|
|
7830
|
+
const lines: string[] = [
|
|
7831
|
+
`## 📈 Trending in the Knowledge Commons`,
|
|
7832
|
+
`*Lessons with the fastest confirmation velocity in the last 7 days*`,
|
|
7833
|
+
``,
|
|
7834
|
+
];
|
|
7835
|
+
|
|
7836
|
+
for (const lesson of res.results) {
|
|
7837
|
+
lines.push(
|
|
7838
|
+
`### ${outcomeIcon(lesson.outcome)} \`${lesson.topic}\` ${severityLabel(lesson.severity)}`,
|
|
7839
|
+
`**Trend:** ${trendBar(lesson.trend_score)} | **Trust:** ${confirmBar(lesson.confirm_count)}`,
|
|
7840
|
+
lesson.what_worked ? `**What worked:** ${lesson.what_worked.slice(0, 200)}${lesson.what_worked.length > 200 ? '…' : ''}` : '',
|
|
7841
|
+
`*ID: \`${lesson.id}\` · ${new Date(lesson.created_at).toLocaleDateString('de-DE')}*`,
|
|
7842
|
+
``,
|
|
7843
|
+
);
|
|
7844
|
+
}
|
|
7845
|
+
|
|
7846
|
+
lines.push(
|
|
7847
|
+
`---`,
|
|
7848
|
+
`**Confirm** (if this helped you): \`syndicate(topic="${res.results[0]?.topic ?? '...'}", what_worked="...")\` → auto-deduped, trust +1`,
|
|
7849
|
+
`**All trending:** \`syndicate_trending(limit=50)\` | **Search:** \`syndicate_search(q="...")\``,
|
|
7850
|
+
);
|
|
7851
|
+
|
|
7852
|
+
return lines.filter(l => l !== '').join('\n');
|
|
7853
|
+
}
|
|
7854
|
+
|
|
7745
7855
|
default:
|
|
7746
7856
|
return null;
|
|
7747
7857
|
}
|