toolcraft 0.0.112 → 0.0.113

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,21 +1,15 @@
1
1
  import http from "node:http";
2
2
  import { afterEach, describe, expect, it } from "vitest";
3
- import {
4
- OAuthError,
5
- type OAuthSessionStore,
6
- type StoredOAuthSession,
7
- } from "mcp-oauth";
8
- import { nodeFetch } from "tiny-http-mcp-server/testing";
3
+ import { OAuthError, type OAuthSessionStore, type StoredOAuthSession } from "mcp-oauth";
4
+ import { installInMemoryHttp, nodeFetch } from "tiny-http-mcp-server/test-support";
9
5
  import {
10
6
  createMcpOAuthTestServer,
11
7
  type McpOAuthTestServerHandle,
12
- type McpOAuthTestServerOptions,
8
+ type McpOAuthTestServerOptions
13
9
  } from "tiny-http-mcp-oauth-test-server";
14
- import {
15
- HttpTransport,
16
- McpClient,
17
- resolveAuthorizationServerMetadataUrl,
18
- } from "./internal.js";
10
+ import { HttpTransport, McpClient, resolveAuthorizationServerMetadataUrl } from "./internal.js";
11
+
12
+ installInMemoryHttp();
19
13
 
20
14
  interface RequestRecord {
21
15
  url: string;
@@ -72,8 +66,8 @@ function createSessionStore(): SessionStoreWithMap {
72
66
  },
73
67
  async clear(resource: string): Promise<void> {
74
68
  sessions.delete(resource);
75
- },
76
- },
69
+ }
70
+ }
77
71
  };
78
72
  }
79
73
 
@@ -82,7 +76,7 @@ function cloneResponse(response: Response, body: string): Response {
82
76
  return new Response(body, {
83
77
  status: response.status,
84
78
  statusText: response.statusText,
85
- headers,
79
+ headers
86
80
  });
87
81
  }
88
82
 
@@ -91,7 +85,9 @@ interface BoundLoopbackServerFactory {
91
85
  port: number;
92
86
  }
93
87
 
94
- async function createBoundLoopbackServerFactory(hostname: string): Promise<BoundLoopbackServerFactory> {
88
+ async function createBoundLoopbackServerFactory(
89
+ hostname: string
90
+ ): Promise<BoundLoopbackServerFactory> {
95
91
  const server = http.createServer();
96
92
 
97
93
  await new Promise<void>((resolve, reject) => {
@@ -127,7 +123,7 @@ async function createBoundLoopbackServerFactory(hostname: string): Promise<Bound
127
123
  createServer(): http.Server {
128
124
  return server;
129
125
  },
130
- port: address.port,
126
+ port: address.port
131
127
  };
132
128
  }
133
129
 
@@ -143,10 +139,7 @@ function parseFormBody(record: RequestRecord): URLSearchParams {
143
139
  return new URLSearchParams(record.body ?? "");
144
140
  }
145
141
 
146
- function requireRequest(
147
- request: RequestRecord | undefined,
148
- description: string
149
- ): RequestRecord {
142
+ function requireRequest(request: RequestRecord | undefined, description: string): RequestRecord {
150
143
  if (request === undefined) {
151
144
  throw new Error(`Expected ${description}`);
152
145
  }
@@ -179,17 +172,14 @@ function summarizeTraffic(
179
172
  const tokenUrl = `${handle.oauth.issuer}/token`;
180
173
 
181
174
  return {
182
- prm: requests.filter(
183
- (request) => request.method === "GET" && request.url === handle.prmUrl
184
- ).length,
175
+ prm: requests.filter((request) => request.method === "GET" && request.url === handle.prmUrl)
176
+ .length,
185
177
  asMetadata: requests.filter(
186
178
  (request) =>
187
- request.method === "GET"
188
- && request.url === authorizationServerMetadataUrl.toString()
189
- ).length,
190
- register: requests.filter(
191
- (request) => request.method === "POST" && request.url === registerUrl
179
+ request.method === "GET" && request.url === authorizationServerMetadataUrl.toString()
192
180
  ).length,
181
+ register: requests.filter((request) => request.method === "POST" && request.url === registerUrl)
182
+ .length,
193
183
  authorize: requests.filter(
194
184
  (request) => request.method === "GET" && request.url.startsWith(authorizeUrl)
195
185
  ).length,
@@ -209,7 +199,7 @@ function summarizeTraffic(
209
199
  }).length,
210
200
  mcpPost: requests.filter(
211
201
  (request) => request.method === "POST" && request.url === handle.mcpUrl
212
- ).length,
202
+ ).length
213
203
  };
214
204
  }
215
205
 
@@ -225,8 +215,7 @@ function summarizeAuthorizationServerTraffic(
225
215
  return {
226
216
  metadata: requestLog.filter(
227
217
  (request) =>
228
- request.method === "GET"
229
- && request.url === authorizationServerMetadataUrl.toString()
218
+ request.method === "GET" && request.url === authorizationServerMetadataUrl.toString()
230
219
  ).length,
231
220
  register: requestLog.filter(
232
221
  (request) => request.method === "POST" && request.url === registerUrl
@@ -247,7 +236,7 @@ function summarizeAuthorizationServerTraffic(
247
236
  }
248
237
 
249
238
  return new URLSearchParams(request.body ?? "").get("grant_type") === "refresh_token";
250
- }).length,
239
+ }).length
251
240
  };
