Commit 1ad1ccd
committed
fix(mcp): pinned fetch dispatch through global fetch so Response passes instanceof checks
createPinnedFetch called a separately-imported undici `fetch` (used for
DNS-pinned MCP OAuth/SSRF-guarded requests), returning a Response
instance from that separate undici module copy. Node's own global
fetch is also undici-backed, but a directly imported `undici` package
copy is a distinct module instance with its own Response constructor
reference — so `instanceof Response` checks against the platform's
global Response fail across that boundary.
The MCP SDK's OAuth error parser (parseErrorResponse) does exactly
that check to decide whether to read the response body as text:
`input instanceof Response ? await input.text() : input`. When it
failed, `body` became the raw Response object itself, which then
stringified to the literal "[object Response]" in the error message
and failed a JSON.parse attempt on that non-JSON string — surfacing a
confusing "Invalid OAuth error response: ... Raw body: [object
Response]" toast on any MCP OAuth error whose response body isn't a
clean OAuth-spec JSON error object.
Dispatch through the global `fetch` instead (passing the same undici
`Agent` as its `dispatcher` option, which Node's fetch forwards to
undici at runtime) so the returned Response is the same class every
consumer's instanceof check expects. Verified directly: a standalone
repro script confirms `instanceof Response` is false via the old
undici-imported fetch and true via the global fetch with a dispatcher.
Updated pinned-fetch.server.test.ts to mock the global fetch instead
of undici's fetch export, matching the new call path (the old mock
target being unused meant those assertions were silently hitting real
network calls).1 parent f477faa commit 1ad1ccd
2 files changed
Lines changed: 32 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
433 | 433 | | |
434 | 434 | | |
435 | 435 | | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
436 | 443 | | |
437 | 444 | | |
438 | 445 | | |
439 | 446 | | |
440 | 447 | | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
448 | 451 | | |
449 | 452 | | |
450 | 453 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
| 5 | + | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
40 | | - | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
41 | 48 | | |
42 | 49 | | |
43 | 50 | | |
| |||
75 | 82 | | |
76 | 83 | | |
77 | 84 | | |
78 | | - | |
79 | | - | |
| 85 | + | |
| 86 | + | |
80 | 87 | | |
81 | 88 | | |
82 | 89 | | |
| |||
89 | 96 | | |
90 | 97 | | |
91 | 98 | | |
92 | | - | |
| 99 | + | |
93 | 100 | | |
94 | 101 | | |
95 | 102 | | |
| |||
99 | 106 | | |
100 | 107 | | |
101 | 108 | | |
102 | | - | |
103 | | - | |
| 109 | + | |
| 110 | + | |
104 | 111 | | |
105 | 112 | | |
106 | 113 | | |
| |||
111 | 118 | | |
112 | 119 | | |
113 | 120 | | |
114 | | - | |
115 | | - | |
| 121 | + | |
| 122 | + | |
116 | 123 | | |
117 | 124 | | |
118 | 125 | | |
119 | | - | |
120 | | - | |
| 126 | + | |
| 127 | + | |
121 | 128 | | |
122 | 129 | | |
123 | 130 | | |
| |||
0 commit comments