cf-memory-mcp 3.21.0 → 3.22.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.
@@ -3580,15 +3580,17 @@ A portable MCP (Model Context Protocol) server for AI memory storage using Cloud
3580
3580
 
3581
3581
  Usage:
3582
3582
  npx cf-memory-mcp Start the MCP server
3583
- npx cf-memory-mcp resume Print the prior resume handoff for cwd (markdown)
3584
- npx cf-memory-mcp resume <id> Print a specific handoff by session_id prefix
3583
+ npx cf-memory-mcp resume [id] Print the prior resume handoff (markdown)
3585
3584
  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
+ npx cf-memory-mcp checkpoint ["<goal>"] Snapshot current state (keep_open)
3588
3586
  npx cf-memory-mcp --version Show version
3589
3587
  npx cf-memory-mcp --help Show this help
3590
3588
  npx cf-memory-mcp --diagnose Test connectivity and report issues
3591
3589
 
3590
+ Subcommand flags:
3591
+ --json, -j Emit JSON instead of formatted text (resume/list/checkpoint)
3592
+ --limit N, -n N For 'list': max number of handoffs (default 5, max 50)
3593
+
3592
3594
  Environment Variables:
3593
3595
  CF_MEMORY_API_KEY=<key> Your CF Memory API key (required)
3594
3596
  CF_MEMORY_BASE_URL=<url> Override the default deployed worker
@@ -3601,6 +3603,25 @@ For more information, visit: https://github.com/johnlam90/cf-memory-mcp
3601
3603
  process.exit(0);
3602
3604
  }
3603
3605
 
3606
+ // Parse positional + flag args for CLI subcommands. Returns
3607
+ // { positional: string[], flags: { json: boolean, limit?: number } }.
3608
+ function parseCliArgs(rest) {
3609
+ const positional = [];
3610
+ const flags = { json: false };
3611
+ for (let i = 0; i < rest.length; i++) {
3612
+ const a = rest[i];
3613
+ if (a === '--json' || a === '-j') flags.json = true;
3614
+ else if (a === '--limit' || a === '-n') {
3615
+ const n = parseInt(rest[++i], 10);
3616
+ if (Number.isFinite(n) && n > 0) flags.limit = Math.min(n, 50);
3617
+ } else if (a.startsWith('--limit=')) {
3618
+ const n = parseInt(a.slice('--limit='.length), 10);
3619
+ if (Number.isFinite(n) && n > 0) flags.limit = Math.min(n, 50);
3620
+ } else positional.push(a);
3621
+ }
3622
+ return { positional, flags };
3623
+ }
3624
+
3604
3625
  // Read-only inspection command: print the prior resume handoff to stdout.
3605
3626
  // Lets a human see what state is captured without involving an MCP client.
