fix(core): bump MCP client and core to 2.4.0 to drop pre-bundled fast-uri 3.1.0 (#15925)

* fix(core): bump MCP client and core to 2.4.0 to drop pre-bundled fast-uri 3.1.0

The MCP client 2.0.0 pre-bundles ajv with an inlined fast-uri 3.1.0,
which dependency audits cannot see and overrides cannot reach. 2.4.0
re-bundles fast-uri 3.1.8, clearing CVE-2026-6321, CVE-2026-6322,
CVE-2026-18446, CVE-2026-75975 and CVE-2026-76172 from the published
bundle. Both packages stay exact-pinned in lockstep because the client
pins core to the same version.

Fixes #15919

Co-authored-by: Qwen-Coder <[email protected]>

* chore(vscode-ide-companion): regenerate NOTICES for MCP client/core 2.4.0

Co-authored-by: Qwen-Coder <[email protected]>

* fix(core): refuse redirects before the SDK, not only inside the fetch

2.4.0 resolves a same-origin 30x in its own layer, against
requestInit.redirect, before the compatibility fetch is called. The Agent
Plugin transport only set headers, so a configured or bearer credential was
replayed to another path on the same origin.

Ask the same question in one place and carry the answer into requestInit on
both transport paths, and pin it with a test that fails when the option is
absent.

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Shaojin Wen <[email protected]>
Co-authored-by: yiliang114 <[email protected]>
This commit is contained in:
authored and GitHub committed 2026-10-31 19:25:36 +08:00
1 parent c726d2cfc1
commit cca888dfcc
5 files changed
+153 -26

No files matched your search

+2 -2
View File
@@ -111,8 +111,8 @@
"@google/genai": "2.6.0",
"@iarna/toml": "^2.2.5",
"@jitl/quickjs-singlefile-mjs-release-sync": "0.32.0",
"@modelcontextprotocol/client": "2.0.0",
"@modelcontextprotocol/core": "2.0.0",
"@modelcontextprotocol/client": "2.4.0",
"@modelcontextprotocol/core": "2.4.0",
"@modelcontextprotocol/sdk": "^1.30.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.221.0",
@@ -2377,6 +2377,31 @@ lOTTGqPpwFUbw2EMOOpFYuIyzGMIpUNMBjE2gvJiqFQ=
});
});
// The assertion above only proves the inner fetch was told to stop.
// The SDK resolves redirects outside it, against `requestInit`, so the
// transport has to carry the same answer or a same-origin 30x is
// replayed with the credential attached.
it('carries the Agent Plugin redirect refusal into the transport', async () => {
const plugin = await transportFor(
{
httpUrl: 'https://example.com/mcp',
headers: { 'X-Api-Key': 'synthetic' },
agentPluginV1: true,
},
'plugin-redirect',
);
const plain = await transportFor(
{
httpUrl: 'https://example.com/mcp',
headers: { 'X-Api-Key': 'synthetic' },
},
'plain-redirect',
);
expect(plugin._requestInit?.redirect).toBe('manual');
expect(plain._requestInit?.redirect).toBeUndefined();
});
/**
* Sends `init` (the optional GET/SSE probe by default) to /mcp through
* the compatibility fetch over a stub answering `body` with `status`.
+48 -9
View File
@@ -272,6 +272,27 @@ function isStreamableHttpGetSseRequest(init?: RequestInit): boolean {
.some((type) => type === 'text/event-stream');
}
/**
* Whether the Agent Plugin transport must refuse redirects: it may only reach
* the address it was configured with, and a configured or bearer credential
* makes a forwarded 30x a credential leak.
*
* The SDK resolves redirects outside the compatibility fetch, against
* `requestInit.redirect`, so both layers have to be told. Asking the same
* question in one place keeps them from disagreeing.
*/
function agentPluginForbidsRedirect(
mcpServerConfig: MCPServerConfig | undefined,
headers: Headers | undefined,
): boolean {
return (
mcpServerConfig?.agentPluginV1 === true &&
((mcpServerConfig.headers !== undefined &&
Object.keys(mcpServerConfig.headers).length > 0) ||
headers?.has('authorization') === true)
);
}
/**
* Wraps fetch to preserve OAuth challenges before the SDK discards response
* metadata and to normalize conventional "GET not supported" rejections of
@@ -297,11 +318,10 @@ export function createStreamableHttpCompatibilityFetch(
const requestHeaders = new Headers(
init?.headers ?? (input instanceof Request ? input.headers : undefined),
);
const stopAgentPluginRedirect =
mcpServerConfig?.agentPluginV1 === true &&
((mcpServerConfig.headers !== undefined &&
Object.keys(mcpServerConfig.headers).length > 0) ||
requestHeaders.has('authorization'));
const stopAgentPluginRedirect = agentPluginForbidsRedirect(
mcpServerConfig,
requestHeaders,
);
const effectiveInit = stopAgentPluginRedirect
? { ...init, redirect: 'manual' as const }
: init;
@@ -1352,13 +1372,20 @@ async function createTransportWithOAuth(
try {
if (mcpServerConfig.httpUrl) {
// Create HTTP transport with OAuth token
const oauthHeaders = {
...mcpServerConfig.headers,
Authorization: `Bearer ${accessToken}`,
};
const oauthTransportOptions: StreamableHTTPClientTransportOptions = {
fetch: createMcpStreamableHttpFetch(mcpServerName, mcpServerConfig),
requestInit: {
headers: {
...mcpServerConfig.headers,
Authorization: `Bearer ${accessToken}`,
},
headers: oauthHeaders,
...(agentPluginForbidsRedirect(
mcpServerConfig,
new Headers(oauthHeaders),
)
? { redirect: 'manual' as const }
: {}),
},
};
@@ -2644,6 +2671,18 @@ export async function createTransport(
};
}
// The compatibility fetch answers the request it issues, but the SDK
// resolves a redirect before that, against this field.
if (
transportOptions.requestInit &&
agentPluginForbidsRedirect(
mcpServerConfig,
new Headers(transportOptions.requestInit.headers as HeadersInit),
)
) {
transportOptions.requestInit.redirect = 'manual';
}
return new StreamableHTTPClientTransport(
new URL(mcpServerConfig.httpUrl),
transportOptions,
+56 -2
View File
@@ -5751,7 +5751,7 @@ SOFTWARE.
============================================================
@modelcontextprotocol/client@2.0.0
@modelcontextprotocol/client@2.4.0
(git+https://github.com/modelcontextprotocol/typescript-sdk.git)
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
@@ -5972,6 +5972,60 @@ CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for
the full license text.
============================================================
[email protected]
(git+ssh://[email protected]/rexxars/eventsource-parser.git)
MIT License
Copyright (c) 2026 Espen Hovlandsdal <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
============================================================
[email protected]
(https://github.com/panva/jose)
The MIT License (MIT)
Copyright (c) 2018 Filip Skokan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
============================================================
[email protected]
(git+https://github.com/colinhacks/zod.git)
@@ -6000,7 +6054,7 @@ SOFTWARE.
============================================================
@modelcontextprotocol/core@2.0.0
@modelcontextprotocol/core@2.4.0
(git+https://github.com/modelcontextprotocol/typescript-sdk.git)
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
+22 -13
View File
@@ -990,11 +990,11 @@ importers:
specifier: 0.32.0
version: 0.32.0
'@modelcontextprotocol/client':
specifier: 2.0.0
version: 2.0.0
specifier: 2.4.0
version: 2.4.0
'@modelcontextprotocol/core':
specifier: 2.0.0
version: 2.0.0
specifier: 2.4.0
version: 2.4.0
'@modelcontextprotocol/sdk':
specifier: ^1.30.0
version: 1.30.0([email protected])([email protected])
@@ -3130,12 +3130,12 @@ packages:
resolution: {integrity: sha512-AAFtGyjsI4LcNhuXavc3ALIeDGqV/1CMclg285rV6h0Wpf5DObZmn9D2fTKTgRHKyGcclVEWc1pt3eJ9KEiPIg==}
engines: {node: '>=18'}
'@modelcontextprotocol/client@2.0.0':
resolution: {integrity: sha512-8f1OghQ2rjzIOfqgUCP+8GiUWqRs89njoWLNqAe8kWmDePv3s1fZXseej+QXemssEuuOvLLmLO/kqM3IQHtISw==}
'@modelcontextprotocol/client@2.4.0':
resolution: {integrity: sha512-LgrD2OphHuG12vfKFKz6SOnq7bKHQmhGJIAYdD+MZBn2npHEyry6uD8zvktodtl5CQM85MO0anUyD9JwmUmxww==}
engines: {node: '>=20'}
'@modelcontextprotocol/core@2.0.0':
resolution: {integrity: sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==}
'@modelcontextprotocol/core@2.4.0':
resolution: {integrity: sha512-z8QBKqdfXLPzkLQuG4xp8hrVEMm1PZ1IgxMN2sMbJiFiAKOWXnAzogXn2W4aqIBlP1ea6U5yiqVquvUNM1Cj6Q==}
engines: {node: '>=20'}
'@modelcontextprotocol/[email protected]':
@@ -3511,6 +3511,7 @@ packages:
'@opentelemetry/[email protected]':
resolution: {integrity: sha512-yw/IX8DL470dSMZJoE82ScfYGp7JWZ/G8kFJo35ZILUVTB2jFPTOaioN+8s09pH0RHsWNhweVZb+ZnjJJpCChg==}
engines: {node: ^18.19.0 || >=20.6.0}
deprecated: Package no longer supported. See https://github.com/open-telemetry/opentelemetry-js/pull/7077
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
@@ -3541,12 +3542,14 @@ packages:
'@opentelemetry/[email protected]':
resolution: {integrity: sha512-GuYQQT7QD2EeO8lcZLRQzcbOyhqAzL+6WWTKTU9mSUBYBazkEDl+VrQcXQhbB08OWM9anD1aHleVadzulpOaUQ==}
engines: {node: ^18.19.0 || >=20.6.0}
deprecated: Use @opentelemetry/sdk-trace package
peerDependencies:
'@opentelemetry/api': '>=1.3.0 <1.10.0'
'@opentelemetry/[email protected]':
resolution: {integrity: sha512-GZK/G6oZyBLGlH1pUgeDch7D91KoHd2uotUGIkWCPi9GI5T9X0p4L7nNAMDR1BQjkRYoDqo+ddfVx9t5Uhys+Q==}
engines: {node: ^18.19.0 || >=20.6.0}
deprecated: Use @opentelemetry/sdk-trace package
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
@@ -6967,6 +6970,10 @@ packages:
resolution: {integrity: sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==}
engines: {node: '>=20.0.0'}
[email protected]:
resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==}
engines: {node: '>=18.0.0'}
[email protected]:
resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
engines: {node: '>=18.0.0'}
@@ -12351,17 +12358,17 @@ snapshots:
'@mobilewright/[email protected]': {}
'@modelcontextprotocol/client@2.0.0':
'@modelcontextprotocol/client@2.4.0':
dependencies:
'@modelcontextprotocol/core': 2.0.0
'@modelcontextprotocol/core': 2.4.0
cross-spawn: 7.0.6
eventsource: 3.0.7
eventsource-parser: 3.0.3
jose: 6.1.3
eventsource-parser: 3.1.1
jose: 6.2.12
pkce-challenge: 5.0.0
zod: 4.4.3
'@modelcontextprotocol/core@2.0.0':
'@modelcontextprotocol/core@2.4.0':
dependencies:
zod: 4.4.3
@@ -16861,6 +16868,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
eventsource-parser: 3.0.3