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

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-engine-bridge/context-engine-mcp-bridge",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
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
@@ -3,7 +3,8 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { execSync } from "node:child_process";
6
- import { createServer } from "node:http";
6
+ import os from "node:os";
7
+ import http, { createServer } from "node:http";
7
8
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
8
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
10
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -14,6 +15,116 @@ import { loadAnyAuthEntry, loadAuthEntry, readConfig, saveAuthEntry } from "./au
14
15
  import { maybeRemapToolArgs, maybeRemapToolResult } from "./resultPathMapping.js";
15
16
  import * as oauthHandler from "./oauthHandler.js";
16
17
 
18
+ let _lspConnCache;
19
+ let _lspConnCacheTs = 0;
20
+ const LSP_CONN_CACHE_TTL = 5000;
21
+ const LSP_CONN_MAX_AGE = 60 * 60 * 1000;
22
+
23
+ function _isValidPort(v) {
24
+ const p = Number.parseInt(String(v), 10);
25
+ return Number.isFinite(p) && p >= 1024 && p <= 65535;
26
+ }
27
+
28
+ function _readLspConnection() {
29
+ const envPort = process.env.CTXCE_LSP_PORT;
30
+ if (envPort && _isValidPort(envPort)) return { port: envPort, secret: process.env.CTXCE_LSP_SECRET || "" };
31
+ const now = Date.now();
32
+ if (_lspConnCache !== undefined && (now - _lspConnCacheTs) < LSP_CONN_CACHE_TTL) return _lspConnCache;
33
+
34
+ function _cacheNull() {
35
+ _lspConnCache = null;
36
+ _lspConnCacheTs = now;
37
+ return null;
38
+ }
39
+
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();
52
+ }
53
+
54
+ const _LSP_ENRICHABLE_TOOLS = new Set([
55
+ "batch_search", "batch_symbol_graph", "batch_graph_query",
56
+ "repo_search", "repo_search_compat", "symbol_graph", "search",
57
+ "code_search", "context_search", "search_tests_for",
58
+ "search_config_for", "search_callers_for", "search_importers_for",
59
+ ]);
60
+
61
+ function _extractPaths(obj, paths, depth = 0) {
62
+ if (!obj || typeof obj !== "object" || depth > 20) return;
63
+ if (Array.isArray(obj)) {
64
+ for (const item of obj) _extractPaths(item, paths, depth + 1);
65
+ return;
66
+ }
67
+ if (typeof obj.path === "string" && (obj.path.startsWith("/") || /^[a-zA-Z]:[/\\]/.test(obj.path))) paths.add(obj.path);
68
+ for (const [key, val] of Object.entries(obj)) {
69
+ if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
70
+ if (val && typeof val === "object") _extractPaths(val, paths, depth + 1);
71
+ }
72
+ }
73
+
74
+ function _callLspHandler(port, secret, operation, params) {
75
+ const postData = JSON.stringify(params);
76
+ return new Promise((resolve) => {
77
+ const req = http.request({
78
+ hostname: "127.0.0.1",
79
+ port: parseInt(port, 10),
80
+ path: `/lsp/${operation}`,
81
+ method: "POST",
82
+ headers: {
83
+ "Content-Type": "application/json",
84
+ "Content-Length": Buffer.byteLength(postData),
85
+ ...(secret ? { "x-lsp-handler-token": secret } : {}),
86
+ },
87
+ timeout: 3000,
88
+ }, (res) => {
89
+ let data = "";
90
+ let exceeded = false;
91
+ const MAX_RESP = 5 * 1024 * 1024;
92
+ res.on("data", chunk => {
93
+ if (exceeded) return;
94
+ data += chunk;
95
+ if (data.length > MAX_RESP) { exceeded = true; req.destroy(); resolve(null); }
96
+ });
97
+ res.on("end", () => { if (!exceeded) { try { resolve(JSON.parse(data)); } catch { resolve(null); } } });
98
+ });
99
+ req.on("error", () => resolve(null));
100
+ req.on("timeout", () => { req.destroy(); resolve(null); });
101
+ req.write(postData);
102
+ req.end();
103
+ });
104
+ }
105
+
106
+ async function _enrichWithLsp(result, lspConn) {
107
+ try {
108
+ if (!Array.isArray(result?.content)) return result;
109
+ const textBlock = result.content.find(c => c.type === "text");
110
+ if (!textBlock?.text) return result;
111
+ let parsed;
112
+ try { parsed = JSON.parse(textBlock.text); } catch { return result; }
113
+ if (!parsed.ok) return result;
114
+ const paths = new Set();
115
+ _extractPaths(parsed, paths);
116
+ if (paths.size === 0) return result;
117
+ const diag = await _callLspHandler(lspConn.port, lspConn.secret, "diagnostics_recent", { paths: [...paths] });
118
+ if (!diag?.ok || !diag.files || diag.total === 0) return result;
119
+ parsed._lsp = { diagnostics: diag.files, total: diag.total };
120
+ textBlock.text = JSON.stringify(parsed);
121
+ return result;
122
+ } catch (err) {
123
+ debugLog("[ctxce] LSP enrichment failed: " + String(err));
124
+ return result;
125
+ }
126
+ }
127
+
17
128
  function debugLog(message) {
18
129
  try {
19
130
  const text = typeof message === "string" ? message : String(message);
@@ -97,6 +208,9 @@ function selectClientForTool(name, indexerClient, memoryClient) {
97
208
  if (memoryClient && lowered.startsWith("memory")) {
98
209
  return memoryClient;
99
210
  }
211
+ if (lowered.startsWith("lsp_")) {
212
+ return null;
213
+ }
100
214
  return indexerClient;
101
215
  }
102
216
 
@@ -796,6 +910,90 @@ async function createBridgeServer(options) {
796
910
  const indexerTools = Array.isArray(remote?.tools) ? remote.tools.slice() : [];
797
911
  const memoryTools = await listMemoryTools(memoryClient);
798
912
  const tools = dedupeTools([...indexerTools, ...memoryTools]);
913
+
914
+ const lspAvailable = !!_readLspConnection();
915
+ if (lspAvailable) {
916
+ const lspProp = {
917
+ type: "boolean",
918
+ description: "When true, auto-enrich results with live LSP diagnostics (errors/warnings) for files in the response. Zero extra tool calls needed.",
919
+ };
920
+ for (const tool of tools) {
921
+ if (_LSP_ENRICHABLE_TOOLS.has(tool.name) && tool.inputSchema?.properties) {
922
+ tool.inputSchema = { ...tool.inputSchema, properties: { ...tool.inputSchema.properties, include_lsp: lspProp } };
923
+ }
924
+ }
925
+
926
+ const pathProp = { type: "string", description: "Absolute file path" };
927
+ const lineProp = { type: "integer", description: "0-based line" };
928
+ const charProp = { type: "integer", description: "0-based column" };
929
+ const positionProps = { path: pathProp, line: lineProp, character: charProp };
930
+ const positionRequired = ["path", "line", "character"];
931
+
932
+ tools.push(
933
+ {
934
+ name: "lsp_diagnostics",
935
+ description: "Get compiler diagnostics (errors, warnings) for a file from the active language server.",
936
+ inputSchema: { type: "object", properties: { path: pathProp }, required: ["path"] },
937
+ },
938
+ {
939
+ name: "lsp_definition",
940
+ description: "Go to definition of symbol at position.",
941
+ inputSchema: { type: "object", properties: { ...positionProps }, required: positionRequired },
942
+ },
943
+ {
944
+ name: "lsp_references",
945
+ description: "Find all references to symbol at position.",
946
+ inputSchema: {
947
+ type: "object",
948
+ properties: { ...positionProps, includeDeclaration: { type: "boolean", description: "Include the declaration itself" } },
949
+ required: positionRequired,
950
+ },
951
+ },
952
+ {
953
+ name: "lsp_hover",
954
+ description: "Get hover information (type, docs) for symbol at position.",
955
+ inputSchema: { type: "object", properties: { ...positionProps }, required: positionRequired },
956
+ },
957
+ {
958
+ name: "lsp_document_symbols",
959
+ description: "Get all symbols in a document.",
960
+ inputSchema: { type: "object", properties: { path: pathProp }, required: ["path"] },
961
+ },
962
+ {
963
+ name: "lsp_workspace_symbols",
964
+ description: "Search for symbols across the workspace.",
965
+ inputSchema: { type: "object", properties: { query: { type: "string", description: "Symbol search query" } }, required: ["query"] },
966
+ },
967
+ {
968
+ name: "lsp_code_actions",
969
+ description: "Get available code actions (quick fixes, refactors) for a range.",
970
+ inputSchema: {
971
+ type: "object",
972
+ properties: {
973
+ path: pathProp,
974
+ startLine: { type: "integer" },
975
+ startChar: { type: "integer" },
976
+ endLine: { type: "integer" },
977
+ endChar: { type: "integer" },
978
+ },
979
+ required: ["path", "startLine", "startChar", "endLine", "endChar"],
980
+ },
981
+ },
982
+ {
983
+ name: "lsp_diagnostics_recent",
984
+ description: "Get recently collected diagnostics from file edits (errors and warnings auto-collected via language server).",
985
+ inputSchema: {
986
+ type: "object",
987
+ properties: {
988
+ paths: { type: "array", items: { type: "string" }, description: "Filter to specific file paths" },
989
+ severity_filter: { type: "string", enum: ["error", "warning", "info", "hint"], description: "Filter by severity" },
990
+ since_ms: { type: "integer", description: "Only return diagnostics newer than this Unix timestamp in ms" },
991
+ },
992
+ },
993
+ },
994
+ );
995
+ }
996
+
799
997
  debugLog(`[ctxce] tools/list: returning ${tools.length} tools`);
800
998
  return { tools };
801
999
  });
@@ -806,6 +1004,13 @@ async function createBridgeServer(options) {
806
1004
  const name = params.name;
807
1005
  let args = params.arguments;
808
1006
 
1007
+ let includeLsp = false;
1008
+ if (args && typeof args === "object" && args.include_lsp === true && _LSP_ENRICHABLE_TOOLS.has(name)) {
1009
+ includeLsp = true;
1010
+ const { include_lsp: _stripped, ...rest } = args;
1011
+ args = rest;
1012
+ }
1013
+
809
1014
  debugLog(`[ctxce] tools/call: ${name || "<no-name>"}`);
810
1015
 
811
1016
  // Refresh session before each call; re-init clients if session changes.
@@ -846,6 +1051,55 @@ async function createBridgeServer(options) {
846
1051
  return indexerResult;
847
1052
  }
848
1053
 
1054
+ if (name && name.toLowerCase().startsWith("lsp_")) {
1055
+ const lspConn = _readLspConnection();
1056
+ const lspPort = lspConn ? lspConn.port : null;
1057
+ const lspSecret = lspConn ? lspConn.secret : "";
1058
+ if (!lspPort) {
1059
+ return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: "LSP proxy not available. Ensure VS Code extension has lsp.enabled=true." }) }] };
1060
+ }
1061
+ const ALLOWED_LSP_OPS = new Set(['diagnostics','definition','references','hover','document_symbols','workspace_symbols','code_actions','diagnostics_recent']);
1062
+ const operation = name.toLowerCase().replace(/^lsp_/, "");
1063
+ if (!ALLOWED_LSP_OPS.has(operation)) {
1064
+ return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: "Unknown LSP operation" }) }] };
1065
+ }
1066
+ try {
1067
+ const lspArgs = params.arguments || {};
1068
+ const postData = JSON.stringify(lspArgs);
1069
+ const result = await new Promise((resolve, reject) => {
1070
+ const req = http.request({
1071
+ hostname: "127.0.0.1",
1072
+ port: parseInt(lspPort, 10),
1073
+ path: `/lsp/${operation}`,
1074
+ method: "POST",
1075
+ headers: Object.assign({ "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) }, lspSecret ? { "x-lsp-handler-token": lspSecret } : {}),
1076
+ timeout: 15000,
1077
+ }, (res) => {
1078
+ let data = "";
1079
+ let exceeded = false;
1080
+ const MAX_RESP = 5 * 1024 * 1024;
1081
+ res.on("data", chunk => {
1082
+ if (exceeded) return;
1083
+ data += chunk;
1084
+ if (data.length > MAX_RESP) { exceeded = true; req.destroy(); resolve({ ok: false, error: "Response too large" }); }
1085
+ });
1086
+ res.on("end", () => {
1087
+ if (!exceeded) { try { resolve(JSON.parse(data)); } catch { resolve({ ok: false, error: "Invalid response from LSP handler" }); } }
1088
+ });
1089
+ });
1090
+ req.on("error", reject);
1091
+ req.on("timeout", () => { req.destroy(); reject(new Error("LSP request timeout")); });
1092
+ req.write(postData);
1093
+ req.end();
1094
+ });
1095
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
1096
+ } catch (err) {
1097
+ debugLog("[ctxce] LSP proxy error: " + String(err));
1098
+ const safeMsg = (err && err.code) ? `LSP proxy error: ${err.code}` : "LSP proxy error: request failed";
1099
+ return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: safeMsg }) }] };
1100
+ }
1101
+ }
1102
+
849
1103
  await initializeRemoteClients(false);
