cf-memory-mcp 3.9.12 → 3.10.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/README.md +1 -0
- package/bin/cf-memory-mcp.js +105 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ Cloudflare-hosted MCP server for semantic code indexing, retrieval, and assistan
|
|
|
14
14
|
- **Self-healing freshness** - Results auto-flag stale chunks with a copy-pasteable `refresh_files` call; `refresh_stale` rebuilds the changed files in seconds; cache invalidates on write
|
|
15
15
|
- **Self-debugging errors** - `retrieve_context` includes `empty_hint` on 0-result queries; `get_file_content` / `get_file_outline` return `{error, hint}` pointing to the next call instead of bare null; calling bridge-only tools server-side returns `bridge_required` install instructions
|
|
16
16
|
- **Smart defaults** - Bridge auto-detects project_id from cwd, returns chunks pre-enriched with file imports + citation + source classification
|
|
17
|
+
- **Cross-chat resume** - `end_session({handoff:{goal, status, next_steps, code_anchors, ...}})` persists a structured ~600-1500 token resume packet; next chat calls `get_context_bootstrap({resume:true})` to pick up where the previous chat left off, with `match_confidence`, branch-mismatch downgrades, and stale-anchor markers + refresh hints. Bridge auto-fills `repo_path`/`branch`/`project_id` from cwd + git.
|
|
17
18
|
- **Contextual embeddings** - Qwen3 8K-context model with Anthropic-style chunk headers
|
|
18
19
|
|
|
19
20
|
The active runtime is at [src-simplified/index.ts](src-simplified/index.ts). It exposes direct MCP over HTTP and a local stdio bridge for clients that want `npx cf-memory-mcp`.
|
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -779,6 +779,19 @@ class CFMemoryMCP {
|
|
|
779
779
|
await this.maybeFillProjectId(message);
|
|
780
780
|
}
|
|
781
781
|
|
|
782
|
+
// For resume-context tools, auto-attach repo_path/branch/project_id
|
|
783
|
+
// from cwd + git when the caller didn't supply them. Makes
|
|
784
|
+
// get_context_bootstrap({resume:true}) zero-config and lets
|
|
785
|
+
// end_session({handoff:{goal,status,next_steps}}) work without
|
|
786
|
+
// the agent having to dig up the repo metadata itself.
|
|
787
|
+
if (message.method === 'tools/call' && message.params && (
|
|
788
|
+
message.params.name === 'get_context_bootstrap' ||
|
|
789
|
+
message.params.name === 'start_session' ||
|
|
790
|
+
message.params.name === 'end_session'
|
|
791
|
+
)) {
|
|
792
|
+
await this.maybeAttachResumeMetadata(message);
|
|
793
|
+
}
|
|
794
|
+
|
|
782
795
|
let response = await this.makeRequest(message);
|
|
783
796
|
_mcpTrace('DISPATCH_DONE', `id=${message.id} method=${message.method} elapsed=${Date.now()-_t0}ms`);
|
|
784
797
|
|
|
@@ -2024,6 +2037,98 @@ class CFMemoryMCP {
|
|
|
2024
2037
|
}
|
|
2025
2038
|
}
|
|
2026
2039
|
|
|
2040
|
+
/**
|
|
2041
|
+
* Detect the current repo path and git branch once per process. Used by
|
|
2042
|
+
* the resume-context plumbing on start_session / end_session /
|
|
2043
|
+
* get_context_bootstrap so callers don't need to pass them manually.
|
|
2044
|
+
* Returns { repo_path, branch } where either may be undefined when
|
|
2045
|
+
* detection fails.
|
|
2046
|
+
*/
|
|
2047
|
+
getRepoMetadata() {
|
|
2048
|
+
if (this._repoMetaCache) return this._repoMetaCache;
|
|
2049
|
+
const result = {};
|
|
2050
|
+
try {
|
|
2051
|
+
const root = process.env.CF_MEMORY_WATCH_PATH || process.cwd();
|
|
2052
|
+
if (root && fs.existsSync(root)) {
|
|
2053
|
+
result.repo_path = path.resolve(root);
|
|
2054
|
+
}
|
|
2055
|
+
} catch (_) { /* leave repo_path undefined */ }
|
|
2056
|
+
try {
|
|
2057
|
+
const { execSync } = require('child_process');
|
|
2058
|
+
// symbolic-ref works on empty repos (no commits yet) where
|
|
2059
|
+
// rev-parse --abbrev-ref HEAD fails. Detached HEAD still throws,
|
|
2060
|
+
// which is the right behavior — we want the branch name, not "HEAD".
|
|
2061
|
+
const branch = execSync('git symbolic-ref --short HEAD', {
|
|
2062
|
+
cwd: result.repo_path || process.cwd(),
|
|
2063
|
+
encoding: 'utf8',
|
|
2064
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
2065
|
+
timeout: 500,
|
|
2066
|
+
}).trim();
|
|
2067
|
+
if (branch) result.branch = branch;
|
|
2068
|
+
} catch (_) { /* not a git repo, detached HEAD, or no branch — leave undefined */ }
|
|
2069
|
+
this._repoMetaCache = result;
|
|
2070
|
+
_mcpTrace('REPO_META', `repo_path=${result.repo_path||'?'} branch=${result.branch||'?'}`);
|
|
2071
|
+
return result;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
/**
|
|
2075
|
+
* Attach repo_path / project_id / branch to start_session,
|
|
2076
|
+
* end_session.handoff and get_context_bootstrap calls when the caller
|
|
2077
|
+
* left them blank. This makes resume work zero-config: just call
|
|
2078
|
+
* get_context_bootstrap({resume:true}) and the bridge fills in the rest.
|
|
2079
|
+
*
|
|
2080
|
+
* The server still treats these as optional, so any of the auto-fill
|
|
2081
|
+
* lookups failing (no git, no indexed project) is safe — the call
|
|
2082
|
+
* proceeds with whatever metadata was already present.
|
|
2083
|
+
*/
|
|
2084
|
+
async maybeAttachResumeMetadata(message) {
|
|
2085
|
+
try {
|
|
2086
|
+
if (message.method !== 'tools/call' || !message.params) return;
|
|
2087
|
+
const toolName = message.params.name;
|
|
2088
|
+
const args = message.params.arguments || (message.params.arguments = {});
|
|
2089
|
+
|
|
2090
|
+
// get_context_bootstrap with resume:true wants repo_path + branch
|
|
2091
|
+
// for matching. We do not force resume:true — that's a caller
|
|
2092
|
+
// choice — but we fill the metadata so resume becomes useful
|
|
2093
|
+
// when the caller does opt in.
|
|
2094
|
+
if (toolName === 'get_context_bootstrap') {
|
|
2095
|
+
const meta = this.getRepoMetadata();
|
|
2096
|
+
if (!args.repo_path && meta.repo_path) args.repo_path = meta.repo_path;
|
|
2097
|
+
if (!args.branch && meta.branch) args.branch = meta.branch;
|
|
2098
|
+
if (!args.project_id) {
|
|
2099
|
+
await this.maybeFillProjectId({ params: { name: 'retrieve_context', arguments: args } });
|
|
2100
|
+
}
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
if (toolName === 'start_session') {
|
|
2105
|
+
const meta = this.getRepoMetadata();
|
|
2106
|
+
if (!args.repo_path && meta.repo_path) args.repo_path = meta.repo_path;
|
|
2107
|
+
if (!args.branch && meta.branch) args.branch = meta.branch;
|
|
2108
|
+
if (!args.project_id) {
|
|
2109
|
+
await this.maybeFillProjectId({ params: { name: 'retrieve_context', arguments: args } });
|
|
2110
|
+
}
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
if (toolName === 'end_session' && args.handoff && typeof args.handoff === 'object') {
|
|
2115
|
+
const meta = this.getRepoMetadata();
|
|
2116
|
+
if (!args.handoff.repo_path && meta.repo_path) args.handoff.repo_path = meta.repo_path;
|
|
2117
|
+
if (!args.handoff.branch && meta.branch) args.handoff.branch = meta.branch;
|
|
2118
|
+
if (!args.handoff.project_id) {
|
|
2119
|
+
const fake = { params: { name: 'retrieve_context', arguments: {} } };
|
|
2120
|
+
await this.maybeFillProjectId(fake);
|
|
2121
|
+
if (fake.params.arguments.project_id) {
|
|
2122
|
+
args.handoff.project_id = fake.params.arguments.project_id;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
} catch (err) {
|
|
2128
|
+
this.logDebug(`maybeAttachResumeMetadata failed: ${err && err.message}`);
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2027
2132
|
/**
|
|
2028
2133
|
* If the just-returned retrieve_context response had stale files,
|
|
2029
2134
|
* refresh them via refreshFilesCore, re-run the original query, and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cf-memory-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.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": {
|