@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.
- package/package.json +1 -1
- package/src/mcpServer.js +43 -27
package/package.json
CHANGED
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
|
|
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))
|
|
47
|
+
if (envPort && _isValidPort(envPort)) {
|
|
48
|
+
return { port: envPort, secret: process.env.CTXCE_LSP_SECRET || "" };
|
|
49
|
+
}
|
|
50
|
+
|
|
31
51
|
const now = Date.now();
|
|
32
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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 =
|
|
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) {
|