cf-memory-mcp 3.55.0 → 3.57.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.
@@ -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', 'explain']);
3922
+ const SUBCOMMANDS = new Set(['resume', 'list', 'checkpoint', 'status', 'clean', 'export', 'import', 'doctor', 'completion', 'delete', 'env', 'history', 'link', 'explain', 'gha']);
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'))) {
@@ -3936,6 +3936,7 @@ Usage:
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
3938
  npx cf-memory-mcp explain <id> Break down the handoff's quality_score
3939
+ npx cf-memory-mcp gha [<id>] Append rendered resume packet to $GITHUB_STEP_SUMMARY
3939
3940
  npx cf-memory-mcp status Show bridge state + server resume availability
3940
3941
  npx cf-memory-mcp clean Delete local disk cache for current cwd
3941
3942
  npx cf-memory-mcp clean --all Delete ALL local disk caches
@@ -4038,6 +4039,12 @@ function parseCliArgs(rest) {
4038
4039
  flags.blockers_only = true;
4039
4040
  } else if (a === '--chain') {
4040
4041
  flags.chain = true;
4042
+ } else if (a === '--include-chain') {
4043
+ const n = parseInt(rest[++i], 10);
4044
+ flags.include_chain = Number.isFinite(n) && n > 0 ? Math.min(n, 10) : 3;
4045
+ } else if (a.startsWith('--include-chain=')) {
4046
+ const n = parseInt(a.slice('--include-chain='.length), 10);
4047
+ flags.include_chain = Number.isFinite(n) && n > 0 ? Math.min(n, 10) : 3;
4041
4048
  } else if (a === '--validate') {
4042
4049
  flags.validate = true;
4043
4050
  } else if (a === '--raw') {
@@ -4614,6 +4621,32 @@ async function runResumeCli() {
4614
4621
  } else {
4615
4622
  process.stdout.write(JSON.stringify(payload.resume_handoff, null, 2) + '\n');
4616
4623
  }
4624
+ // --include-chain N: walk parent_session_id back N times and
4625
+ // append each parent's resume_prompt inline so the agent sees
4626
+ // the full thread arc in one output.
4627
+ if (flags.include_chain && flags.include_chain > 0) {
4628
+ let cur = payload.resume_handoff;
4629
+ for (let i = 0; i < flags.include_chain; i++) {
4630
+ const parentId = cur?.handoff?.parent_session_id;
4631
+ if (!parentId) break;
4632
+ const parentRes = await server.makeRequest({
4633
+ jsonrpc: '2.0', id: `cli-include-chain-${i}-${Date.now()}`,
4634
+ method: 'tools/call',
4635
+ params: { name: 'get_context_bootstrap', arguments: { resume: true, session_id_hint: parentId } },
4636
+ });
4637
+ const parentText = parentRes?.result?.content?.[0]?.text;
4638
+ const parentPayload = JSON.parse(parentText || '{}');
4639
+ if (!parentPayload.resume_handoff) break;
4640
+ process.stdout.write(`\n---\n## ↑ Parent ${i + 1}: ${(parentPayload.resume_handoff.session_id||'').slice(0,8)}\n\n`);
4641
+ if (parentPayload.resume_prompt) {
4642
+ // Strip the parent's own "## Resume context" header
4643
+ // to avoid duplicated h2s.
4644
+ const cleaned = parentPayload.resume_prompt.replace(/^## Resume context from previous session\n+/, '');
4645
+ process.stdout.write(cleaned + '\n');
4646
+ }
4647
+ cur = parentPayload.resume_handoff;
4648
+ }
4649
+ }
4617
4650
  if (Array.isArray(payload.recent_handoffs) && payload.recent_handoffs.length > 1) {
4618
4651
  process.stdout.write('\n---\nOther recent handoffs:\n');
4619
4652
  for (const h of payload.recent_handoffs.slice(0, 4)) {
@@ -4635,6 +4668,59 @@ async function runResumeCli() {
4635
4668
  }
4636
4669
  }
4637
4670
 
4671
+ async function runGhaCli() {
4672
+ if (!API_KEY) {
4673
+ console.error('Error: CF_MEMORY_API_KEY environment variable is required');
4674
+ process.exit(1);
4675
+ }
4676
+ const { positional } = parseCliArgs(process.argv.slice(3));
4677
+ const sessionArg = positional[0]; // optional
4678
+ const server = new CFMemoryMCP();
4679
+ server.logDebug = () => {};
4680
+ try {
4681
+ const meta = server.getRepoMetadata();
4682
+ const args = { resume: true };
4683
+ if (meta.repo_path) args.repo_path = meta.repo_path;
4684
+ if (meta.branch) args.branch = meta.branch;
4685
+ if (sessionArg) args.session_id_hint = sessionArg;
4686
+ const fake = { params: { name: 'retrieve_context', arguments: {} } };
4687
+ await server.maybeFillProjectId(fake);
4688
+ if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
4689
+
4690
+ const response = await server.makeRequest({
4691
+ jsonrpc: '2.0', id: `cli-gha-${Date.now()}`,
4692
+ method: 'tools/call',
4693
+ params: { name: 'get_context_bootstrap', arguments: args },
4694
+ });
4695
+ const text = response?.result?.content?.[0]?.text;
4696
+ const payload = JSON.parse(text || '{}');
4697
+ if (!payload.resume_handoff || !payload.resume_prompt) {
4698
+ process.stderr.write((payload.empty_hint || 'No resume handoff available.') + '\n');
4699
+ process.exit(3);
4700
+ }
4701
+ const summary = process.env.GITHUB_STEP_SUMMARY;
4702
+ const body = payload.resume_prompt + '\n';
4703
+ if (summary) {
4704
+ try {
4705
+ fs.appendFileSync(summary, body);
4706
+ process.stderr.write(`Appended resume packet to $GITHUB_STEP_SUMMARY (${body.length} chars)\n`);
4707
+ process.exit(0);
4708
+ } catch (err) {
4709
+ process.stderr.write(`Failed to write to $GITHUB_STEP_SUMMARY: ${err.message}\n`);
4710
+ process.exit(1);
4711
+ }
4712
+ }
4713
+ // Fallback: outside GHA, print to stdout. Lets users test the
4714
+ // formatting locally before deploying.
4715
+ process.stdout.write(body);
4716
+ process.stderr.write(`(GITHUB_STEP_SUMMARY not set — printed to stdout. In GHA, this would append to the step summary.)\n`);
4717
+ process.exit(0);
4718
+ } catch (err) {
4719
+ console.error('gha command failed:', err.message);
4720
+ process.exit(1);
4721
+ }
4722
+ }
4723
+
4638
4724
  async function runExplainCli() {
4639
4725
  if (!API_KEY) {
4640
4726
  console.error('Error: CF_MEMORY_API_KEY environment variable is required');
@@ -5211,7 +5297,7 @@ function runCompletionCli() {
5211
5297
  process.stderr.write(`\nDone. Installed completion for ${installed} shell${installed === 1 ? '' : 's'}.\n`);
5212
5298
  process.exit(installed > 0 ? 0 : 1);
5213
5299
  }
5214
- const commands = ['resume', 'list', 'history', 'checkpoint', 'link', 'explain', 'status', 'clean', 'export', 'import', 'delete', 'doctor', 'env', 'completion'];
5300
+ const commands = ['resume', 'list', 'history', 'checkpoint', 'link', 'explain', 'gha', 'status', 'clean', 'export', 'import', 'delete', 'doctor', 'env', 'completion'];
5215
5301
  const flags = ['--json', '-j', '--limit', '-n', '--md', '--all', '--force', '-f', '--version', '-v', '--help', '-h', '--diagnose'];
5216
5302
 
5217
5303
  // Determine the install target for each shell. Use user-local paths
@@ -5391,6 +5477,7 @@ const PER_COMMAND_HELP = {
5391
5477
  --decisions-only decisions, one per line.
5392
5478
  --blockers-only open blockers, one per line.
5393
5479
  --chain Walk parent_session_id back; show the thread history.
5480
+ --include-chain N Inline the last N parent handoffs in the rendered output (default 3, max 10).
5394
5481
  --diff <other-id> Compare this handoff against another (added/removed/changed fields).
5395
5482
  --validate Check that files_touched + code_anchors still exist locally.
5396
5483
  --raw Print just the raw handoff JSON (no envelope metadata).
@@ -5486,6 +5573,10 @@ const PER_COMMAND_HELP = {
5486
5573
  showing what's earned + what's missing. Lets users see why a handoff
5487
5574
  scored 0.5 vs 0.9 — and how to improve it.
5488
5575
  --json, -j Emit the breakdown as JSON.`,
5576
+ gha: `cf-memory-mcp gha [<session-id-or-prefix>]
5577
+ GitHub Actions integration: append the rendered resume packet to
5578
+ $GITHUB_STEP_SUMMARY. Falls back to stdout when run outside GHA.
5579
+ Useful in a workflow step to surface what the agent was doing.`,
5489
5580
  };
5490
5581
 
5491
5582
  function printPerCommandHelp(cmd) {
@@ -6293,6 +6384,11 @@ if (process.argv[2] === 'explain') {
6293
6384
  return;
6294
6385
  }
6295
6386
 
6387
+ if (process.argv[2] === 'gha') {
6388
+ runGhaCli();
6389
+ return;
6390
+ }
6391
+
6296
6392
  if (process.argv.includes('--diagnose')) {
6297
6393
  (async () => {
6298
6394
  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.55.0",
3
+ "version": "3.57.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": {