cf-memory-mcp 3.22.0 → 3.24.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 +284 -16
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -216,7 +216,8 @@ const TOOLS_LIST = [
|
|
|
216
216
|
session_id_hint: { type: 'string', description: 'Resume a specific session by id (overrides repo/branch matching). Full UUID or short prefix (>=8 chars). Useful after seeing recent_handoffs.' },
|
|
217
217
|
max_age_minutes: { type: 'number', description: 'Hard cutoff: hide handoffs older than this many minutes. Without it, older handoffs surface with reduced confidence.' },
|
|
218
218
|
goal_contains: { type: 'string', description: 'Substring filter on handoff content (goal/notes/decisions). Case-insensitive. Lets agents find a specific thread by what it was about.' },
|
|
219
|
-
since: { type: 'string', description: 'Lower bound on handoff timestamp (ISO 8601). Scope resume to a time window.' }
|
|
219
|
+
since: { type: 'string', description: 'Lower bound on handoff timestamp (ISO 8601). Scope resume to a time window.' },
|
|
220
|
+
status_filter: { description: 'Restrict matches to handoffs with this status. Single string or array of strings (e.g., ["in_progress","blocked"]).' }
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
},
|
|
@@ -433,13 +434,40 @@ class CFMemoryMCP {
|
|
|
433
434
|
this.logDebug(`User Agent: ${this.userAgent}`);
|
|
434
435
|
}
|
|
435
436
|
|
|
437
|
+
/**
|
|
438
|
+
* Append a line to the persistent bridge log file if configured.
|
|
439
|
+
* Honors CF_MEMORY_LOG_FILE (explicit path) or CF_MEMORY_LOG=1/true
|
|
440
|
+
* (defaults to ~/.cf-memory/bridge.log). Bounded: rotates when the
|
|
441
|
+
* file exceeds 5MB to prevent runaway disk usage.
|
|
442
|
+
*/
|
|
443
|
+
appendBridgeLog(line) {
|
|
444
|
+
try {
|
|
445
|
+
const explicit = process.env.CF_MEMORY_LOG_FILE;
|
|
446
|
+
const enabled = explicit || process.env.CF_MEMORY_LOG === '1' || process.env.CF_MEMORY_LOG === 'true';
|
|
447
|
+
if (!enabled) return;
|
|
448
|
+
const target = explicit || path.join(os.homedir(), '.cf-memory', 'bridge.log');
|
|
449
|
+
const dir = path.dirname(target);
|
|
450
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
451
|
+
// Rotate if file > 5MB.
|
|
452
|
+
try {
|
|
453
|
+
const st = fs.statSync(target);
|
|
454
|
+
if (st.size > 5 * 1024 * 1024) {
|
|
455
|
+
fs.renameSync(target, target + '.1');
|
|
456
|
+
}
|
|
457
|
+
} catch (_) { /* file doesn't exist yet */ }
|
|
458
|
+
fs.appendFileSync(target, line);
|
|
459
|
+
} catch (_) { /* logging failure is non-fatal */ }
|
|
460
|
+
}
|
|
461
|
+
|
|
436
462
|
/**
|
|
437
463
|
* Log debug messages to stderr (won't interfere with MCP communication)
|
|
438
464
|
*/
|
|
439
465
|
logDebug(message) {
|
|
466
|
+
const line = `[DEBUG] ${new Date().toISOString()} ${message}\n`;
|
|
440
467
|
if (process.env.DEBUG || process.env.MCP_DEBUG) {
|
|
441
|
-
process.stderr.write(
|
|
468
|
+
process.stderr.write(line);
|
|
442
469
|
}
|
|
470
|
+
this.appendBridgeLog(line);
|
|
443
471
|
}
|
|
444
472
|
|
|
445
473
|
/**
|
|
@@ -447,9 +475,13 @@ class CFMemoryMCP {
|
|
|
447
475
|
*/
|
|
448
476
|
logError(message, error = null) {
|
|
449
477
|
const timestamp = new Date().toISOString();
|
|
450
|
-
|
|
478
|
+
const line1 = `[ERROR] ${timestamp} ${message}\n`;
|
|
479
|
+
process.stderr.write(line1);
|
|
480
|
+
this.appendBridgeLog(line1);
|
|
451
481
|
if (error && error.stack) {
|
|
452
|
-
|
|
482
|
+
const line2 = `[ERROR] ${timestamp} ${error.stack}\n`;
|
|
483
|
+
process.stderr.write(line2);
|
|
484
|
+
this.appendBridgeLog(line2);
|
|
453
485
|
}
|
|
454
486
|
}
|
|
455
487
|
|
|
@@ -695,7 +727,11 @@ class CFMemoryMCP {
|
|
|
695
727
|
// cfm://resume/current and recent handoffs at
|
|
696
728
|
// cfm://resume/recent for clients that prefer the
|
|
697
729
|
// resources protocol over tool calls.
|
|
698
|
-
resources: {}
|
|
730
|
+
resources: {},
|
|
731
|
+
// Prompts capability exposes /resume and /list_threads
|
|
732
|
+
// for clients (Claude Desktop, etc.) that surface
|
|
733
|
+
// prompts as slash-commands in their UI.
|
|
734
|
+
prompts: {}
|
|
699
735
|
},
|
|
700
736
|
serverInfo: {
|
|
701
737
|
name: 'cf-memory-mcp-simplified',
|
|
@@ -856,17 +892,147 @@ class CFMemoryMCP {
|
|
|
856
892
|
return;
|
|
857
893
|
}
|
|
858
894
|
|
|
859
|
-
// Handle prompts/list
|
|
895
|
+
// Handle prompts/list — advertise the resume + threads prompts.
|
|
896
|
+
// These let MCP clients (Claude Desktop, etc.) show a slash-
|
|
897
|
+
// command UI like /resume that injects the prior handoff into
|
|
898
|
+
// the next message without an explicit tool call.
|
|
860
899
|
if (message.method === 'prompts/list') {
|
|
861
900
|
const response = {
|
|
862
901
|
jsonrpc: '2.0',
|
|
863
902
|
id: message.id,
|
|
864
|
-
result: {
|
|
903
|
+
result: {
|
|
904
|
+
prompts: [
|
|
905
|
+
{
|
|
906
|
+
name: 'resume',
|
|
907
|
+
description: 'Insert the prior resume handoff for this repo into the chat so the agent can pick up where the last session left off.',
|
|
908
|
+
arguments: [
|
|
909
|
+
{ name: 'session_id', description: 'Optional: resume a specific session (full UUID or short prefix >=8 chars).', required: false },
|
|
910
|
+
],
|
|
911
|
+
},
|
|
912
|
+
{
|
|
913
|
+
name: 'list_threads',
|
|
914
|
+
description: 'Insert a list of recent handoffs for this repo so the user can pick a specific thread to resume.',
|
|
915
|
+
arguments: [
|
|
916
|
+
{ name: 'status', description: 'Optional: filter by status (in_progress, blocked, completed, abandoned).', required: false },
|
|
917
|
+
],
|
|
918
|
+
},
|
|
919
|
+
],
|
|
920
|
+
},
|
|
865
921
|
};
|
|
866
922
|
process.stdout.write(JSON.stringify(response) + '\n');
|
|
867
923
|
return;
|
|
868
924
|
}
|
|
869
925
|
|
|
926
|
+
// Handle prompts/get — render the requested prompt with current
|
|
927
|
+
// resume state baked in.
|
|
928
|
+
if (message.method === 'prompts/get') {
|
|
929
|
+
const promptName = message.params?.name;
|
|
930
|
+
const promptArgs = message.params?.arguments || {};
|
|
931
|
+
try {
|
|
932
|
+
if (promptName === 'resume') {
|
|
933
|
+
const meta = this.getRepoMetadata();
|
|
934
|
+
const args = { resume: true };
|
|
935
|
+
if (meta.repo_path) args.repo_path = meta.repo_path;
|
|
936
|
+
if (meta.branch) args.branch = meta.branch;
|
|
937
|
+
if (promptArgs.session_id) args.session_id_hint = promptArgs.session_id;
|
|
938
|
+
const fake = { params: { name: 'retrieve_context', arguments: {} } };
|
|
939
|
+
await this.maybeFillProjectId(fake);
|
|
940
|
+
if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
|
|
941
|
+
const bootstrap = await this.makeRequest({
|
|
942
|
+
jsonrpc: '2.0',
|
|
943
|
+
id: `prompt-resume-${Date.now()}`,
|
|
944
|
+
method: 'tools/call',
|
|
945
|
+
params: { name: 'get_context_bootstrap', arguments: args },
|
|
946
|
+
});
|
|
947
|
+
const text = bootstrap?.result?.content?.[0]?.text || '{}';
|
|
948
|
+
const payload = JSON.parse(text);
|
|
949
|
+
const body = payload.resume_prompt
|
|
950
|
+
|| (payload.empty_hint || 'No prior resume handoff for this context.');
|
|
951
|
+
const response = {
|
|
952
|
+
jsonrpc: '2.0',
|
|
953
|
+
id: message.id,
|
|
954
|
+
result: {
|
|
955
|
+
description: `Resume context for ${meta.repo_path || 'this cwd'}`,
|
|
956
|
+
messages: [
|
|
957
|
+
{ role: 'user', content: { type: 'text', text: body } },
|
|
958
|
+
],
|
|
959
|
+
},
|
|
960
|
+
};
|
|
961
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
if (promptName === 'list_threads') {
|
|
965
|
+
const meta = this.getRepoMetadata();
|
|
966
|
+
const args = { resume: true };
|
|
967
|
+
if (meta.repo_path) args.repo_path = meta.repo_path;
|
|
968
|
+
if (meta.branch) args.branch = meta.branch;
|
|
969
|
+
if (promptArgs.status) args.status_filter = promptArgs.status;
|
|
970
|
+
const fake = { params: { name: 'retrieve_context', arguments: {} } };
|
|
971
|
+
await this.maybeFillProjectId(fake);
|
|
972
|
+
if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
|
|
973
|
+
const bootstrap = await this.makeRequest({
|
|
974
|
+
jsonrpc: '2.0',
|
|
975
|
+
id: `prompt-list-${Date.now()}`,
|
|
976
|
+
method: 'tools/call',
|
|
977
|
+
params: { name: 'get_context_bootstrap', arguments: args },
|
|
978
|
+
});
|
|
979
|
+
const text = bootstrap?.result?.content?.[0]?.text || '{}';
|
|
980
|
+
const payload = JSON.parse(text);
|
|
981
|
+
const list = Array.isArray(payload.recent_handoffs) ? payload.recent_handoffs : [];
|
|
982
|
+
const fmtAge = (iso) => {
|
|
983
|
+
if (!iso) return '?';
|
|
984
|
+
const min = Math.round((Date.now() - new Date(iso).getTime()) / 60000);
|
|
985
|
+
if (min < 60) return `${min}m`;
|
|
986
|
+
if (min < 1440) return `${Math.round(min/60)}h`;
|
|
987
|
+
return `${Math.round(min/1440)}d`;
|
|
988
|
+
};
|
|
989
|
+
const lines = ['## Recent handoffs for this repo', ''];
|
|
990
|
+
if (list.length === 0) {
|
|
991
|
+
lines.push(payload.empty_hint || '(no handoffs)');
|
|
992
|
+
} else {
|
|
993
|
+
for (const h of list) {
|
|
994
|
+
const shortId = (h.session_id || '').slice(0, 8);
|
|
995
|
+
const age = fmtAge(h.ended_at || h.started_at);
|
|
996
|
+
lines.push(`- \`${shortId}\` [${h.status || '?'}] ${age} ago — ${h.goal || '(no goal)'}`);
|
|
997
|
+
if (h.next_step) lines.push(` next: ${h.next_step}`);
|
|
998
|
+
}
|
|
999
|
+
lines.push('', 'Pick one via `/resume <id>` or call `get_context_bootstrap({resume:true, session_id_hint:"<id>"})`.');
|
|
1000
|
+
}
|
|
1001
|
+
const response = {
|
|
1002
|
+
jsonrpc: '2.0',
|
|
1003
|
+
id: message.id,
|
|
1004
|
+
result: {
|
|
1005
|
+
description: `Recent handoffs for ${meta.repo_path || 'this cwd'}`,
|
|
1006
|
+
messages: [
|
|
1007
|
+
{ role: 'user', content: { type: 'text', text: lines.join('\n') } },
|
|
1008
|
+
],
|
|
1009
|
+
},
|
|
1010
|
+
};
|
|
1011
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
// Unknown prompt name
|
|
1015
|
+
const response = {
|
|
1016
|
+
jsonrpc: '2.0',
|
|
1017
|
+
id: message.id,
|
|
1018
|
+
error: {
|
|
1019
|
+
code: -32602,
|
|
1020
|
+
message: `Unknown prompt: ${promptName}. Supported: resume, list_threads`,
|
|
1021
|
+
},
|
|
1022
|
+
};
|
|
1023
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
1024
|
+
return;
|
|
1025
|
+
} catch (err) {
|
|
1026
|
+
const response = {
|
|
1027
|
+
jsonrpc: '2.0',
|
|
1028
|
+
id: message.id,
|
|
1029
|
+
error: { code: -32603, message: `Failed to render prompt: ${err && err.message}` },
|
|
1030
|
+
};
|
|
1031
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
870
1036
|
// Handle ping locally
|
|
871
1037
|
if (message.method === 'ping') {
|
|
872
1038
|
const response = {
|
|
@@ -3583,6 +3749,7 @@ Usage:
|
|
|
3583
3749
|
npx cf-memory-mcp resume [id] Print the prior resume handoff (markdown)
|
|
3584
3750
|
npx cf-memory-mcp list List recent handoffs for cwd
|
|
3585
3751
|
npx cf-memory-mcp checkpoint ["<goal>"] Snapshot current state (keep_open)
|
|
3752
|
+
npx cf-memory-mcp status Show bridge state + server resume availability
|
|
3586
3753
|
npx cf-memory-mcp --version Show version
|
|
3587
3754
|
npx cf-memory-mcp --help Show this help
|
|
3588
3755
|
npx cf-memory-mcp --diagnose Test connectivity and report issues
|
|
@@ -3657,13 +3824,15 @@ async function runResumeCli() {
|
|
|
3657
3824
|
process.exit(2);
|
|
3658
3825
|
}
|
|
3659
3826
|
const payload = JSON.parse(text);
|
|
3660
|
-
//
|
|
3661
|
-
//
|
|
3827
|
+
// Exit codes:
|
|
3828
|
+
// 0 — handoff found and printed
|
|
3829
|
+
// 3 — no handoff found (lets scripts branch: `if ! cf-memory-mcp resume; then ...`)
|
|
3830
|
+
const found = !!payload.resume_handoff?.handoff;
|
|
3662
3831
|
if (flags.json) {
|
|
3663
3832
|
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
3664
|
-
process.exit(
|
|
3833
|
+
process.exit(found ? 0 : 3);
|
|
3665
3834
|
}
|
|
3666
|
-
if (
|
|
3835
|
+
if (found) {
|
|
3667
3836
|
if (payload.resume_prompt) {
|
|
3668
3837
|
process.stdout.write(payload.resume_prompt + '\n');
|
|
3669
3838
|
} else {
|
|
@@ -3679,8 +3848,10 @@ async function runResumeCli() {
|
|
|
3679
3848
|
}
|
|
3680
3849
|
process.exit(0);
|
|
3681
3850
|
} else {
|
|
3682
|
-
|
|
3683
|
-
|
|
3851
|
+
// No handoff: print empty_hint to stderr so it doesn't pollute
|
|
3852
|
+
// stdout for scripts that pipe the output.
|
|
3853
|
+
process.stderr.write((payload.empty_hint || 'No resume handoff available.') + '\n');
|
|
3854
|
+
process.exit(3);
|
|
3684
3855
|
}
|
|
3685
3856
|
} catch (err) {
|
|
3686
3857
|
console.error('resume command failed:', err.message);
|
|
@@ -3725,11 +3896,11 @@ async function runListCli() {
|
|
|
3725
3896
|
handoffs: list,
|
|
3726
3897
|
empty_hint: list.length === 0 ? payload.empty_hint : undefined,
|
|
3727
3898
|
}, null, 2) + '\n');
|
|
3728
|
-
process.exit(0);
|
|
3899
|
+
process.exit(list.length === 0 ? 3 : 0);
|
|
3729
3900
|
}
|
|
3730
3901
|
if (list.length === 0) {
|
|
3731
|
-
process.
|
|
3732
|
-
process.exit(
|
|
3902
|
+
process.stderr.write((payload.empty_hint || 'No handoffs for this context.') + '\n');
|
|
3903
|
+
process.exit(3);
|
|
3733
3904
|
}
|
|
3734
3905
|
// Render a compact table to terminal.
|
|
3735
3906
|
process.stdout.write(`Recent handoffs for ${meta.repo_path || 'this cwd'}:\n\n`);
|
|
@@ -3757,6 +3928,98 @@ async function runListCli() {
|
|
|
3757
3928
|
}
|
|
3758
3929
|
}
|
|
3759
3930
|
|
|
3931
|
+
async function runStatusCli() {
|
|
3932
|
+
const { flags } = parseCliArgs(process.argv.slice(3));
|
|
3933
|
+
const server = new CFMemoryMCP();
|
|
3934
|
+
server.logDebug = () => {};
|
|
3935
|
+
server.logError = (...a) => process.stderr.write(a.join(' ') + '\n');
|
|
3936
|
+
try {
|
|
3937
|
+
// Local bridge state (no network call required).
|
|
3938
|
+
const meta = server.getRepoMetadata();
|
|
3939
|
+
const cwd = process.env.CF_MEMORY_WATCH_PATH || process.cwd();
|
|
3940
|
+
const diskCachePath = server.getDiskCachePath();
|
|
3941
|
+
const diskCacheExists = diskCachePath && fs.existsSync(diskCachePath);
|
|
3942
|
+
let diskCacheAge = null;
|
|
3943
|
+
if (diskCacheExists) {
|
|
3944
|
+
try {
|
|
3945
|
+
const entry = JSON.parse(fs.readFileSync(diskCachePath, 'utf8'));
|
|
3946
|
+
diskCacheAge = Math.round((Date.now() - new Date(entry.cached_at).getTime()) / 60000);
|
|
3947
|
+
} catch (_) { /* unreadable cache */ }
|
|
3948
|
+
}
|
|
3949
|
+
// Lookup the live worker count of handoffs for this cwd (best-effort).
|
|
3950
|
+
let serverHandoffCount = null;
|
|
3951
|
+
let resumeAvailable = false;
|
|
3952
|
+
let latestGoal = null;
|
|
3953
|
+
if (API_KEY) {
|
|
3954
|
+
try {
|
|
3955
|
+
const args = { resume: true };
|
|
3956
|
+
if (meta.repo_path) args.repo_path = meta.repo_path;
|
|
3957
|
+
if (meta.branch) args.branch = meta.branch;
|
|
3958
|
+
const fake = { params: { name: 'retrieve_context', arguments: {} } };
|
|
3959
|
+
await server.maybeFillProjectId(fake);
|
|
3960
|
+
if (fake.params.arguments.project_id) args.project_id = fake.params.arguments.project_id;
|
|
3961
|
+
const response = await server.makeRequest({
|
|
3962
|
+
jsonrpc: '2.0',
|
|
3963
|
+
id: `cli-status-${Date.now()}`,
|
|
3964
|
+
method: 'tools/call',
|
|
3965
|
+
params: { name: 'get_context_bootstrap', arguments: args },
|
|
3966
|
+
});
|
|
3967
|
+
const text = response?.result?.content?.[0]?.text;
|
|
3968
|
+
const payload = JSON.parse(text || '{}');
|
|
3969
|
+
serverHandoffCount = Array.isArray(payload.recent_handoffs) ? payload.recent_handoffs.length : 0;
|
|
3970
|
+
resumeAvailable = !!payload.resume_handoff;
|
|
3971
|
+
latestGoal = payload.resume_handoff?.handoff?.goal || null;
|
|
3972
|
+
} catch (err) {
|
|
3973
|
+
// Network unreachable — that's OK, we still have local info.
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
|
|
3977
|
+
const status = {
|
|
3978
|
+
version: PACKAGE_VERSION,
|
|
3979
|
+
cwd,
|
|
3980
|
+
repo_path: meta.repo_path || null,
|
|
3981
|
+
branch: meta.branch || null,
|
|
3982
|
+
base_url: BASE_URL,
|
|
3983
|
+
api_key_set: !!API_KEY,
|
|
3984
|
+
disk_cache: diskCacheExists
|
|
3985
|
+
? { path: diskCachePath, age_minutes: diskCacheAge }
|
|
3986
|
+
: null,
|
|
3987
|
+
server: API_KEY
|
|
3988
|
+
? { handoff_count: serverHandoffCount, resume_available: resumeAvailable, latest_goal: latestGoal }
|
|
3989
|
+
: { reachable: false, reason: 'CF_MEMORY_API_KEY not set' },
|
|
3990
|
+
};
|
|
3991
|
+
|
|
3992
|
+
if (flags.json) {
|
|
3993
|
+
process.stdout.write(JSON.stringify(status, null, 2) + '\n');
|
|
3994
|
+
process.exit(0);
|
|
3995
|
+
}
|
|
3996
|
+
process.stdout.write(`cf-memory-mcp v${PACKAGE_VERSION}\n`);
|
|
3997
|
+
process.stdout.write(` cwd: ${cwd}\n`);
|
|
3998
|
+
if (meta.repo_path) process.stdout.write(` repo: ${meta.repo_path}\n`);
|
|
3999
|
+
if (meta.branch) process.stdout.write(` branch: ${meta.branch}\n`);
|
|
4000
|
+
process.stdout.write(` server: ${BASE_URL}${API_KEY ? '' : ' (no API key set)'}\n`);
|
|
4001
|
+
if (diskCacheExists) {
|
|
4002
|
+
process.stdout.write(` cache: ${diskCachePath} (${diskCacheAge}m old)\n`);
|
|
4003
|
+
} else {
|
|
4004
|
+
process.stdout.write(` cache: (none)\n`);
|
|
4005
|
+
}
|
|
4006
|
+
if (API_KEY) {
|
|
4007
|
+
if (resumeAvailable) {
|
|
4008
|
+
process.stdout.write(` resume: ✓ available — "${latestGoal || '(no goal)'}"\n`);
|
|
4009
|
+
} else {
|
|
4010
|
+
process.stdout.write(` resume: (no handoff for this context)\n`);
|
|
4011
|
+
}
|
|
4012
|
+
if (serverHandoffCount !== null) {
|
|
4013
|
+
process.stdout.write(` threads: ${serverHandoffCount} recent handoff${serverHandoffCount === 1 ? '' : 's'}\n`);
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
process.exit(0);
|
|
4017
|
+
} catch (err) {
|
|
4018
|
+
console.error('status command failed:', err.message);
|
|
4019
|
+
process.exit(1);
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
|
|
3760
4023
|
async function runCheckpointCli() {
|
|
3761
4024
|
if (!API_KEY) {
|
|
3762
4025
|
console.error('Error: CF_MEMORY_API_KEY environment variable is required');
|
|
@@ -3844,6 +4107,11 @@ if (process.argv[2] === 'checkpoint') {
|
|
|
3844
4107
|
return;
|
|
3845
4108
|
}
|
|
3846
4109
|
|
|
4110
|
+
if (process.argv[2] === 'status') {
|
|
4111
|
+
runStatusCli();
|
|
4112
|
+
return;
|
|
4113
|
+
}
|
|
4114
|
+
|
|
3847
4115
|
if (process.argv.includes('--diagnose')) {
|
|
3848
4116
|
(async () => {
|
|
3849
4117
|
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.
|
|
3
|
+
"version": "3.24.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": {
|