252
241
  }
253
242
 
@@ -266,20 +255,20 @@ function getJsonRpcMethod(record: RequestRecord): string | undefined {
266
255
 
267
256
  function getTextContent(result: unknown): string | undefined {
268
257
  if (
269
- typeof result !== "object"
270
- || result === null
271
- || !("content" in result)
272
- || !Array.isArray(result.content)
258
+ typeof result !== "object" ||
259
+ result === null ||
260
+ !("content" in result) ||
261
+ !Array.isArray(result.content)
273
262
  ) {
274
263
  return undefined;
275
264
  }
276
265
 
277
266
  const [firstItem] = result.content;
278
267
  if (
279
- typeof firstItem !== "object"
280
- || firstItem === null
281
- || !("text" in firstItem)
282
- || typeof firstItem.text !== "string"
268
+ typeof firstItem !== "object" ||
269
+ firstItem === null ||
270
+ !("text" in firstItem) ||
271
+ typeof firstItem.text !== "string"
283
272
  ) {
284
273
  return undefined;
285
274
  }
@@ -296,41 +285,43 @@ function getStoredSession(harness: OAuthClientHarness): StoredOAuthSession {
296
285
  return session;
297
286
  }
298
287
 
299
- async function createHarness(options: {
300
- now?: () => number;
301
- oauthClient?:
302
- | {
303
- mode: "dynamic";
304
- metadata?: {
305
- clientName?: string;
306
- scope?: string;
307
- };
308
- }
309
- | {
310
- mode: "static";
311
- clientId: string;
312
- clientSecret?: string;
313
- metadata?: {
314
- clientName?: string;
315
- scope?: string;
288
+ async function createHarness(
289
+ options: {
290
+ now?: () => number;
291
+ oauthClient?:
292
+ | {
293
+ mode: "dynamic";
294
+ metadata?: {
295
+ clientName?: string;
296
+ scope?: string;
297
+ };
298
+ }
299
+ | {
300
+ mode: "static";
301
+ clientId: string;
302
+ clientSecret?: string;
303
+ metadata?: {
304
+ clientName?: string;
305
+ scope?: string;
306
+ };
316
307
  };
317
- };
318
- responseTransform?: (input: {
319
- handle: McpOAuthTestServerHandle;
320
- record: RequestRecord;
321
- response: Response;
322
- }) => Promise<Response | undefined>;
323
- serverOptions?: McpOAuthTestServerOptions;
324
- createServer?: () => http.Server;
325
- } = {}): Promise<OAuthClientHarness> {
308
+ responseTransform?: (input: {
309
+ handle: McpOAuthTestServerHandle;
310
+ record: RequestRecord;
311
+ response: Response;
312
+ }) => Promise<Response | undefined>;
313
+ serverOptions?: McpOAuthTestServerOptions;
314
+ createServer?: () => http.Server;
315
+ } = {}
316
+ ): Promise<OAuthClientHarness> {
326
317
  const server = createMcpOAuthTestServer({
327
318
  autoApprove: true,
328
319
  scopes: ["mcp.read"],
329
- ...(options.serverOptions ?? {}),
320
+ ...(options.serverOptions ?? {})
330
321
  });
331
322
  const handle = await server.listen({
332
323
  port: 0,
333
- hostname: "127.0.0.1",
324
+ hostname: "127.0.0.1"
334
325
  });
335
326
  const requests: RequestRecord[] = [];
336
327
  const sessionStore = createSessionStore();
@@ -341,16 +332,17 @@ async function createHarness(options: {
341
332
  method: init.method ?? "GET",
342
333
  authorization: new Headers(init.headers).get("authorization"),
343
334
  sessionId: new Headers(init.headers).get("mcp-session-id"),
344
- body: typeof init.body === "string" ? init.body : undefined,
335
+ body: typeof init.body === "string" ? init.body : undefined
345
336
  };
346
337
  const response = await nodeFetch(record.url, init);
347
- const transformed = options.responseTransform === undefined
348
- ? undefined
349
- : await options.responseTransform({
350
- handle,
351
- record,
352
- response,
353
- });
338
+ const transformed =
339
+ options.responseTransform === undefined
340
+ ? undefined
341
+ : await options.responseTransform({
342
+ handle,
343
+ record,
344
+ response
345
+ });
354
346
 
355
347
  requests.push(record);
356
348
  return transformed ?? response;
@@ -358,8 +350,8 @@ async function createHarness(options: {
358
350
  const client = new McpClient({
359
351
  clientInfo: {
360
352
  name: "tiny-mcp-client-http-oauth-integration-test",
361
- version: "1.0.0",
362
- },
353
+ version: "1.0.0"
354
+ }
363
355
  });
364
356
  const transport = new HttpTransport({
365
357
  url: handle.mcpUrl,
@@ -368,13 +360,13 @@ async function createHarness(options: {
368
360
  client: options.oauthClient ?? {
369
361
  mode: "dynamic",
370
362
  metadata: {
371
- clientName: "tiny-mcp-client integration test",
372
- },
363
+ clientName: "tiny-mcp-client integration test"
364
+ }
373
365
  },
374
366
  browser: {
375
367
  async openBrowser(authorizationUrl) {
376
368
  const authorizationResponse = await fetchImpl(authorizationUrl, {
377
- method: "GET",
369
+ method: "GET"
378
370
  });
379
371
  if (authorizationResponse.status !== 302) {
380
372
  throw new Error(
@@ -386,7 +378,7 @@ async function createHarness(options: {
386
378
  expect(callbackUrl).toBeTruthy();
387
379
 
388
380
  const callbackResponse = await fetchImpl(callbackUrl ?? "", {
389
- method: "GET",
381
+ method: "GET"
390
382
  });
391
383
  expect(callbackResponse.ok).toBe(true);
392
384
  await callbackResponse.text();
@@ -394,12 +386,12 @@ async function createHarness(options: {
394
386
  ...(options.createServer === undefined
395
387
  ? {}
396
388
  : {
397
- createServer: options.createServer,
398
- }),
389
+ createServer: options.createServer
390
+ })
399
391
  },
400
392
  now: () => currentNow,
401
- sessionStore: sessionStore.store,
402
- },
393
+ sessionStore: sessionStore.store
394
+ }
403
395
  });
404
396
 
405
397
  return {
@@ -414,7 +406,7 @@ async function createHarness(options: {
414
406
  setNow(value: number): void {
415
407
  currentNow = value;
416
408
  },
417
- transport,
409
+ transport
418
410
  };
419
411
  }
420
412
 
@@ -438,8 +430,8 @@ describe("HttpTransport OAuth integration", () => {
438
430
  const firstResult = await harness.client.callTool({
439
431
  name: "echo",
440
432
  arguments: {
441
- text: "first-call",
442
- },
433
+ text: "first-call"
434
+ }
443
435
  });
444
436
 
445
437
  expect(getTextContent(firstResult)).toBe("first-call");
@@ -452,21 +444,21 @@ describe("HttpTransport OAuth integration", () => {
452
444
  prm: 1,
453
445
  register: 1,
454
446
  tokenAuthorizationCode: 1,
455
- tokenRefresh: 0,
447
+ tokenRefresh: 0
456
448
  });
457
449
  expect(summarizeAuthorizationServerTraffic(harness.handle)).toEqual({
458
450
  authorize: 1,
459
451
  metadata: 1,
460
452
  register: 1,
461
453
  tokenAuthorizationCode: 1,
462
- tokenRefresh: 0,
454
+ tokenRefresh: 0
463
455
  });
464
456
 
465
457
  const initializePosts = harness.requests.filter(
466
458
  (request) =>
467
- request.method === "POST"
468
- && request.url === harness.handle.mcpUrl
469
- && getJsonRpcMethod(request) === "initialize"
459
+ request.method === "POST" &&
460
+ request.url === harness.handle.mcpUrl &&
461
+ getJsonRpcMethod(request) === "initialize"
470
462
  );
471
463
  expect(initializePosts).toHaveLength(2);
472
464
  expect(initializePosts[0]?.authorization).toBeNull();
@@ -474,52 +466,56 @@ describe("HttpTransport OAuth integration", () => {
474
466
 
475
467
  const callToolPosts = harness.requests.filter(
476
468
  (request) =>
477
- request.method === "POST"
478
- && request.url === harness.handle.mcpUrl
479
- && getJsonRpcMethod(request) === "tools/call"
469
+ request.method === "POST" &&
470
+ request.url === harness.handle.mcpUrl &&
471
+ getJsonRpcMethod(request) === "tools/call"
480
472
  );
481
473
  expect(callToolPosts).toHaveLength(1);
482
474
  expect(callToolPosts[0]?.authorization).toMatch(/^Bearer /);
483
475
 
484
476
  const registrationRequest = harness.requests.find(
485
- (request) => request.method === "POST" && request.url === `${harness.handle.oauth.issuer}/register`
477
+ (request) =>
478
+ request.method === "POST" && request.url === `${harness.handle.oauth.issuer}/register`
486
479
  );
487
- expect(parseJsonBody(requireRequest(registrationRequest, "registration request"))).toMatchObject({
480
+ expect(
481
+ parseJsonBody(requireRequest(registrationRequest, "registration request"))
482
+ ).toMatchObject({
488
483
  client_name: "tiny-mcp-client integration test",
489
484
  grant_types: ["authorization_code", "refresh_token"],
490
485
  response_types: ["code"],
491
- token_endpoint_auth_method: "none",
486
+ token_endpoint_auth_method: "none"
492
487
  });
493
488
 
494
489
  const authorizationRequest = harness.requests.find(
495
490
  (request) =>
496
- request.method === "GET"
497
- && request.url.startsWith(`${harness.handle.oauth.issuer}/authorize`)
498
- );
499
- expect(new URL(requireRequest(authorizationRequest, "authorization request").url).searchParams.get("resource")).toBe(
500
- harness.handle.mcpUrl
491
+ request.method === "GET" &&
492
+ request.url.startsWith(`${harness.handle.oauth.issuer}/authorize`)
501
493
  );
494
+ expect(
495
+ new URL(requireRequest(authorizationRequest, "authorization request").url).searchParams.get(
496
+ "resource"
497
+ )
498
+ ).toBe(harness.handle.mcpUrl);
502
499
 
503
500
  const tokenRequest = harness.requests.find((request) => {
504
- if (
505
- request.method !== "POST"
506
- || request.url !== `${harness.handle.oauth.issuer}/token`
507
- ) {
501
+ if (request.method !== "POST" || request.url !== `${harness.handle.oauth.issuer}/token`) {
508
502
  return false;
509
503
  }
510
504
 
511
505
  return parseFormBody(request).get("grant_type") === "authorization_code";
512
506
  });
513
- expect(parseFormBody(requireRequest(tokenRequest, "authorization-code token request")).get("resource")).toBe(
514
- harness.handle.mcpUrl
515
- );
507
+ expect(
508
+ parseFormBody(requireRequest(tokenRequest, "authorization-code token request")).get(
509
+ "resource"
510
+ )
511
+ ).toBe(harness.handle.mcpUrl);
516
512
 
517
513
  const secondCallBaseline = summarizeTraffic(harness.requests, harness.handle);
518
514
  const secondResult = await harness.client.callTool({
519
515
  name: "echo",
520
516
  arguments: {
521
- text: "second-call",
522
- },
517
+ text: "second-call"
518
+ }
523
519
  });
524
520
 
525
521
  expect(getTextContent(secondResult)).toBe("second-call");
@@ -529,7 +525,9 @@ describe("HttpTransport OAuth integration", () => {
529
525
  harness.handle
530
526
  );
531
527
  expect(summaryAfterSecondCall.authorize - secondCallBaseline.authorize).toBe(0);
532
- expect(summaryAfterSecondCall.tokenAuthorizationCode - secondCallBaseline.tokenAuthorizationCode).toBe(0);
528
+ expect(
529
+ summaryAfterSecondCall.tokenAuthorizationCode - secondCallBaseline.tokenAuthorizationCode
530
+ ).toBe(0);
533
531
  expect(summaryAfterSecondCall.tokenRefresh - secondCallBaseline.tokenRefresh).toBe(0);
534
532
  expect(summaryAfterSecondCall.mcpPost - secondCallBaseline.mcpPost).toBe(1);
535
533
  expect(authorizationServerSummaryAfterSecondCall).toEqual({
@@ -537,7 +535,7 @@ describe("HttpTransport OAuth integration", () => {
537
535
  metadata: 1,
538
536
  register: 1,
539
537
  tokenAuthorizationCode: 1,
540
- tokenRefresh: 0,
538
+ tokenRefresh: 0
541
539
  });
542
540
  });
543
541
 
@@ -548,17 +546,17 @@ describe("HttpTransport OAuth integration", () => {
548
546
  createServer: loopbackServer.createServer,
549
547
  oauthClient: {
550
548
  mode: "static",
551
- clientId: "static-client",
549
+ clientId: "static-client"
552
550
  },
553
551
  serverOptions: {
554
552
  staticClients: [
555
553
  {
556
554
  clientId: "static-client",
557
555
  redirectUris: [redirectUri],
558
- scopes: ["mcp.read"],
559
- },
560
- ],
561
- },
556
+ scopes: ["mcp.read"]
557
+ }
558
+ ]
559
+ }
562
560
  });
563
561
  cleanups.add(harness.close);
564
562
 
@@ -567,16 +565,14 @@ describe("HttpTransport OAuth integration", () => {
567
565
  const result = await harness.client.callTool({
568
566
  name: "echo",
569
567
  arguments: {
570
- text: "static-client",
571
- },
568
+ text: "static-client"
569
+ }
572
570
  });
573
571
 
574
572
  expect(getTextContent(result)).toBe("static-client");
575
573
 
576
574
  const summary = summarizeTraffic(harness.requests, harness.handle);
577
- const authorizationServerSummary = summarizeAuthorizationServerTraffic(
578
- harness.handle
579
- );
575
+ const authorizationServerSummary = summarizeAuthorizationServerTraffic(harness.handle);
580
576
  expect(summary.register).toBe(0);
581
577
  expect(summary.authorize).toBe(1);
582
578
  expect(summary.tokenAuthorizationCode).toBe(1);
@@ -585,31 +581,32 @@ describe("HttpTransport OAuth integration", () => {
585
581
  metadata: 1,
586
582
  register: 0,
587
583
  tokenAuthorizationCode: 1,
588
- tokenRefresh: 0,
584
+ tokenRefresh: 0
589
585
  });
590
586
 
591
587
  const authorizationRequest = harness.requests.find(
592
588
  (request) =>
593
- request.method === "GET"
594
- && request.url.startsWith(`${harness.handle.oauth.issuer}/authorize`)
595
- );
596
- expect(new URL(requireRequest(authorizationRequest, "authorization request").url).searchParams.get("client_id")).toBe(
597
- "static-client"
589
+ request.method === "GET" &&
590
+ request.url.startsWith(`${harness.handle.oauth.issuer}/authorize`)
598
591
  );
592
+ expect(
593
+ new URL(requireRequest(authorizationRequest, "authorization request").url).searchParams.get(
594
+ "client_id"
595
+ )
596
+ ).toBe("static-client");
599
597
 
600
598
  const tokenRequest = harness.requests.find((request) => {
601
- if (
602
- request.method !== "POST"
603
- || request.url !== `${harness.handle.oauth.issuer}/token`
604
- ) {
599
+ if (request.method !== "POST" || request.url !== `${harness.handle.oauth.issuer}/token`) {
605
600
  return false;
606
601
  }
607
602
 
608
603
  return parseFormBody(request).get("grant_type") === "authorization_code";
609
604
  });
610
- expect(parseFormBody(requireRequest(tokenRequest, "authorization-code token request")).get("client_id")).toBe(
611
- "static-client"
612
- );
605
+ expect(
606
+ parseFormBody(requireRequest(tokenRequest, "authorization-code token request")).get(
607
+ "client_id"
608
+ )
609
+ ).toBe("static-client");
613
610
  });
614
611
 
615
612
  it("refreshes once after the current access token is revoked and the MCP server returns invalid_token", async () => {
@@ -620,8 +617,8 @@ describe("HttpTransport OAuth integration", () => {
620
617
  await harness.client.callTool({
621
618
  name: "echo",
622
619
  arguments: {
623
- text: "before-revoke",
624
- },
620
+ text: "before-revoke"
621
+ }
625
622
  });
626
623
 
627
624
  const initialSession = getStoredSession(harness);
@@ -630,42 +627,37 @@ describe("HttpTransport OAuth integration", () => {
630
627
  harness.handle.oauth.revoke(revokedAccessToken);
631
628
 
632
629
  const baseline = summarizeTraffic(harness.requests, harness.handle);
633
- const authorizationServerBaseline = summarizeAuthorizationServerTraffic(
634
- harness.handle
635
- );
630
+ const authorizationServerBaseline = summarizeAuthorizationServerTraffic(harness.handle);
636
631
  const refreshedResult = await harness.client.callTool({
637
632
  name: "echo",
638
633
  arguments: {
639
- text: "after-revoke",
640
- },
634
+ text: "after-revoke"
635
+ }
641
636
  });
642
637
 
643
638
  expect(getTextContent(refreshedResult)).toBe("after-revoke");
644
639
 
645
640
  const summary = summarizeTraffic(harness.requests, harness.handle);
646
- const authorizationServerSummary = summarizeAuthorizationServerTraffic(
647
- harness.handle
648
- );
641
+ const authorizationServerSummary = summarizeAuthorizationServerTraffic(harness.handle);
649
642
  expect(summary.authorize - baseline.authorize).toBe(0);
650
643
  expect(summary.tokenRefresh - baseline.tokenRefresh).toBe(1);
651
644
  expect(summary.mcpPost - baseline.mcpPost).toBe(2);
652
- expect(
653
- authorizationServerSummary.tokenRefresh - authorizationServerBaseline.tokenRefresh
654
- ).toBe(1);
655
-
656
- const refreshRequest = findLastRequest(harness.requests, (request) => {
657
- if (
658
- request.method !== "POST"
659
- || request.url !== `${harness.handle.oauth.issuer}/token`
660
- ) {
661
- return false;
662
- }
645
+ expect(authorizationServerSummary.tokenRefresh - authorizationServerBaseline.tokenRefresh).toBe(
646
+ 1
647
+ );
663
648
 
664
- return parseFormBody(request).get("grant_type") === "refresh_token";
665
- }, "refresh token request");
666
- expect(parseFormBody(refreshRequest).get("resource")).toBe(
667
- harness.handle.mcpUrl
649
+ const refreshRequest = findLastRequest(
650
+ harness.requests,
651
+ (request) => {
652
+ if (request.method !== "POST" || request.url !== `${harness.handle.oauth.issuer}/token`) {
653
+ return false;
654
+ }
655
+
656
+ return parseFormBody(request).get("grant_type") === "refresh_token";
657
+ },
658
+ "refresh token request"
668
659
  );
660
+ expect(parseFormBody(refreshRequest).get("resource")).toBe(harness.handle.mcpUrl);
669
661
 
670
662
  const updatedSession = getStoredSession(harness);
671
663
  expect(updatedSession.tokens?.accessToken).toBeTruthy();
@@ -680,22 +672,20 @@ describe("HttpTransport OAuth integration", () => {
680
672
  await harness.client.callTool({
681
673
  name: "echo",
682
674
  arguments: {
683
- text: "seed-token",
684
- },
675
+ text: "seed-token"
676
+ }
685
677
  });
686
678
 
687
679
  harness.setNow(80_000);
688
680
  const baseline = summarizeTraffic(harness.requests, harness.handle);
689
- const authorizationServerBaseline = summarizeAuthorizationServerTraffic(
690
- harness.handle
691
- );
681
+ const authorizationServerBaseline = summarizeAuthorizationServerTraffic(harness.handle);
692
682
  const results = await Promise.all(
693
683
  Array.from({ length: 5 }, (_, index) =>
694
684
  harness.client.callTool({
695
685
  name: "echo",
696
686
  arguments: {
697
- text: `parallel-${index}`,
698
- },
687
+ text: `parallel-${index}`
688
+ }
699
689
  })
700
690
  )
701
691
  );
@@ -705,44 +695,42 @@ describe("HttpTransport OAuth integration", () => {
705
695
  "parallel-1",
706
696
  "parallel-2",
707
697
  "parallel-3",
708
- "parallel-4",
698
+ "parallel-4"
709
699
  ]);
710
700
 
711
701
  const summary = summarizeTraffic(harness.requests, harness.handle);
712
- const authorizationServerSummary = summarizeAuthorizationServerTraffic(
713
- harness.handle
714
- );
702
+ const authorizationServerSummary = summarizeAuthorizationServerTraffic(harness.handle);
715
703
  expect(summary.authorize - baseline.authorize).toBe(0);
716
704
  expect(summary.tokenRefresh - baseline.tokenRefresh).toBe(1);
717
705
  expect(summary.mcpPost - baseline.mcpPost).toBe(5);
718
- expect(
719
- authorizationServerSummary.tokenRefresh - authorizationServerBaseline.tokenRefresh
720
- ).toBe(1);
706
+ expect(authorizationServerSummary.tokenRefresh - authorizationServerBaseline.tokenRefresh).toBe(
707
+ 1
708
+ );
721
709
  });
722
710
 
723
711
  it("maps verifier audience mismatches to a typed OAuthError instead of a generic transport error", async () => {
724
712
  const harness = await createHarness({
725
713
  responseTransform: async ({ handle, record, response }) => {
726
714
  if (
727
- record.method !== "POST"
728
- || record.url !== `${handle.oauth.issuer}/token`
729
- || parseFormBody(record).get("grant_type") !== "authorization_code"
715
+ record.method !== "POST" ||
716
+ record.url !== `${handle.oauth.issuer}/token` ||
717
+ parseFormBody(record).get("grant_type") !== "authorization_code"
730
718
  ) {
731
719
  return undefined;
732
720
  }
733
721
 
734
- const payload = await response.clone().json() as Record<string, unknown>;
722
+ const payload = (await response.clone().json()) as Record<string, unknown>;
735
723
  const wrongAudienceToken = await handle.oauth.issueTokenFor({
736
724
  clientId: parseFormBody(record).get("client_id") ?? "unknown-client",
737
725
  resource: `${handle.mcpUrl}/wrong-audience`,
738
- scopes: ["mcp.read"],
726
+ scopes: ["mcp.read"]
739
727
  });
740
728
 
741
729
  payload.access_token = wrongAudienceToken;
742
730
  delete payload.refresh_token;
743
731
 
744
732
  return cloneResponse(response, JSON.stringify(payload));
745
- },
733
+ }
746
734
  });
747
735
  cleanups.add(harness.close);
748
736
 
@@ -758,7 +746,7 @@ describe("HttpTransport OAuth integration", () => {
758
746
  expect(caughtError).toMatchObject({
759
747
  error: "invalid_token",
760
748
  errorDescription: "audience mismatch",
761
- status: 401,
749
+ status: 401
762
750
  });
763
751
  expect((caughtError as Error).message).toBe("audience mismatch");
764
752
  });
@@ -767,25 +755,25 @@ describe("HttpTransport OAuth integration", () => {
767
755
  const harness = await createHarness({
768
756
  responseTransform: async ({ handle, record, response }) => {
769
757
  if (
770
- record.method !== "POST"
771
- || record.url !== `${handle.oauth.issuer}/token`
772
- || parseFormBody(record).get("grant_type") !== "authorization_code"
758
+ record.method !== "POST" ||
759
+ record.url !== `${handle.oauth.issuer}/token` ||
760
+ parseFormBody(record).get("grant_type") !== "authorization_code"
773
761
  ) {
774
762
  return undefined;
775
763
  }
776
764
 
777
- const payload = await response.clone().json() as Record<string, unknown>;
765
+ const payload = (await response.clone().json()) as Record<string, unknown>;
778
766
  const insufficientScopeToken = await handle.oauth.issueTokenFor({
779
767
  clientId: parseFormBody(record).get("client_id") ?? "unknown-client",
780
768
  resource: handle.mcpUrl,
781
- scopes: ["mcp.write"],
769
+ scopes: ["mcp.write"]
782
770
  });
783
771
 
784
772
  payload.access_token = insufficientScopeToken;
785
773
  delete payload.refresh_token;
786
774
 
787
775
  return cloneResponse(response, JSON.stringify(payload));
788
- },
776
+ }
789
777
  });
790
778
  cleanups.add(harness.close);
791
779
 
@@ -801,7 +789,7 @@ describe("HttpTransport OAuth integration", () => {
801
789
  expect(caughtError).toMatchObject({
802
790
  error: "insufficient_scope",
803
791
  errorDescription: "insufficient scope",
804
- status: 403,
792
+ status: 403
805
793
  });
806
794
  expect((caughtError as Error).message).toBe("insufficient scope");
807
795
  });