@context-engine-bridge/context-engine-mcp-bridge 0.0.1 → 0.0.2
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/docs/debugging.md +20 -0
- package/package.json +1 -1
- package/publish.sh +34 -0
- package/src/mcpServer.js +81 -52
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"context-engine": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": [
|
|
6
|
+
"C:/Users/Admin/Documents/GitHub/Context-Engine/ctx-mcp-bridge/bin/ctxce.js",
|
|
7
|
+
"mcp-serve",
|
|
8
|
+
"--indexer-url",
|
|
9
|
+
"http://192.168.100.249:30806/mcp",
|
|
10
|
+
"--memory-url",
|
|
11
|
+
"http://192.168.100.249:30804/mcp",
|
|
12
|
+
"--workspace",
|
|
13
|
+
"C:/Users/Admin/Documents/GitHub/Pirate Survivors"
|
|
14
|
+
],
|
|
15
|
+
"env": {
|
|
16
|
+
"CTXCE_DEBUG_LOG": "C:/Users/Admin/ctxce-mcp.log"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
package/publish.sh
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Simple helper to login (if needed) and publish the package.
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./publish.sh # publishes current version
|
|
7
|
+
# ./publish.sh 0.0.2 # bumps version to 0.0.2 then publishes
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
+
cd "$SCRIPT_DIR"
|
|
11
|
+
|
|
12
|
+
PACKAGE_NAME="@context-engine-bridge/context-engine-mcp-bridge"
|
|
13
|
+
|
|
14
|
+
echo "[publish] Verifying npm authentication..."
|
|
15
|
+
if ! npm whoami >/dev/null 2>&1; then
|
|
16
|
+
echo "[publish] Not logged in; running npm login"
|
|
17
|
+
npm login
|
|
18
|
+
else
|
|
19
|
+
echo "[publish] Already authenticated as $(npm whoami)"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
if [[ $# -gt 0 ]]; then
|
|
23
|
+
VERSION="$1"
|
|
24
|
+
echo "[publish] Bumping version to $VERSION"
|
|
25
|
+
npm version "$VERSION" --no-git-tag-version
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
echo "[publish] Packing $PACKAGE_NAME for verification..."
|
|
29
|
+
npm pack >/dev/null
|
|
30
|
+
|
|
31
|
+
echo "[publish] Publishing $PACKAGE_NAME..."
|
|
32
|
+
npm publish --access public
|
|
33
|
+
|
|
34
|
+
echo "[publish] Done!"
|
package/src/mcpServer.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
function debugLog(message) {
|
|
2
|
+
try {
|
|
3
|
+
const text = typeof message === "string" ? message : String(message);
|
|
4
|
+
console.error(text);
|
|
5
|
+
const dest = process.env.CTXCE_DEBUG_LOG;
|
|
6
|
+
if (dest) {
|
|
7
|
+
fs.appendFileSync(dest, `${new Date().toISOString()} ${text}\n`, "utf8");
|
|
8
|
+
}
|
|
9
|
+
} catch {
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
async function sendSessionDefaults(client, payload, label) {
|
|
2
14
|
if (!client) {
|
|
3
15
|
return;
|
|
@@ -36,15 +48,52 @@ async function listMemoryTools(client) {
|
|
|
36
48
|
return [];
|
|
37
49
|
}
|
|
38
50
|
try {
|
|
39
|
-
const remote = await
|
|
51
|
+
const remote = await withTimeout(
|
|
52
|
+
client.listTools(),
|
|
53
|
+
5000,
|
|
54
|
+
"memory tools/list",
|
|
55
|
+
);
|
|
40
56
|
return Array.isArray(remote?.tools) ? remote.tools.slice() : [];
|
|
41
57
|
} catch (err) {
|
|
42
|
-
|
|
43
|
-
console.error("[ctxce] Error calling memory tools/list:", err);
|
|
58
|
+
debugLog("[ctxce] Error calling memory tools/list: " + String(err));
|
|
44
59
|
return [];
|
|
45
60
|
}
|
|
46
61
|
}
|
|
47
62
|
|
|
63
|
+
function withTimeout(promise, ms, label) {
|
|
64
|
+
return new Promise((resolve, reject) => {
|
|
65
|
+
let settled = false;
|
|
66
|
+
const timer = setTimeout(() => {
|
|
67
|
+
if (settled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
settled = true;
|
|
71
|
+
const errorMessage =
|
|
72
|
+
label != null
|
|
73
|
+
? `[ctxce] Timeout after ${ms}ms in ${label}`
|
|
74
|
+
: `[ctxce] Timeout after ${ms}ms`;
|
|
75
|
+
reject(new Error(errorMessage));
|
|
76
|
+
}, ms);
|
|
77
|
+
promise
|
|
78
|
+
.then((value) => {
|
|
79
|
+
if (settled) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
settled = true;
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
resolve(value);
|
|
85
|
+
})
|
|
86
|
+
.catch((err) => {
|
|
87
|
+
if (settled) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
settled = true;
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
reject(err);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
48
97
|
function selectClientForTool(name, indexerClient, memoryClient) {
|
|
49
98
|
if (!name) {
|
|
50
99
|
return indexerClient;
|
|
@@ -84,8 +133,7 @@ export async function runMcpServer(options) {
|
|
|
84
133
|
const defaultUnder =
|
|
85
134
|
config && typeof config.default_under === "string" ? config.default_under : null;
|
|
86
135
|
|
|
87
|
-
|
|
88
|
-
console.error(
|
|
136
|
+
debugLog(
|
|
89
137
|
`[ctxce] MCP low-level stdio bridge starting: workspace=${workspace}, indexerUrl=${indexerUrl}`,
|
|
90
138
|
);
|
|
91
139
|
|
|
@@ -115,8 +163,7 @@ export async function runMcpServer(options) {
|
|
|
115
163
|
try {
|
|
116
164
|
await indexerClient.connect(indexerTransport);
|
|
117
165
|
} catch (err) {
|
|
118
|
-
|
|
119
|
-
console.error("[ctxce] Failed to connect MCP HTTP client to indexer:", err);
|
|
166
|
+
debugLog("[ctxce] Failed to connect MCP HTTP client to indexer: " + String(err));
|
|
120
167
|
throw err;
|
|
121
168
|
}
|
|
122
169
|
|
|
@@ -138,11 +185,9 @@ export async function runMcpServer(options) {
|
|
|
138
185
|
},
|
|
139
186
|
);
|
|
140
187
|
await memoryClient.connect(memoryTransport);
|
|
141
|
-
|
|
142
|
-
console.error("[ctxce] Connected memory MCP client:", memoryUrl);
|
|
188
|
+
debugLog(`[ctxce] Connected memory MCP client: ${memoryUrl}`);
|
|
143
189
|
} catch (err) {
|
|
144
|
-
|
|
145
|
-
console.error("[ctxce] Failed to connect memory MCP client:", err);
|
|
190
|
+
debugLog("[ctxce] Failed to connect memory MCP client: " + String(err));
|
|
146
191
|
memoryClient = null;
|
|
147
192
|
}
|
|
148
193
|
}
|
|
@@ -186,45 +231,47 @@ export async function runMcpServer(options) {
|
|
|
186
231
|
},
|
|
187
232
|
);
|
|
188
233
|
|
|
189
|
-
// tools/list → fetch tools from remote indexer
|
|
234
|
+
// tools/list → fetch tools from remote indexer
|
|
190
235
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
191
236
|
let remote;
|
|
192
237
|
try {
|
|
193
|
-
|
|
238
|
+
debugLog("[ctxce] tools/list: fetching tools from indexer");
|
|
239
|
+
remote = await withTimeout(
|
|
240
|
+
indexerClient.listTools(),
|
|
241
|
+
10000,
|
|
242
|
+
"indexer tools/list",
|
|
243
|
+
);
|
|
194
244
|
} catch (err) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
245
|
+
debugLog("[ctxce] Error calling remote tools/list: " + String(err));
|
|
246
|
+
const memoryToolsFallback = await listMemoryTools(memoryClient);
|
|
247
|
+
const toolsFallback = dedupeTools([...memoryToolsFallback]);
|
|
248
|
+
return { tools: toolsFallback };
|
|
198
249
|
}
|
|
199
250
|
|
|
200
|
-
|
|
201
|
-
|
|
251
|
+
try {
|
|
252
|
+
const toolNames =
|
|
253
|
+
remote && Array.isArray(remote.tools)
|
|
254
|
+
? remote.tools.map((t) => (t && typeof t.name === "string" ? t.name : "<unnamed>"))
|
|
255
|
+
: [];
|
|
256
|
+
debugLog("[ctxce] tools/list remote result tools: " + JSON.stringify(toolNames));
|
|
257
|
+
} catch (err) {
|
|
258
|
+
debugLog("[ctxce] tools/list remote result: <unserializable> " + String(err));
|
|
259
|
+
}
|
|
202
260
|
|
|
203
261
|
const indexerTools = Array.isArray(remote?.tools) ? remote.tools.slice() : [];
|
|
204
262
|
const memoryTools = await listMemoryTools(memoryClient);
|
|
205
|
-
const tools = dedupeTools([...indexerTools, ...memoryTools
|
|
263
|
+
const tools = dedupeTools([...indexerTools, ...memoryTools]);
|
|
264
|
+
debugLog(`[ctxce] tools/list: returning ${tools.length} tools`);
|
|
206
265
|
return { tools };
|
|
207
266
|
});
|
|
208
267
|
|
|
209
|
-
// tools/call →
|
|
268
|
+
// tools/call → proxied to indexer or memory server
|
|
210
269
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
211
270
|
const params = request.params || {};
|
|
212
271
|
const name = params.name;
|
|
213
272
|
let args = params.arguments;
|
|
214
273
|
|
|
215
|
-
|
|
216
|
-
const branch = detectGitBranch(workspace);
|
|
217
|
-
const text = args && typeof args.text === "string" ? args.text : "pong";
|
|
218
|
-
const suffix = branch ? ` (branch=${branch})` : "";
|
|
219
|
-
return {
|
|
220
|
-
content: [
|
|
221
|
-
{
|
|
222
|
-
type: "text",
|
|
223
|
-
text: `${text}${suffix}`,
|
|
224
|
-
},
|
|
225
|
-
],
|
|
226
|
-
};
|
|
227
|
-
}
|
|
274
|
+
debugLog(`[ctxce] tools/call: ${name || "<no-name>"}`);
|
|
228
275
|
|
|
229
276
|
// Attach session id so the target server can apply per-session defaults.
|
|
230
277
|
if (sessionId && (args === undefined || args === null || typeof args === "object")) {
|
|
@@ -241,8 +288,7 @@ export async function runMcpServer(options) {
|
|
|
241
288
|
try {
|
|
242
289
|
await memoryClient.callTool({ name, arguments: args });
|
|
243
290
|
} catch (err) {
|
|
244
|
-
|
|
245
|
-
console.error("[ctxce] Memory set_session_defaults failed:", err);
|
|
291
|
+
debugLog("[ctxce] Memory set_session_defaults failed: " + String(err));
|
|
246
292
|
}
|
|
247
293
|
}
|
|
248
294
|
return indexerResult;
|
|
@@ -295,23 +341,6 @@ function loadConfig(startDir) {
|
|
|
295
341
|
return null;
|
|
296
342
|
}
|
|
297
343
|
|
|
298
|
-
function buildPingTool() {
|
|
299
|
-
return {
|
|
300
|
-
name: "ping",
|
|
301
|
-
description: "Basic ping tool exposed by the ctx bridge",
|
|
302
|
-
inputSchema: {
|
|
303
|
-
type: "object",
|
|
304
|
-
properties: {
|
|
305
|
-
text: {
|
|
306
|
-
type: "string",
|
|
307
|
-
description: "Optional text to echo back.",
|
|
308
|
-
},
|
|
309
|
-
},
|
|
310
|
-
required: [],
|
|
311
|
-
},
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
344
|
function detectGitBranch(workspace) {
|
|
316
345
|
try {
|
|
317
346
|
const out = execSync("git rev-parse --abbrev-ref HEAD", {
|