cf-memory-mcp 3.16.0 → 3.17.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 +102 -0
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -932,6 +932,7 @@ class CFMemoryMCP {
|
|
|
932
932
|
message.params.arguments?.resume) {
|
|
933
933
|
const cached = this.maybeServePrewarmedResume(message);
|
|
934
934
|
if (cached) {
|
|
935
|
+
this.injectRepoDiffIntoResume(cached);
|
|
935
936
|
_mcpTrace('RESUME_PREWARM', `served get_context_bootstrap id=${message.id} from cache`);
|
|
936
937
|
process.stdout.write(JSON.stringify(cached) + '\n');
|
|
937
938
|
return;
|
|
@@ -986,6 +987,16 @@ class CFMemoryMCP {
|
|
|
986
987
|
this.cacheImplicitSessionFromResponse(response);
|
|
987
988
|
}
|
|
988
989
|
|
|
990
|
+
// Inject bridge-side git diff into resume responses. Lets the
|
|
991
|
+
// agent see what's changed in the repo since the handoff was
|
|
992
|
+
// written — files modified, commits added, branch moves —
|
|
993
|
+
// without having to call git themselves.
|
|
994
|
+
if (message.method === 'tools/call' &&
|
|
995
|
+
message.params?.name === 'get_context_bootstrap' &&
|
|
996
|
+
message.params.arguments?.resume) {
|
|
997
|
+
this.injectRepoDiffIntoResume(response);
|
|
998
|
+
}
|
|
999
|
+
|
|
989
1000
|
// Send response to stdout
|
|
990
1001
|
process.stdout.write(JSON.stringify(response) + '\n');
|
|
991
1002
|
|
|
@@ -2502,6 +2513,97 @@ class CFMemoryMCP {
|
|
|
2502
2513
|
}
|
|
2503
2514
|
}
|
|
2504
2515
|
|
|
2516
|
+
/**
|
|
2517
|
+
* Mutates a get_context_bootstrap response to attach a `repo_diff`
|
|
2518
|
+
* field describing what's changed in the local repo since the
|
|
2519
|
+
* handoff. Bridge-only — server has no git access. Best-effort, silent
|
|
2520
|
+
* on failure.
|
|
2521
|
+
*
|
|
2522
|
+
* Opt out via CF_MEMORY_RESUME_DIFF=off.
|
|
2523
|
+
*/
|
|
2524
|
+
injectRepoDiffIntoResume(response) {
|
|
2525
|
+
try {
|
|
2526
|
+
const opt = process.env.CF_MEMORY_RESUME_DIFF;
|
|
2527
|
+
if (opt === '0' || opt === 'false' || opt === 'off') return;
|
|
2528
|
+
const text = response?.result?.content?.[0]?.text;
|
|
2529
|
+
if (!text) return;
|
|
2530
|
+
let parsed;
|
|
2531
|
+
try { parsed = JSON.parse(text); } catch (_) { return; }
|
|
2532
|
+
const envelope = parsed?.resume_handoff;
|
|
2533
|
+
if (!envelope) return;
|
|
2534
|
+
|
|
2535
|
+
const meta = this.getRepoMetadata();
|
|
2536
|
+
const repoRoot = meta.repo_path;
|
|
2537
|
+
if (!repoRoot) return;
|
|
2538
|
+
// Reference point: prefer ended_at, fall back to started_at.
|
|
2539
|
+
const since = envelope.ended_at || envelope.started_at;
|
|
2540
|
+
if (!since) return;
|
|
2541
|
+
|
|
2542
|
+
const diff = this.computeRepoDiff(repoRoot, since, envelope.handoff?.branch || meta.branch);
|
|
2543
|
+
if (diff) {
|
|
2544
|
+
envelope.repo_diff = diff;
|
|
2545
|
+
// Re-serialize the modified envelope back into the response.
|
|
2546
|
+
response.result.content[0].text = JSON.stringify(parsed);
|
|
2547
|
+
}
|
|
2548
|
+
} catch (err) {
|
|
2549
|
+
this.logDebug(`injectRepoDiffIntoResume failed: ${err && err.message}`);
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
/**
|
|
2554
|
+
* Run a bounded git query in the repo root to summarize changes since
|
|
2555
|
+
* the handoff was written. Returns { commits, files_changed,
|
|
2556
|
+
* branch_now, branch_at_handoff } or null if git isn't available.
|
|
2557
|
+
*/
|
|
2558
|
+
computeRepoDiff(repoRoot, sinceIso, handoffBranch) {
|
|
2559
|
+
try {
|
|
2560
|
+
const { execSync } = require('child_process');
|
|
2561
|
+
const run = (cmd) => execSync(cmd, {
|
|
2562
|
+
cwd: repoRoot,
|
|
2563
|
+
encoding: 'utf8',
|
|
2564
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
2565
|
+
timeout: 1000,
|
|
2566
|
+
});
|
|
2567
|
+
// Git accepts ISO timestamps via --since
|
|
2568
|
+
const commitsOut = run(`git log --since='${sinceIso}' --pretty=format:'%h %s' -n 25`);
|
|
2569
|
+
const commits = commitsOut.split('\n').filter(Boolean).map(line => {
|
|
2570
|
+
const [hash, ...rest] = line.split(' ');
|
|
2571
|
+
return { hash, subject: rest.join(' ').slice(0, 120) };
|
|
2572
|
+
});
|
|
2573
|
+
|
|
2574
|
+
// Files changed since the handoff. Compare HEAD against the
|
|
2575
|
+
// commit closest to the handoff time. If no commits since,
|
|
2576
|
+
// diff vs. HEAD~0 returns nothing.
|
|
2577
|
+
let filesChanged = [];
|
|
2578
|
+
try {
|
|
2579
|
+
const namesOut = run(`git log --since='${sinceIso}' --name-only --pretty=format:''`);
|
|
2580
|
+
const names = new Set(namesOut.split('\n').map(s => s.trim()).filter(Boolean));
|
|
2581
|
+
filesChanged = Array.from(names).slice(0, 50);
|
|
2582
|
+
} catch (_) { /* empty diff is fine */ }
|
|
2583
|
+
|
|
2584
|
+
// Branch information.
|
|
2585
|
+
let branchNow = null;
|
|
2586
|
+
try {
|
|
2587
|
+
branchNow = run('git symbolic-ref --short HEAD').trim();
|
|
2588
|
+
} catch (_) { /* detached HEAD */ }
|
|
2589
|
+
|
|
2590
|
+
const diff = {
|
|
2591
|
+
commits_since_handoff: commits,
|
|
2592
|
+
files_changed_count: filesChanged.length,
|
|
2593
|
+
files_changed: filesChanged,
|
|
2594
|
+
};
|
|
2595
|
+
if (branchNow) diff.branch_now = branchNow;
|
|
2596
|
+
if (handoffBranch) diff.branch_at_handoff = handoffBranch;
|
|
2597
|
+
if (handoffBranch && branchNow && handoffBranch !== branchNow) {
|
|
2598
|
+
diff.branch_changed = true;
|
|
2599
|
+
}
|
|
2600
|
+
return diff;
|
|
2601
|
+
} catch (err) {
|
|
2602
|
+
this.logDebug(`computeRepoDiff failed: ${err && err.message}`);
|
|
2603
|
+
return null;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2505
2607
|
/**
|
|
2506
2608
|
* Build a minimal handoff packet from observed bridge activity. Used by
|
|
2507
2609
|
* end_session auto-synthesis, the periodic auto-checkpoint, and the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cf-memory-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.17.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": {
|