mcp-proxy 5.12.0 → 5.12.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.
@@ -28,33 +28,47 @@ interface TestEnvironment {
28
28
  streamClient: Client;
29
29
  }
30
30
 
31
- async function createTestEnvironment(config: TestConfig = {}): Promise<TestEnvironment> {
32
- const {
33
- requestTimeout,
34
- serverDelay,
35
- serverFixture = "simple-stdio-server.ts"
31
+ async function createTestEnvironment(
32
+ config: TestConfig = {},
33
+ ): Promise<TestEnvironment> {
34
+ const {
35
+ requestTimeout,
36
+ serverDelay,
37
+ serverFixture = "simple-stdio-server.ts",
36
38
  } = config;
37
-
39
+
38
40
  const stdioTransport = new StdioClientTransport({
39
41
  args: [`src/fixtures/${serverFixture}`],
40
42
  command: "tsx",
41
- env: serverDelay ? { ...process.env, RESPONSE_DELAY: serverDelay } as Record<string, string> : process.env as Record<string, string>,
43
+ env: serverDelay
44
+ ? ({ ...process.env, RESPONSE_DELAY: serverDelay } as Record<
45
+ string,
46
+ string
47
+ >)
48
+ : (process.env as Record<string, string>),
42
49
  });
43
50
 
44
51
  const stdioClient = new Client(
45
52
  { name: "mcp-proxy-test", version: "1.0.0" },
46
- { capabilities: {} }
53
+ { capabilities: {} },
47
54
  );
48
55
 
49
56
  await stdioClient.connect(stdioTransport);
50
57
 
51
- const serverVersion = stdioClient.getServerVersion() as { name: string; version: string };
52
- const serverCapabilities = stdioClient.getServerCapabilities() as { capabilities: Record<string, unknown> };
58
+ const serverVersion = stdioClient.getServerVersion() as {
59
+ name: string;
60
+ version: string;
61
+ };
62
+ const serverCapabilities = stdioClient.getServerCapabilities() as {
63
+ capabilities: Record<string, unknown>;
64
+ };
53
65
  const port = await getRandomPort();
54
66
 
55
67
  const httpServer = await startHTTPServer({
56
68
  createServer: async () => {
57
- const mcpServer = new Server(serverVersion, { capabilities: serverCapabilities });
69
+ const mcpServer = new Server(serverVersion, {
70
+ capabilities: serverCapabilities,
71
+ });
58
72
  await proxyServer({
59
73
  client: stdioClient,
60
74
  requestTimeout,
@@ -68,20 +82,22 @@ async function createTestEnvironment(config: TestConfig = {}): Promise<TestEnvir
68
82
 
69
83
  const streamClient = new Client(
70
84
  { name: "stream-client", version: "1.0.0" },
71
- { capabilities: {} }
85
+ { capabilities: {} },
72
86
  );
73
87
 
74
- const transport = new StreamableHTTPClientTransport(new URL(`http://localhost:${port}/mcp`));
88
+ const transport = new StreamableHTTPClientTransport(
89
+ new URL(`http://localhost:${port}/mcp`),
90
+ );
75
91
  await streamClient.connect(transport);
76
92
 
77
- return {
93
+ return {
78
94
  cleanup: async () => {
79
95
  await streamClient.close();
80
96
  await stdioClient.close();
81
- },
82
- httpServer,
83
- stdioClient,
84
- streamClient
97
+ },
98
+ httpServer,
99
+ stdioClient,
100
+ streamClient,
85
101
  };
86
102
  }
87
103
 
@@ -90,7 +106,7 @@ describe("proxyServer timeout functionality", () => {
90
106
  const { cleanup, streamClient } = await createTestEnvironment({
91
107
  requestTimeout: 1000,
92
108
  serverDelay: "500",
93
- serverFixture: "slow-stdio-server.ts"
109
+ serverFixture: "slow-stdio-server.ts",
94
110
  });
95
111
 
96
112
  // This should succeed as timeout (1s) > delay (500ms)
@@ -105,7 +121,7 @@ describe("proxyServer timeout functionality", () => {
105
121
  const { cleanup, streamClient } = await createTestEnvironment({
106
122
  requestTimeout: 500,
107
123
  serverDelay: "1000",
108
- serverFixture: "slow-stdio-server.ts"
124
+ serverFixture: "slow-stdio-server.ts",
109
125
  });
110
126
 
111
127
  // This should throw a timeout error as delay (1s) > timeout (500ms)
@@ -128,7 +144,7 @@ describe("proxyServer timeout functionality", () => {
128
144
  const { cleanup, streamClient } = await createTestEnvironment({
129
145
  requestTimeout: 600,
130
146
  serverDelay: "300",
131
- serverFixture: "slow-stdio-server.ts"
147
+ serverFixture: "slow-stdio-server.ts",
132
148
  });
133
149
 
134
150
  // First get the resources
@@ -141,7 +157,9 @@ describe("proxyServer timeout functionality", () => {
141
157
  });
142
158
 
143
159
  expect(resourceContent.contents).toBeDefined();
144
- expect(resourceContent.contents[0].text).toContain("300ms delay");
160
+ expect((resourceContent.contents[0] as { text: string }).text).toContain(
161
+ "300ms delay",
162
+ );
145
163
 
146
164
  await cleanup();
147
165
  }, 10000);
@@ -1339,8 +1339,8 @@ it("returns 401 with custom error message when { authenticated: false, error: '.
1339
1339
  },
1340
1340
  }),
1341
1341
  headers: {
1342
- "Accept": "application/json, text/event-stream",
1343
- "Authorization": "Bearer expired-token",
1342
+ Accept: "application/json, text/event-stream",
1343
+ Authorization: "Bearer expired-token",
1344
1344
  "Content-Type": "application/json",
1345
1345
  },
1346
1346
  method: "POST",
@@ -1408,8 +1408,8 @@ it("returns 401 when createServer throws authentication error", async () => {
1408
1408
  },
1409
1409
  }),
1410
1410
  headers: {
1411
- "Accept": "application/json, text/event-stream",
1412
- "Authorization": "Bearer test-token",
1411
+ Accept: "application/json, text/event-stream",
1412
+ Authorization: "Bearer test-token",
1413
1413
  "Content-Type": "application/json",
1414
1414
  },
1415
1415
  method: "POST",
@@ -1451,7 +1451,7 @@ it("returns 401 when createServer throws JWT-related error", async () => {
1451
1451
  },
1452
1452
  }),
1453
1453
  headers: {
1454
- "Accept": "application/json, text/event-stream",
1454
+ Accept: "application/json, text/event-stream",
1455
1455
  "Content-Type": "application/json",
1456
1456
  },
1457
1457
  method: "POST",
@@ -1492,7 +1492,7 @@ it("returns 401 when createServer throws Token-related error", async () => {
1492
1492
  },
1493
1493
  }),
1494
1494
  headers: {
1495
- "Accept": "application/json, text/event-stream",
1495
+ Accept: "application/json, text/event-stream",
1496
1496
  "Content-Type": "application/json",
1497
1497
  },
1498
1498
  method: "POST",
@@ -1533,7 +1533,7 @@ it("returns 401 when createServer throws Unauthorized error", async () => {
1533
1533
  },
1534
1534
  }),
1535
1535
  headers: {
1536
- "Accept": "application/json, text/event-stream",
1536
+ Accept: "application/json, text/event-stream",
1537
1537
  "Content-Type": "application/json",
1538
1538
  },
1539
1539
  method: "POST",
@@ -1574,7 +1574,7 @@ it("returns 500 when createServer throws non-auth error", async () => {
1574
1574
  },
1575
1575
  }),
1576
1576
  headers: {
1577
- "Accept": "application/json, text/event-stream",
1577
+ Accept: "application/json, text/event-stream",
1578
1578
  "Content-Type": "application/json",
1579
1579
  },
1580
1580
  method: "POST",
@@ -1614,7 +1614,7 @@ it("includes WWW-Authenticate header in 401 response with OAuth config", async (
1614
1614
  },
1615
1615
  }),
1616
1616
  headers: {
1617
- "Accept": "application/json, text/event-stream",
1617
+ Accept: "application/json, text/event-stream",
1618
1618
  "Content-Type": "application/json",
1619
1619
  },
1620
1620
  method: "POST",
@@ -1624,9 +1624,11 @@ it("includes WWW-Authenticate header in 401 response with OAuth config", async (
1624
1624
 
1625
1625
  const wwwAuthHeader = response.headers.get("WWW-Authenticate");
1626
1626
  expect(wwwAuthHeader).toBeTruthy();
1627
- expect(wwwAuthHeader).toContain('Bearer');
1627
+ expect(wwwAuthHeader).toContain("Bearer");
1628
1628
  expect(wwwAuthHeader).toContain('realm="mcp-server"');
1629
- expect(wwwAuthHeader).toContain('resource_metadata="https://example.com/.well-known/oauth-protected-resource"');
1629
+ expect(wwwAuthHeader).toContain(
1630
+ 'resource_metadata="https://example.com/.well-known/oauth-protected-resource"',
1631
+ );
1630
1632
  expect(wwwAuthHeader).toContain('error="invalid_token"');
1631
1633
  expect(wwwAuthHeader).toContain('error_description="Invalid JWT token"');
1632
1634
 
@@ -1636,7 +1638,9 @@ it("includes WWW-Authenticate header in 401 response with OAuth config", async (
1636
1638
  it("includes WWW-Authenticate header when authenticate callback fails with OAuth", async () => {
1637
1639
  const port = await getRandomPort();
1638
1640
 
1639
- const authenticate = vi.fn().mockRejectedValue(new Error("Token signature verification failed"));
1641
+ const authenticate = vi
1642
+ .fn()
1643
+ .mockRejectedValue(new Error("Token signature verification failed"));
1640
1644
 
1641
1645
  const httpServer = await startHTTPServer({
1642
1646
  authenticate,
@@ -1670,8 +1674,8 @@ it("includes WWW-Authenticate header when authenticate callback fails with OAuth
1670
1674
  },
1671
1675
  }),
1672
1676
  headers: {
1673
- "Accept": "application/json, text/event-stream",
1674
- "Authorization": "Bearer expired-token",
1677
+ Accept: "application/json, text/event-stream",
1678
+ Authorization: "Bearer expired-token",
1675
1679
  "Content-Type": "application/json",
1676
1680
  },
1677
1681
  method: "POST",
@@ -1682,12 +1686,18 @@ it("includes WWW-Authenticate header when authenticate callback fails with OAuth
1682
1686
 
1683
1687
  const wwwAuthHeader = response.headers.get("WWW-Authenticate");
1684
1688
  expect(wwwAuthHeader).toBeTruthy();
1685
- expect(wwwAuthHeader).toContain('Bearer');
1689
+ expect(wwwAuthHeader).toContain("Bearer");
1686
1690
  expect(wwwAuthHeader).toContain('realm="example-api"');
1687
- expect(wwwAuthHeader).toContain('resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"');
1691
+ expect(wwwAuthHeader).toContain(
1692
+ 'resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"',
1693
+ );
1688
1694
  expect(wwwAuthHeader).toContain('error="invalid_token"');
1689
- expect(wwwAuthHeader).toContain('error_description="Token signature verification failed"');
1690
- expect(wwwAuthHeader).toContain('error_uri="https://example.com/docs/errors"');
1695
+ expect(wwwAuthHeader).toContain(
1696
+ 'error_description="Token signature verification failed"',
1697
+ );
1698
+ expect(wwwAuthHeader).toContain(
1699
+ 'error_uri="https://example.com/docs/errors"',
1700
+ );
1691
1701
 
1692
1702
  await httpServer.close();
1693
1703
  });
@@ -1715,7 +1725,7 @@ it("does not include WWW-Authenticate header in 401 response without OAuth confi
1715
1725
  },
1716
1726
  }),
1717
1727
  headers: {
1718
- "Accept": "application/json, text/event-stream",
1728
+ Accept: "application/json, text/event-stream",
1719
1729
  "Content-Type": "application/json",
1720
1730
  },
1721
1731
  method: "POST",
@@ -1916,7 +1926,9 @@ it("supports origin validation with array", async () => {
1916
1926
  });
1917
1927
 
1918
1928
  expect(response1.status).toBe(204);
1919
- expect(response1.headers.get("Access-Control-Allow-Origin")).toBe("https://app.example.com");
1929
+ expect(response1.headers.get("Access-Control-Allow-Origin")).toBe(
1930
+ "https://app.example.com",
1931
+ );
1920
1932
 
1921
1933
  // Test with disallowed origin
1922
1934
  const response2 = await fetch(`http://localhost:${port}/mcp`, {
@@ -1958,7 +1970,9 @@ it("supports origin validation with function", async () => {
1958
1970
  });
1959
1971
 
1960
1972
  expect(response1.status).toBe(204);
1961
- expect(response1.headers.get("Access-Control-Allow-Origin")).toBe("https://subdomain.example.com");
1973
+ expect(response1.headers.get("Access-Control-Allow-Origin")).toBe(
1974
+ "https://subdomain.example.com",
1975
+ );
1962
1976
 
1963
1977
  // Test with disallowed origin
1964
1978
  const response2 = await fetch(`http://localhost:${port}/mcp`, {
@@ -2029,7 +2043,9 @@ it("uses default CORS settings when cors: true", async () => {
2029
2043
 
2030
2044
  expect(response.status).toBe(204);
2031
2045
  expect(response.headers.get("Access-Control-Allow-Origin")).toBe("*");
2032
- expect(response.headers.get("Access-Control-Allow-Headers")).toBe("Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id");
2046
+ expect(response.headers.get("Access-Control-Allow-Headers")).toBe(
2047
+ "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id",
2048
+ );
2033
2049
  expect(response.headers.get("Access-Control-Allow-Credentials")).toBe("true");
2034
2050
 
2035
2051
  await httpServer.close();
@@ -2062,7 +2078,9 @@ it("supports custom methods and maxAge", async () => {
2062
2078
  });
2063
2079
 
2064
2080
  expect(response.status).toBe(204);
2065
- expect(response.headers.get("Access-Control-Allow-Methods")).toBe("GET, POST, PUT, DELETE");
2081
+ expect(response.headers.get("Access-Control-Allow-Methods")).toBe(
2082
+ "GET, POST, PUT, DELETE",
2083
+ );
2066
2084
  expect(response.headers.get("Access-Control-Max-Age")).toBe("86400");
2067
2085
 
2068
2086
  await httpServer.close();
@@ -81,7 +81,9 @@ const getWWWAuthenticateHeader = (
81
81
 
82
82
  // Add resource_metadata if configured
83
83
  if (oauth.protectedResource?.resource) {
84
- params.push(`resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`);
84
+ params.push(
85
+ `resource_metadata="${oauth.protectedResource.resource}/.well-known/oauth-protected-resource"`,
86
+ );
85
87
  }
86
88
 
87
89
  // Add error from options or config (options takes precedence)
@@ -91,7 +93,8 @@ const getWWWAuthenticateHeader = (
91
93
  }
92
94
 
93
95
  // Add error_description from options or config (options takes precedence)
94
- const error_description = options?.error_description || oauth.error_description;
96
+ const error_description =
97
+ options?.error_description || oauth.error_description;
95
98
  if (error_description) {
96
99
  // Escape quotes in error description
97
100
  const escaped = error_description.replace(/"/g, '\\"');
@@ -119,7 +122,9 @@ const getWWWAuthenticateHeader = (
119
122
  };
120
123
 
121
124
  // Helper function to detect scope challenge errors
122
- const isScopeChallengeError = (error: unknown): error is {
125
+ const isScopeChallengeError = (
126
+ error: unknown,
127
+ ): error is {
123
128
  data: {
124
129
  error: string;
125
130
  errorDescription?: string;
@@ -147,11 +152,12 @@ const handleResponseError = async (
147
152
  ): Promise<boolean> => {
148
153
  // Check if it's a Response-like object (duck typing)
149
154
  // The instanceof check may fail due to different Response implementations across module boundaries
150
- const isResponseLike = error &&
151
- typeof error === 'object' &&
152
- 'status' in error &&
153
- 'headers' in error &&
154
- 'statusText' in error;
155
+ const isResponseLike =
156
+ error &&
157
+ typeof error === "object" &&
158
+ "status" in error &&
159
+ "headers" in error &&
160
+ "statusText" in error;
155
161
 
156
162
  if (isResponseLike || error instanceof Response) {
157
163
  const responseError = error as Response;
@@ -210,7 +216,8 @@ const applyCorsHeaders = (
210
216
 
211
217
  // Default CORS configuration for backward compatibility
212
218
  const defaultCorsOptions: CorsOptions = {
213
- allowedHeaders: "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id",
219
+ allowedHeaders:
220
+ "Content-Type, Authorization, Accept, Mcp-Session-Id, Last-Event-Id",
214
221
  credentials: true,
215
222
  exposedHeaders: ["Mcp-Session-Id"],
216
223
  methods: ["GET", "POST", "OPTIONS"],
@@ -246,7 +253,9 @@ const applyCorsHeaders = (
246
253
  ? origin.origin
247
254
  : "false";
248
255
  } else if (typeof finalCorsOptions.origin === "function") {
249
- allowedOrigin = finalCorsOptions.origin(origin.origin) ? origin.origin : "false";
256
+ allowedOrigin = finalCorsOptions.origin(origin.origin)
257
+ ? origin.origin
258
+ : "false";
250
259
  }
251
260
  }
252
261
 
@@ -256,30 +265,43 @@ const applyCorsHeaders = (
256
265
 
257
266
  // Handle credentials
258
267
  if (finalCorsOptions.credentials !== undefined) {
259
- res.setHeader("Access-Control-Allow-Credentials", finalCorsOptions.credentials.toString());
268
+ res.setHeader(
269
+ "Access-Control-Allow-Credentials",
270
+ finalCorsOptions.credentials.toString(),
271
+ );
260
272
  }
261
273
 
262
274
  // Handle methods
263
275
  if (finalCorsOptions.methods) {
264
- res.setHeader("Access-Control-Allow-Methods", finalCorsOptions.methods.join(", "));
276
+ res.setHeader(
277
+ "Access-Control-Allow-Methods",
278
+ finalCorsOptions.methods.join(", "),
279
+ );
265
280
  }
266
281
 
267
282
  // Handle allowed headers
268
283
  if (finalCorsOptions.allowedHeaders) {
269
- const allowedHeaders = typeof finalCorsOptions.allowedHeaders === "string"
270
- ? finalCorsOptions.allowedHeaders
271
- : finalCorsOptions.allowedHeaders.join(", ");
284
+ const allowedHeaders =
285
+ typeof finalCorsOptions.allowedHeaders === "string"
286
+ ? finalCorsOptions.allowedHeaders
287
+ : finalCorsOptions.allowedHeaders.join(", ");
272
288
  res.setHeader("Access-Control-Allow-Headers", allowedHeaders);
273
289
  }
274
290
 
275
291
  // Handle exposed headers
276
292
  if (finalCorsOptions.exposedHeaders) {
277
- res.setHeader("Access-Control-Expose-Headers", finalCorsOptions.exposedHeaders.join(", "));
293
+ res.setHeader(
294
+ "Access-Control-Expose-Headers",
295
+ finalCorsOptions.exposedHeaders.join(", "),
296
+ );
278
297
  }
279
298
 
280
299
  // Handle max age
281
300
  if (finalCorsOptions.maxAge !== undefined) {
282
- res.setHeader("Access-Control-Max-Age", finalCorsOptions.maxAge.toString());
301
+ res.setHeader(
302
+ "Access-Control-Max-Age",
303
+ finalCorsOptions.maxAge.toString(),
304
+ );
283
305
  }
284
306
  } catch (error) {
285
307
  console.error("[mcp-proxy] error parsing origin", error);
@@ -340,10 +362,18 @@ const handleStreamRequest = async <T extends ServerLike>({
340
362
  const authResult = await authenticate(req);
341
363
 
342
364
  // Check for both falsy AND { authenticated: false } pattern
343
- if (!authResult || (typeof authResult === 'object' && 'authenticated' in authResult && !authResult.authenticated)) {
365
+ if (
366
+ !authResult ||
367
+ (typeof authResult === "object" &&
368
+ "authenticated" in authResult &&
369
+ !authResult.authenticated)
370
+ ) {
344
371
  // Extract error message if available
345
372
  const errorMessage =
346
- authResult && typeof authResult === 'object' && 'error' in authResult && typeof authResult.error === 'string'
373
+ authResult &&
374
+ typeof authResult === "object" &&
375
+ "error" in authResult &&
376
+ typeof authResult.error === "string"
347
377
  ? authResult.error
348
378
  : "Unauthorized: Authentication failed";
349
379
 
@@ -362,11 +392,11 @@ const handleStreamRequest = async <T extends ServerLike>({
362
392
  JSON.stringify({
363
393
  error: {
364
394
  code: -32000,
365
- message: errorMessage
395
+ message: errorMessage,
366
396
  },
367
397
  id: (body as { id?: unknown })?.id ?? null,
368
- jsonrpc: "2.0"
369
- })
398
+ jsonrpc: "2.0",
399
+ }),
370
400
  );
371
401
  return true;
372
402
  }
@@ -377,7 +407,10 @@ const handleStreamRequest = async <T extends ServerLike>({
377
407
  }
378
408
 
379
409
  // Extract error details from thrown errors
380
- const errorMessage = error instanceof Error ? error.message : "Unauthorized: Authentication error";
410
+ const errorMessage =
411
+ error instanceof Error
412
+ ? error.message
413
+ : "Unauthorized: Authentication error";
381
414
  console.error("Authentication error:", error);
382
415
  res.setHeader("Content-Type", "application/json");
383
416
 
@@ -394,11 +427,11 @@ const handleStreamRequest = async <T extends ServerLike>({
394
427
  JSON.stringify({
395
428
  error: {
396
429
  code: -32000,
397
- message: errorMessage
430
+ message: errorMessage,
398
431
  },
399
432
  id: (body as { id?: unknown })?.id ?? null,
400
- jsonrpc: "2.0"
401
- })
433
+ jsonrpc: "2.0",
434
+ }),
402
435
  );
403
436
  return true;
404
437
  }
@@ -464,11 +497,13 @@ const handleStreamRequest = async <T extends ServerLike>({
464
497
  }
465
498
 
466
499
  // Detect authentication errors and return HTTP 401
467
- const errorMessage = error instanceof Error ? error.message : String(error);
468
- const isAuthError = errorMessage.includes('Authentication') ||
469
- errorMessage.includes('Invalid JWT') ||
470
- errorMessage.includes('Token') ||
471
- errorMessage.includes('Unauthorized');
500
+ const errorMessage =
501
+ error instanceof Error ? error.message : String(error);
502
+ const isAuthError =
503
+ errorMessage.includes("Authentication") ||
504
+ errorMessage.includes("Invalid JWT") ||
505
+ errorMessage.includes("Token") ||
506
+ errorMessage.includes("Unauthorized");
472
507
 
473
508
  if (isAuthError) {
474
509
  res.setHeader("Content-Type", "application/json");
@@ -482,14 +517,16 @@ const handleStreamRequest = async <T extends ServerLike>({
482
517
  res.setHeader("WWW-Authenticate", wwwAuthHeader);
483
518
  }
484
519
 
485
- res.writeHead(401).end(JSON.stringify({
486
- error: {
487
- code: -32000,
488
- message: errorMessage
489
- },
490
- id: (body as { id?: unknown })?.id ?? null,
491
- jsonrpc: "2.0"
492
- }));
520
+ res.writeHead(401).end(
521
+ JSON.stringify({
522
+ error: {
523
+ code: -32000,
524
+ message: errorMessage,
525
+ },
526
+ id: (body as { id?: unknown })?.id ?? null,
527
+ jsonrpc: "2.0",
528
+ }),
529
+ );
493
530
  return true;
494
531
  }
495
532
 
@@ -527,11 +564,13 @@ const handleStreamRequest = async <T extends ServerLike>({
527
564
  }
528
565
 
529
566
  // Detect authentication errors and return HTTP 401
530
- const errorMessage = error instanceof Error ? error.message : String(error);
531
- const isAuthError = errorMessage.includes('Authentication') ||
532
- errorMessage.includes('Invalid JWT') ||
533
- errorMessage.includes('Token') ||
534
- errorMessage.includes('Unauthorized');
567
+ const errorMessage =
568
+ error instanceof Error ? error.message : String(error);
569
+ const isAuthError =
570
+ errorMessage.includes("Authentication") ||
571
+ errorMessage.includes("Invalid JWT") ||
572
+ errorMessage.includes("Token") ||
573
+ errorMessage.includes("Unauthorized");
535
574
 
536
575
  if (isAuthError) {
537
576
  res.setHeader("Content-Type", "application/json");
@@ -545,14 +584,16 @@ const handleStreamRequest = async <T extends ServerLike>({
545
584
  res.setHeader("WWW-Authenticate", wwwAuthHeader);
546
585
  }
547
586
 
548
- res.writeHead(401).end(JSON.stringify({
549
- error: {
550
- code: -32000,
551
- message: errorMessage
552
- },
553
- id: (body as { id?: unknown })?.id ?? null,
554
- jsonrpc: "2.0"
555
- }));
587
+ res.writeHead(401).end(
588
+ JSON.stringify({
589
+ error: {
590
+ code: -32000,
591
+ message: errorMessage,
592
+ },
593
+ id: (body as { id?: unknown })?.id ?? null,
594
+ jsonrpc: "2.0",
595
+ }),
596
+ );
556
597
  return true;
557
598
  }
558
599
 
@@ -19,9 +19,8 @@ describe("startStdioServer.test.ts", () => {
19
19
  let proc: ChildProcess;
20
20
 
21
21
  beforeEach(async () => {
22
- const serverPath = require.resolve(
23
- "@modelcontextprotocol/sdk/examples/server/sseAndStreamableHttpCompatibleServer.js",
24
- );
22
+ const serverPath =
23
+ require.resolve("@modelcontextprotocol/sdk/examples/server/sseAndStreamableHttpCompatibleServer.js");
25
24
  proc = fork(serverPath, [], {
26
25
  stdio: "pipe",
27
26
  });
@@ -83,9 +82,11 @@ describe("startStdioServer.test.ts", () => {
83
82
  {
84
83
  description:
85
84
  "Starts sending periodic notifications for testing resumability",
85
+ execution: {
86
+ taskSupport: "forbidden",
87
+ },
86
88
  inputSchema: {
87
89
  $schema: "http://json-schema.org/draft-07/schema#",
88
- additionalProperties: false,
89
90
  properties: {
90
91
  count: {
91
92
  default: 50,
@@ -177,9 +178,11 @@ describe("startStdioServer.test.ts", () => {
177
178
  {
178
179
  description:
179
180
  "Starts sending periodic notifications for testing resumability",
181
+ execution: {
182
+ taskSupport: "forbidden",
183
+ },
180
184
  inputSchema: {
181
185
  $schema: "http://json-schema.org/draft-07/schema#",
182
- additionalProperties: false,
183
186
  properties: {
184
187
  count: {
185
188
  default: 50,