mcp-proxy 5.10.0 → 5.11.1
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/bin/mcp-proxy.js +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.js +1 -1
- package/dist/{stdio-DF5lH8jj.js → stdio-DLSsHME0.js} +77 -21
- package/dist/stdio-DLSsHME0.js.map +1 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/InMemoryEventStore.test.ts +72 -0
- package/src/InMemoryEventStore.ts +19 -2
- package/src/authentication.test.ts +145 -7
- package/src/authentication.ts +51 -5
- package/src/proxyServer.ts +8 -6
- package/src/startHTTPServer.test.ts +144 -0
- package/src/startHTTPServer.ts +106 -22
- package/dist/stdio-DF5lH8jj.js.map +0 -1
package/dist/bin/mcp-proxy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-
|
|
2
|
+
import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-DLSsHME0.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { basename, dirname, extname, join, normalize, relative, resolve } from "path";
|
|
5
5
|
import { format, inspect } from "util";
|
package/dist/index.d.ts
CHANGED
|
@@ -11,15 +11,25 @@ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
|
11
11
|
interface AuthConfig {
|
|
12
12
|
apiKey?: string;
|
|
13
13
|
oauth?: {
|
|
14
|
+
error?: string;
|
|
15
|
+
error_description?: string;
|
|
16
|
+
error_uri?: string;
|
|
14
17
|
protectedResource?: {
|
|
15
18
|
resource?: string;
|
|
16
19
|
};
|
|
20
|
+
realm?: string;
|
|
21
|
+
scope?: string;
|
|
17
22
|
};
|
|
18
23
|
}
|
|
19
24
|
declare class AuthenticationMiddleware {
|
|
20
25
|
private config;
|
|
21
26
|
constructor(config?: AuthConfig);
|
|
22
|
-
getUnauthorizedResponse(
|
|
27
|
+
getUnauthorizedResponse(options?: {
|
|
28
|
+
error?: string;
|
|
29
|
+
error_description?: string;
|
|
30
|
+
error_uri?: string;
|
|
31
|
+
scope?: string;
|
|
32
|
+
}): {
|
|
23
33
|
body: string;
|
|
24
34
|
headers: Record<string, string>;
|
|
25
35
|
};
|
|
@@ -34,6 +44,8 @@ declare class AuthenticationMiddleware {
|
|
|
34
44
|
*/
|
|
35
45
|
declare class InMemoryEventStore implements EventStore {
|
|
36
46
|
private events;
|
|
47
|
+
private lastTimestamp;
|
|
48
|
+
private lastTimestampCounter;
|
|
37
49
|
/**
|
|
38
50
|
* Replays events that occurred after a specific event ID
|
|
39
51
|
* Implements EventStore.replayEventsAfter
|
|
@@ -49,7 +61,8 @@ declare class InMemoryEventStore implements EventStore {
|
|
|
49
61
|
*/
|
|
50
62
|
storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
|
|
51
63
|
/**
|
|
52
|
-
* Generates a unique event ID
|
|
64
|
+
* Generates a monotonic unique event ID in
|
|
65
|
+
* `${streamId}_${timestamp}_${counter}_${random}` format.
|
|
53
66
|
*/
|
|
54
67
|
private generateEventId;
|
|
55
68
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType } from "./stdio-
|
|
1
|
+
import { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType } from "./stdio-DLSsHME0.js";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
|
|
4
4
|
//#region node_modules/.pnpm/eventsource-parser@3.0.6/node_modules/eventsource-parser/dist/index.js
|
|
@@ -35,14 +35,27 @@ var AuthenticationMiddleware = class {
|
|
|
35
35
|
constructor(config = {}) {
|
|
36
36
|
this.config = config;
|
|
37
37
|
}
|
|
38
|
-
getUnauthorizedResponse() {
|
|
38
|
+
getUnauthorizedResponse(options) {
|
|
39
39
|
const headers = { "Content-Type": "application/json" };
|
|
40
|
-
if (this.config.oauth
|
|
40
|
+
if (this.config.oauth) {
|
|
41
|
+
const params = [];
|
|
42
|
+
if (this.config.oauth.realm) params.push(`realm="${this.config.oauth.realm}"`);
|
|
43
|
+
if (this.config.oauth.protectedResource?.resource) params.push(`resource_metadata="${this.config.oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`);
|
|
44
|
+
const error = options?.error || this.config.oauth.error || "invalid_token";
|
|
45
|
+
params.push(`error="${error}"`);
|
|
46
|
+
const escaped = (options?.error_description || this.config.oauth.error_description || "Unauthorized: Invalid or missing API key").replace(/"/g, "\\\"");
|
|
47
|
+
params.push(`error_description="${escaped}"`);
|
|
48
|
+
const error_uri = options?.error_uri || this.config.oauth.error_uri;
|
|
49
|
+
if (error_uri) params.push(`error_uri="${error_uri}"`);
|
|
50
|
+
const scope = options?.scope || this.config.oauth.scope;
|
|
51
|
+
if (scope) params.push(`scope="${scope}"`);
|
|
52
|
+
if (params.length > 0) headers["WWW-Authenticate"] = `Bearer ${params.join(", ")}`;
|
|
53
|
+
}
|
|
41
54
|
return {
|
|
42
55
|
body: JSON.stringify({
|
|
43
56
|
error: {
|
|
44
57
|
code: 401,
|
|
45
|
-
message: "Unauthorized: Invalid or missing API key"
|
|
58
|
+
message: options?.error_description || "Unauthorized: Invalid or missing API key"
|
|
46
59
|
},
|
|
47
60
|
id: null,
|
|
48
61
|
jsonrpc: "2.0"
|
|
@@ -67,6 +80,8 @@ var AuthenticationMiddleware = class {
|
|
|
67
80
|
*/
|
|
68
81
|
var InMemoryEventStore = class {
|
|
69
82
|
events = /* @__PURE__ */ new Map();
|
|
83
|
+
lastTimestamp = 0;
|
|
84
|
+
lastTimestampCounter = 0;
|
|
70
85
|
/**
|
|
71
86
|
* Replays events that occurred after a specific event ID
|
|
72
87
|
* Implements EventStore.replayEventsAfter
|
|
@@ -100,10 +115,20 @@ var InMemoryEventStore = class {
|
|
|
100
115
|
return eventId;
|
|
101
116
|
}
|
|
102
117
|
/**
|
|
103
|
-
* Generates a unique event ID
|
|
118
|
+
* Generates a monotonic unique event ID in
|
|
119
|
+
* `${streamId}_${timestamp}_${counter}_${random}` format.
|
|
104
120
|
*/
|
|
105
121
|
generateEventId(streamId) {
|
|
106
|
-
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
if (now === this.lastTimestamp) this.lastTimestampCounter++;
|
|
124
|
+
else {
|
|
125
|
+
this.lastTimestampCounter = 0;
|
|
126
|
+
this.lastTimestamp = now;
|
|
127
|
+
}
|
|
128
|
+
const timestamp = now.toString();
|
|
129
|
+
const counter = this.lastTimestampCounter.toString(36).padStart(4, "0");
|
|
130
|
+
const random = Math.random().toString(36).substring(2, 5);
|
|
131
|
+
return `${streamId}_${timestamp}_${counter}_${random}`;
|
|
107
132
|
}
|
|
108
133
|
/**
|
|
109
134
|
* Extracts the stream ID from an event ID
|
|
@@ -4476,7 +4501,7 @@ const proxyServer = async ({ client, requestTimeout, server, serverCapabilities
|
|
|
4476
4501
|
return client.listTools(args.params, requestTimeout ? { timeout: requestTimeout } : void 0);
|
|
4477
4502
|
});
|
|
4478
4503
|
}
|
|
4479
|
-
server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
4504
|
+
if (serverCapabilities?.completions) server.setRequestHandler(CompleteRequestSchema, async (args) => {
|
|
4480
4505
|
return client.complete(args.params, requestTimeout ? { timeout: requestTimeout } : void 0);
|
|
4481
4506
|
});
|
|
4482
4507
|
};
|
|
@@ -15026,19 +15051,37 @@ const createJsonRpcErrorResponse = (code, message) => {
|
|
|
15026
15051
|
jsonrpc: "2.0"
|
|
15027
15052
|
});
|
|
15028
15053
|
};
|
|
15029
|
-
const getWWWAuthenticateHeader = (oauth) => {
|
|
15030
|
-
if (!oauth
|
|
15031
|
-
|
|
15054
|
+
const getWWWAuthenticateHeader = (oauth, options) => {
|
|
15055
|
+
if (!oauth) return;
|
|
15056
|
+
const params = [];
|
|
15057
|
+
if (oauth.realm) params.push(`realm="${oauth.realm}"`);
|
|
15058
|
+
if (oauth.protectedResource?.resource) params.push(`resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`);
|
|
15059
|
+
const error = options?.error || oauth.error;
|
|
15060
|
+
if (error) params.push(`error="${error}"`);
|
|
15061
|
+
const error_description = options?.error_description || oauth.error_description;
|
|
15062
|
+
if (error_description) {
|
|
15063
|
+
const escaped = error_description.replace(/"/g, "\\\"");
|
|
15064
|
+
params.push(`error_description="${escaped}"`);
|
|
15065
|
+
}
|
|
15066
|
+
const error_uri = options?.error_uri || oauth.error_uri;
|
|
15067
|
+
if (error_uri) params.push(`error_uri="${error_uri}"`);
|
|
15068
|
+
const scope = options?.scope || oauth.scope;
|
|
15069
|
+
if (scope) params.push(`scope="${scope}"`);
|
|
15070
|
+
if (params.length === 0) return;
|
|
15071
|
+
return `Bearer ${params.join(", ")}`;
|
|
15032
15072
|
};
|
|
15033
|
-
const handleResponseError = (error, res) => {
|
|
15034
|
-
if (error instanceof Response) {
|
|
15073
|
+
const handleResponseError = async (error, res) => {
|
|
15074
|
+
if (error && typeof error === "object" && "status" in error && "headers" in error && "statusText" in error || error instanceof Response) {
|
|
15075
|
+
const responseError = error;
|
|
15035
15076
|
const fixedHeaders = {};
|
|
15036
|
-
|
|
15077
|
+
responseError.headers.forEach((value, key$1) => {
|
|
15037
15078
|
if (fixedHeaders[key$1]) if (Array.isArray(fixedHeaders[key$1])) fixedHeaders[key$1].push(value);
|
|
15038
15079
|
else fixedHeaders[key$1] = [fixedHeaders[key$1], value];
|
|
15039
15080
|
else fixedHeaders[key$1] = value;
|
|
15040
15081
|
});
|
|
15041
|
-
|
|
15082
|
+
const body = await responseError.text();
|
|
15083
|
+
res.writeHead(responseError.status, responseError.statusText, fixedHeaders);
|
|
15084
|
+
res.end(body);
|
|
15042
15085
|
return true;
|
|
15043
15086
|
}
|
|
15044
15087
|
return false;
|
|
@@ -15104,7 +15147,10 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15104
15147
|
if (!authResult || typeof authResult === "object" && "authenticated" in authResult && !authResult.authenticated) {
|
|
15105
15148
|
const errorMessage = authResult && typeof authResult === "object" && "error" in authResult && typeof authResult.error === "string" ? authResult.error : "Unauthorized: Authentication failed";
|
|
15106
15149
|
res.setHeader("Content-Type", "application/json");
|
|
15107
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15150
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15151
|
+
error: "invalid_token",
|
|
15152
|
+
error_description: errorMessage
|
|
15153
|
+
});
|
|
15108
15154
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15109
15155
|
res.writeHead(401).end(JSON.stringify({
|
|
15110
15156
|
error: {
|
|
@@ -15117,10 +15163,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15117
15163
|
return true;
|
|
15118
15164
|
}
|
|
15119
15165
|
} catch (error) {
|
|
15166
|
+
if (await handleResponseError(error, res)) return true;
|
|
15120
15167
|
const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
|
|
15121
15168
|
console.error("Authentication error:", error);
|
|
15122
15169
|
res.setHeader("Content-Type", "application/json");
|
|
15123
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15170
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15171
|
+
error: "invalid_token",
|
|
15172
|
+
error_description: errorMessage
|
|
15173
|
+
});
|
|
15124
15174
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15125
15175
|
res.writeHead(401).end(JSON.stringify({
|
|
15126
15176
|
error: {
|
|
@@ -15166,10 +15216,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15166
15216
|
try {
|
|
15167
15217
|
server = await createServer(req);
|
|
15168
15218
|
} catch (error) {
|
|
15219
|
+
if (await handleResponseError(error, res)) return true;
|
|
15169
15220
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15170
15221
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15171
15222
|
res.setHeader("Content-Type", "application/json");
|
|
15172
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15223
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15224
|
+
error: "invalid_token",
|
|
15225
|
+
error_description: errorMessage
|
|
15226
|
+
});
|
|
15173
15227
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15174
15228
|
res.writeHead(401).end(JSON.stringify({
|
|
15175
15229
|
error: {
|
|
@@ -15181,7 +15235,6 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15181
15235
|
}));
|
|
15182
15236
|
return true;
|
|
15183
15237
|
}
|
|
15184
|
-
if (handleResponseError(error, res)) return true;
|
|
15185
15238
|
res.writeHead(500).end("Error creating server");
|
|
15186
15239
|
return true;
|
|
15187
15240
|
}
|
|
@@ -15199,10 +15252,14 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15199
15252
|
try {
|
|
15200
15253
|
server = await createServer(req);
|
|
15201
15254
|
} catch (error) {
|
|
15255
|
+
if (await handleResponseError(error, res)) return true;
|
|
15202
15256
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15203
15257
|
if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
|
|
15204
15258
|
res.setHeader("Content-Type", "application/json");
|
|
15205
|
-
const wwwAuthHeader = getWWWAuthenticateHeader(oauth
|
|
15259
|
+
const wwwAuthHeader = getWWWAuthenticateHeader(oauth, {
|
|
15260
|
+
error: "invalid_token",
|
|
15261
|
+
error_description: errorMessage
|
|
15262
|
+
});
|
|
15206
15263
|
if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
|
|
15207
15264
|
res.writeHead(401).end(JSON.stringify({
|
|
15208
15265
|
error: {
|
|
@@ -15214,7 +15271,6 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
|
|
|
15214
15271
|
}));
|
|
15215
15272
|
return true;
|
|
15216
15273
|
}
|
|
15217
|
-
if (handleResponseError(error, res)) return true;
|
|
15218
15274
|
res.writeHead(500).end("Error creating server");
|
|
15219
15275
|
return true;
|
|
15220
15276
|
}
|
|
@@ -15284,7 +15340,7 @@ const handleSSERequest = async ({ activeTransports, createServer, endpoint, onCl
|
|
|
15284
15340
|
try {
|
|
15285
15341
|
server = await createServer(req);
|
|
15286
15342
|
} catch (error) {
|
|
15287
|
-
if (handleResponseError(error, res)) return true;
|
|
15343
|
+
if (await handleResponseError(error, res)) return true;
|
|
15288
15344
|
res.writeHead(500).end("Error creating server");
|
|
15289
15345
|
return true;
|
|
15290
15346
|
}
|
|
@@ -21589,4 +21645,4 @@ function serializeMessage(message) {
|
|
|
21589
21645
|
|
|
21590
21646
|
//#endregion
|
|
21591
21647
|
export { AuthenticationMiddleware, Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, __commonJS, __toESM, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType };
|
|
21592
|
-
//# sourceMappingURL=stdio-
|
|
21648
|
+
//# sourceMappingURL=stdio-DLSsHME0.js.map
|