@aiwerk/mcp-bridge 1.6.1 → 1.6.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/dist/src/protocol.js
CHANGED
|
@@ -3,14 +3,23 @@ import { join, dirname } from "path";
|
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
const __filename = fileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = dirname(__filename);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
function loadPackageVersion() {
|
|
7
|
+
const candidates = [
|
|
8
|
+
join(__dirname, "..", "package.json"),
|
|
9
|
+
join(__dirname, "..", "..", "package.json"),
|
|
10
|
+
join(__dirname, "..", "..", "..", "package.json"),
|
|
11
|
+
];
|
|
12
|
+
for (const p of candidates) {
|
|
13
|
+
try {
|
|
14
|
+
const pkg = JSON.parse(readFileSync(p, "utf-8"));
|
|
15
|
+
if (pkg.version)
|
|
16
|
+
return pkg.version;
|
|
17
|
+
}
|
|
18
|
+
catch { /* try next candidate */ }
|
|
12
19
|
}
|
|
13
|
-
|
|
20
|
+
return "0.0.0";
|
|
21
|
+
}
|
|
22
|
+
export const PACKAGE_VERSION = loadPackageVersion();
|
|
14
23
|
export async function initializeProtocol(transport, version) {
|
|
15
24
|
const initRequest = {
|
|
16
25
|
jsonrpc: "2.0",
|
|
@@ -13,7 +13,8 @@ export declare class StandaloneServer {
|
|
|
13
13
|
private directConnections;
|
|
14
14
|
constructor(config: BridgeConfig, logger: Logger);
|
|
15
15
|
private isRouterMode;
|
|
16
|
-
/** Start stdio mode: read JSON-RPC from stdin, write responses to stdout.
|
|
16
|
+
/** Start stdio mode: read JSON-RPC from stdin, write responses to stdout.
|
|
17
|
+
* Supports both newline-delimited JSON and LSP Content-Length framing. */
|
|
17
18
|
startStdio(): Promise<void>;
|
|
18
19
|
private processLine;
|
|
19
20
|
private writeResponse;
|
|
@@ -27,19 +27,73 @@ export class StandaloneServer {
|
|
|
27
27
|
isRouterMode() {
|
|
28
28
|
return (this.config.mode ?? "router") === "router";
|
|
29
29
|
}
|
|
30
|
-
/** Start stdio mode: read JSON-RPC from stdin, write responses to stdout.
|
|
30
|
+
/** Start stdio mode: read JSON-RPC from stdin, write responses to stdout.
|
|
31
|
+
* Supports both newline-delimited JSON and LSP Content-Length framing. */
|
|
31
32
|
async startStdio() {
|
|
32
33
|
const stdin = process.stdin;
|
|
33
34
|
const stdout = process.stdout;
|
|
34
35
|
stdin.setEncoding("utf8");
|
|
35
36
|
let buffer = "";
|
|
37
|
+
// LSP framing state
|
|
38
|
+
let lspContentLength = -1; // -1 means not in LSP mode for current message
|
|
39
|
+
let lspHeadersDone = false;
|
|
36
40
|
stdin.on("data", (chunk) => {
|
|
37
41
|
buffer += chunk;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// Process buffer in a loop — it may contain multiple messages
|
|
43
|
+
let progress = true;
|
|
44
|
+
while (progress) {
|
|
45
|
+
progress = false;
|
|
46
|
+
// If we're reading an LSP body, check if we have enough bytes
|
|
47
|
+
if (lspContentLength >= 0 && lspHeadersDone) {
|
|
48
|
+
if (buffer.length >= lspContentLength) {
|
|
49
|
+
const body = buffer.slice(0, lspContentLength);
|
|
50
|
+
buffer = buffer.slice(lspContentLength);
|
|
51
|
+
lspContentLength = -1;
|
|
52
|
+
lspHeadersDone = false;
|
|
53
|
+
const trimmed = body.trim();
|
|
54
|
+
if (trimmed) {
|
|
55
|
+
this.processLine(trimmed, stdout);
|
|
56
|
+
}
|
|
57
|
+
progress = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// Not enough data yet — wait for more
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
// Look for complete lines to detect framing
|
|
64
|
+
const newlineIdx = buffer.indexOf("\n");
|
|
65
|
+
if (newlineIdx === -1)
|
|
66
|
+
break;
|
|
67
|
+
const line = buffer.slice(0, newlineIdx);
|
|
41
68
|
const trimmed = line.trim();
|
|
42
|
-
|
|
69
|
+
// LSP header detection
|
|
70
|
+
if (lspContentLength >= 0 && !lspHeadersDone) {
|
|
71
|
+
// We're reading LSP headers — consume until empty line
|
|
72
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
73
|
+
progress = true;
|
|
74
|
+
if (trimmed === "") {
|
|
75
|
+
// End of headers — next read the body
|
|
76
|
+
lspHeadersDone = true;
|
|
77
|
+
}
|
|
78
|
+
// Ignore other headers (Content-Type, etc.)
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (trimmed.startsWith("Content-Length:")) {
|
|
82
|
+
// Start of LSP-framed message
|
|
83
|
+
const lengthStr = trimmed.slice("Content-Length:".length).trim();
|
|
84
|
+
const length = parseInt(lengthStr, 10);
|
|
85
|
+
if (!isNaN(length) && length > 0) {
|
|
86
|
+
lspContentLength = length;
|
|
87
|
+
lspHeadersDone = false;
|
|
88
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
89
|
+
progress = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Newline-delimited JSON: consume the line
|
|
94
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
95
|
+
progress = true;
|
|
96
|
+
if (!trimmed || !trimmed.startsWith("{"))
|
|
43
97
|
continue;
|
|
44
98
|
this.processLine(trimmed, stdout);
|
|
45
99
|
}
|
|
@@ -185,7 +239,8 @@ export class StandaloneServer {
|
|
|
185
239
|
jsonrpc: "2.0",
|
|
186
240
|
id,
|
|
187
241
|
result: {
|
|
188
|
-
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
242
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
243
|
+
isError: true
|
|
189
244
|
}
|
|
190
245
|
};
|
|
191
246
|
}
|
|
@@ -54,7 +54,7 @@ export declare abstract class BaseTransport implements McpTransport {
|
|
|
54
54
|
* @param contextDescription - Human-readable context for error messages (e.g. 'header "Authorization"')
|
|
55
55
|
* @param extraEnv - Additional env vars to check before process.env (e.g. merged child process env)
|
|
56
56
|
*/
|
|
57
|
-
export declare function resolveEnvVars(value: string, contextDescription: string, extraEnv?: Record<string, string | undefined>): string;
|
|
57
|
+
export declare function resolveEnvVars(value: string, contextDescription: string, extraEnv?: Record<string, string | undefined>, envFallback?: () => Record<string, string>): string;
|
|
58
58
|
/**
|
|
59
59
|
* Resolve ${VAR} placeholders in all values of a Record<string, string>.
|
|
60
60
|
*
|
|
@@ -62,14 +62,14 @@ export declare function resolveEnvVars(value: string, contextDescription: string
|
|
|
62
62
|
* @param contextPrefix - Prefix for error context (e.g. "header", "env key")
|
|
63
63
|
* @param extraEnv - Additional env vars to check before process.env
|
|
64
64
|
*/
|
|
65
|
-
export declare function resolveEnvRecord(record: Record<string, string>, contextPrefix: string, extraEnv?: Record<string, string | undefined>): Record<string, string>;
|
|
65
|
+
export declare function resolveEnvRecord(record: Record<string, string>, contextPrefix: string, extraEnv?: Record<string, string | undefined>, envFallback?: () => Record<string, string>): Record<string, string>;
|
|
66
66
|
/**
|
|
67
67
|
* Resolve ${VAR} placeholders in an array of command arguments.
|
|
68
68
|
*
|
|
69
69
|
* @param args - Array of argument strings with potential ${VAR} placeholders
|
|
70
70
|
* @param extraEnv - Additional env vars to check before process.env
|
|
71
71
|
*/
|
|
72
|
-
export declare function resolveArgs(args: string[], extraEnv?: Record<string, string | undefined>): string[];
|
|
72
|
+
export declare function resolveArgs(args: string[], extraEnv?: Record<string, string | undefined>, envFallback?: () => Record<string, string>): string[];
|
|
73
73
|
/**
|
|
74
74
|
* Warn if a URL uses non-TLS HTTP to a remote (non-localhost) host.
|
|
75
75
|
*/
|
|
@@ -117,16 +117,17 @@ export class BaseTransport {
|
|
|
117
117
|
* @param contextDescription - Human-readable context for error messages (e.g. 'header "Authorization"')
|
|
118
118
|
* @param extraEnv - Additional env vars to check before process.env (e.g. merged child process env)
|
|
119
119
|
*/
|
|
120
|
-
export function resolveEnvVars(value, contextDescription, extraEnv) {
|
|
120
|
+
export function resolveEnvVars(value, contextDescription, extraEnv, envFallback) {
|
|
121
121
|
return value.replace(/\$\{(\w+)\}/g, (_, varName) => {
|
|
122
122
|
const resolved = extraEnv?.[varName] ?? process.env[varName];
|
|
123
|
-
// If resolved is undefined or empty string, try the
|
|
124
|
-
//
|
|
125
|
-
// pre-existing empty env var
|
|
123
|
+
// If resolved is undefined or empty string, try the env fallback.
|
|
124
|
+
// Default fallback is loadOpenClawDotEnvFallback (handles the case where
|
|
125
|
+
// dotenv(override:false) didn't overwrite a pre-existing empty env var).
|
|
126
126
|
if (resolved === undefined || resolved === "") {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
const fallbackFn = envFallback ?? loadOpenClawDotEnvFallback;
|
|
128
|
+
const fallbackVal = fallbackFn()[varName];
|
|
129
|
+
if (fallbackVal !== undefined && fallbackVal !== "") {
|
|
130
|
+
return fallbackVal;
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
if (resolved === undefined) {
|
|
@@ -142,10 +143,10 @@ export function resolveEnvVars(value, contextDescription, extraEnv) {
|
|
|
142
143
|
* @param contextPrefix - Prefix for error context (e.g. "header", "env key")
|
|
143
144
|
* @param extraEnv - Additional env vars to check before process.env
|
|
144
145
|
*/
|
|
145
|
-
export function resolveEnvRecord(record, contextPrefix, extraEnv) {
|
|
146
|
+
export function resolveEnvRecord(record, contextPrefix, extraEnv, envFallback) {
|
|
146
147
|
const resolved = {};
|
|
147
148
|
for (const [key, value] of Object.entries(record)) {
|
|
148
|
-
resolved[key] = resolveEnvVars(value, `${contextPrefix} "${key}"`, extraEnv);
|
|
149
|
+
resolved[key] = resolveEnvVars(value, `${contextPrefix} "${key}"`, extraEnv, envFallback);
|
|
149
150
|
}
|
|
150
151
|
return resolved;
|
|
151
152
|
}
|
|
@@ -155,8 +156,8 @@ export function resolveEnvRecord(record, contextPrefix, extraEnv) {
|
|
|
155
156
|
* @param args - Array of argument strings with potential ${VAR} placeholders
|
|
156
157
|
* @param extraEnv - Additional env vars to check before process.env
|
|
157
158
|
*/
|
|
158
|
-
export function resolveArgs(args, extraEnv) {
|
|
159
|
-
return args.map(arg => resolveEnvVars(arg, `arg "${arg}"`, extraEnv));
|
|
159
|
+
export function resolveArgs(args, extraEnv, envFallback) {
|
|
160
|
+
return args.map(arg => resolveEnvVars(arg, `arg "${arg}"`, extraEnv, envFallback));
|
|
160
161
|
}
|
|
161
162
|
/**
|
|
162
163
|
* Warn if a URL uses non-TLS HTTP to a remote (non-localhost) host.
|
package/dist/src/types.d.ts
CHANGED