@context-engine-bridge/context-engine-mcp-bridge 0.0.31 → 0.0.32

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/mcpServer.js +43 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-engine-bridge/context-engine-mcp-bridge",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "description": "Context Engine MCP bridge (http/stdio proxy combining indexer + memory servers)",
5
5
  "bin": {
6
6
  "ctxce": "bin/ctxce.js",
package/src/mcpServer.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import process from "node:process";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import { randomUUID } from "node:crypto";
4
+ import { randomUUID, createHash } from "node:crypto";
5
5
  import { execSync } from "node:child_process";
6
6
  import os from "node:os";
7
7
  import http, { createServer } from "node:http";
@@ -15,40 +15,56 @@ import { loadAnyAuthEntry, loadAuthEntry, readConfig, saveAuthEntry } from "./au
15
15
  import { maybeRemapToolArgs, maybeRemapToolResult } from "./resultPathMapping.js";
16
16
  import * as oauthHandler from "./oauthHandler.js";
17
17
 
18
- let _lspConnCache;
19
- let _lspConnCacheTs = 0;
20
18
  const LSP_CONN_CACHE_TTL = 5000;
21
- const LSP_CONN_MAX_AGE = 60 * 60 * 1000;
19
+ const LSP_CONN_MAX_AGE = 24 * 60 * 60 * 1000;
20
+ let _lspConnCache = { value: undefined, ts: 0, key: "" };
22
21
 
23
22
  function _isValidPort(v) {
24
23
  const p = Number.parseInt(String(v), 10);
25
24
  return Number.isFinite(p) && p >= 1024 && p <= 65535;
26
25
  }
27
26
 
28
- function _readLspConnection() {
27
+ function _computeWorkspaceDir(workspacePath) {
28
+ const normalized = path.resolve(workspacePath).replace(/\\/g, "/").toLowerCase();
29
+ const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12);
30
+ const safeName = path.basename(workspacePath).replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 50);
31
+ return path.join(os.homedir(), ".ctxce", "workspaces", `${safeName}-${hash}`);
32
+ }
33
+
34
+ function _tryReadConnFile(connPath, now) {
35
+ try {
36
+ const conn = JSON.parse(fs.readFileSync(connPath, "utf8"));
37
+ if (!conn.port || !_isValidPort(conn.port) || !conn.pid) return null;
38
+ try { process.kill(conn.pid, 0); } catch (_) { return null; }
39
+ if (conn.created_at && (now - conn.created_at) > LSP_CONN_MAX_AGE) return null;
40
+ return { port: String(conn.port), secret: conn.secret || "" };
41
+ } catch (_) {}
42
+ return null;
43
+ }
44
+
45
+ function _readLspConnection(workspace) {
29
46
  const envPort = process.env.CTXCE_LSP_PORT;
30
- if (envPort && _isValidPort(envPort)) return { port: envPort, secret: process.env.CTXCE_LSP_SECRET || "" };
47
+ if (envPort && _isValidPort(envPort)) {
48
+ return { port: envPort, secret: process.env.CTXCE_LSP_SECRET || "" };
49
+ }
50
+
31
51
  const now = Date.now();
32
- if (_lspConnCache !== undefined && (now - _lspConnCacheTs) < LSP_CONN_CACHE_TTL) return _lspConnCache;
52
+ const cacheKey = workspace || "";
53
+ if (_lspConnCache.value !== undefined && (now - _lspConnCache.ts) < LSP_CONN_CACHE_TTL && _lspConnCache.key === cacheKey) {
54
+ return _lspConnCache.value;
55
+ }
33
56
 
34
- function _cacheNull() {
35
- _lspConnCache = null;
36
- _lspConnCacheTs = now;
37
- return null;
57
+ let result = null;
58
+ if (workspace) {
59
+ const wsDir = _computeWorkspaceDir(workspace);
60
+ result = _tryReadConnFile(path.join(wsDir, "lsp-connection.json"), now);
61
+ }
62
+ if (!result) {
63
+ result = _tryReadConnFile(path.join(os.homedir(), ".ctxce", "lsp-connection.json"), now);
38
64
  }
39
65
 
40
- try {
41
- const connPath = path.join(os.homedir(), ".ctxce", "lsp-connection.json");
42
- const conn = JSON.parse(fs.readFileSync(connPath, "utf8"));
43
- if (conn.port && _isValidPort(conn.port) && conn.pid) {
44
- try { process.kill(conn.pid, 0); } catch (_) { return _cacheNull(); }
45
- if (conn.created_at && (now - conn.created_at) > LSP_CONN_MAX_AGE) return _cacheNull();
46
- _lspConnCache = { port: String(conn.port), secret: conn.secret || "" };
47
- _lspConnCacheTs = now;
48
- return _lspConnCache;
49
- }
50
- } catch (_) {}
51
- return _cacheNull();
66
+ _lspConnCache = { value: result, ts: now, key: cacheKey };
67
+ return result;
52
68
  }
53
69
 
54
70
  const _LSP_ENRICHABLE_TOOLS = new Set([
@@ -911,7 +927,7 @@ async function createBridgeServer(options) {
911
927
  const memoryTools = await listMemoryTools(memoryClient);
912
928
  const tools = dedupeTools([...indexerTools, ...memoryTools]);
913
929
 
914
- const lspAvailable = !!_readLspConnection();
930
+ const lspAvailable = !!_readLspConnection(workspace);
915
931
  if (lspAvailable) {
916
932
  const lspProp = {
917
933
  type: "boolean",
@@ -1052,7 +1068,7 @@ async function createBridgeServer(options) {
1052
1068
  }
1053
1069
 
1054
1070
  if (name && name.toLowerCase().startsWith("lsp_")) {
1055
- const lspConn = _readLspConnection();
1071
+ const lspConn = _readLspConnection(workspace);
1056
1072
  const lspPort = lspConn ? lspConn.port : null;
1057
1073
  const lspSecret = lspConn ? lspConn.secret : "";
1058
1074
  if (!lspPort) {
@@ -1064,7 +1080,7 @@ async function createBridgeServer(options) {
1064
1080
  return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: "Unknown LSP operation" }) }] };
1065
1081
  }
1066
1082
  try {
1067
- const lspArgs = params.arguments || {};
1083
+ const lspArgs = args || {};
1068
1084
  const postData = JSON.stringify(lspArgs);
1069
1085
  const result = await new Promise((resolve, reject) => {
1070
1086
  const req = http.request({
@@ -1129,7 +1145,7 @@ async function createBridgeServer(options) {
1129
1145
  { timeout: timeoutMs },
1130
1146
  );
1131
1147
  let finalResult = maybeRemapToolResult(name, result, workspace);
1132
- const lspConn = includeLsp && _readLspConnection();
1148
+ const lspConn = includeLsp && _readLspConnection(workspace);
1133
1149
  if (lspConn) finalResult = await _enrichWithLsp(finalResult, lspConn);
1134
1150
  return finalResult;
1135
1151
  } catch (err) {