mcp-proxy 5.8.0 → 5.9.0

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-so1-I7Pn.js";
2
+ import { Client, InMemoryEventStore, ReadBuffer, Server, __commonJS, __toESM, proxyServer, serializeMessage, startHTTPServer } from "../stdio-CsjPjeWC.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
@@ -1,4 +1,4 @@
1
- import http from "http";
1
+ import http, { IncomingMessage } from "http";
2
2
  import { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
3
  import { JSONRPCMessage, ServerCapabilities } from "@modelcontextprotocol/sdk/types.js";
4
4
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -7,8 +7,26 @@ import { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.
7
7
  import { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
8
8
  import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
9
9
 
10
+ //#region src/authentication.d.ts
11
+ interface AuthConfig {
12
+ apiKey?: string;
13
+ oauth?: {
14
+ protectedResource?: {
15
+ resource?: string;
16
+ };
17
+ };
18
+ }
19
+ declare class AuthenticationMiddleware {
20
+ private config;
21
+ constructor(config?: AuthConfig);
22
+ getUnauthorizedResponse(): {
23
+ body: string;
24
+ headers: Record<string, string>;
25
+ };
26
+ validateRequest(req: IncomingMessage): boolean;
27
+ }
28
+ //#endregion
10
29
  //#region src/InMemoryEventStore.d.ts
11
-
12
30
  /**
13
31
  * Simple in-memory implementation of the EventStore interface for resumability
14
32
  * This is primarily intended for examples and testing, not for production use
@@ -68,6 +86,7 @@ declare const startHTTPServer: <T extends ServerLike>({
68
86
  enableJsonResponse,
69
87
  eventStore,
70
88
  host,
89
+ oauth,
71
90
  onClose,
72
91
  onConnect,
73
92
  onUnhandledRequest,
@@ -82,6 +101,7 @@ declare const startHTTPServer: <T extends ServerLike>({
82
101
  enableJsonResponse?: boolean;
83
102
  eventStore?: EventStore;
84
103
  host?: string;
104
+ oauth?: AuthConfig["oauth"];
85
105
  onClose?: (server: T) => Promise<void>;
86
106
  onConnect?: (server: T) => Promise<void>;
87
107
  onUnhandledRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
@@ -129,5 +149,5 @@ type TransportEvent = {
129
149
  };
130
150
  declare const tapTransport: (transport: Transport, eventHandler: (event: TransportEvent) => void) => Transport;
131
151
  //#endregion
132
- export { InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
152
+ export { type AuthConfig, AuthenticationMiddleware, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
133
153
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType } from "./stdio-so1-I7Pn.js";
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-CsjPjeWC.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
@@ -1850,5 +1850,5 @@ const tapTransport = (transport, eventHandler) => {
1850
1850
  };
1851
1851
 
1852
1852
  //#endregion
1853
- export { InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
1853
+ export { AuthenticationMiddleware, InMemoryEventStore, ServerType, proxyServer, startHTTPServer, startStdioServer, tapTransport };
1854
1854
  //# sourceMappingURL=index.js.map
@@ -29,6 +29,35 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  }) : target, mod));
30
30
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
31
 
32
+ //#endregion
33
+ //#region src/authentication.ts
34
+ var AuthenticationMiddleware = class {
35
+ constructor(config = {}) {
36
+ this.config = config;
37
+ }
38
+ getUnauthorizedResponse() {
39
+ const headers = { "Content-Type": "application/json" };
40
+ if (this.config.oauth?.protectedResource?.resource) headers["WWW-Authenticate"] = `Bearer resource_metadata="${this.config.oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`;
41
+ return {
42
+ body: JSON.stringify({
43
+ error: {
44
+ code: 401,
45
+ message: "Unauthorized: Invalid or missing API key"
46
+ },
47
+ id: null,
48
+ jsonrpc: "2.0"
49
+ }),
50
+ headers
51
+ };
52
+ }
53
+ validateRequest(req) {
54
+ if (!this.config.apiKey) return true;
55
+ const apiKey = req.headers["x-api-key"];
56
+ if (!apiKey || typeof apiKey !== "string") return false;
57
+ return apiKey === this.config.apiKey;
58
+ }
59
+ };
60
+
32
61
  //#endregion
33
62
  //#region src/InMemoryEventStore.ts
34
63
  /**
@@ -14968,33 +14997,6 @@ var StreamableHTTPServerTransport = class {
14968
14997
  }
14969
14998
  };
14970
14999
 
14971
- //#endregion
14972
- //#region src/authentication.ts
14973
- var AuthenticationMiddleware = class {
14974
- constructor(config = {}) {
14975
- this.config = config;
14976
- }
14977
- getUnauthorizedResponse() {
14978
- return {
14979
- body: JSON.stringify({
14980
- error: {
14981
- code: 401,
14982
- message: "Unauthorized: Invalid or missing API key"
14983
- },
14984
- id: null,
14985
- jsonrpc: "2.0"
14986
- }),
14987
- headers: { "Content-Type": "application/json" }
14988
- };
14989
- }
14990
- validateRequest(req) {
14991
- if (!this.config.apiKey) return true;
14992
- const apiKey = req.headers["x-api-key"];
14993
- if (!apiKey || typeof apiKey !== "string") return false;
14994
- return apiKey === this.config.apiKey;
14995
- }
14996
- };
14997
-
14998
15000
  //#endregion
14999
15001
  //#region src/startHTTPServer.ts
15000
15002
  const getBody = (request) => {
@@ -15024,6 +15026,10 @@ const createJsonRpcErrorResponse = (code, message) => {
15024
15026
  jsonrpc: "2.0"
15025
15027
  });
15026
15028
  };
15029
+ const getWWWAuthenticateHeader = (oauth) => {
15030
+ if (!oauth?.protectedResource?.resource) return;
15031
+ return `Bearer resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`;
15032
+ };
15027
15033
  const handleResponseError = (error, res) => {
15028
15034
  if (error instanceof Response) {
15029
15035
  const fixedHeaders = {};
@@ -15045,7 +15051,7 @@ const cleanupServer = async (server, onClose) => {
15045
15051
  console.error("[mcp-proxy] error closing server", error);
15046
15052
  }
15047
15053
  };
15048
- const handleStreamRequest = async ({ activeTransports, authenticate, createServer, enableJsonResponse, endpoint, eventStore, onClose, onConnect, req, res, stateless }) => {
15054
+ const handleStreamRequest = async ({ activeTransports, authenticate, createServer, enableJsonResponse, endpoint, eventStore, oauth, onClose, onConnect, req, res, stateless }) => {
15049
15055
  if (req.method === "POST" && new URL(req.url, "http://localhost").pathname === endpoint) {
15050
15056
  try {
15051
15057
  const sessionId = Array.isArray(req.headers["mcp-session-id"]) ? req.headers["mcp-session-id"][0] : req.headers["mcp-session-id"];
@@ -15053,12 +15059,16 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
15053
15059
  let server;
15054
15060
  const body = await getBody(req);
15055
15061
  if (stateless && authenticate) try {
15056
- if (!await authenticate(req)) {
15062
+ const authResult = await authenticate(req);
15063
+ if (!authResult || typeof authResult === "object" && "authenticated" in authResult && !authResult.authenticated) {
15064
+ const errorMessage = authResult && typeof authResult === "object" && "error" in authResult && typeof authResult.error === "string" ? authResult.error : "Unauthorized: Authentication failed";
15057
15065
  res.setHeader("Content-Type", "application/json");
15066
+ const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
15067
+ if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
15058
15068
  res.writeHead(401).end(JSON.stringify({
15059
15069
  error: {
15060
15070
  code: -32e3,
15061
- message: "Unauthorized: Authentication failed"
15071
+ message: errorMessage
15062
15072
  },
15063
15073
  id: body?.id ?? null,
15064
15074
  jsonrpc: "2.0"
@@ -15066,12 +15076,15 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
15066
15076
  return true;
15067
15077
  }
15068
15078
  } catch (error) {
15079
+ const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
15069
15080
  console.error("Authentication error:", error);
15070
15081
  res.setHeader("Content-Type", "application/json");
15082
+ const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
15083
+ if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
15071
15084
  res.writeHead(401).end(JSON.stringify({
15072
15085
  error: {
15073
15086
  code: -32e3,
15074
- message: "Unauthorized: Authentication error"
15087
+ message: errorMessage
15075
15088
  },
15076
15089
  id: body?.id ?? null,
15077
15090
  jsonrpc: "2.0"
@@ -15112,6 +15125,21 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
15112
15125
  try {
15113
15126
  server = await createServer(req);
15114
15127
  } catch (error) {
15128
+ const errorMessage = error instanceof Error ? error.message : String(error);
15129
+ if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
15130
+ res.setHeader("Content-Type", "application/json");
15131
+ const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
15132
+ if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
15133
+ res.writeHead(401).end(JSON.stringify({
15134
+ error: {
15135
+ code: -32e3,
15136
+ message: errorMessage
15137
+ },
15138
+ id: body?.id ?? null,
15139
+ jsonrpc: "2.0"
15140
+ }));
15141
+ return true;
15142
+ }
15115
15143
  if (handleResponseError(error, res)) return true;
15116
15144
  res.writeHead(500).end("Error creating server");
15117
15145
  return true;
@@ -15130,6 +15158,21 @@ const handleStreamRequest = async ({ activeTransports, authenticate, createServe
15130
15158
  try {
15131
15159
  server = await createServer(req);
15132
15160
  } catch (error) {
15161
+ const errorMessage = error instanceof Error ? error.message : String(error);
15162
+ if (errorMessage.includes("Authentication") || errorMessage.includes("Invalid JWT") || errorMessage.includes("Token") || errorMessage.includes("Unauthorized")) {
15163
+ res.setHeader("Content-Type", "application/json");
15164
+ const wwwAuthHeader = getWWWAuthenticateHeader(oauth);
15165
+ if (wwwAuthHeader) res.setHeader("WWW-Authenticate", wwwAuthHeader);
15166
+ res.writeHead(401).end(JSON.stringify({
15167
+ error: {
15168
+ code: -32e3,
15169
+ message: errorMessage
15170
+ },
15171
+ id: body?.id ?? null,
15172
+ jsonrpc: "2.0"
15173
+ }));
15174
+ return true;
15175
+ }
15133
15176
  if (handleResponseError(error, res)) return true;
15134
15177
  res.writeHead(500).end("Error creating server");
15135
15178
  return true;
@@ -15246,10 +15289,13 @@ const handleSSERequest = async ({ activeTransports, createServer, endpoint, onCl
15246
15289
  }
15247
15290
  return false;
15248
15291
  };
15249
- const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonResponse, eventStore, host = "::", onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
15292
+ const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonResponse, eventStore, host = "::", oauth, onClose, onConnect, onUnhandledRequest, port, sseEndpoint = "/sse", stateless, streamEndpoint = "/mcp" }) => {
15250
15293
  const activeSSETransports = {};
15251
15294
  const activeStreamTransports = {};
15252
- const authMiddleware = new AuthenticationMiddleware({ apiKey });
15295
+ const authMiddleware = new AuthenticationMiddleware({
15296
+ apiKey,
15297
+ oauth
15298
+ });
15253
15299
  /**
15254
15300
  * @author https://dev.classmethod.jp/articles/mcp-sse/
15255
15301
  */
@@ -15295,6 +15341,7 @@ const startHTTPServer = async ({ apiKey, authenticate, createServer, enableJsonR
15295
15341
  enableJsonResponse,
15296
15342
  endpoint: streamEndpoint,
15297
15343
  eventStore,
15344
+ oauth,
15298
15345
  onClose,
15299
15346
  onConnect,
15300
15347
  req,
@@ -21509,5 +21556,5 @@ function serializeMessage(message) {
21509
21556
  }
21510
21557
 
21511
21558
  //#endregion
21512
- export { Client, InMemoryEventStore, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, NEVER, ReadBuffer, Server, ZodIssueCode, __commonJS, __toESM, anyType, arrayType, booleanType, isInitializedNotification, isJSONRPCRequest, isJSONRPCResponse, numberType, objectType, proxyServer, serializeMessage, startHTTPServer, stringType };
21513
- //# sourceMappingURL=stdio-so1-I7Pn.js.map
21559
+ 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 };
21560
+ //# sourceMappingURL=stdio-CsjPjeWC.js.map