cf-memory-mcp 3.32.0 → 3.33.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.
@@ -418,7 +418,8 @@ const TOOLS_LIST = [
418
418
  session_id: { type: 'string', description: 'Full session UUID to delete (not a prefix).' },
419
419
  status: { description: 'Status filter: single string or array of statuses (in_progress, blocked, completed, abandoned).' },
420
420
  older_than_days: { type: 'number', description: 'Delete sessions older than N days.' },
421
- repo_path: { type: 'string', description: 'Restrict to a specific repo_path.' }
421
+ repo_path: { type: 'string', description: 'Restrict to a specific repo_path.' },
422
+ dry_run: { type: 'boolean', description: 'When true, preview what would be deleted without actually deleting.' }
422
423
  }
423
424
  }
424
425
  }
@@ -3894,6 +3895,10 @@ function parseCliArgs(rest) {
3894
3895
  flags.repo_path = rest[++i];
3895
3896
  } else if (a.startsWith('--repo=')) {
3896
3897
  flags.repo_path = a.slice('--repo='.length);
3898
+ } else if (a === '--since') {
3899
+ flags.since = rest[++i];
3900
+ } else if (a.startsWith('--since=')) {
3901
+ flags.since = a.slice('--since='.length);
3897
3902
  } else if (a === '--yes' || a === '-y') {
3898
3903
  flags.yes = true;
3899
3904
  } else positional.push(a);
