cf-memory-mcp 3.50.0 → 3.51.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/bin/cf-memory-mcp.js +131 -2
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -3919,7 +3919,7 @@ if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
|
3919
3919
|
|
|
3920
3920
|
// Global --help only when no subcommand is present. With a subcommand, fall
|
|
3921
3921
|
// through to the per-command help dispatch below.
|
|
3922
|
-
const SUBCOMMANDS = new Set(['resume', 'list', 'checkpoint', 'status', 'clean', 'export', 'import', 'doctor', 'completion', 'delete', 'env', 'history', 'link']);
|
|
3922
|
+
const SUBCOMMANDS = new Set(['resume', 'list', 'checkpoint', 'status', 'clean', 'export', 'import', 'doctor', 'completion', 'delete', 'env', 'history', 'link', 'explain']);
|
|
3923
3923
|
const hasSubcommand = process.argv[2] && SUBCOMMANDS.has(process.argv[2]);
|
|
3924
3924
|
|
|
3925
3925
|
if (!hasSubcommand && (process.argv.includes('--help') || process.argv.includes('-h'))) {
|
|
@@ -3935,6 +3935,7 @@ Usage:
|
|
|
3935
3935
|
npx cf-memory-mcp history List all handoffs for cwd, chronological
|
|
3936
3936
|
npx cf-memory-mcp checkpoint ["<goal>"] Snapshot current state (keep_open)
|
|
3937
3937
|
npx cf-memory-mcp link <child> --parent <id> Retroactively link a child session to a parent
|
|
3938
|
+
npx cf-memory-mcp explain <id> Break down the handoff's quality_score
|
|
3938
3939
|
npx cf-memory-mcp status Show bridge state + server resume availability
|
|
3939
3940
|
npx cf-memory-mcp clean Delete local disk cache for current cwd
|
|
3940
3941
|
npx cf-memory-mcp clean --all Delete ALL local disk caches
|
|
@@ -4576,6 +4577,102 @@ async function runResumeCli() {
|
|
|
4576
4577
|
}
|
|
4577
4578
|
}
|
|
4578
4579
|
|
|
4580
|
+
async function runExplainCli() {
|
|
4581
|
+
if (!API_KEY) {
|
|
4582
|
+
console.error('Error: CF_MEMORY_API_KEY environment variable is required');
|
|
4583
|
+
process.exit(1);
|
|
4584
|
+
}
|
|
4585
|
+
const { positional, flags } = parseCliArgs(process.argv.slice(3));
|
|
4586
|
+
const idArg = positional[0];
|
|
4587
|
+
if (!idArg) {
|
|
4588
|
+
console.error('Usage: cf-memory-mcp explain <session-id-or-prefix>');
|
|
4589
|
+
process.exit(1);
|
|
4590
|
+
}
|
|
4591
|
+
const server = new CFMemoryMCP();
|
|
4592
|
+
server.logDebug = () => {};
|
|
4593
|
+
try {
|
|
4594
|
+
const response = await server.makeRequest({
|
|
4595
|
+
jsonrpc: '2.0', id: `cli-explain-${Date.now()}`,
|
|
4596
|
+
method: 'tools/call',
|
|
4597
|
+
params: { name: 'get_context_bootstrap', arguments: { resume: true, session_id_hint: idArg } },
|
|
4598
|
+
});
|
|
4599
|
+
const text = response?.result?.content?.[0]?.text;
|
|
4600
|
+
const payload = JSON.parse(text || '{}');
|
|
4601
|
+
const envelope = payload.resume_handoff;
|
|
4602
|
+
if (!envelope?.handoff) {
|
|
4603
|
+
process.stderr.write((payload.empty_hint || `No handoff found for "${idArg}".`) + '\n');
|
|
4604
|
+
process.exit(3);
|
|
4605
|
+
}
|
|
4606
|
+
const h = envelope.handoff;
|
|
4607
|
+
const ageMin = envelope.handoff_age_minutes;
|
|
4608
|
+
const sizeBytes = envelope.handoff_size_bytes ?? 0;
|
|
4609
|
+
|
|
4610
|
+
// Mirror the server-side rubric (see computeQualityScore).
|
|
4611
|
+
const components = [];
|
|
4612
|
+
const add = (label, points, present, detail) =>
|
|
4613
|
+
components.push({ label, points, present, detail });
|
|
4614
|
+
|
|
4615
|
+
add('goal present (>=5 chars)', 0.20, !!(h.goal && h.goal.length >= 5), h.goal ? `"${h.goal.slice(0,40)}"` : 'missing');
|
|
4616
|
+
add('next_steps present', 0.20,
|
|
4617
|
+
Array.isArray(h.next_steps) && h.next_steps.length > 0,
|
|
4618
|
+
`${h.next_steps?.length ?? 0} step${(h.next_steps?.length ?? 0) === 1 ? '' : 's'}`);
|
|
4619
|
+
add('code_anchors present', 0.15,
|
|
4620
|
+
Array.isArray(h.code_anchors) && h.code_anchors.length > 0,
|
|
4621
|
+
`${h.code_anchors?.length ?? 0} anchor${(h.code_anchors?.length ?? 0) === 1 ? '' : 's'}`);
|
|
4622
|
+
add('files_touched present', 0.10,
|
|
4623
|
+
Array.isArray(h.files_touched) && h.files_touched.length > 0,
|
|
4624
|
+
`${h.files_touched?.length ?? 0} file${(h.files_touched?.length ?? 0) === 1 ? '' : 's'}`);
|
|
4625
|
+
add('decisions present', 0.10,
|
|
4626
|
+
Array.isArray(h.decisions) && h.decisions.length > 0,
|
|
4627
|
+
`${h.decisions?.length ?? 0} decision${(h.decisions?.length ?? 0) === 1 ? '' : 's'}`);
|
|
4628
|
+
|
|
4629
|
+
// Recency
|
|
4630
|
+
let recency = 0;
|
|
4631
|
+
let recencyDetail = '?';
|
|
4632
|
+
if (ageMin !== undefined) {
|
|
4633
|
+
if (ageMin <= 1440) recency = 0.15;
|
|
4634
|
+
else if (ageMin <= 10080) recency = 0.15 * (1 - (ageMin - 1440) / (10080 - 1440));
|
|
4635
|
+
recencyDetail = `${ageMin}m old`;
|
|
4636
|
+
}
|
|
4637
|
+
components.push({ label: 'recency (decays past 24h)', points: 0.15, present: recency > 0, detail: `${recencyDetail} → +${recency.toFixed(3)}` });
|
|
4638
|
+
|
|
4639
|
+
// Size in target band
|
|
4640
|
+
let sizeBonus = 0;
|
|
4641
|
+
let sizeDetail;
|
|
4642
|
+
if (sizeBytes >= 500 && sizeBytes <= 8000) { sizeBonus = 0.10; sizeDetail = 'in target 500-8000 byte range'; }
|
|
4643
|
+
else if (sizeBytes >= 200 && sizeBytes <= 16000) { sizeBonus = 0.05; sizeDetail = 'in extended 200-16000 byte range'; }
|
|
4644
|
+
else { sizeDetail = sizeBytes < 200 ? 'too small (<200 bytes)' : 'too large (>16000 bytes)'; }
|
|
4645
|
+
components.push({ label: 'size sweet spot', points: 0.10, present: sizeBonus > 0, detail: `${sizeBytes} bytes — ${sizeDetail}` });
|
|
4646
|
+
|
|
4647
|
+
if (flags.json) {
|
|
4648
|
+
process.stdout.write(JSON.stringify({
|
|
4649
|
+
session_id: envelope.session_id,
|
|
4650
|
+
quality_score: envelope.quality_score,
|
|
4651
|
+
components,
|
|
4652
|
+
}, null, 2) + '\n');
|
|
4653
|
+
process.exit(0);
|
|
4654
|
+
}
|
|
4655
|
+
const shortId = (envelope.session_id || '').slice(0, 8);
|
|
4656
|
+
process.stdout.write(`Quality breakdown for ${shortId} (final score: ${envelope.quality_score}):\n\n`);
|
|
4657
|
+
let earned = 0;
|
|
4658
|
+
for (const c of components) {
|
|
4659
|
+
const mark = c.present ? '✓' : '✗';
|
|
4660
|
+
const earned_pts = c.present ? c.points : 0;
|
|
4661
|
+
earned += earned_pts;
|
|
4662
|
+
process.stdout.write(` ${mark} ${c.label.padEnd(32)} +${c.points.toFixed(2)} ${c.detail || ''}\n`);
|
|
4663
|
+
}
|
|
4664
|
+
process.stdout.write(`\n Total earned: ${earned.toFixed(2)} / 1.00\n`);
|
|
4665
|
+
const missing = components.filter(c => !c.present);
|
|
4666
|
+
if (missing.length > 0) {
|
|
4667
|
+
process.stdout.write(`\n To improve: add ${missing.map(m => m.label).join(', ')}\n`);
|
|
4668
|
+
}
|
|
4669
|
+
process.exit(0);
|
|
4670
|
+
} catch (err) {
|
|
4671
|
+
console.error('explain command failed:', err.message);
|
|
4672
|
+
process.exit(1);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4579
4676
|
async function runListCli() {
|
|
4580
4677
|
if (!API_KEY) {
|
|
4581
4678
|
console.error('Error: CF_MEMORY_API_KEY environment variable is required');
|
|
@@ -5019,7 +5116,8 @@ function runEnvCli() {
|
|
|
5019
5116
|
function runCompletionCli() {
|
|
5020
5117
|
const shell = process.argv[3] || 'bash';
|
|
5021
5118
|
const install = process.argv.includes('--install');
|
|
5022
|
-
const
|
|
5119
|
+
const uninstall = process.argv.includes('--uninstall');
|
|
5120
|
+
const commands = ['resume', 'list', 'history', 'checkpoint', 'link', 'explain', 'status', 'clean', 'export', 'import', 'delete', 'doctor', 'env', 'completion'];
|
|
5023
5121
|
const flags = ['--json', '-j', '--limit', '-n', '--md', '--all', '--force', '-f', '--version', '-v', '--help', '-h', '--diagnose'];
|
|
5024
5122
|
|
|
5025
5123
|
// Determine the install target for each shell. Use user-local paths
|
|
@@ -5047,6 +5145,27 @@ function runCompletionCli() {
|
|
|
5047
5145
|
}
|
|
5048
5146
|
return null;
|
|
5049
5147
|
})();
|
|
5148
|
+
// --uninstall: delete the previously-installed completion file. No
|
|
5149
|
+
// need to generate the script. Idempotent.
|
|
5150
|
+
if (uninstall) {
|
|
5151
|
+
if (!installTarget) {
|
|
5152
|
+
process.stderr.write(`No uninstall target for shell ${shell}.\n`);
|
|
5153
|
+
process.exit(1);
|
|
5154
|
+
}
|
|
5155
|
+
try {
|
|
5156
|
+
if (fs.existsSync(installTarget)) {
|
|
5157
|
+
fs.unlinkSync(installTarget);
|
|
5158
|
+
process.stderr.write(`Uninstalled ${shell} completion from ${installTarget}\n`);
|
|
5159
|
+
} else {
|
|
5160
|
+
process.stderr.write(`Nothing to uninstall (no file at ${installTarget}).\n`);
|
|
5161
|
+
}
|
|
5162
|
+
process.exit(0);
|
|
5163
|
+
} catch (err) {
|
|
5164
|
+
process.stderr.write(`Failed to uninstall: ${err.message}\n`);
|
|
5165
|
+
process.exit(1);
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
5168
|
+
|
|
5050
5169
|
// Buffer the output so we can either print or write-to-disk.
|
|
5051
5170
|
let output = '';
|
|
5052
5171
|
const emit = (chunk) => { output += chunk; };
|
|
@@ -5260,6 +5379,11 @@ const PER_COMMAND_HELP = {
|
|
|
5260
5379
|
a parent in the chain. Useful when you forgot --force on checkpoint
|
|
5261
5380
|
or want to manually chain sessions across repos.
|
|
5262
5381
|
--json, -j Emit a JSON status object.`,
|
|
5382
|
+
explain: `cf-memory-mcp explain <session-id-or-prefix> [--json]
|
|
5383
|
+
Break down the handoff's quality_score into its rubric components,
|
|
5384
|
+
showing what's earned + what's missing. Lets users see why a handoff
|
|
5385
|
+
scored 0.5 vs 0.9 — and how to improve it.
|
|
5386
|
+
--json, -j Emit the breakdown as JSON.`,
|
|
5263
5387
|
};
|
|
5264
5388
|
|
|
5265
5389
|
function printPerCommandHelp(cmd) {
|
|
@@ -6045,6 +6169,11 @@ if (process.argv[2] === 'link') {
|
|
|
6045
6169
|
return;
|
|
6046
6170
|
}
|
|
6047
6171
|
|
|
6172
|
+
if (process.argv[2] === 'explain') {
|
|
6173
|
+
runExplainCli();
|
|
6174
|
+
return;
|
|
6175
|
+
}
|
|
6176
|
+
|
|
6048
6177
|
if (process.argv.includes('--diagnose')) {
|
|
6049
6178
|
(async () => {
|
|
6050
6179
|
console.log(`CF Memory MCP v${PACKAGE_VERSION} - Diagnostics`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cf-memory-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.51.0",
|
|
4
4
|
"description": "Cloudflare-hosted MCP server for code indexing, retrieval, and assistant memory with a direct remote MCP endpoint and local stdio bridge.",
|
|
5
5
|
"main": "bin/cf-memory-mcp.js",
|
|
6
6
|
"bin": {
|