Skip to content

Commit 870b5e3

Browse files
authored
fix: hono node v16 (#374)
<!-- 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 * **Refactor** * Several MCP-related components now load lazily at runtime and controller registration is instance-based to reduce startup overhead and improve compatibility. * **Bug Fixes** * Improved transport message-key handling to reduce transient lookup/type issues and increase reliability. * **Tests** * Test setup now runs conditionally on newer runtimes to avoid failures on older Node versions. <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 759db34 commit 870b5e3

File tree

5 files changed

+29
-16
lines changed

5 files changed

+29
-16
lines changed

core/mcp-client/test/fixtures/streamable-mcp-server/http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import http from 'node:http';
22

33
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4-
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
54
import * as z from 'zod/v4';
65

76
// Create an MCP server
@@ -39,6 +38,7 @@ export const headers = {};
3938
export let httpServer;
4039
export async function startStreamableServer(port = 17243){
4140
const httpServer = http.createServer(async (req, res) => {
41+
const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
4242
const url = new URL(`http://127.0.0.1:${port}${req.url!}`);
4343
const headerKey = `${req.method}${url.pathname}`;
4444
const serverCode = req.headers['x-mcp-server-code'] as string;
@@ -47,7 +47,7 @@ export async function startStreamableServer(port = 17243){
4747
headers[serverCode][headerKey].push(req.headers);
4848
if (req.method === 'POST') {
4949
try {
50-
const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
50+
const transport: typeof StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
5151
sessionIdGenerator: undefined,
5252
});
5353
await server.connect(transport);

plugin/controller/app.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { ControllerMetadataManager } from './lib/ControllerMetadataManager';
1111
import { EggControllerPrototypeHook } from './lib/EggControllerPrototypeHook';
1212
import { RootProtoManager } from './lib/RootProtoManager';
1313
import { EggControllerLoader } from './lib/EggControllerLoader';
14-
import { MCPControllerRegister } from './lib/impl/mcp/MCPControllerRegister';
1514
import { middlewareGraphHook } from './lib/MiddlewareGraphHook';
1615
import assert from 'node:assert';
1716

@@ -28,6 +27,8 @@ export default class ControllerAppBootHook {
2827
private controllerLoadUnitHandler: ControllerLoadUnitHandler;
2928
private readonly controllerPrototypeHook: EggControllerPrototypeHook;
3029

30+
private mcpControllerRegister?: typeof import('./lib/impl/mcp/MCPControllerRegister').MCPControllerRegister;
31+
3132
constructor(app: Application) {
3233
this.app = app;
3334
this.controllerRegisterFactory = new ControllerRegisterFactory(this.app);
@@ -36,6 +37,11 @@ export default class ControllerAppBootHook {
3637
this.app.controllerMetaBuilderFactory = ControllerMetaBuilderFactory;
3738
this.loadUnitHook = new AppLoadUnitControllerHook(this.controllerRegisterFactory, this.app.rootProtoManager);
3839
this.controllerPrototypeHook = new EggControllerPrototypeHook();
40+
41+
if (parseInt(process.versions.node.split('.')[0], 10) >= 18) {
42+
// eslint-disable-next-line @typescript-eslint/no-var-requires
43+
this.mcpControllerRegister = require('./lib/impl/mcp/MCPControllerRegister').MCPControllerRegister;
44+
}
3945
}
4046

4147
configWillLoad() {
@@ -75,8 +81,8 @@ export default class ControllerAppBootHook {
7581

7682
// init http root proto middleware
7783
this.prepareMiddleware(this.app.config.coreMiddleware);
78-
if (this.mcpEnable()) {
79-
this.controllerRegisterFactory.registerControllerRegister(ControllerType.MCP, MCPControllerRegister.create);
84+
if (this.mcpEnable() && this.mcpControllerRegister) {
85+
this.controllerRegisterFactory.registerControllerRegister(ControllerType.MCP, this.mcpControllerRegister.create);
8086
// Don't let the mcp's body be consumed
8187
this.app.config.coreMiddleware.unshift('mcpBodyMiddleware');
8288

@@ -134,20 +140,20 @@ export default class ControllerAppBootHook {
134140
// and register methods after collect is done.
135141
HTTPControllerRegister.instance?.doRegister(this.app.rootProtoManager);
136142

137-
this.app.config.mcp.hooks = MCPControllerRegister.hooks;
143+
this.app.config.mcp.hooks = this.mcpControllerRegister?.hooks;
138144
}
139145

140146
configDidLoad() {
141147
GlobalGraph.instance!.registerBuildHook(middlewareGraphHook);
142148
}
143149

144150
async willReady() {
145-
if (this.mcpEnable()) {
146-
await MCPControllerRegister.connectStatelessStreamTransport();
147-
const names = MCPControllerRegister.instance?.mcpConfig.getMultipleServerNames();
151+
if (this.mcpEnable() && this.mcpControllerRegister) {
152+
await this.mcpControllerRegister.connectStatelessStreamTransport();
153+
const names = this.mcpControllerRegister.instance?.mcpConfig.getMultipleServerNames();
148154
if (names && names.length > 0) {
149155
for (const name of names) {
150-
await MCPControllerRegister.connectStatelessStreamTransport(name);
156+
await this.mcpControllerRegister.connectStatelessStreamTransport(name);
151157
}
152158
}
153159
}
@@ -165,6 +171,6 @@ export default class ControllerAppBootHook {
165171
this.app.eggPrototypeLifecycleUtil.deleteLifecycle(this.controllerPrototypeHook);
166172
ControllerMetadataManager.instance.clear();
167173
HTTPControllerRegister.clean();
168-
MCPControllerRegister.clean();
174+
this.mcpControllerRegister?.clean();
169175
}
170176
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ class InnerSSEServerTransport extends SSEServerTransport {
7070
// eslint-disable-next-line @typescript-eslint/no-use-before-define
7171
const map = MCPControllerRegister.instance?.sseTransportsRequestMap.get(this);
7272
if (map && 'id' in message) {
73-
const { resolve, reject } = map[message.id] ?? {};
73+
const { resolve, reject } = map[message.id!] ?? {};
7474
if (resolve) {
7575
res ? reject(res) : resolve(res);
76-
delete map[message.id];
76+
delete map[String(message.id)];
7777
}
7878
}
7979
}

plugin/controller/test/mcp/helper.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
77
import * as z from 'zod/v4';
88
import assert from 'assert';
99

10-
import { MCPServerHelper } from '../../lib/impl/mcp/MCPServerHelper';
1110
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
1211

1312
describe('plugin/controller/test/mcp/mcp.test.ts', () => {
13+
14+
if (parseInt(process.versions.node, 10) < 18) {
15+
return;
16+
}
17+
18+
// eslint-disable-next-line @typescript-eslint/no-var-requires
19+
const { MCPServerHelper } = require('../../lib/impl/mcp/MCPServerHelper');
1420
it('MCPServerHelper should work', async () => {
1521
const PromptType = {
1622
name: z.string(),

plugin/mcp-client/test/fixtures/streamable-mcp-server/http.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import http from 'node:http';
22

33
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4-
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
54
import * as z from 'zod/v4';
65

76
// Create an MCP server
@@ -38,6 +37,8 @@ export const headers = {};
3837
export let httpServer;
3938
export async function startStreamableServer(port = 17243) {
4039
const httpServer = http.createServer(async (req, res) => {
40+
// eslint-disable-next-line @typescript-eslint/no-var-requires
41+
const { StreamableHTTPServerTransport } = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
4142
const url = new URL(`http://127.0.0.1:${port}${req.url!}`);
4243
const headerKey = `${req.method}${url.pathname}`;
4344
const serverCode = req.headers['x-mcp-server-code'] as string;
@@ -46,7 +47,7 @@ export async function startStreamableServer(port = 17243) {
4647
headers[serverCode][headerKey].push(req.headers);
4748
if (req.method === 'POST') {
4849
try {
49-
const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
50+
const transport: typeof StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
5051
sessionIdGenerator: undefined,
5152
});
5253
await server.connect(transport);

0 commit comments

Comments
 (0)