Skip to content

Commit 5371cb7

Browse files
authored
fix: missing mcp logger config (#4413)
* fix: mcp logger * fix: lint
1 parent fac2a20 commit 5371cb7

File tree

4 files changed

+222
-3
lines changed

4 files changed

+222
-3
lines changed

packages/mcp/src/configuration.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ import { MidwayMCPFramework } from './framework';
1919
messages: '/messages',
2020
},
2121
},
22+
midwayLogger: {
23+
clients: {
24+
mcpLogger: {
25+
fileLogName: 'midway-mcp.log',
26+
},
27+
},
28+
},
2229
},
2330
},
2431
],

packages/mcp/test/index.test.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,4 +674,164 @@ describe('/test/index.test.ts', () => {
674674
}
675675
}
676676
});
677+
678+
it('should test Tool with complex parameters', async () => {
679+
const clientManager = new SSEMCPClientManager();
680+
let app: any;
681+
682+
try {
683+
// Start the app server with Tool that requires complex parameters
684+
@mcp.Tool('complexParamTool', {
685+
description: 'Tool that accepts complex parameters including nested objects and arrays',
686+
inputSchema: {
687+
user: z.object({
688+
name: z.string().describe('User name'),
689+
age: z.number().describe('User age'),
690+
email: z.string().email().describe('User email')
691+
}).describe('User information'),
692+
preferences: z.array(z.string()).describe('User preferences'),
693+
metadata: z.object({
694+
source: z.string().describe('Data source'),
695+
timestamp: z.string().optional().describe('Optional timestamp')
696+
}).optional().describe('Optional metadata'),
697+
action: z.enum(['create', 'update', 'delete']).describe('Action to perform')
698+
}
699+
})
700+
class ComplexParamTool implements mcp.IMcpTool {
701+
name = 'complexParamTool';
702+
703+
async execute(args: any): Promise<CallToolResult> {
704+
const { user, preferences, metadata, action } = args;
705+
706+
const result = {
707+
action,
708+
user: `${user.name} (${user.age}, ${user.email})`,
709+
preferences: preferences.join(', '),
710+
metadata: metadata ? `Source: ${metadata.source}${metadata.timestamp ? `, Time: ${metadata.timestamp}` : ''}` : 'No metadata'
711+
};
712+
713+
return {
714+
content: [{
715+
type: 'text',
716+
text: `Action: ${result.action}\nUser: ${result.user}\nPreferences: ${result.preferences}\nMetadata: ${result.metadata}`
717+
}]
718+
};
719+
}
720+
}
721+
722+
app = await createApp({
723+
baseDir: null,
724+
imports: [
725+
express,
726+
mcp,
727+
],
728+
preloadModules: [
729+
ComplexParamTool,
730+
],
731+
globalConfig: {
732+
express: {
733+
keys: ['test'],
734+
port: 7010,
735+
},
736+
mcp: {
737+
serverInfo: {
738+
name: 'test-complex-param-mcp',
739+
version: '1.0.0',
740+
},
741+
transportType: 'stream-http',
742+
}
743+
},
744+
loggerFactory: new DefaultConsoleLoggerFactory(),
745+
});
746+
747+
// Create StreamHTTP MCP client
748+
const client = await clientManager.createTestStreamHTTPClient('http://localhost:7010/mcp', 'test-complex-param-client');
749+
750+
// List tools
751+
const { tools } = await client.listTools();
752+
const complexTool = tools.find(tool => tool.name === 'complexParamTool');
753+
754+
if (!complexTool) {
755+
throw new Error('complexParamTool should be available');
756+
}
757+
758+
// Test with all parameters
759+
const fullResult = await client.callTool({
760+
name: 'complexParamTool',
761+
arguments: {
762+
user: {
763+
name: 'John Doe',
764+
age: 30,
765+
email: 'john@example.com'
766+
},
767+
preferences: ['coding', 'reading', 'gaming'],
768+
metadata: {
769+
source: 'api',
770+
timestamp: '2023-01-01T00:00:00Z'
771+
},
772+
action: 'create'
773+
}
774+
});
775+
776+
if (!fullResult.content || !fullResult.content[0]?.text?.includes('Action: create') ||
777+
!fullResult.content[0]?.text?.includes('User: John Doe (30, john@example.com)') ||
778+
!fullResult.content[0]?.text?.includes('Preferences: coding, reading, gaming') ||
779+
!fullResult.content[0]?.text?.includes('Source: api, Time: 2023-01-01T00:00:00Z')) {
780+
throw new Error('Tool should return expected result with full parameters');
781+
}
782+
783+
// Test with optional parameter omitted
784+
const partialResult = await client.callTool({
785+
name: 'complexParamTool',
786+
arguments: {
787+
user: {
788+
name: 'Jane Smith',
789+
age: 25,
790+
email: 'jane@example.com'
791+
},
792+
preferences: ['music', 'travel'],
793+
action: 'update'
794+
}
795+
});
796+
797+
if (!partialResult.content || !partialResult.content[0]?.text?.includes('Action: update') ||
798+
!partialResult.content[0]?.text?.includes('User: Jane Smith (25, jane@example.com)') ||
799+
!partialResult.content[0]?.text?.includes('Preferences: music, travel') ||
800+
!partialResult.content[0]?.text?.includes('Metadata: No metadata')) {
801+
throw new Error('Tool should work with optional parameters omitted');
802+
}
803+
804+
// Test with partial metadata (timestamp omitted)
805+
const partialMetadataResult = await client.callTool({
806+
name: 'complexParamTool',
807+
arguments: {
808+
user: {
809+
name: 'Bob Wilson',
810+
age: 35,
811+
email: 'bob@example.com'
812+
},
813+
preferences: ['sports'],
814+
metadata: {
815+
source: 'database'
816+
},
817+
action: 'delete'
818+
}
819+
});
820+
821+
if (!partialMetadataResult.content || !partialMetadataResult.content[0]?.text?.includes('Action: delete') ||
822+
!partialMetadataResult.content[0]?.text?.includes('User: Bob Wilson (35, bob@example.com)') ||
823+
!partialMetadataResult.content[0]?.text?.includes('Preferences: sports') ||
824+
!partialMetadataResult.content[0]?.text?.includes('Source: database') ||
825+
partialMetadataResult.content[0]?.text?.includes('Time:')) {
826+
throw new Error('Tool should work with partial metadata (timestamp omitted)');
827+
}
828+
829+
} finally {
830+
// Ensure cleanup always happens
831+
await clientManager.closeAllClients();
832+
if (app) {
833+
await close(app);
834+
}
835+
}
836+
});
677837
})