3606
3627
  async function runResumeCli() {
@@ -3608,6 +3629,7 @@ async function runResumeCli() {
3608
3629
  console.error('Error: CF_MEMORY_API_KEY environment variable is required');
3609
3630
  process.exit(1);
3610
3631
  }
3632
+ const { positional, flags } = parseCliArgs(process.argv.slice(3));
3611
3633
  const server = new CFMemoryMCP();
3612
3634
  server.logDebug = () => {};
3613
3635
  server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
@@ -3617,7 +3639,7 @@ async function runResumeCli() {
3617
3639
  if (meta.repo_path) args.repo_path = meta.repo_path;
3618
3640
  if (meta.branch) args.branch = meta.branch;
3619
3641
  // Optional positional session_id argument.
3620
- const sessionArg = process.argv[3];
3642
+ const sessionArg = positional[0];
3621
3643
  if (sessionArg) args.session_id_hint = sessionArg;
3622
3644
  const fake = { params: { name: 'retrieve_context', arguments: {} } };
3623
3645
  await server.maybeFillProjectId(fake);
@@ -3635,6 +3657,12 @@ async function runResumeCli() {
3635
3657
  process.exit(2);
3636
3658
  }
3637
3659
  const payload = JSON.parse(text);
3660
+ // JSON output mode: emit the full payload as a single JSON object.
3661
+ // Scripts can pipe through jq to extract specific fields.
3662
+ if (flags.json) {
3663
+ process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
3664
+ process.exit(payload.resume_handoff ? 0 : 0);
3665
+ }
3638
3666
  if (payload.resume_handoff?.handoff) {
3639
3667
  if (payload.resume_prompt) {
3640
3668
  process.stdout.write(payload.resume_prompt + '\n');
@@ -3665,6 +3693,7 @@ async function runListCli() {
3665
3693
  console.error('Error: CF_MEMORY_API_KEY environment variable is required');
3666
3694
  process.exit(1);
3667
3695
  }
3696
+ const { flags } = parseCliArgs(process.argv.slice(3));
3668
3697
  const server = new CFMemoryMCP();
3669
3698
  server.logDebug = () => {};
3670
3699
  server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
@@ -3685,7 +3714,19 @@ async function runListCli() {
3685
3714
  });
3686
3715
  const text = response?.result?.content?.[0]?.text;
3687
3716
  const payload = JSON.parse(text || '{}');
3688
- const list = Array.isArray(payload.recent_handoffs) ? payload.recent_handoffs : [];
3717
+ const allList = Array.isArray(payload.recent_handoffs) ? payload.recent_handoffs : [];
3718
+ const list = flags.limit ? allList.slice(0, flags.limit) : allList;
3719
+
3720
+ if (flags.json) {
3721
+ process.stdout.write(JSON.stringify({
3722
+ repo_path: meta.repo_path,
3723
+ branch: meta.branch,
3724
+ count: list.length,
3725
+ handoffs: list,
3726
+ empty_hint: list.length === 0 ? payload.empty_hint : undefined,
3727
+ }, null, 2) + '\n');
3728
+ process.exit(0);
3729
+ }
3689
3730
  if (list.length === 0) {
3690
3731
  process.stdout.write((payload.empty_hint || 'No handoffs for this context.') + '\n');
3691
3732
  process.exit(0);
@@ -3721,12 +3762,13 @@ async function runCheckpointCli() {
3721
3762
  console.error('Error: CF_MEMORY_API_KEY environment variable is required');
3722
3763
  process.exit(1);
3723
3764
  }
3765
+ const { positional, flags } = parseCliArgs(process.argv.slice(3));
3724
3766
  const server = new CFMemoryMCP();
3725
3767
  server.logDebug = () => {};
3726
3768
  server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
3727
3769
  try {
3728
3770
  // Optional positional goal argument: `cf-memory-mcp checkpoint "<goal text>"`
3729
- const goalArg = process.argv.slice(3).join(' ').trim();
3771
+ const goalArg = positional.join(' ').trim();
3730
3772
  const meta = server.getRepoMetadata();
3731
3773
  // Need a session to attach the handoff to. Use or create the
3732
3774
  // implicit session for this cwd (creates a new one if no implicit).
@@ -3758,6 +3800,19 @@ async function runCheckpointCli() {
3758
3800
  });
3759
3801
  const text = response?.result?.content?.[0]?.text;
3760
3802
  const payload = JSON.parse(text || '{}');
3803
+ if (flags.json) {
3804
+ process.stdout.write(JSON.stringify({
3805
+ session_id: sessionId,
3806
+ short_id: sessionId.slice(0, 8),
3807
+ handoff_stored: !!payload.handoff_stored,
3808
+ kept_open: !!payload.kept_open,
3809
+ goal: handoff.goal,
3810
+ repo_path: handoff.repo_path,
3811
+ branch: handoff.branch,
3812
+ resume_command: `npx cf-memory-mcp resume ${sessionId.slice(0, 8)}`,
3813
+ }, null, 2) + '\n');
3814
+ process.exit(payload.handoff_stored ? 0 : 2);
3815
+ }
3761
3816
  if (payload.handoff_stored) {
3762
3817
  const shortId = sessionId.slice(0, 8);
3763
3818
  process.stdout.write(`Checkpoint saved (session ${shortId}).\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cf-memory-mcp",
3
- "version": "3.21.0",
3
+ "version": "3.22.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": {