Skip to content

Commit d79cf73

Browse files
authored
fix: mcp proxy header (#397)
<!-- Thank you for your pull request. Please review below requirements. Bug fixes and new features should include tests and possibly benchmarks. Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md 感谢您贡献代码。请确认下列 checklist 的完成情况。 Bug 修复和新功能必须包含测试,必要时请附上性能测试。 Contributors guide: https://github.com/eggjs/egg/blob/master/CONTRIBUTING.md --> ##### Checklist <!-- Remove items that do not apply. For completed items, change [ ] to [x]. --> - [ ] `npm test` passes - [ ] tests and/or benchmarks are included - [ ] documentation is changed or added - [ ] commit message follows commit guidelines ##### Affected core subsystem(s) <!-- Provide affected core subsystem(s). --> ##### Description of change <!-- Provide a description of the change below this comment. --> <!-- - any feature? - close https://github.com/eggjs/egg/ISSUE_URL --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Removed explicit transfer-encoding headers from Server-Sent Events (SSE) streaming responses to improve protocol compliance and stream reliability. * **Tests** * Added runtime checks validating header consistency (content-length vs transfer-encoding) and improved fetch handling for streaming transport tests to catch regressions earlier. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 48e0cd2 commit d79cf73

File tree

4 files changed

+12
-9
lines changed

4 files changed

+12
-9
lines changed

plugin/controller/lib/impl/mcp/MCPControllerRegister.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ export class MCPControllerRegister implements ControllerRegister {
219219
ctx.respond = false;
220220
ctx.set({
221221
'content-type': 'text/event-stream',
222-
'transfer-encoding': 'chunked',
223222
});
224223
await ctx.app.ctxStorage.run(ctx, async () => {
225224
await mw(ctx, async () => {
@@ -352,7 +351,6 @@ export class MCPControllerRegister implements ControllerRegister {
352351

353352
ctx.set({
354353
'content-type': 'text/event-stream',
355-
'transfer-encoding': 'chunked',
356354
});
357355

358356
await mcpServerHelper.server.connect(transport);
@@ -402,7 +400,6 @@ export class MCPControllerRegister implements ControllerRegister {
402400
ctx.respond = false;
403401
ctx.set({
404402
'content-type': 'text/event-stream',
405-
'transfer-encoding': 'chunked',
406403
});
407404

408405
await ctx.app.ctxStorage.run(ctx, async () => {
@@ -471,7 +468,6 @@ export class MCPControllerRegister implements ControllerRegister {
471468
self.transports[id] = transport;
472469
ctx.set({
473470
'content-type': 'text/event-stream',
474-
'transfer-encoding': 'chunked',
475471
});
476472
ctx.respond = false;
477473
const mcpServerHelper = self.mcpServerHelperMap[name ?? 'default']();

plugin/controller/test/fixtures/apps/mcp-app/hook-plugin/lib/MCPControllerHook.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export const GetAlipayTeggHook = (app: Application) => {
66
ctx.set({
77
'content-type': 'text/event-stream',
88
'cache-control': 'no-cache',
9-
'transfer-encoding': 'chunked',
109
});
1110
try {
1211
const auth = ctx.get('authorization');

plugin/mcp-proxy/test/fixtures/apps/mcp-proxy/app/controller/app.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ export default class App extends Controller {
166166
this.ctx.set({
167167
'content-type': 'text/event-stream',
168168
'cache-control': 'no-cache',
169-
'transfer-encoding': 'chunked',
170169
});
171170
const self = this;
172171
const transport = new SSEServerTransport('/message', this.ctx.res);
@@ -255,7 +254,6 @@ export default class App extends Controller {
255254
this.ctx.set({
256255
'content-type': 'text/event-stream',
257256
'cache-control': 'no-cache',
258-
'transfer-encoding': 'chunked',
259257
});
260258
const eventStore = new InMemoryEventStore();
261259
const self = this;
@@ -305,7 +303,6 @@ export default class App extends Controller {
305303
this.ctx.set({
306304
'content-type': 'text/event-stream',
307305
'cache-control': 'no-cache',
308-
'transfer-encoding': 'chunked',
309306
});
310307
const transport = transports[sessionId] as StreamableHTTPServerTransport;
311308
await transport.handleRequest(this.ctx.req, this.ctx.res);

plugin/mcp-proxy/test/proxy.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
44
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
55
import { CallToolRequest, CallToolResultSchema, ListToolsRequest, ListToolsResultSchema, LoggingMessageNotificationSchema } from '@modelcontextprotocol/sdk/types.js';
66
import assert from 'assert';
7+
import { fetch } from 'urllib';
78

89
async function listTools(client: Client) {
910
const toolsRequest: ListToolsRequest = {
@@ -133,7 +134,17 @@ describe('plugin/mcp-proxy/test/proxy.test.ts', () => {
133134
});
134135
const baseUrl = await app.httpRequest()
135136
.post('/stream').url;
136-
const streamableTransport = new StreamableHTTPClientTransport(new URL(baseUrl));
137+
const streamableTransport = new StreamableHTTPClientTransport(new URL(baseUrl), {
138+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
139+
// @ts-ignore
140+
fetch: async (...args) => {
141+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
142+
// @ts-ignore
143+
const res = await fetch(...args);
144+
assert.deepEqual(res.headers.has('content-length'), !res.headers.has('transfer-encoding'));
145+
return res;
146+
},
147+
});
137148
const streamableNotifications: { level: string, data: string }[] = [];
138149
streamableClient.setNotificationHandler(LoggingMessageNotificationSchema, notification => {
139150
streamableNotifications.push({ level: notification.params.level, data: notification.params.data as string });

0 commit comments

Comments
 (0)