@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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-engine-bridge/context-engine-mcp-bridge",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Context Engine MCP bridge (stdio proxy combining indexer + memory servers)",
5
5
  "bin": {
6
6
  "ctxce": "bin/ctxce.js",
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 client.listTools();
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
- // eslint-disable-next-line no-console
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
- // eslint-disable-next-line no-console
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
- // eslint-disable-next-line no-console
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
- // eslint-disable-next-line no-console
142
- console.error("[ctxce] Connected memory MCP client:", memoryUrl);
188
+ debugLog(`[ctxce] Connected memory MCP client: ${memoryUrl}`);
143
189
  } catch (err) {
144
- // eslint-disable-next-line no-console
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 and append local ping tool
234
+ // tools/list → fetch tools from remote indexer
190
235
  server.setRequestHandler(ListToolsRequestSchema, async () => {
191
236
  let remote;
192
237
  try {
193
- remote = await indexerClient.listTools();
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
- // eslint-disable-next-line no-console
196
- console.error("[ctxce] Error calling remote tools/list:", err);
197
- return { tools: [buildPingTool()] };
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
- // eslint-disable-next-line no-console
201
- console.error("[ctxce] tools/list remote result:", JSON.stringify(remote));
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, buildPingTool()]);
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 → handle ping locally, everything else is proxied to indexer
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
- if (name === "ping") {
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
- // eslint-disable-next-line no-console
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", {