site/docs/extensions/mcp.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,24 @@ $ npm i @midwayjs/mcp@4 --save
3737
$ npm i @modelcontextprotocol/sdk zod --save
3838
```
3939

40+
:::warning
41+
**⚠️ Zod 版本兼容性重要提示**
42+
43+
MCP SDK (`@modelcontextprotocol/sdk`) 当前使用 Zod v3.x 版本。为确保兼容性,您的项目**必须**使用 Zod 3.x 版本,不要使用 Zod v4.x 或更高版本,否则会导致类型兼容性问题。
44+
45+
**推荐安装特定版本**
46+
```bash
47+
$ npm i zod@^3.24.1 --save
48+
```
49+
:::
50+
4051
如果使用 `sse``stream-http` 传输类型,还需要安装 HTTP 框架组件(选择其中一个):
4152

4253
```bash
4354
# Express 框架
4455
$ npm i @midwayjs/express@4 --save
4556

46-
# 或者 Koa 框架
57+
# 或者 Koa 框架
4758
$ npm i @midwayjs/koa@4 --save
4859

4960
# 或者 Egg.js 框架
@@ -57,7 +68,7 @@ $ npm i @midwayjs/web@4 --save
5768
"dependencies": {
5869
"@midwayjs/mcp": "^4.0.0",
5970
"@modelcontextprotocol/sdk": "^1.19.0",
60-
"zod": "^3.24.0",
71+
"zod": "^3.24.1",
6172
"@midwayjs/express": "^4.0.0"
6273
}
6374
}
@@ -192,6 +203,21 @@ export default {
192203
**向下兼容说明**:当服务器配置为 `stream-http` 传输类型时,传统的 SSE 客户端仍然可以通过 `/sse` 端点正常连接和通信。
193204
:::
194205

206+
### 日志配置
207+
208+
MCP 组件默认志输出,可以通过 `mcpLogger` 进一步配置日志详情。
209+
210+
```typescript
211+
// src/config/config.default.ts
212+
export default {
213+
midwayLogger: {
214+
mcpLogger: {
215+
// ...
216+
}
217+
},
218+
}
219+
```
220+
195221
## 使用方式
196222

197223
### 工具(Tools)

site/i18n/en/docusaurus-plugin-content-docs/current/extensions/mcp.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ $ npm i @midwayjs/mcp@4 --save
3737
$ npm i @modelcontextprotocol/sdk zod --save
3838
```
3939

40+
:::warning
41+
Important Zod compatibility notice
42+
43+
The MCP SDK (`@modelcontextprotocol/sdk`) currently uses Zod v3.x. To ensure compatibility, your project must use Zod 3.x. Do not use Zod v4.x or higher, otherwise type compatibility issues may occur.
44+
45+
Recommended specific version:
46+
```bash
47+
$ npm i zod@^3.24.1 --save
48+
```
49+
:::
50+
4051
If you use the `sse` or `stream-http` transport, you also need to install one of the HTTP framework components (choose one):
4152

4253
```bash
@@ -57,7 +68,7 @@ Or add the following dependencies to `package.json` and reinstall.
5768
"dependencies": {
5869
"@midwayjs/mcp": "^4.0.0",
5970
"@modelcontextprotocol/sdk": "^1.19.0",
60-
"zod": "^3.24.0",
71+
"zod": "^3.24.1",
6172
"@midwayjs/express": "^4.0.0"
6273
}
6374
}
@@ -192,6 +203,21 @@ Assuming the server runs at `http://localhost:3000`, the default endpoints are:
192203
Backward compatibility: When the server is configured with the `stream-http` transport, legacy SSE clients can still connect and communicate via the `/sse` endpoint.
193204
:::
194205

206+
### Logging configuration
207+
208+
The MCP component outputs logs by default. You can further configure logging details via `mcpLogger`.
209+
210+
```typescript
211+
// src/config/config.default.ts
212+
export default {
213+
midwayLogger: {
214+
mcpLogger: {
215+
// ...
216+
}
217+
},
218+
}
219+
```
220+
195221
## Usage
196222

197223
### Tools

0 commit comments

Comments
 (0)