850
1104
 
851
1105
  const timeoutMs = getBridgeToolTimeoutMs();
@@ -862,7 +1116,7 @@ async function createBridgeServer(options) {
862
1116
 
863
1117
  const targetClient = selectClientForTool(name, indexerClient, memoryClient);
864
1118
  if (!targetClient) {
865
- throw new Error(`Tool ${name} not available on any configured MCP server`);
1119
+ return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Tool ${name} not available on any configured MCP server` }) }] };
866
1120
  }
867
1121
 
868
1122
  try {
@@ -874,7 +1128,10 @@ async function createBridgeServer(options) {
874
1128
  undefined,
875
1129
  { timeout: timeoutMs },
876
1130
  );
877
- return maybeRemapToolResult(name, result, workspace);
1131
+ let finalResult = maybeRemapToolResult(name, result, workspace);
1132
+ const lspConn = includeLsp && _readLspConnection();
1133
+ if (lspConn) finalResult = await _enrichWithLsp(finalResult, lspConn);
1134
+ return finalResult;
878
1135
  } catch (err) {
879
1136
  lastError = err;
880
1137
 
@@ -1,6 +0,0 @@
1
- {
2
- "timestamp": "2026-02-20T02:56:43.457Z",
3
- "backgroundTasks": [],
4
- "sessionStartTimestamp": "2026-02-20T02:54:38.180Z",
5
- "sessionId": "391fa45d902019af"
6
- }
@@ -1,7 +0,0 @@
1
- {
2
- "active": true,
3
- "started_at": "2026-01-25T14:25:53.146Z",
4
- "original_prompt": "/oh-my-claude-sisyphus:ultrawork we need to figure out, research context engine a bit.... how to make our agent tools better via mcp... (the claude.example.md is\n clear) but maybe we need an agents.md, we have claude skills... can we make the descriptors better? research alot fo other\n tools and see",
5
- "reinforcement_count": 5,
6
- "last_checked_at": "2026-01-25T14:43:28.449Z"
7
- }
package/AGENTS.md DELETED
@@ -1,69 +0,0 @@
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 DELETED
@@ -1,34 +0,0 @@
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/docs/AGENTS.md DELETED
@@ -1,22 +0,0 @@
1
- <!-- Parent: ../AGENTS.md -->
2
- <!-- Generated: 2026-02-19 | Updated: 2026-02-19 -->
3
-
4
- # docs
5
-
6
- ## Purpose
7
-
8
- Debugging guides and developer documentation for the MCP bridge. Currently contains minimal documentation; most usage is covered in the main `README.md`.
9
-
10
- ## Key Files
11
-
12
- | File | Description |
13
- |------|-------------|
14
- | `debugging.md` | Debug logging and troubleshooting tips |
15
-
16
- ## For AI Agents
17
-
18
- ### Working In This Directory
19
-
20
- This directory is for developer guides, not API documentation (which belongs in the main README). When adding debugging tips or advanced usage patterns, place them here.
21
-
22
- <!-- MANUAL: Any manually added notes below this line are preserved on regeneration -->
package/docs/debugging.md DELETED
@@ -1,20 +0,0 @@
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/publish.sh DELETED
@@ -1,34 +0,0 @@
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/AGENTS.md DELETED
@@ -1,59 +0,0 @@
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 -->