@cachly-dev/mcp-server 0.7.0 → 0.8.0
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 +122 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +175 -16
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ import { Redis } from 'ioredis';
|
|
|
47
47
|
const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
|
|
48
48
|
const JWT = process.env.CACHLY_JWT ?? '';
|
|
49
49
|
const EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
|
|
50
|
-
const CURRENT_VERSION = '0.
|
|
50
|
+
const CURRENT_VERSION = '0.8.0';
|
|
51
51
|
/**
|
|
52
52
|
* ┌──────────────────────────────────────────────────────────────────────┐
|
|
53
53
|
* │ EMBEDDING PROVIDER — pluggable, client-side first │
|
|
@@ -3406,7 +3406,8 @@ const TOOLS = [
|
|
|
3406
3406
|
'The lesson is immediately searchable by any other AI using syndicate_search. ' +
|
|
3407
3407
|
'This is how individual knowledge becomes collective intelligence. ' +
|
|
3408
3408
|
'Call this AFTER every learn_from_attempts that is worth sharing universally ' +
|
|
3409
|
-
'(critical bugs, deployment gotchas, architecture discoveries).'
|
|
3409
|
+
'(critical bugs, deployment gotchas, architecture discoveries). ' +
|
|
3410
|
+
'Use scope="org" to keep the lesson private to your organisation.',
|
|
3410
3411
|
inputSchema: {
|
|
3411
3412
|
type: 'object',
|
|
3412
3413
|
properties: {
|
|
@@ -3416,6 +3417,7 @@ const TOOLS = [
|
|
|
3416
3417
|
what_failed: { type: 'string', description: 'What failed or was wrong — helps others avoid the same trap.' },
|
|
3417
3418
|
severity: { type: 'string', enum: ['critical', 'major', 'minor'], description: 'How severe the issue was (default: minor)' },
|
|
3418
3419
|
tags: { type: 'array', items: { type: 'string' }, description: 'Up to 10 keywords for better discoverability' },
|
|
3420
|
+
scope: { type: 'string', enum: ['public', 'org'], description: 'Visibility: "public" = global commons (default), "org" = private to your org only' },
|
|
3419
3421
|
},
|
|
3420
3422
|
required: ['topic', 'what_worked'],
|
|
3421
3423
|
},
|
|
@@ -3431,11 +3433,38 @@ const TOOLS = [
|
|
|
3431
3433
|
type: 'object',
|
|
3432
3434
|
properties: {
|
|
3433
3435
|
q: { type: 'string', description: 'Free-text search query (leave empty for most recent lessons)' },
|
|
3436
|
+
category: { type: 'string', description: 'Filter by category prefix: "fix", "deploy", "debug", "infra", "api", "web"' },
|
|
3437
|
+
scope: { type: 'string', enum: ['public', 'org'], description: '"public" = global commons (default), "org" = public + your org-private lessons' },
|
|
3434
3438
|
limit: { type: 'number', description: 'Max results to return (default: 20, max: 50)' },
|
|
3435
3439
|
},
|
|
3436
3440
|
required: [],
|
|
3437
3441
|
},
|
|
3438
3442
|
},
|
|
3443
|
+
{
|
|
3444
|
+
name: 'syndicate_stats',
|
|
3445
|
+
description: 'Show the health of the global Knowledge Commons: total lessons, total confirms, ' +
|
|
3446
|
+
'top categories, most-trusted lessons, growth in the last 7 days, and top contributors (anonymous scores). ' +
|
|
3447
|
+
'Use for weekly reviews or to explore what the community knows.',
|
|
3448
|
+
inputSchema: {
|
|
3449
|
+
type: 'object',
|
|
3450
|
+
properties: {},
|
|
3451
|
+
required: [],
|
|
3452
|
+
},
|
|
3453
|
+
},
|
|
3454
|
+
{
|
|
3455
|
+
name: 'syndicate_trending',
|
|
3456
|
+
description: 'Show the TRENDING lessons in the global Knowledge Commons — those with the fastest confirmation velocity ' +
|
|
3457
|
+
'in the last 7 days (confirm_count / age_in_days). ' +
|
|
3458
|
+
'Use this at the start of a session or weekly review to see what the community is actively validating. ' +
|
|
3459
|
+
'Lessons need at least 2 independent confirms to appear here.',
|
|
3460
|
+
inputSchema: {
|
|
3461
|
+
type: 'object',
|
|
3462
|
+
properties: {
|
|
3463
|
+
limit: { type: 'number', description: 'Max results (default: 10, max: 50)' },
|
|
3464
|
+
},
|
|
3465
|
+
required: [],
|
|
3466
|
+
},
|
|
3467
|
+
},
|
|
3439
3468
|
];
|
|
3440
3469
|
// ── Handlers ──────────────────────────────────────────────────────────────────
|
|
3441
3470
|
function formatInstance(inst) {
|
|
@@ -7043,30 +7072,40 @@ smart_recall(
|
|
|
7043
7072
|
}
|
|
7044
7073
|
// ── v0.7 Knowledge Syndication: syndicate ────────────────────────────────
|
|
7045
7074
|
case 'syndicate': {
|
|
7046
|
-
const { topic, outcome = 'success', what_worked, what_failed = '', severity = 'minor', tags = [] } = args;
|
|
7075
|
+
const { topic, outcome = 'success', what_worked, what_failed = '', severity = 'minor', tags = [], scope = 'public' } = args;
|
|
7047
7076
|
if (!topic || !what_worked) {
|
|
7048
7077
|
throw new McpError(ErrorCode.InvalidParams, 'topic and what_worked are required');
|
|
7049
7078
|
}
|
|
7050
|
-
const body = { topic, outcome, what_worked, what_failed, severity, tags };
|
|
7079
|
+
const body = { topic, outcome, what_worked, what_failed, severity, tags, scope };
|
|
7051
7080
|
const res = await apiFetch('/api/v1/syndication/contribute', { method: 'POST', body: JSON.stringify(body) });
|
|
7081
|
+
const scopeLabel = scope === 'org' ? '🏢 org-private' : '🌐 global commons';
|
|
7082
|
+
const dedupNote = res.deduped
|
|
7083
|
+
? `\n> ♻️ Duplicate detected — trust score incremented for the existing lesson.`
|
|
7084
|
+
: '';
|
|
7052
7085
|
return [
|
|
7053
|
-
|
|
7086
|
+
`${scope === 'org' ? '🏢' : '🌐'} **Lesson syndicated to the ${scope === 'org' ? 'org Knowledge Commons' : 'global Knowledge Commons'}**${dedupNote}`,
|
|
7054
7087
|
``,
|
|
7055
7088
|
`**ID:** \`${res.id}\``,
|
|
7056
|
-
`**Topic:** \`${res.topic}\` · **Outcome:** ${res.outcome}`,
|
|
7089
|
+
`**Topic:** \`${res.topic}\` · **Outcome:** ${res.outcome} · **Scope:** ${scopeLabel}`,
|
|
7057
7090
|
``,
|
|
7058
|
-
|
|
7059
|
-
|
|
7091
|
+
scope === 'org'
|
|
7092
|
+
? `This lesson is visible only within your organisation. Use \`syndicate_search(scope="org")\` to find it.`
|
|
7093
|
+
: `Your lesson is now searchable by every AI brain in the network.`,
|
|
7094
|
+
`When another instance confirms it works, its trust score rises — and so does your contributor reputation.`,
|
|
7060
7095
|
``,
|
|
7061
7096
|
`**Tip:** Use \`syndicate_search(q="${topic}")\` to see all community lessons on this topic.`,
|
|
7062
7097
|
].join('\n');
|
|
7063
7098
|
}
|
|
7064
7099
|
// ── v0.7 Knowledge Syndication: syndicate_search ─────────────────────────
|
|
7065
7100
|
case 'syndicate_search': {
|
|
7066
|
-
const { q = '', limit = 20 } = args;
|
|
7101
|
+
const { q = '', limit = 20, category = '', scope = '' } = args;
|
|
7067
7102
|
const params = new URLSearchParams();
|
|
7068
7103
|
if (q)
|
|
7069
7104
|
params.set('q', q);
|
|
7105
|
+
if (category)
|
|
7106
|
+
params.set('category', category);
|
|
7107
|
+
if (scope)
|
|
7108
|
+
params.set('scope', scope);
|
|
7070
7109
|
params.set('limit', String(Math.min(Math.max(1, limit), 50)));
|
|
7071
7110
|
const res = await apiFetch(`/api/v1/syndication/search?${params}`);
|
|
7072
7111
|
if (!res.results || res.results.length === 0) {
|
|
@@ -7080,15 +7119,86 @@ smart_recall(
|
|
|
7080
7119
|
const filled = Math.min(10, Math.round(n / 5));
|
|
7081
7120
|
return '█'.repeat(filled) + '░'.repeat(10 - filled) + ` ×${n}`;
|
|
7082
7121
|
};
|
|
7122
|
+
const header = [q, category].filter(Boolean).join(' · ');
|
|
7083
7123
|
const lines = [
|
|
7084
|
-
`## 🌐 Global Knowledge Commons${
|
|
7124
|
+
`## 🌐 Global Knowledge Commons${header ? ` — ${header}` : ' — Recent'}`,
|
|
7085
7125
|
`*${res.count} lesson${res.count === 1 ? '' : 's'} found*`,
|
|
7086
7126
|
``,
|
|
7087
7127
|
];
|
|
7088
7128
|
for (const lesson of res.results) {
|
|
7089
|
-
lines.push(`### ${outcomeIcon(lesson.outcome)} \`${lesson.topic}\` ${severityLabel(lesson.severity)}`, `**Trust:** ${confirmBar(lesson.confirm_count)}`, lesson.what_worked ? `**What worked:** ${lesson.what_worked}` : '', lesson.what_failed ? `**What failed:** ${lesson.what_failed}` : '', `*Contributed ${new Date(lesson.created_at).toLocaleDateString('de-DE')}
|
|
7129
|
+
lines.push(`### ${outcomeIcon(lesson.outcome)} \`${lesson.topic}\` ${severityLabel(lesson.severity)}`, `**Trust:** ${confirmBar(lesson.confirm_count)}`, lesson.what_worked ? `**What worked:** ${lesson.what_worked}` : '', lesson.what_failed ? `**What failed:** ${lesson.what_failed}` : '', `*Contributed ${new Date(lesson.created_at).toLocaleDateString('de-DE')} · ID: \`${lesson.id}\`*`, ``);
|
|
7130
|
+
}
|
|
7131
|
+
lines.push(`---`, `**Confirm** (this helped you): \`syndicate(topic="${res.results[0]?.topic ?? '...'}", what_worked="...")\` → auto-deduped, trust +1`, `**Contribute your own:** \`syndicate(topic="fix:...", what_worked="...")\``, `**Filter by category:** \`syndicate_search(category="fix")\``);
|
|
7132
|
+
return lines.filter(l => l !== '').join('\n');
|
|
7133
|
+
}
|
|
7134
|
+
// ── v0.7 Knowledge Syndication: syndicate_stats ──────────────────────────
|
|
7135
|
+
case 'syndicate_stats': {
|
|
7136
|
+
const res = await apiFetch('/api/v1/syndication/stats');
|
|
7137
|
+
const confirmBar = (n) => {
|
|
7138
|
+
const filled = Math.min(10, Math.round(n / 5));
|
|
7139
|
+
return '█'.repeat(filled) + '░'.repeat(10 - filled) + ` ×${n}`;
|
|
7140
|
+
};
|
|
7141
|
+
const lines = [
|
|
7142
|
+
`## 🌐 Global Knowledge Commons — Stats`,
|
|
7143
|
+
``,
|
|
7144
|
+
`| Metric | Value |`,
|
|
7145
|
+
`|---|---|`,
|
|
7146
|
+
`| Total lessons | **${res.total_lessons.toLocaleString()}** |`,
|
|
7147
|
+
`| Total confirms | **${res.total_confirms.toLocaleString()}** |`,
|
|
7148
|
+
`| Added last 7 days | **${res.added_last_7_days}** |`,
|
|
7149
|
+
``,
|
|
7150
|
+
`### Top Categories`,
|
|
7151
|
+
];
|
|
7152
|
+
for (const cat of res.top_categories ?? []) {
|
|
7153
|
+
lines.push(`- \`${cat.category}\` — ${cat.count} lesson${cat.count === 1 ? '' : 's'}`);
|
|
7154
|
+
}
|
|
7155
|
+
lines.push(``, `### Most Trusted Lessons`);
|
|
7156
|
+
for (const lesson of res.most_trusted ?? []) {
|
|
7157
|
+
lines.push(`**\`${lesson.topic}\`** ${confirmBar(lesson.confirm_count)}`, `> ${lesson.what_worked.slice(0, 120)}${lesson.what_worked.length > 120 ? '…' : ''}`, ``);
|
|
7158
|
+
}
|
|
7159
|
+
lines.push(`---`, `**Contribute:** \`syndicate(topic="...", what_worked="...")\` | **Search:** \`syndicate_search(q="your problem")\``);
|
|
7160
|
+
// Top contributors (anonymous scores)
|
|
7161
|
+
if (res.top_contributors?.length) {
|
|
7162
|
+
lines.push(``, `### 🏅 Top Contributors (anonymous)`);
|
|
7163
|
+
for (const c of res.top_contributors) {
|
|
7164
|
+
lines.push(`- Trust **${c.trust_score}** · ${c.lessons_count} lesson${c.lessons_count === 1 ? '' : 's'} · ${c.confirms_received} confirms received`);
|
|
7165
|
+
}
|
|
7166
|
+
}
|
|
7167
|
+
return lines.join('\n');
|
|
7168
|
+
}
|
|
7169
|
+
// ── v0.8 Knowledge Syndication: syndicate_trending ───────────────────────
|
|
7170
|
+
case 'syndicate_trending': {
|
|
7171
|
+
const { limit = 10 } = args;
|
|
7172
|
+
const params = new URLSearchParams({ limit: String(Math.min(Math.max(1, limit), 50)) });
|
|
7173
|
+
const res = await apiFetch(`/api/v1/syndication/trending?${params}`);
|
|
7174
|
+
if (!res.results || res.results.length === 0) {
|
|
7175
|
+
return [
|
|
7176
|
+
`## 📈 Trending in the Knowledge Commons`,
|
|
7177
|
+
``,
|
|
7178
|
+
`No trending lessons yet (need at least 2 confirms in the last 7 days).`,
|
|
7179
|
+
``,
|
|
7180
|
+
`Contribute and confirm lessons to see them trend: \`syndicate(topic="...", what_worked="...")\``,
|
|
7181
|
+
].join('\n');
|
|
7182
|
+
}
|
|
7183
|
+
const outcomeIcon = (o) => o === 'success' ? '✅' : o === 'failure' ? '❌' : '⚠️';
|
|
7184
|
+
const severityLabel = (s) => s === 'critical' ? '🔴' : s === 'major' ? '🟡' : '🟢';
|
|
7185
|
+
const confirmBar = (n) => {
|
|
7186
|
+
const filled = Math.min(10, Math.round(n / 5));
|
|
7187
|
+
return '█'.repeat(filled) + '░'.repeat(10 - filled) + ` ×${n}`;
|
|
7188
|
+
};
|
|
7189
|
+
const trendBar = (score) => {
|
|
7190
|
+
const filled = Math.min(10, Math.round(score * 2));
|
|
7191
|
+
return '▲'.repeat(filled) + '△'.repeat(10 - filled) + ` ${score.toFixed(2)}/day`;
|
|
7192
|
+
};
|
|
7193
|
+
const lines = [
|
|
7194
|
+
`## 📈 Trending in the Knowledge Commons`,
|
|
7195
|
+
`*Lessons with the fastest confirmation velocity in the last 7 days*`,
|
|
7196
|
+
``,
|
|
7197
|
+
];
|
|
7198
|
+
for (const lesson of res.results) {
|
|
7199
|
+
lines.push(`### ${outcomeIcon(lesson.outcome)} \`${lesson.topic}\` ${severityLabel(lesson.severity)}`, `**Trend:** ${trendBar(lesson.trend_score)} | **Trust:** ${confirmBar(lesson.confirm_count)}`, lesson.what_worked ? `**What worked:** ${lesson.what_worked.slice(0, 200)}${lesson.what_worked.length > 200 ? '…' : ''}` : '', `*ID: \`${lesson.id}\` · ${new Date(lesson.created_at).toLocaleDateString('de-DE')}*`, ``);
|
|
7090
7200
|
}
|
|
7091
|
-
lines.push(`---`, `**Confirm
|
|
7201
|
+
lines.push(`---`, `**Confirm** (if this helped you): \`syndicate(topic="${res.results[0]?.topic ?? '...'}", what_worked="...")\` → auto-deduped, trust +1`, `**All trending:** \`syndicate_trending(limit=50)\` | **Search:** \`syndicate_search(q="...")\``);
|
|
7092
7202
|
return lines.filter(l => l !== '').join('\n');
|
|
7093
7203
|
}
|
|
7094
7204
|
default:
|