cf-memory-mcp 3.32.0 → 3.34.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 +109 -21
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -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
|
}
|
|
@@ -3869,6 +3870,8 @@ function parseCliArgs(rest) {
|
|
|
3869
3870
|
flags.md_path = rest[++i];
|
|
3870
3871
|
} else if (a.startsWith('--md=')) {
|
|
3871
3872
|
flags.md_path = a.slice('--md='.length);
|
|
3873
|
+
} else if (a === '--next-only') {
|
|
3874
|
+
flags.next_only = true;
|
|
3872
3875
|
} else if (a === '--older-than') {
|
|
3873
3876
|
// Accept "7d" / "30d" / "12h" / raw number (days).
|
|
3874
3877
|
const raw = rest[++i] || '';
|
|
@@ -3894,6 +3897,10 @@ function parseCliArgs(rest) {
|
|
|
3894
3897
|
flags.repo_path = rest[++i];
|
|
3895
3898
|
} else if (a.startsWith('--repo=')) {
|
|
3896
3899
|
flags.repo_path = a.slice('--repo='.length);
|
|
3900
|
+
} else if (a === '--since') {
|
|
3901
|
+
flags.since = rest[++i];
|
|
3902
|
+
} else if (a.startsWith('--since=')) {
|
|
3903
|
+
flags.since = a.slice('--since='.length);
|
|
3897
3904
|
} else if (a === '--yes' || a === '-y') {
|
|
3898
3905
|
flags.yes = true;
|
|
3899
3906
|
} else positional.push(a);
|
|
@@ -3947,6 +3954,21 @@ async function runResumeCli() {
|
|
|
3947
3954
|
// offline-fallback cache, not just MCP-stdio usage.
|
|
3948
3955
|
if (found) server.saveResumeToDisk(response);
|
|
3949
3956
|
|
|
3957
|
+
// --next-only: print just the first next_step. Useful for
|
|
3958
|
+
// shell prompts, status bars, one-liner scripting:
|
|
3959
|
+
// $ cf-memory-mcp resume --next-only
|
|
3960
|
+
if (flags.next_only) {
|
|
3961
|
+
const next = (payload.next_actions && payload.next_actions[0])
|
|
3962
|
+
|| (payload.resume_handoff?.handoff?.next_steps && payload.resume_handoff.handoff.next_steps[0])
|
|
3963
|
+
|| '';
|
|
3964
|
+
if (next) {
|
|
3965
|
+
process.stdout.write(next + '\n');
|
|
3966
|
+
process.exit(0);
|
|
3967
|
+
} else {
|
|
3968
|
+
process.exit(3);
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
|
|
3950
3972
|
// --md <path>: write the rendered markdown to a file instead of
|
|
3951
3973
|
// (or in addition to) stdout. Useful for piping to a markdown
|
|
3952
3974
|
// viewer or saving to the project.
|
|
@@ -4006,9 +4028,19 @@ async function runListCli() {
|
|
|
4006
4028
|
const args = { resume: true };
|
|
4007
4029
|
if (meta.repo_path) args.repo_path = meta.repo_path;
|
|
4008
4030
|
if (meta.branch) args.branch = meta.branch;
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
if (
|
|
4031
|
+
// Pass-through server-side filters when set on the CLI.
|
|
4032
|
+
if (flags.status) args.status_filter = flags.status;
|
|
4033
|
+
if (flags.since) args.since = flags.since;
|
|
4034
|
+
if (flags.repo_path) {
|
|
4035
|
+
// --repo overrides cwd → skip cwd's project_id too. Otherwise
|
|
4036
|
+
// tier-1 project_id_exact would short-circuit the lookup and
|
|
4037
|
+
// return cwd's handoff regardless of repo_path.
|
|
4038
|
+
args.repo_path = flags.repo_path;
|
|
4039
|
+
} else {
|
|
4040
|
+
const fake = { params: { name: 'retrieve_context', arguments: {} } };
|
|
4041
|
+
await server.maybeFillProjectId(fake);
|
|
4042
|
+
if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
|
|
4043
|
+
}
|
|
4012
4044
|
|
|
4013
4045
|
const response = await server.makeRequest({
|
|
4014
4046
|
jsonrpc: '2.0',
|
|
@@ -4025,8 +4057,10 @@ async function runListCli() {
|
|
|
4025
4057
|
|
|
4026
4058
|
if (flags.json) {
|
|
4027
4059
|
process.stdout.write(JSON.stringify({
|
|
4028
|
-
repo_path: meta.repo_path,
|
|
4029
|
-
branch: meta.branch,
|
|
4060
|
+
repo_path: args.repo_path || meta.repo_path,
|
|
4061
|
+
branch: args.branch || meta.branch,
|
|
4062
|
+
status_filter: flags.status,
|
|
4063
|
+
since: flags.since,
|
|
4030
4064
|
count: list.length,
|
|
4031
4065
|
handoffs: list,
|
|
4032
4066
|
empty_hint: list.length === 0 ? payload.empty_hint : undefined,
|
|
@@ -4047,8 +4081,10 @@ async function runListCli() {
|
|
|
4047
4081
|
const countSummary = Object.entries(counts)
|
|
4048
4082
|
.map(([s, n]) => `${n} ${s}`)
|
|
4049
4083
|
.join(', ');
|
|
4050
|
-
// Render a compact table to terminal.
|
|
4051
|
-
|
|
4084
|
+
// Render a compact table to terminal. Show the actual filter
|
|
4085
|
+
// applied (--repo override, or cwd default).
|
|
4086
|
+
const displayRepo = args.repo_path || 'this cwd';
|
|
4087
|
+
process.stdout.write(`Recent handoffs for ${displayRepo} (${countSummary}):\n\n`);
|
|
4052
4088
|
const fmtAge = (iso) => {
|
|
4053
4089
|
if (!iso) return '?';
|
|
4054
4090
|
const min = Math.round((Date.now() - new Date(iso).getTime()) / 60000);
|
|
@@ -4094,22 +4130,69 @@ async function runDeleteCli() {
|
|
|
4094
4130
|
server.logDebug = () => {};
|
|
4095
4131
|
try {
|
|
4096
4132
|
if (bulkMode) {
|
|
4097
|
-
// Bulk delete path. First dry-run: query matching sessions
|
|
4098
|
-
// count via list, then confirm with --yes for >5.
|
|
4099
4133
|
const args = {};
|
|
4100
4134
|
if (flags.status) args.status = flags.status;
|
|
4101
4135
|
if (flags.older_than_days !== undefined) args.older_than_days = flags.older_than_days;
|
|
4102
4136
|
if (flags.repo_path) args.repo_path = flags.repo_path;
|
|
4103
4137
|
|
|
4104
|
-
//
|
|
4105
|
-
//
|
|
4106
|
-
//
|
|
4107
|
-
// approximation; the server handles all of them anyway.
|
|
4108
|
-
// Use --yes to skip the preview/confirm prompt.
|
|
4138
|
+
// Dry-run preview when --yes is missing. The server returns
|
|
4139
|
+
// {deleted:false, deleted_count, deleted_session_ids[]} so the
|
|
4140
|
+
// user can see what WOULD be deleted before committing.
|
|
4109
4141
|
if (!flags.yes) {
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4142
|
+
const previewRes = await server.makeRequest({
|
|
4143
|
+
jsonrpc: '2.0', id: `cli-delete-preview-${Date.now()}`,
|
|
4144
|
+
method: 'tools/call',
|
|
4145
|
+
params: { name: 'delete_session', arguments: { ...args, dry_run: true } },
|
|
4146
|
+
});
|
|
4147
|
+
const previewText = previewRes?.result?.content?.[0]?.text;
|
|
4148
|
+
const preview = JSON.parse(previewText || '{}');
|
|
4149
|
+
if (flags.json) {
|
|
4150
|
+
process.stdout.write(JSON.stringify({ ...preview, would_delete: true }, null, 2) + '\n');
|
|
4151
|
+
process.exit(2);
|
|
4152
|
+
}
|
|
4153
|
+
if (preview.deleted_count === 0) {
|
|
4154
|
+
process.stderr.write(`No sessions match the filters. Nothing to delete.\n`);
|
|
4155
|
+
process.exit(3);
|
|
4156
|
+
}
|
|
4157
|
+
process.stderr.write(`Would delete ${preview.deleted_count} session${preview.deleted_count === 1 ? '' : 's'}:\n`);
|
|
4158
|
+
const previewIds = preview.deleted_session_ids || [];
|
|
4159
|
+
for (const id of previewIds.slice(0, 10)) {
|
|
4160
|
+
process.stderr.write(` ${id.slice(0, 8)}\n`);
|
|
4161
|
+
}
|
|
4162
|
+
if (previewIds.length > 10) {
|
|
4163
|
+
process.stderr.write(` ... and ${preview.deleted_count - 10} more\n`);
|
|
4164
|
+
}
|
|
4165
|
+
// Interactive TTY: prompt for confirmation instead of
|
|
4166
|
+
// requiring --yes. Piped/non-TTY stdin falls through to
|
|
4167
|
+
// the "re-run with --yes" path (avoids hangs in scripts).
|
|
4168
|
+
if (process.stdin.isTTY && process.stderr.isTTY) {
|
|
4169
|
+
process.stderr.write(`\nProceed with deletion? [y/N] `);
|
|
4170
|
+
const answer = await new Promise((resolve) => {
|
|
4171
|
+
process.stdin.setEncoding('utf8');
|
|
4172
|
+
let buf = '';
|
|
4173
|
+
const onData = (chunk) => {
|
|
4174
|
+
buf += chunk;
|
|
4175
|
+
const nl = buf.indexOf('\n');
|
|
4176
|
+
if (nl !== -1) {
|
|
4177
|
+
process.stdin.removeListener('data', onData);
|
|
4178
|
+
process.stdin.pause();
|
|
4179
|
+
resolve(buf.slice(0, nl).trim().toLowerCase());
|
|
4180
|
+
}
|
|
4181
|
+
};
|
|
4182
|
+
process.stdin.on('data', onData);
|
|
4183
|
+
process.stdin.resume();
|
|
4184
|
+
});
|
|
4185
|
+
if (answer === 'y' || answer === 'yes') {
|
|
4186
|
+
// Fall through to the actual delete below.
|
|
4187
|
+
} else {
|
|
4188
|
+
process.stderr.write(`Aborted.\n`);
|
|
4189
|
+
process.exit(2);
|
|
4190
|
+
}
|
|
4191
|
+
} else {
|
|
4192
|
+
process.stderr.write(`\nRe-run with --yes to confirm:\n`);
|
|
4193
|
+
process.stderr.write(` cf-memory-mcp delete ${process.argv.slice(3).join(' ')} --yes\n`);
|
|
4194
|
+
process.exit(2);
|
|
4195
|
+
}
|
|
4113
4196
|
}
|
|
4114
4197
|
|
|
4115
4198
|
const deleteRes = await server.makeRequest({
|
|
@@ -4284,14 +4367,19 @@ complete -c cf-memory-mcp -l version -s v -d 'Show version'
|
|
|
4284
4367
|
|
|
4285
4368
|
// Per-command help texts. Used when "cf-memory-mcp <cmd> --help" is invoked.
|
|
4286
4369
|
const PER_COMMAND_HELP = {
|
|
4287
|
-
resume: `cf-memory-mcp resume [<session-id-prefix>] [--md path] [--json]
|
|
4370
|
+
resume: `cf-memory-mcp resume [<session-id-prefix>] [--md path] [--next-only] [--json]
|
|
4288
4371
|
Print the prior resume handoff (markdown by default).
|
|
4289
4372
|
<session-id-prefix> Optional: pick a specific session (>=8 char prefix or full UUID).
|
|
4290
4373
|
--md <path> Write the markdown to a file instead of stdout.
|
|
4374
|
+
--next-only Print just the first next_step (for shell prompts / one-liners).
|
|
4291
4375
|
--json, -j Emit the full bootstrap payload as JSON for scripts.
|
|
4292
4376
|
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.
|
|
4377
|
+
list: `cf-memory-mcp list [--status S] [--since ISO] [--repo PATH] [--limit N] [--json]
|
|
4378
|
+
List recent handoffs for the current cwd, status-ranked. Header shows
|
|
4379
|
+
a status-count summary.
|
|
4380
|
+
--status S Restrict to a given status (in_progress, completed, ...).
|
|
4381
|
+
--since ISO Lower bound on handoff timestamp (ISO 8601).
|
|
4382
|
+
--repo PATH Override the cwd's repo (peek at another repo).
|
|
4295
4383
|
--limit N, -n N Max number of entries (default 5, max 50).
|
|
4296
4384
|
--json, -j Emit a JSON array for scripts.`,
|
|
4297
4385
|
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.
|
|
3
|
+
"version": "3.34.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": {
|