mcp-proxy 5.7.0 → 5.8.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.
@@ -93,6 +93,7 @@ const cleanupServer = async <T extends ServerLike>(
93
93
 
94
94
  const handleStreamRequest = async <T extends ServerLike>({
95
95
  activeTransports,
96
+ authenticate,
96
97
  createServer,
97
98
  enableJsonResponse,
98
99
  endpoint,
@@ -107,6 +108,7 @@ const handleStreamRequest = async <T extends ServerLike>({
107
108
  string,
108
109
  { server: T; transport: StreamableHTTPServerTransport }
109
110
  >;
111
+ authenticate?: (request: http.IncomingMessage) => Promise<unknown>;
110
112
  createServer: (request: http.IncomingMessage) => Promise<T>;
111
113
  enableJsonResponse?: boolean;
112
114
  endpoint: string;
@@ -132,6 +134,51 @@ const handleStreamRequest = async <T extends ServerLike>({
132
134
 
133
135
  const body = await getBody(req);
134
136
 
137
+ // Per-request authentication in stateless mode
138
+ if (stateless && authenticate) {
139
+ try {
140
+ const authResult = await authenticate(req);
141
+
142
+ // Check for both falsy AND { authenticated: false } pattern
143
+ if (!authResult || (typeof authResult === 'object' && 'authenticated' in authResult && !authResult.authenticated)) {
144
+ // Extract error message if available
145
+ const errorMessage =
146
+ authResult && typeof authResult === 'object' && 'error' in authResult && typeof authResult.error === 'string'
147
+ ? authResult.error
148
+ : "Unauthorized: Authentication failed";
149
+
150
+ res.setHeader("Content-Type", "application/json");
151
+ res.writeHead(401).end(
152
+ JSON.stringify({
153
+ error: {
154
+ code: -32000,
155
+ message: errorMessage
156
+ },
157
+ id: (body as { id?: unknown })?.id ?? null,
158
+ jsonrpc: "2.0"
159
+ })
160
+ );
161
+ return true;
162
+ }
163
+ } catch (error) {
164
+ // Extract error details from thrown errors
165
+ const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
166
+ console.error("Authentication error:", error);
167
+ res.setHeader("Content-Type", "application/json");
168
+ res.writeHead(401).end(
169
+ JSON.stringify({
170
+ error: {
171
+ code: -32000,
172
+ message: errorMessage
173
+ },
174
+ id: (body as { id?: unknown })?.id ?? null,
175
+ jsonrpc: "2.0"
176
+ })
177
+ );
178
+ return true;
179
+ }
180
+ }
181
+
135
182
  if (sessionId) {
136
183
  const activeTransport = activeTransports[sessionId];
137
184
  if (!activeTransport) {
@@ -186,6 +233,26 @@ const handleStreamRequest = async <T extends ServerLike>({
186
233
  try {
187
234
  server = await createServer(req);
188
235
  } catch (error) {
236
+ // Detect authentication errors and return HTTP 401
237
+ const errorMessage = error instanceof Error ? error.message : String(error);
238
+ const isAuthError = errorMessage.includes('Authentication') ||
239
+ errorMessage.includes('Invalid JWT') ||
240
+ errorMessage.includes('Token') ||
241
+ errorMessage.includes('Unauthorized');
242
+
243
+ if (isAuthError) {
244
+ res.setHeader("Content-Type", "application/json");
245
+ res.writeHead(401).end(JSON.stringify({
246
+ error: {
247
+ code: -32000,
248
+ message: errorMessage
249
+ },
250
+ id: (body as { id?: unknown })?.id ?? null,
251
+ jsonrpc: "2.0"
252
+ }));
253
+ return true;
254
+ }
255
+
189
256
  if (handleResponseError(error, res)) {
190
257
  return true;
191
258
  }
@@ -218,6 +285,26 @@ const handleStreamRequest = async <T extends ServerLike>({
218
285
  try {
219
286
  server = await createServer(req);
220
287
  } catch (error) {
288
+ // Detect authentication errors and return HTTP 401
289
+ const errorMessage = error instanceof Error ? error.message : String(error);
290
+ const isAuthError = errorMessage.includes('Authentication') ||
291
+ errorMessage.includes('Invalid JWT') ||
292
+ errorMessage.includes('Token') ||
293
+ errorMessage.includes('Unauthorized');
294
+
295
+ if (isAuthError) {
296
+ res.setHeader("Content-Type", "application/json");
297
+ res.writeHead(401).end(JSON.stringify({
298
+ error: {
299
+ code: -32000,
300
+ message: errorMessage
301
+ },
302
+ id: (body as { id?: unknown })?.id ?? null,
303
+ jsonrpc: "2.0"
304
+ }));
305
+ return true;
306
+ }
307
+
221
308
  if (handleResponseError(error, res)) {
222
309
  return true;
223
310
  }
@@ -457,6 +544,7 @@ const handleSSERequest = async <T extends ServerLike>({
457
544
 
458
545
  export const startHTTPServer = async <T extends ServerLike>({
459
546
  apiKey,
547
+ authenticate,
460
548
  createServer,
461
549
  enableJsonResponse,
462
550
  eventStore,
@@ -470,6 +558,7 @@ export const startHTTPServer = async <T extends ServerLike>({
470
558
  streamEndpoint = "/mcp",
471
559
  }: {
472
560
  apiKey?: string;
561
+ authenticate?: (request: http.IncomingMessage) => Promise<unknown>;
473
562
  createServer: (request: http.IncomingMessage) => Promise<T>;
474
563
  enableJsonResponse?: boolean;
475
564
  eventStore?: EventStore;
@@ -508,8 +597,8 @@ export const startHTTPServer = async <T extends ServerLike>({
508
597
  res.setHeader("Access-Control-Allow-Origin", origin.origin);
509
598
  res.setHeader("Access-Control-Allow-Credentials", "true");
510
599
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
511
- res.setHeader("Access-Control-Allow-Headers", "*");
512
- res.setHeader("Access-Control-Expose-Headers", "mcp-session-id");
600
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id");
601
+ res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id");
513
602
  } catch (error) {
514
603
  console.error("[mcp-proxy] error parsing origin", error);
515
604
  }
@@ -553,6 +642,7 @@ export const startHTTPServer = async <T extends ServerLike>({
553
642
  streamEndpoint &&
554
643
  (await handleStreamRequest({
555
644
  activeTransports: activeStreamTransports,
645
+ authenticate,
556
646
  createServer,
557
647
  enableJsonResponse,
558
648
  endpoint: streamEndpoint,