@context-engine-bridge/context-engine-mcp-bridge 0.0.84 → 0.0.86
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/AGENTS.md +69 -0
- package/bin/AGENTS.md +34 -0
- package/package.json +1 -1
- package/src/AGENTS.md +59 -0
- package/src/mcpServer.js +77 -130
package/AGENTS.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!-- Parent: ../AGENTS.md -->
|
|
2
|
+
<!-- Generated: 2026-02-19 | Updated: 2026-02-19 -->
|
|
3
|
+
|
|
4
|
+
# ctx-mcp-bridge
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
The MCP bridge (`ctxce` CLI) is a Model Context Protocol server that aggregates the Context Engine indexer and memory servers into a single unified MCP server. It supports both stdio and HTTP transport modes, making it compatible with MCP clients like Claude Code, Windsurf, Augment, and others. The bridge is primarily launched by the VS Code extension but can run standalone.
|
|
9
|
+
|
|
10
|
+
## Key Files
|
|
11
|
+
|
|
12
|
+
| File | Description |
|
|
13
|
+
|------|-------------|
|
|
14
|
+
| `bin/ctxce.js` | CLI entry point and executable (chmod +x 755) |
|
|
15
|
+
| `src/cli.js` | Command routing and argument parsing for `mcp-serve`, `mcp-http-serve`, `auth`, `connect` |
|
|
16
|
+
| `src/mcpServer.js` | MCP server implementation with stdio/HTTP transport, tool deduping, and auth handling |
|
|
17
|
+
| `src/authCli.js` | Auth command handlers: `login`, `logout`, `status` with token and password flows |
|
|
18
|
+
| `src/authConfig.js` | Session storage and management in `~/.ctxce/auth.json` |
|
|
19
|
+
| `src/oauthHandler.js` | OAuth protocol support for remote deployments |
|
|
20
|
+
| `src/uploader.js` | Standalone code uploader integration |
|
|
21
|
+
| `src/connectCli.js` | Connection validation and setup helpers |
|
|
22
|
+
| `src/resultPathMapping.js` | Path remapping for tool results (container/host paths) |
|
|
23
|
+
| `package.json` | Node.js package manifest (requires Node >= 18) |
|
|
24
|
+
|
|
25
|
+
## Subdirectories
|
|
26
|
+
|
|
27
|
+
| Directory | Purpose |
|
|
28
|
+
|-----------|---------|
|
|
29
|
+
| `bin/` | Executable CLI entry point |
|
|
30
|
+
| `docs/` | Debugging guides and documentation |
|
|
31
|
+
| `src/` | Core MCP server and auth logic (see `src/AGENTS.md`) |
|
|
32
|
+
|
|
33
|
+
## For AI Agents
|
|
34
|
+
|
|
35
|
+
### Working In This Directory
|
|
36
|
+
|
|
37
|
+
This is a Node.js MCP bridge package. Changes to MCP routing, tool forwarding, or auth handling require updates to `src/cli.js` and `src/mcpServer.js`. The bridge proxies requests between MCP clients and remote indexer/memory HTTP servers, so test both stdio and HTTP modes.
|
|
38
|
+
|
|
39
|
+
### Testing Requirements
|
|
40
|
+
|
|
41
|
+
- Run with `npm start` or `node bin/ctxce.js --help`
|
|
42
|
+
- Test MCP stdio mode: `ctxce mcp-serve --workspace /tmp/test`
|
|
43
|
+
- Test MCP HTTP mode: `ctxce mcp-http-serve --workspace /tmp/test --port 30810`
|
|
44
|
+
- Test auth commands: `ctxce auth login --backend-url http://localhost:8004 --token TEST_TOKEN`
|
|
45
|
+
- Verify auth state: `ctxce auth status --backend-url http://localhost:8004 --json`
|
|
46
|
+
- E2E tests: `npm run test:e2e`
|
|
47
|
+
|
|
48
|
+
### Common Patterns
|
|
49
|
+
|
|
50
|
+
- Environment variables: `CTXCE_INDEXER_URL`, `CTXCE_MEMORY_URL`, `CTXCE_HTTP_PORT`, `CTXCE_AUTH_*`
|
|
51
|
+
- Auth sessions stored in `~/.ctxce/auth.json` keyed by backend URL
|
|
52
|
+
- MCP tools are deduplicated and forwarded from indexer and memory servers
|
|
53
|
+
- Path remapping (host paths <-> container paths) handled transparently
|
|
54
|
+
- All MCP requests are logged to stderr or `CTXCE_DEBUG_LOG` if set
|
|
55
|
+
|
|
56
|
+
## Dependencies
|
|
57
|
+
|
|
58
|
+
### Internal
|
|
59
|
+
- Context Engine indexer (HTTP endpoint at `CTXCE_INDEXER_URL` or `http://localhost:8003/mcp`)
|
|
60
|
+
- Context Engine memory server (HTTP endpoint at `CTXCE_MEMORY_URL` or `http://localhost:8002/mcp`)
|
|
61
|
+
- Auth backend (optional, at `CTXCE_AUTH_BACKEND_URL` or `http://localhost:8004`)
|
|
62
|
+
|
|
63
|
+
### External
|
|
64
|
+
- `@modelcontextprotocol/sdk` (^1.24.3) – MCP protocol implementation
|
|
65
|
+
- `zod` (^3.25.0) – Runtime type validation
|
|
66
|
+
- `tar` (^7.5.9) – Archive support for uploads
|
|
67
|
+
- `ignore` (^7.0.5) – .gitignore-style file filtering
|
|
68
|
+
|
|
69
|
+
<!-- MANUAL: Any manually added notes below this line are preserved on regeneration -->
|
package/bin/AGENTS.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- Parent: ../AGENTS.md -->
|
|
2
|
+
<!-- Generated: 2026-02-19 | Updated: 2026-02-19 -->
|
|
3
|
+
|
|
4
|
+
# bin
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Executable CLI entry point for the `ctxce` command (also aliased as `ctxce-bridge`). This directory contains the shebang-wrapped Node.js script that is installed globally or via npm when the package is installed.
|
|
9
|
+
|
|
10
|
+
## Key Files
|
|
11
|
+
|
|
12
|
+
| File | Description |
|
|
13
|
+
|------|-------------|
|
|
14
|
+
| `ctxce.js` | CLI executable entry point (Node.js script, chmod +x 755) |
|
|
15
|
+
|
|
16
|
+
## For AI Agents
|
|
17
|
+
|
|
18
|
+
### Working In This Directory
|
|
19
|
+
|
|
20
|
+
Do not modify `ctxce.js` directly unless changing the CLI bootstrap. The actual CLI logic is in `src/cli.js`. The executable must have a shebang (`#!/usr/bin/env node`) and be marked executable on Unix systems.
|
|
21
|
+
|
|
22
|
+
### Testing Requirements
|
|
23
|
+
|
|
24
|
+
- Verify executable permission: `ls -l bin/ctxce.js` should show `-rwxr-xr-x`
|
|
25
|
+
- Test global install: `npm install -g` and run `ctxce --help`
|
|
26
|
+
- Test npx mode: `npx @context-engine-bridge/context-engine-mcp-bridge ctxce --help`
|
|
27
|
+
- Postinstall script auto-fixes permissions on non-Windows systems
|
|
28
|
+
|
|
29
|
+
## Dependencies
|
|
30
|
+
|
|
31
|
+
### Internal
|
|
32
|
+
- `src/cli.js` – Main CLI router and handler
|
|
33
|
+
|
|
34
|
+
<!-- MANUAL: Any manually added notes below this line are preserved on regeneration -->
|
package/package.json
CHANGED
package/src/AGENTS.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- Parent: ../AGENTS.md -->
|
|
2
|
+
<!-- Generated: 2026-02-19 | Updated: 2026-02-19 -->
|
|
3
|
+
|
|
4
|
+
# src
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
Core MCP server implementation, auth handling, and CLI routing for the `ctxce` bridge. This module aggregates the Context Engine indexer and memory servers, manages authentication sessions, and handles both stdio and HTTP transport modes.
|
|
9
|
+
|
|
10
|
+
## Key Files
|
|
11
|
+
|
|
12
|
+
| File | Description |
|
|
13
|
+
|------|-------------|
|
|
14
|
+
| `cli.js` | Main command router for `mcp-serve`, `mcp-http-serve`, `auth`, `connect` subcommands; parses CLI flags and environment variables |
|
|
15
|
+
| `mcpServer.js` | MCP server implementation; proxies requests to indexer/memory servers, dedupes tools, handles auth, supports stdio and HTTP transports |
|
|
16
|
+
| `authCli.js` | Auth command handlers for `login`, `logout`, `status` with token and password flows; manages session lifecycle |
|
|
17
|
+
| `authConfig.js` | Persistent auth state in `~/.ctxce/auth.json`; session loading, saving, TTL handling, OAuth support |
|
|
18
|
+
| `oauthHandler.js` | OAuth protocol implementation for token refresh and remote auth flows |
|
|
19
|
+
| `uploader.js` | Integration with the standalone code uploader (tar archive support, progress tracking) |
|
|
20
|
+
| `connectCli.js` | Connection validation, workspace discovery, and setup helpers |
|
|
21
|
+
| `resultPathMapping.js` | Path remapping for tool results (host paths <-> container paths); handles path translation for Docker environments |
|
|
22
|
+
|
|
23
|
+
## For AI Agents
|
|
24
|
+
|
|
25
|
+
### Working In This Directory
|
|
26
|
+
|
|
27
|
+
This is the core business logic. Changes to MCP command handling, tool routing, or auth flows affect both the CLI and the VS Code extension. The server proxies all tool requests to remote indexer/memory servers and dedupes tool lists to prevent duplicates. Auth is optional but handles session TTL, token refresh, and fallback to dev tokens.
|
|
28
|
+
|
|
29
|
+
### Testing Requirements
|
|
30
|
+
|
|
31
|
+
- Test MCP stdio transport: `node src/cli.js mcp-serve --workspace /tmp/test`
|
|
32
|
+
- Test MCP HTTP transport: `node src/cli.js mcp-http-serve --workspace /tmp/test --port 30810`
|
|
33
|
+
- Test auth login: `node src/cli.js auth login --backend-url http://localhost:8004 --token TOKEN`
|
|
34
|
+
- Test auth status: `node src/cli.js auth status --backend-url http://localhost:8004 --json`
|
|
35
|
+
- Verify tool deduping: Check that tools from indexer and memory are merged without duplicates
|
|
36
|
+
- Test path remapping: Verify that container paths are correctly mapped for Docker environments
|
|
37
|
+
- Run E2E tests: `npm run test:e2e`, `npm run test:e2e:auth`, `npm run test:e2e:happy`, `npm run test:e2e:edge`
|
|
38
|
+
|
|
39
|
+
### Common Patterns
|
|
40
|
+
|
|
41
|
+
- Environment variables guide server initialization: `CTXCE_INDEXER_URL`, `CTXCE_MEMORY_URL`, `CTXCE_HTTP_PORT`, `CTXCE_AUTH_BACKEND_URL`, `CTXCE_AUTH_ENABLED`, `CTXCE_DEBUG_LOG`
|
|
42
|
+
- Sessions are stored per backend URL in `~/.ctxce/auth.json` with TTL tracking
|
|
43
|
+
- All MCP tools from indexer and memory are merged and deduplicated before listing
|
|
44
|
+
- Path remapping is applied to tool arguments and results for Docker host/container path translation
|
|
45
|
+
- Debug logging goes to stderr and optionally to a file (set `CTXCE_DEBUG_LOG` env var)
|
|
46
|
+
- HTTP transport uses Node.js `createServer` with MCP's `StreamableHTTPServerTransport`
|
|
47
|
+
|
|
48
|
+
## Dependencies
|
|
49
|
+
|
|
50
|
+
### Internal
|
|
51
|
+
- `bin/ctxce.js` – CLI entry point that imports and runs these modules
|
|
52
|
+
|
|
53
|
+
### External
|
|
54
|
+
- `@modelcontextprotocol/sdk` – MCP protocol (Server, StdioServerTransport, StreamableHTTPServerTransport, Client, StreamableHTTPClientTransport)
|
|
55
|
+
- `zod` – Runtime type validation (used in config parsing)
|
|
56
|
+
- `tar` – Archive handling for uploader
|
|
57
|
+
- `ignore` – File filtering for .gitignore patterns
|
|
58
|
+
|
|
59
|
+
<!-- MANUAL: Any manually added notes below this line are preserved on regeneration -->
|
package/src/mcpServer.js
CHANGED
|
@@ -13,7 +13,6 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|
|
13
13
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
14
14
|
import {
|
|
15
15
|
clearResolvedCollection,
|
|
16
|
-
loadAnyAuthEntry,
|
|
17
16
|
loadAuthEntry,
|
|
18
17
|
loadResolvedCollection,
|
|
19
18
|
readConfig,
|
|
@@ -265,7 +264,7 @@ async function sendSessionDefaults(client, payload, label) {
|
|
|
265
264
|
try {
|
|
266
265
|
await client.callTool({
|
|
267
266
|
name: "set_session_defaults",
|
|
268
|
-
arguments: payload,
|
|
267
|
+
arguments: { ...payload },
|
|
269
268
|
});
|
|
270
269
|
} catch (err) {
|
|
271
270
|
// eslint-disable-next-line no-console
|
|
@@ -649,15 +648,8 @@ function resolveAuthBackendContext(indexerUrl, memoryUrl) {
|
|
|
649
648
|
}
|
|
650
649
|
}
|
|
651
650
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
const stored = normalizeBackendUrl(any?.backendUrl || "");
|
|
655
|
-
if (stored) {
|
|
656
|
-
return { backendUrl: stored, source: "auth_entry" };
|
|
657
|
-
}
|
|
658
|
-
} catch {
|
|
659
|
-
// ignore auth config read failures
|
|
660
|
-
}
|
|
651
|
+
// Fail-closed: do NOT fall back to loadAnyAuthEntry() here.
|
|
652
|
+
// Borrowing a session from an unrelated backend is a cross-account leak.
|
|
661
653
|
return { backendUrl: "", source: "" };
|
|
662
654
|
}
|
|
663
655
|
|
|
@@ -1120,10 +1112,20 @@ async function createBridgeServer(options) {
|
|
|
1120
1112
|
let sessionId = explicitSession;
|
|
1121
1113
|
|
|
1122
1114
|
function sessionFromEntry(entry) {
|
|
1123
|
-
if (!entry || typeof entry
|
|
1115
|
+
if (!entry || typeof entry !== "object") {
|
|
1124
1116
|
return "";
|
|
1125
1117
|
}
|
|
1126
|
-
|
|
1118
|
+
// Support both camelCase (sessionId/expiresAt) and snake_case (session_id/expires_at)
|
|
1119
|
+
const sid = (typeof entry.sessionId === "string" && entry.sessionId)
|
|
1120
|
+
? entry.sessionId
|
|
1121
|
+
: (typeof entry.session_id === "string" && entry.session_id)
|
|
1122
|
+
? entry.session_id
|
|
1123
|
+
: "";
|
|
1124
|
+
if (!sid) {
|
|
1125
|
+
return "";
|
|
1126
|
+
}
|
|
1127
|
+
const expiresAt = (typeof entry.expiresAt === "number") ? entry.expiresAt
|
|
1128
|
+
: (typeof entry.expires_at === "number") ? entry.expires_at : undefined;
|
|
1127
1129
|
if (
|
|
1128
1130
|
typeof expiresAt === "number" &&
|
|
1129
1131
|
Number.isFinite(expiresAt) &&
|
|
@@ -1136,9 +1138,9 @@ async function createBridgeServer(options) {
|
|
|
1136
1138
|
return "";
|
|
1137
1139
|
}
|
|
1138
1140
|
debugLog("[ctxce] Session expired but within 5min grace period; using it (server will validate).");
|
|
1139
|
-
return
|
|
1141
|
+
return sid;
|
|
1140
1142
|
}
|
|
1141
|
-
return
|
|
1143
|
+
return sid;
|
|
1142
1144
|
}
|
|
1143
1145
|
|
|
1144
1146
|
function findSavedSession(backends) {
|
|
@@ -1158,16 +1160,8 @@ async function createBridgeServer(options) {
|
|
|
1158
1160
|
// ignore lookup failures
|
|
1159
1161
|
}
|
|
1160
1162
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
const session = any ? sessionFromEntry(any.entry) : "";
|
|
1164
|
-
if (session && any?.backendUrl) {
|
|
1165
|
-
backendHint = any.backendUrl;
|
|
1166
|
-
return session;
|
|
1167
|
-
}
|
|
1168
|
-
} catch {
|
|
1169
|
-
// ignore lookup failures
|
|
1170
|
-
}
|
|
1163
|
+
// Fail-closed: do NOT fall back to loadAnyAuthEntry().
|
|
1164
|
+
// Borrowing an unrelated account's session is a cross-account leak.
|
|
1171
1165
|
return "";
|
|
1172
1166
|
}
|
|
1173
1167
|
|
|
@@ -1242,6 +1236,62 @@ async function createBridgeServer(options) {
|
|
|
1242
1236
|
uploadServiceUrl,
|
|
1243
1237
|
});
|
|
1244
1238
|
|
|
1239
|
+
async function recoverDeletedCollection(reason) {
|
|
1240
|
+
debugLog(`[ctxce] Collection appears deleted (${reason}), clearing cache and re-resolving`);
|
|
1241
|
+
defaultsPayload.collection = "";
|
|
1242
|
+
try {
|
|
1243
|
+
_clearExactWorkspaceCachedCollection(workspace);
|
|
1244
|
+
} catch (wsErr) {
|
|
1245
|
+
debugLog("[ctxce] Failed to clear workspace collection cache: " + String(wsErr));
|
|
1246
|
+
}
|
|
1247
|
+
try {
|
|
1248
|
+
if (backendHint) {
|
|
1249
|
+
const authEntry = loadAuthEntry(backendHint);
|
|
1250
|
+
let repoId = "";
|
|
1251
|
+
try { repoId = computeLogicalRepoIdentity(workspace)?.id || ""; } catch { repoId = ""; }
|
|
1252
|
+
clearResolvedCollection(backendHint, {
|
|
1253
|
+
orgId: authEntry?.org_id,
|
|
1254
|
+
orgSlug: authEntry?.org_slug,
|
|
1255
|
+
logicalRepoId: repoId,
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
} catch (clearErr) {
|
|
1259
|
+
debugLog("[ctxce] Failed to clear resolved collection cache: " + String(clearErr));
|
|
1260
|
+
}
|
|
1261
|
+
try {
|
|
1262
|
+
const freshPayload = await buildDefaultsPayload({
|
|
1263
|
+
workspace,
|
|
1264
|
+
sessionId,
|
|
1265
|
+
explicitCollection: "",
|
|
1266
|
+
defaultCollection: "",
|
|
1267
|
+
defaultMode,
|
|
1268
|
+
defaultUnder,
|
|
1269
|
+
config,
|
|
1270
|
+
backendHint,
|
|
1271
|
+
uploadServiceUrl,
|
|
1272
|
+
});
|
|
1273
|
+
if (Object.hasOwn(freshPayload, "collection")) {
|
|
1274
|
+
defaultsPayload.collection = freshPayload.collection;
|
|
1275
|
+
}
|
|
1276
|
+
if (freshPayload.collection) {
|
|
1277
|
+
debugLog("[ctxce] Re-resolved collection after deletion: " + freshPayload.collection);
|
|
1278
|
+
}
|
|
1279
|
+
} catch (reResolveErr) {
|
|
1280
|
+
debugLog("[ctxce] Failed to re-resolve collection after deletion: " + String(reResolveErr));
|
|
1281
|
+
}
|
|
1282
|
+
try {
|
|
1283
|
+
if (indexerClient) {
|
|
1284
|
+
await sendSessionDefaults(indexerClient, defaultsPayload, "indexer");
|
|
1285
|
+
}
|
|
1286
|
+
if (memoryClient) {
|
|
1287
|
+
await sendSessionDefaults(memoryClient, defaultsPayload, "memory");
|
|
1288
|
+
}
|
|
1289
|
+
debugLog(`[ctxce] Re-sent session defaults after collection deletion detection (${reason})`);
|
|
1290
|
+
} catch (sdErr) {
|
|
1291
|
+
debugLog("[ctxce] Failed to re-send session defaults after deletion: " + String(sdErr));
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1245
1295
|
async function initializeRemoteClients(forceRecreate = false) {
|
|
1246
1296
|
if (!forceRecreate && indexerClient) {
|
|
1247
1297
|
return;
|
|
@@ -1705,59 +1755,7 @@ async function createBridgeServer(options) {
|
|
|
1705
1755
|
}
|
|
1706
1756
|
// Detect explicit collection_deleted flag in a successful response
|
|
1707
1757
|
if (resultIndicatesCollectionDeleted(result)) {
|
|
1708
|
-
|
|
1709
|
-
defaultsPayload.collection = "";
|
|
1710
|
-
try {
|
|
1711
|
-
_clearExactWorkspaceCachedCollection(workspace);
|
|
1712
|
-
} catch (wsErr) {
|
|
1713
|
-
debugLog("[ctxce] Failed to clear workspace collection cache: " + String(wsErr));
|
|
1714
|
-
}
|
|
1715
|
-
try {
|
|
1716
|
-
if (backendHint) {
|
|
1717
|
-
const authEntry = loadAuthEntry(backendHint);
|
|
1718
|
-
let repoId = "";
|
|
1719
|
-
try { repoId = computeLogicalRepoIdentity(workspace)?.id || ""; } catch { repoId = ""; }
|
|
1720
|
-
clearResolvedCollection(backendHint, {
|
|
1721
|
-
orgId: authEntry?.org_id,
|
|
1722
|
-
orgSlug: authEntry?.org_slug,
|
|
1723
|
-
logicalRepoId: repoId,
|
|
1724
|
-
});
|
|
1725
|
-
}
|
|
1726
|
-
} catch (clearErr) {
|
|
1727
|
-
debugLog("[ctxce] Failed to clear resolved collection cache: " + String(clearErr));
|
|
1728
|
-
}
|
|
1729
|
-
// Best-effort re-resolve via /bridge/state
|
|
1730
|
-
try {
|
|
1731
|
-
const freshPayload = await buildDefaultsPayload({
|
|
1732
|
-
workspace,
|
|
1733
|
-
sessionId,
|
|
1734
|
-
explicitCollection: "",
|
|
1735
|
-
defaultCollection: "",
|
|
1736
|
-
defaultMode,
|
|
1737
|
-
defaultUnder,
|
|
1738
|
-
config,
|
|
1739
|
-
backendHint,
|
|
1740
|
-
uploadServiceUrl,
|
|
1741
|
-
});
|
|
1742
|
-
if (freshPayload.collection) {
|
|
1743
|
-
defaultsPayload.collection = freshPayload.collection;
|
|
1744
|
-
debugLog("[ctxce] Re-resolved collection after deletion: " + freshPayload.collection);
|
|
1745
|
-
}
|
|
1746
|
-
} catch (reResolveErr) {
|
|
1747
|
-
debugLog("[ctxce] Failed to re-resolve collection after deletion: " + String(reResolveErr));
|
|
1748
|
-
}
|
|
1749
|
-
// Re-send session defaults so remote MCP servers stop using the stale collection
|
|
1750
|
-
try {
|
|
1751
|
-
if (indexerClient) {
|
|
1752
|
-
await sendSessionDefaults(indexerClient, defaultsPayload, "indexer");
|
|
1753
|
-
}
|
|
1754
|
-
if (memoryClient) {
|
|
1755
|
-
await sendSessionDefaults(memoryClient, defaultsPayload, "memory");
|
|
1756
|
-
}
|
|
1757
|
-
debugLog("[ctxce] Re-sent session defaults after collection deletion detection");
|
|
1758
|
-
} catch (sdErr) {
|
|
1759
|
-
debugLog("[ctxce] Failed to re-send session defaults after deletion: " + String(sdErr));
|
|
1760
|
-
}
|
|
1758
|
+
await recoverDeletedCollection("result path");
|
|
1761
1759
|
}
|
|
1762
1760
|
|
|
1763
1761
|
return maybeRemapToolResult(name, result, workspace);
|
|
@@ -1766,58 +1764,7 @@ async function createBridgeServer(options) {
|
|
|
1766
1764
|
|
|
1767
1765
|
// Detect collection deletion from error signals
|
|
1768
1766
|
if (isCollectionDeletedSignal(err)) {
|
|
1769
|
-
|
|
1770
|
-
defaultsPayload.collection = "";
|
|
1771
|
-
try {
|
|
1772
|
-
_clearExactWorkspaceCachedCollection(workspace);
|
|
1773
|
-
} catch (wsErr) {
|
|
1774
|
-
debugLog("[ctxce] Failed to clear workspace collection cache: " + String(wsErr));
|
|
1775
|
-
}
|
|
1776
|
-
try {
|
|
1777
|
-
if (backendHint) {
|
|
1778
|
-
const authEntry = loadAuthEntry(backendHint);
|
|
1779
|
-
let repoId = "";
|
|
1780
|
-
try { repoId = computeLogicalRepoIdentity(workspace)?.id || ""; } catch { repoId = ""; }
|
|
1781
|
-
clearResolvedCollection(backendHint, {
|
|
1782
|
-
orgId: authEntry?.org_id,
|
|
1783
|
-
orgSlug: authEntry?.org_slug,
|
|
1784
|
-
logicalRepoId: repoId,
|
|
1785
|
-
});
|
|
1786
|
-
}
|
|
1787
|
-
} catch (clearErr) {
|
|
1788
|
-
debugLog("[ctxce] Failed to clear resolved collection cache: " + String(clearErr));
|
|
1789
|
-
}
|
|
1790
|
-
// Best-effort re-resolve via /bridge/state (fire-and-forget)
|
|
1791
|
-
buildDefaultsPayload({
|
|
1792
|
-
workspace,
|
|
1793
|
-
sessionId,
|
|
1794
|
-
explicitCollection: "",
|
|
1795
|
-
defaultCollection: "",
|
|
1796
|
-
defaultMode,
|
|
1797
|
-
defaultUnder,
|
|
1798
|
-
config,
|
|
1799
|
-
backendHint,
|
|
1800
|
-
uploadServiceUrl,
|
|
1801
|
-
}).then(async (freshPayload) => {
|
|
1802
|
-
if (freshPayload.collection) {
|
|
1803
|
-
defaultsPayload.collection = freshPayload.collection;
|
|
1804
|
-
debugLog("[ctxce] Re-resolved collection after deletion: " + freshPayload.collection);
|
|
1805
|
-
}
|
|
1806
|
-
// Re-send session defaults so remote MCP servers stop using the stale collection
|
|
1807
|
-
try {
|
|
1808
|
-
if (indexerClient) {
|
|
1809
|
-
await sendSessionDefaults(indexerClient, defaultsPayload, "indexer");
|
|
1810
|
-
}
|
|
1811
|
-
if (memoryClient) {
|
|
1812
|
-
await sendSessionDefaults(memoryClient, defaultsPayload, "memory");
|
|
1813
|
-
}
|
|
1814
|
-
debugLog("[ctxce] Re-sent session defaults after collection deletion detection (error path)");
|
|
1815
|
-
} catch (sdErr) {
|
|
1816
|
-
debugLog("[ctxce] Failed to re-send session defaults after deletion: " + String(sdErr));
|
|
1817
|
-
}
|
|
1818
|
-
}).catch((reResolveErr) => {
|
|
1819
|
-
debugLog("[ctxce] Failed to re-resolve collection after deletion: " + String(reResolveErr));
|
|
1820
|
-
});
|
|
1767
|
+
await recoverDeletedCollection("error path");
|
|
1821
1768
|
}
|
|
1822
1769
|
|
|
1823
1770
|
if (isConnectionDeadError(err) && !connectionRetried) {
|