cf-memory-mcp 3.20.0 → 3.21.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.
@@ -3582,6 +3582,9 @@ Usage:
3582
3582
  npx cf-memory-mcp Start the MCP server
3583
3583
  npx cf-memory-mcp resume Print the prior resume handoff for cwd (markdown)
3584
3584
  npx cf-memory-mcp resume <id> Print a specific handoff by session_id prefix
3585
+ npx cf-memory-mcp list List recent handoffs for cwd
3586
+ npx cf-memory-mcp checkpoint Snapshot current state to a fresh handoff (keep session open)
3587
+ npx cf-memory-mcp checkpoint "<goal>" Same, with an explicit goal string
3585
3588
  npx cf-memory-mcp --version Show version
3586
3589
  npx cf-memory-mcp --help Show this help
3587
3590
  npx cf-memory-mcp --diagnose Test connectivity and report issues
@@ -3657,11 +3660,135 @@ async function runResumeCli() {
3657
3660
  }
3658
3661
  }
3659
3662
 
3663
+ async function runListCli() {
3664
+ if (!API_KEY) {
3665
+ console.error('Error: CF_MEMORY_API_KEY environment variable is required');
3666
+ process.exit(1);
3667
+ }
3668
+ const server = new CFMemoryMCP();
3669
+ server.logDebug = () => {};
3670
+ server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
3671
+ try {
3672
+ const meta = server.getRepoMetadata();
3673
+ const args = { resume: true };
3674
+ if (meta.repo_path) args.repo_path = meta.repo_path;
3675
+ if (meta.branch) args.branch = meta.branch;
3676
+ const fake = { params: { name: 'retrieve_context', arguments: {} } };
3677
+ await server.maybeFillProjectId(fake);
3678
+ if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
3679
+
3680
+ const response = await server.makeRequest({
3681
+ jsonrpc: '2.0',
3682
+ id: `cli-list-${Date.now()}`,
3683
+ method: 'tools/call',
3684
+ params: { name: 'get_context_bootstrap', arguments: args },
3685
+ });
3686
+ const text = response?.result?.content?.[0]?.text;
3687
+ const payload = JSON.parse(text || '{}');
3688
+ const list = Array.isArray(payload.recent_handoffs) ? payload.recent_handoffs : [];
3689
+ if (list.length === 0) {
3690
+ process.stdout.write((payload.empty_hint || 'No handoffs for this context.') + '\n');
3691
+ process.exit(0);
3692
+ }
3693
+ // Render a compact table to terminal.
3694
+ process.stdout.write(`Recent handoffs for ${meta.repo_path || 'this cwd'}:\n\n`);
3695
+ const fmtAge = (iso) => {
3696
+ if (!iso) return '?';
3697
+ const min = Math.round((Date.now() - new Date(iso).getTime()) / 60000);
3698
+ if (min < 60) return `${min}m`;
3699
+ if (min < 1440) return `${Math.round(min/60)}h`;
3700
+ return `${Math.round(min/1440)}d`;
3701
+ };
3702
+ for (const h of list) {
3703
+ const shortId = (h.session_id || '').slice(0, 8);
3704
+ const age = fmtAge(h.ended_at || h.started_at);
3705
+ const status = (h.status || 'unknown').padEnd(11);
3706
+ const branch = h.branch ? `[${h.branch}] ` : '';
3707
+ const goal = (h.goal || '(no goal)').slice(0, 80);
3708
+ process.stdout.write(` ${shortId} ${status} ${age.padStart(4)} ago ${branch}${goal}\n`);
3709
+ if (h.next_step) process.stdout.write(` next: ${h.next_step.slice(0, 80)}\n`);
3710
+ }
3711
+ process.stdout.write(`\n(Run "npx cf-memory-mcp resume <id>" to see a specific handoff)\n`);
3712
+ process.exit(0);
3713
+ } catch (err) {
3714
+ console.error('list command failed:', err.message);
3715
+ process.exit(1);
3716
+ }
3717
+ }
3718
+
3719
+ async function runCheckpointCli() {
3720
+ if (!API_KEY) {
3721
+ console.error('Error: CF_MEMORY_API_KEY environment variable is required');
3722
+ process.exit(1);
3723
+ }
3724
+ const server = new CFMemoryMCP();
3725
+ server.logDebug = () => {};
3726
+ server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
3727
+ try {
3728
+ // Optional positional goal argument: `cf-memory-mcp checkpoint "<goal text>"`
3729
+ const goalArg = process.argv.slice(3).join(' ').trim();
3730
+ const meta = server.getRepoMetadata();
3731
+ // Need a session to attach the handoff to. Use or create the
3732
+ // implicit session for this cwd (creates a new one if no implicit).
3733
+ const sessionId = await server.getOrCreateImplicitSession();
3734
+ if (!sessionId) {
3735
+ console.error('Could not create or find an implicit session for this cwd.');
3736
+ process.exit(1);
3737
+ }
3738
+ // Build handoff: if agent provided a goal, use it; otherwise
3739
+ // synthesize from bridge activity (which is likely sparse since
3740
+ // this is a fresh process).
3741
+ const handoff = server.synthesizeMinimalHandoff();
3742
+ if (goalArg) handoff.goal = goalArg;
3743
+ if (meta.repo_path) handoff.repo_path = meta.repo_path;
3744
+ if (meta.branch) handoff.branch = meta.branch;
3745
+ const fake = { params: { name: 'retrieve_context', arguments: {} } };
3746
+ await server.maybeFillProjectId(fake);
3747
+ if (fake.params.arguments.project_id) handoff.project_id = fake.params.arguments.project_id;
3748
+
3749
+ const response = await server.makeRequest({
3750
+ jsonrpc: '2.0',
3751
+ id: `cli-checkpoint-${Date.now()}`,
3752
+ method: 'tools/call',
3753
+ params: { name: 'end_session', arguments: {
3754
+ session_id: sessionId,
3755
+ keep_open: true,
3756
+ handoff,
3757
+ } },
3758
+ });
3759
+ const text = response?.result?.content?.[0]?.text;
3760
+ const payload = JSON.parse(text || '{}');
3761
+ if (payload.handoff_stored) {
3762
+ const shortId = sessionId.slice(0, 8);
3763
+ process.stdout.write(`Checkpoint saved (session ${shortId}).\n`);
3764
+ process.stdout.write(`Goal: ${handoff.goal}\n`);
3765
+ process.stdout.write(`To resume later: npx cf-memory-mcp resume ${shortId}\n`);
3766
+ process.exit(0);
3767
+ }
3768
+ process.stdout.write('Checkpoint did not store a handoff.\n');
3769
+ if (payload.error) process.stdout.write(`Error: ${payload.error}\n`);
3770
+ process.exit(2);
3771
+ } catch (err) {
3772
+ console.error('checkpoint command failed:', err.message);
3773
+ process.exit(1);
3774
+ }
3775
+ }
3776
+
3660
3777
  if (process.argv[2] === 'resume') {
3661
3778
  runResumeCli();
3662
3779
  return;
3663
3780
  }
3664
3781
 
3782
+ if (process.argv[2] === 'list') {
3783
+ runListCli();
3784
+ return;
3785
+ }
3786
+
3787
+ if (process.argv[2] === 'checkpoint') {
3788
+ runCheckpointCli();
3789
+ return;
3790
+ }
3791
+
3665
3792
  if (process.argv.includes('--diagnose')) {
3666
3793
  (async () => {
3667
3794
  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.20.0",
3
+ "version": "3.21.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": {