🧵 chore: Raise MCP SSE Line Default (#13224)
Some checks are pending
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
GitNexus Index / index (push) Waiting to run
GitNexus Index / post-index (push) Blocked by required conditions
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions

This commit is contained in:
Danny Avila 2026-05-21 09:06:02 -04:00 • committed by GitHub
parent 1ed84ee4eb
commit f34150e8e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 3 deletions

View file

@ -898,8 +898,8 @@ OPENWEATHER_API_KEY=
# MCP_STREAMABLE_HTTP_MAX_RESPONSE_BYTES=16777216
# Max bytes allowed in a single SSE line for non-GET streamable HTTP MCP responses.
# Set to 0 to disable. Default: 1048576 (1 MiB)
# MCP_STREAMABLE_HTTP_MAX_LINE_BYTES=1048576
# Set to 0 to disable. Default: 5242880 (5 MiB)
# MCP_STREAMABLE_HTTP_MAX_LINE_BYTES=5242880
# Skip code challenge method validation (e.g., for AWS Cognito that supports S256 but doesn't advertise it)
# When set to true, forces S256 code challenge even if not advertised in .well-known/openid-configuration

View file

@ -1185,6 +1185,33 @@ describe('MCP SSRF protection – customFetch input shapes', () => {
}
});
it('should allow SSE lines above the old 1 MiB default when no line override is set', async () => {
delete process.env.MCP_STREAMABLE_HTTP_MAX_LINE_BYTES;
const payload = 'x'.repeat(2 * 1024 * 1024);
const server = await createRawResponseServer((_req, res) => {
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
res.end(`data: ${payload}\n\n`);
});
try {
conn = new MCPConnection({
serverName: 'customfetch-sse-default-line-limit',
serverConfig: { type: 'streamable-http', url: server.url },
useSSRFProtection: false,
});
const customFetch = getGuardedStreamableHTTPCustomFetch(conn);
const response = await customFetch(server.url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', method: 'notifications/cancelled' }),
});
await expect(response.text()).resolves.toContain(payload.slice(0, 128));
} finally {
await server.close();
}
});
it('should fail an actual streamable HTTP tool call promptly with a clear oversized SSE line error', async () => {
process.env.MCP_STREAMABLE_HTTP_MAX_LINE_BYTES = '512';
target = await createOversizedToolResultStreamableServer(2048);

View file

@ -75,7 +75,7 @@ const DEFAULT_INIT_TIMEOUT = 30000;
/** Max 307/308 redirects to follow per request (prevents redirect loops) */
const MAX_REDIRECTS = 5;
const DEFAULT_MCP_STREAMABLE_HTTP_MAX_RESPONSE_BYTES = 16 * 1024 * 1024;
const DEFAULT_MCP_STREAMABLE_HTTP_MAX_LINE_BYTES = 1024 * 1024;
const DEFAULT_MCP_STREAMABLE_HTTP_MAX_LINE_BYTES = 5 * 1024 * 1024;
function getNonNegativeIntegerEnv(name: string, defaultValue: number): number {
const raw = process.env[name];