@@ -4006,9 +4011,19 @@ async function runListCli() {
4006
4011
  const args = { resume: true };
4007
4012
  if (meta.repo_path) args.repo_path = meta.repo_path;
4008
4013
  if (meta.branch) args.branch = meta.branch;
4009
- const fake = { params: { name: 'retrieve_context', arguments: {} } };
4010
- await server.maybeFillProjectId(fake);
4011
- if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
4014
+ // Pass-through server-side filters when set on the CLI.
4015
+ if (flags.status) args.status_filter = flags.status;
4016
+ if (flags.since) args.since = flags.since;
4017
+ if (flags.repo_path) {
4018
+ // --repo overrides cwd → skip cwd's project_id too. Otherwise
4019
+ // tier-1 project_id_exact would short-circuit the lookup and
4020
+ // return cwd's handoff regardless of repo_path.
4021
+ args.repo_path = flags.repo_path;
4022
+ } else {
4023
+ const fake = { params: { name: 'retrieve_context', arguments: {} } };
4024
+ await server.maybeFillProjectId(fake);
4025
+ if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
4026
+ }
4012
4027
 
4013
4028
  const response = await server.makeRequest({
4014
4029
  jsonrpc: '2.0',
@@ -4025,8 +4040,10 @@ async function runListCli() {
4025
4040
 
4026
4041
  if (flags.json) {
4027
4042
  process.stdout.write(JSON.stringify({
4028
- repo_path: meta.repo_path,
4029
- branch: meta.branch,
4043
+ repo_path: args.repo_path || meta.repo_path,
4044
+ branch: args.branch || meta.branch,
4045
+ status_filter: flags.status,
4046
+ since: flags.since,
4030
4047
  count: list.length,
4031
4048
  handoffs: list,
4032
4049
  empty_hint: list.length === 0 ? payload.empty_hint : undefined,
@@ -4047,8 +4064,10 @@ async function runListCli() {
4047
4064
  const countSummary = Object.entries(counts)
4048
4065
  .map(([s, n]) => `${n} ${s}`)
4049
4066
  .join(', ');
4050
- // Render a compact table to terminal.
4051
- process.stdout.write(`Recent handoffs for ${meta.repo_path || 'this cwd'} (${countSummary}):\n\n`);
4067
+ // Render a compact table to terminal. Show the actual filter
4068
+ // applied (--repo override, or cwd default).
4069
+ const displayRepo = args.repo_path || 'this cwd';
4070
+ process.stdout.write(`Recent handoffs for ${displayRepo} (${countSummary}):\n\n`);
4052
4071
  const fmtAge = (iso) => {
4053
4072
  if (!iso) return '?';
4054
4073
  const min = Math.round((Date.now() - new Date(iso).getTime()) / 60000);
@@ -4094,21 +4113,40 @@ async function runDeleteCli() {
4094
4113
  server.logDebug = () => {};
4095
4114
  try {
4096
4115
  if (bulkMode) {
4097
- // Bulk delete path. First dry-run: query matching sessions
4098
- // count via list, then confirm with --yes for >5.
4099
4116
  const args = {};
4100
4117
  if (flags.status) args.status = flags.status;
4101
4118
  if (flags.older_than_days !== undefined) args.older_than_days = flags.older_than_days;
4102
4119
  if (flags.repo_path) args.repo_path = flags.repo_path;
4103
4120
 
4104
- // Preview: do an initial delete_session with the same filters
4105
- // to count matches via the response's deleted_session_ids
4106
- // (capped at 50). For larger counts we accept the cap as an
4107
- // approximation; the server handles all of them anyway.
4108
- // Use --yes to skip the preview/confirm prompt.
4121
+ // Dry-run preview when --yes is missing. The server returns
4122
+ // {deleted:false, deleted_count, deleted_session_ids[]} so the
4123
+ // user can see what WOULD be deleted before committing.
4109
4124
  if (!flags.yes) {
4110
- process.stderr.write(`Dry-run: previewing matches without confirm prompt is not supported yet.\n`);
4111
- process.stderr.write(`Run again with --yes to confirm: cf-memory-mcp delete ${process.argv.slice(3).join(' ')} --yes\n`);
4125
+ const previewRes = await server.makeRequest({
4126
+ jsonrpc: '2.0', id: `cli-delete-preview-${Date.now()}`,
4127
+ method: 'tools/call',
4128
+ params: { name: 'delete_session', arguments: { ...args, dry_run: true } },
4129
+ });
4130
+ const previewText = previewRes?.result?.content?.[0]?.text;
4131
+ const preview = JSON.parse(previewText || '{}');
4132
+ if (flags.json) {
4133
+ process.stdout.write(JSON.stringify({ ...preview, would_delete: true }, null, 2) + '\n');
4134
+ process.exit(2);
4135
+ }
4136
+ if (preview.deleted_count === 0) {
4137
+ process.stderr.write(`No sessions match the filters. Nothing to delete.\n`);
4138
+ process.exit(3);
4139
+ }
4140
+ process.stderr.write(`Would delete ${preview.deleted_count} session${preview.deleted_count === 1 ? '' : 's'}:\n`);
4141
+ const previewIds = preview.deleted_session_ids || [];
4142
+ for (const id of previewIds.slice(0, 10)) {
4143
+ process.stderr.write(` ${id.slice(0, 8)}\n`);
4144
+ }
4145
+ if (previewIds.length > 10) {
4146
+ process.stderr.write(` ... and ${preview.deleted_count - 10} more\n`);
4147
+ }
4148
+ process.stderr.write(`\nRe-run with --yes to confirm:\n`);
4149
+ process.stderr.write(` cf-memory-mcp delete ${process.argv.slice(3).join(' ')} --yes\n`);
4112
4150
  process.exit(2);
4113
4151
  }
4114
4152
 
@@ -4290,8 +4328,12 @@ const PER_COMMAND_HELP = {
4290
4328
  --md <path> Write the markdown to a file instead of stdout.
4291
4329
  --json, -j Emit the full bootstrap payload as JSON for scripts.
4292
4330
  Exit codes: 0 = handoff found, 3 = no handoff found.`,
4293
- list: `cf-memory-mcp list [--limit N] [--json]
4294
- List recent handoffs for the current cwd, status-ranked.
4331
+ list: `cf-memory-mcp list [--status S] [--since ISO] [--repo PATH] [--limit N] [--json]
4332
+ List recent handoffs for the current cwd, status-ranked. Header shows
4333
+ a status-count summary.
4334
+ --status S Restrict to a given status (in_progress, completed, ...).
4335
+ --since ISO Lower bound on handoff timestamp (ISO 8601).
4336
+ --repo PATH Override the cwd's repo (peek at another repo).
4295
4337
  --limit N, -n N Max number of entries (default 5, max 50).
4296
4338
  --json, -j Emit a JSON array for scripts.`,
4297
4339
  checkpoint: `cf-memory-mcp checkpoint ["<goal>"] [--force] [--json]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cf-memory-mcp",
3
- "version": "3.32.0",
3
+ "version": "3.33.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": {