@z_ai/mcp-server 0.0.13 → 0.0.14-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -35
- package/README.zh-CN.md +2 -30
- package/build/{utils/common.js → core/api-common.js} +0 -2
- package/build/core/chat-service.js +6 -7
- package/build/core/environment.js +17 -57
- package/build/index.js +7 -1
- package/build/tools/image-analysis.js +4 -15
- package/build/tools/video-analysis.js +4 -15
- package/build/utils/logger.js +89 -11
- package/build/{core → utils}/validation.js +1 -16
- package/package.json +12 -8
- /package/build/{core → types}/validation-types.js +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# ZAI MCP Server
|
|
2
2
|
|
|
3
|
-
[中文文档](https://docs.bigmodel.cn//cn/guide/tools/mcp-server) | [English Document](https://docs.z.ai/guides/tools/mcp-server)
|
|
4
|
-
|
|
5
3
|
A Model Context Protocol (MCP) server that provides AI capabilities powered by Z.AI.
|
|
6
4
|
|
|
7
5
|
## Environment Variables
|
|
@@ -9,55 +7,32 @@ A Model Context Protocol (MCP) server that provides AI capabilities powered by Z
|
|
|
9
7
|
- `Z_AI_MODE` - The platform to use for AI services (default: `ZHIPU`) ZHIPU or ZAI
|
|
10
8
|
- `Z_AI_API_KEY` - Your API key
|
|
11
9
|
|
|
12
|
-
For ZAI: Use ZAI platform https://z.ai/model-api
|
|
13
|
-
|
|
10
|
+
For ZAI: Use ZAI platform https://z.ai/model-api
|
|
11
|
+
|
|
12
|
+
For ZHIPU: Use Zhipu AI platform https://bigmodel.cn
|
|
14
13
|
|
|
15
14
|
## Usage
|
|
16
15
|
|
|
17
16
|
### Use this MCP Server in Claude Code
|
|
18
17
|
|
|
19
|
-
It is recommended to use the version Node.js
|
|
18
|
+
It is recommended to use the version Node.js 18+, Claude Code 2.0.14+.
|
|
19
|
+
|
|
20
|
+
**Note**: You need to configure `Z_AI_MODE` as `ZAI` or `ZHIPU` depending on the platform.
|
|
20
21
|
|
|
21
22
|
For ZAI Use,
|
|
22
23
|
|
|
23
24
|
```shell
|
|
24
|
-
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key Z_AI_MODE=ZAI -- npx -y @z_ai/mcp-server
|
|
25
|
+
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key Z_AI_MODE=ZAI -- npx -y "@z_ai/mcp-server"
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
For ZHIPU Use,
|
|
28
29
|
|
|
29
30
|
```shell
|
|
30
|
-
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key Z_AI_MODE=ZHIPU -- npx -y @z_ai/mcp-server
|
|
31
|
+
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key Z_AI_MODE=ZHIPU -- npx -y "@z_ai/mcp-server"
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
### Use this MCP Server in Others MCP Client
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```json
|
|
38
|
-
{
|
|
39
|
-
"mcpServers": {
|
|
40
|
-
"zai-mcp-server": {
|
|
41
|
-
"type": "stdio",
|
|
42
|
-
"command": "npx",
|
|
43
|
-
"args": [
|
|
44
|
-
"-y",
|
|
45
|
-
"@z_ai/mcp-server"
|
|
46
|
-
],
|
|
47
|
-
"env": {
|
|
48
|
-
"Z_AI_API_KEY": "your_api_key",
|
|
49
|
-
"Z_AI_MODE": "ZHIPU"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Run with MCP Inspector
|
|
57
|
-
|
|
58
|
-
```
|
|
59
|
-
node ./build/index.js
|
|
60
|
-
|
|
61
|
-
npx @modelcontextprotocol/inspector node ./build/index.js
|
|
36
|
+
For Z.ai Use, refer the [Vision MCP Doc](https://docs.z.ai/devpack/mcp/vision-mcp-server)
|
|
62
37
|
|
|
63
|
-
|
|
38
|
+
For ZhiPU Use, refer the [Vision MCP Doc](https://docs.bigmodel.cn/cn/coding-plan/mcp/vision-mcp-server)
|
package/README.zh-CN.md
CHANGED
|
@@ -30,37 +30,9 @@ npm i @z_ai/mcp-server
|
|
|
30
30
|
### 在 Claude Code 中使用此 MCP 服务器
|
|
31
31
|
|
|
32
32
|
```shell
|
|
33
|
-
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key -- npx -y @z_ai/mcp-server
|
|
33
|
+
claude mcp add zai-mcp-server --env Z_AI_API_KEY=your_api_key -- npx -y "@z_ai/mcp-server"
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
### 在其他客户端中使用此 MCP 服务器
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
"mcpServers": {
|
|
41
|
-
"zai-mcp-server": {
|
|
42
|
-
"type": "stdio",
|
|
43
|
-
"command": "npx",
|
|
44
|
-
"args": [
|
|
45
|
-
"-y",
|
|
46
|
-
"@z_ai/mcp-server"
|
|
47
|
-
],
|
|
48
|
-
"env": {
|
|
49
|
-
"Z_AI_API_KEY": "your_api_key",
|
|
50
|
-
"Z_AI_MODE": "ZHIPU"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### 使用 MCP Inspector 运行
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
pnpm build
|
|
61
|
-
|
|
62
|
-
node ./build/index.js
|
|
63
|
-
|
|
64
|
-
npx @modelcontextprotocol/inspector node ./build/index.js
|
|
65
|
-
|
|
66
|
-
```
|
|
38
|
+
参考文档 [视觉理解 MCP](https://docs.bigmodel.cn/cn/coding-plan/mcp/vision-mcp-server)
|
|
@@ -12,19 +12,18 @@ export class ChatService {
|
|
|
12
12
|
/**
|
|
13
13
|
* ZAI chat completions API for vision analysis
|
|
14
14
|
*/
|
|
15
|
-
async visionCompletions(messages
|
|
15
|
+
async visionCompletions(messages) {
|
|
16
16
|
const visionConfig = configurationService.getVisionConfig();
|
|
17
|
-
const modelName = this.environmentService.getModelName('vision');
|
|
18
17
|
const requestBody = {
|
|
19
|
-
model:
|
|
18
|
+
model: visionConfig.model,
|
|
20
19
|
messages,
|
|
21
20
|
thinking: { type: 'enabled' },
|
|
22
21
|
stream: false,
|
|
23
|
-
temperature:
|
|
24
|
-
top_p:
|
|
25
|
-
|
|
22
|
+
temperature: visionConfig.temperature,
|
|
23
|
+
top_p: visionConfig.topP,
|
|
24
|
+
max_tokens: visionConfig.maxTokens
|
|
26
25
|
};
|
|
27
|
-
console.info('Request ZAI chat completions API for vision analysis', { model:
|
|
26
|
+
console.info('Request ZAI chat completions API for vision analysis', { model: visionConfig.model, messageCount: messages.length });
|
|
28
27
|
try {
|
|
29
28
|
const response = await this.chatCompletions(visionConfig.url, requestBody);
|
|
30
29
|
const result = response.choices?.[0]?.message?.content;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import * as dotenv from 'dotenv';
|
|
4
1
|
import { ApiError } from '../types/index.js';
|
|
5
2
|
/**
|
|
6
3
|
* Environment configuration service using singleton pattern
|
|
@@ -28,25 +25,14 @@ export class EnvironmentService {
|
|
|
28
25
|
return this.config;
|
|
29
26
|
}
|
|
30
27
|
/**
|
|
31
|
-
* Load environment configuration from
|
|
28
|
+
* Load environment configuration from process.env
|
|
32
29
|
*/
|
|
33
30
|
loadEnvironmentConfig() {
|
|
34
31
|
const envConfig = { ...process.env };
|
|
35
|
-
const envPaths = [
|
|
36
|
-
path.join(process.cwd(), '.env'),
|
|
37
|
-
path.join(path.dirname(import.meta.dirname), '..', '.env'),
|
|
38
|
-
];
|
|
39
|
-
for (const envPath of envPaths) {
|
|
40
|
-
if (fs.existsSync(envPath)) {
|
|
41
|
-
const env = dotenv.parse(fs.readFileSync(envPath));
|
|
42
|
-
Object.assign(envConfig, env);
|
|
43
|
-
console.debug('Loaded environment file', { path: envPath });
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
32
|
if (!envConfig.Z_AI_BASE_URL) {
|
|
47
33
|
// for z.ai paas is https://api.z.ai/api/paas/v4/
|
|
48
34
|
// for zhipuai is https://open.bigmodel.cn/api/paas/v4/
|
|
49
|
-
envConfig.Z_AI_BASE_URL = 'https://
|
|
35
|
+
envConfig.Z_AI_BASE_URL = 'https://open.bigmodel.cn/api/paas/v4/';
|
|
50
36
|
}
|
|
51
37
|
if (envConfig.PLATFORM_MODE != null) {
|
|
52
38
|
console.info('Running in mode', { mode: envConfig.PLATFORM_MODE });
|
|
@@ -64,53 +50,34 @@ export class EnvironmentService {
|
|
|
64
50
|
envConfig.PLATFORM_MODE = 'ZHIPU';
|
|
65
51
|
}
|
|
66
52
|
if (!envConfig.Z_AI_API_KEY) {
|
|
67
|
-
|
|
53
|
+
if (envConfig.ZAI_API_KEY) {
|
|
54
|
+
envConfig.Z_AI_API_KEY = envConfig.ZAI_API_KEY;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new ApiError('Z_AI_API_KEY environment variable is required');
|
|
58
|
+
}
|
|
68
59
|
}
|
|
69
60
|
return {
|
|
70
61
|
Z_AI_BASE_URL: envConfig.Z_AI_BASE_URL,
|
|
71
62
|
Z_AI_API_KEY: envConfig.Z_AI_API_KEY,
|
|
72
63
|
Z_AI_VISION_MODEL: envConfig.Z_AI_VISION_MODEL,
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
Z_AI_VISION_MODEL_TEMPERATURE: envConfig.Z_AI_VISION_MODEL_TEMPERATURE,
|
|
65
|
+
Z_AI_VISION_MODEL_TOP_P: envConfig.Z_AI_VISION_MODEL_TOP_P,
|
|
66
|
+
Z_AI_VISION_MODEL_MAX_TOKENS: envConfig.Z_AI_VISION_MODEL_MAX_TOKENS,
|
|
75
67
|
Z_AI_TIMEOUT: envConfig.Z_AI_TIMEOUT,
|
|
76
68
|
Z_AI_RETRY_COUNT: envConfig.Z_AI_RETRY_COUNT,
|
|
77
|
-
Z_AI_TEMPERATURE: envConfig.Z_AI_TEMPERATURE,
|
|
78
|
-
Z_AI_TOP_P: envConfig.Z_AI_TOP_P,
|
|
79
|
-
Z_AI_MAX_TOKENS: envConfig.Z_AI_MAX_TOKENS,
|
|
80
69
|
SERVER_NAME: envConfig.SERVER_NAME,
|
|
81
70
|
SERVER_VERSION: envConfig.SERVER_VERSION,
|
|
82
71
|
PLATFORM_MODE: envConfig.PLATFORM_MODE
|
|
83
72
|
};
|
|
84
73
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Get model configuration (implements ConfigurationService)
|
|
87
|
-
*/
|
|
88
|
-
getModelConfig(type) {
|
|
89
|
-
const modelName = this.getModelName(type === 'image' ? 'vision' : type === 'video' ? 'vision' : 'image');
|
|
90
|
-
return {
|
|
91
|
-
name: modelName,
|
|
92
|
-
version: '1.0.0',
|
|
93
|
-
capabilities: this.getCapabilitiesForModel(type)
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get capabilities for model type
|
|
98
|
-
*/
|
|
99
|
-
getCapabilitiesForModel(type) {
|
|
100
|
-
const capabilityMap = {
|
|
101
|
-
image: ['image_analysis', 'multimodal_understanding'],
|
|
102
|
-
video: ['video_analysis', 'temporal_understanding'],
|
|
103
|
-
generation: ['image_generation', 'creative_synthesis']
|
|
104
|
-
};
|
|
105
|
-
return capabilityMap[type] || [];
|
|
106
|
-
}
|
|
107
74
|
/**
|
|
108
75
|
* Get server configuration
|
|
109
76
|
*/
|
|
110
77
|
getServerConfig() {
|
|
111
78
|
const config = this.getConfig();
|
|
112
79
|
return {
|
|
113
|
-
name: config.SERVER_NAME || 'zai-mcp',
|
|
80
|
+
name: config.SERVER_NAME || 'zai-mcp-server',
|
|
114
81
|
version: config.SERVER_VERSION || '0.1.0'
|
|
115
82
|
};
|
|
116
83
|
}
|
|
@@ -127,12 +94,13 @@ export class EnvironmentService {
|
|
|
127
94
|
getVisionConfig() {
|
|
128
95
|
const config = this.getConfig();
|
|
129
96
|
return {
|
|
97
|
+
model: config.Z_AI_VISION_MODEL || 'glm-4.5v',
|
|
130
98
|
timeout: parseInt(config.Z_AI_TIMEOUT || '300000'),
|
|
131
|
-
retryCount: parseInt(config.Z_AI_RETRY_COUNT || '
|
|
99
|
+
retryCount: parseInt(config.Z_AI_RETRY_COUNT || '1'),
|
|
132
100
|
url: config.Z_AI_BASE_URL + 'chat/completions',
|
|
133
|
-
temperature: parseFloat(config.
|
|
134
|
-
topP: parseFloat(config.
|
|
135
|
-
maxTokens: parseInt(config.
|
|
101
|
+
temperature: parseFloat(config.Z_AI_VISION_MODEL_TEMPERATURE || '0.8'),
|
|
102
|
+
topP: parseFloat(config.Z_AI_VISION_MODEL_TOP_P || '0.6'),
|
|
103
|
+
maxTokens: parseInt(config.Z_AI_VISION_MODEL_MAX_TOKENS || '16384')
|
|
136
104
|
};
|
|
137
105
|
}
|
|
138
106
|
/**
|
|
@@ -141,14 +109,6 @@ export class EnvironmentService {
|
|
|
141
109
|
getApiKey() {
|
|
142
110
|
return this.getConfig().Z_AI_API_KEY;
|
|
143
111
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Get model name for specific type (image, file)
|
|
146
|
-
*/
|
|
147
|
-
getModelName(type) {
|
|
148
|
-
const config = this.getConfig();
|
|
149
|
-
const envVar = `Z_AI_${type.toUpperCase()}_MODEL`;
|
|
150
|
-
return config[envVar] || `glm-4.5v`; // Default fallback
|
|
151
|
-
}
|
|
152
112
|
}
|
|
153
113
|
/**
|
|
154
114
|
* Global environment service instance
|
package/build/index.js
CHANGED
|
@@ -9,6 +9,7 @@ setupConsoleRedirection();
|
|
|
9
9
|
// Import tool registration functions
|
|
10
10
|
import { registerImageAnalysisTool } from './tools/image-analysis.js';
|
|
11
11
|
import { registerVideoAnalysisTool } from './tools/video-analysis.js';
|
|
12
|
+
import { McpError } from "./types/index.js";
|
|
12
13
|
/**
|
|
13
14
|
* MCP Server Application class
|
|
14
15
|
*/
|
|
@@ -145,7 +146,12 @@ async function main() {
|
|
|
145
146
|
await app.start();
|
|
146
147
|
}
|
|
147
148
|
catch (error) {
|
|
148
|
-
|
|
149
|
+
if (error instanceof McpError) {
|
|
150
|
+
console.error('Application startup failed:', { message: error.message });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.error('Application startup failed:', { error });
|
|
154
|
+
}
|
|
149
155
|
process.exit(1);
|
|
150
156
|
}
|
|
151
157
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
3
|
import { ToolExecutionError } from '../core/error-handler.js';
|
|
4
|
-
import { CommonSchemas, ToolSchemaBuilder } from '../
|
|
5
|
-
import { createMultiModalMessage, createImageContent, formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../
|
|
4
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
5
|
+
import { createMultiModalMessage, createImageContent, formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
6
6
|
import { fileService } from '../core/file-service.js';
|
|
7
7
|
import { chatService } from '../core/chat-service.js';
|
|
8
8
|
/**
|
|
@@ -46,13 +46,7 @@ export class ImageAnalysisService {
|
|
|
46
46
|
}
|
|
47
47
|
// Create multimodal message
|
|
48
48
|
const messages = createMultiModalMessage([imageContent], request.prompt);
|
|
49
|
-
|
|
50
|
-
const analysisOptions = {
|
|
51
|
-
temperature: request.options?.temperature,
|
|
52
|
-
topP: request.options?.topP,
|
|
53
|
-
maxTokens: request.options?.maxTokens
|
|
54
|
-
};
|
|
55
|
-
const result = await this.chatService.visionCompletions(messages, analysisOptions);
|
|
49
|
+
const result = await this.chatService.visionCompletions(messages);
|
|
56
50
|
console.info('Image analysis completed', {
|
|
57
51
|
imageSource: request.imageSource
|
|
58
52
|
});
|
|
@@ -98,12 +92,7 @@ export function registerImageAnalysisTool(server) {
|
|
|
98
92
|
// Build request object
|
|
99
93
|
const request = {
|
|
100
94
|
imageSource: params.image_source,
|
|
101
|
-
prompt: params.prompt
|
|
102
|
-
options: {
|
|
103
|
-
temperature: params.temperature,
|
|
104
|
-
topP: params.top_p,
|
|
105
|
-
maxTokens: params.max_tokens
|
|
106
|
-
}
|
|
95
|
+
prompt: params.prompt
|
|
107
96
|
};
|
|
108
97
|
// Execute analysis
|
|
109
98
|
const result = await retryableAnalyze(request);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { FileNotFoundError, ApiError } from '../types/index.js';
|
|
3
3
|
import { ToolExecutionError } from '../core/error-handler.js';
|
|
4
|
-
import { CommonSchemas, ToolSchemaBuilder } from '../
|
|
5
|
-
import { createMultiModalMessage, createVideoContent, formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../
|
|
4
|
+
import { CommonSchemas, ToolSchemaBuilder } from '../utils/validation.js';
|
|
5
|
+
import { createMultiModalMessage, createVideoContent, formatMcpResponse, createSuccessResponse, createErrorResponse, withRetry } from '../core/api-common.js';
|
|
6
6
|
import { fileService } from '../core/file-service.js';
|
|
7
7
|
import { chatService } from '../core/chat-service.js';
|
|
8
8
|
/**
|
|
@@ -46,13 +46,7 @@ export class VideoAnalysisService {
|
|
|
46
46
|
}
|
|
47
47
|
// Create multimodal message
|
|
48
48
|
const messages = createMultiModalMessage([videoContent], request.prompt);
|
|
49
|
-
|
|
50
|
-
const analysisOptions = {
|
|
51
|
-
temperature: request.options?.temperature,
|
|
52
|
-
topP: request.options?.topP,
|
|
53
|
-
maxTokens: request.options?.maxTokens
|
|
54
|
-
};
|
|
55
|
-
const result = await this.chatService.visionCompletions(messages, analysisOptions);
|
|
49
|
+
const result = await this.chatService.visionCompletions(messages);
|
|
56
50
|
console.info('Video analysis completed', {
|
|
57
51
|
videoSource: request.videoSource
|
|
58
52
|
});
|
|
@@ -98,12 +92,7 @@ export function registerVideoAnalysisTool(server) {
|
|
|
98
92
|
// Build request object
|
|
99
93
|
const request = {
|
|
100
94
|
videoSource: params.video_source,
|
|
101
|
-
prompt: params.prompt
|
|
102
|
-
options: {
|
|
103
|
-
temperature: params.temperature,
|
|
104
|
-
topP: params.top_p,
|
|
105
|
-
maxTokens: params.max_tokens
|
|
106
|
-
}
|
|
95
|
+
prompt: params.prompt
|
|
107
96
|
};
|
|
108
97
|
// Execute analysis
|
|
109
98
|
const result = await retryableAnalyze(request);
|
package/build/utils/logger.js
CHANGED
|
@@ -1,29 +1,90 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Logger utility that
|
|
3
|
-
*
|
|
2
|
+
* Logger utility that writes to stderr and a log file.
|
|
3
|
+
* Stderr keeps MCP JSON on stdout clean; file provides persistent logs.
|
|
4
4
|
*/
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as os from 'os';
|
|
5
8
|
class Logger {
|
|
6
|
-
|
|
9
|
+
logStream;
|
|
10
|
+
logFilePath;
|
|
11
|
+
constructor(logFilePath) {
|
|
12
|
+
if (logFilePath) {
|
|
13
|
+
this.setLogFile(logFilePath);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
setLogFile(logFilePath) {
|
|
17
|
+
try {
|
|
18
|
+
this.logFilePath = logFilePath;
|
|
19
|
+
const dir = path.dirname(logFilePath);
|
|
20
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
21
|
+
if (this.logStream) {
|
|
22
|
+
this.logStream.end();
|
|
23
|
+
}
|
|
24
|
+
this.logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const timestamp = new Date().toISOString();
|
|
28
|
+
const msg = `[${timestamp}] ERROR: Failed to initialize log file '${logFilePath}': ${String(err)}`;
|
|
29
|
+
process.stderr.write(msg + '\n');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
safeStringify(obj) {
|
|
33
|
+
// Serialize Error objects so that message/stack and custom fields are visible
|
|
34
|
+
const replacer = (_key, value) => {
|
|
35
|
+
if (value instanceof Error) {
|
|
36
|
+
const base = {
|
|
37
|
+
name: value.name,
|
|
38
|
+
message: value.message,
|
|
39
|
+
stack: value.stack
|
|
40
|
+
};
|
|
41
|
+
// Include enumerable own properties (e.g., code, statusCode, details, context)
|
|
42
|
+
for (const k of Object.keys(value)) {
|
|
43
|
+
if (!(k in base)) {
|
|
44
|
+
base[k] = value[k];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return base;
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
};
|
|
51
|
+
try {
|
|
52
|
+
return JSON.stringify(obj, replacer);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
try {
|
|
56
|
+
return String(obj);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return '[Unserializable]';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
write(level, message, ...args) {
|
|
7
64
|
const timestamp = new Date().toISOString();
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
65
|
+
const serializedArgs = args.length > 0 ? ` ${this.safeStringify(args)}` : '';
|
|
66
|
+
const logMessage = `[${timestamp}] ${level.toUpperCase()}: ${message}${serializedArgs}`;
|
|
67
|
+
// Write to stderr (visible console output without polluting stdout)
|
|
11
68
|
process.stderr.write(logMessage + '\n');
|
|
69
|
+
// Write to log file if configured
|
|
70
|
+
if (this.logStream) {
|
|
71
|
+
this.logStream.write(logMessage + '\n');
|
|
72
|
+
}
|
|
12
73
|
}
|
|
13
74
|
info(message, ...args) {
|
|
14
|
-
this.
|
|
75
|
+
this.write('info', message, ...args);
|
|
15
76
|
}
|
|
16
77
|
error(message, ...args) {
|
|
17
|
-
this.
|
|
78
|
+
this.write('error', message, ...args);
|
|
18
79
|
}
|
|
19
80
|
warn(message, ...args) {
|
|
20
|
-
this.
|
|
81
|
+
this.write('warn', message, ...args);
|
|
21
82
|
}
|
|
22
83
|
debug(message, ...args) {
|
|
23
|
-
this.
|
|
84
|
+
this.write('debug', message, ...args);
|
|
24
85
|
}
|
|
25
86
|
log(message, ...args) {
|
|
26
|
-
this.
|
|
87
|
+
this.write('info', message, ...args);
|
|
27
88
|
}
|
|
28
89
|
}
|
|
29
90
|
export const logger = new Logger();
|
|
@@ -33,6 +94,23 @@ export const logger = new Logger();
|
|
|
33
94
|
*/
|
|
34
95
|
export function setupConsoleRedirection() {
|
|
35
96
|
const originalConsole = { ...console };
|
|
97
|
+
// Cross-platform log file path:
|
|
98
|
+
// - If env ZAI_MCP_LOG_PATH is set, use it
|
|
99
|
+
// - Otherwise use user home directory: ~/.zai/zai-mcp-YYYY-MM-DD.log (Windows/macOS/Linux)
|
|
100
|
+
const resolveLogFilePath = () => {
|
|
101
|
+
const envPath = process.env.ZAI_MCP_LOG_PATH;
|
|
102
|
+
if (envPath && envPath.trim().length > 0) {
|
|
103
|
+
return path.resolve(envPath);
|
|
104
|
+
}
|
|
105
|
+
const homeDir = os.homedir();
|
|
106
|
+
const now = new Date();
|
|
107
|
+
const yyyy = now.getFullYear();
|
|
108
|
+
const mm = String(now.getMonth() + 1).padStart(2, '0');
|
|
109
|
+
const dd = String(now.getDate()).padStart(2, '0');
|
|
110
|
+
const dateStr = `${yyyy}-${mm}-${dd}`;
|
|
111
|
+
return path.join(homeDir, '.zai', `zai-mcp-${dateStr}.log`);
|
|
112
|
+
};
|
|
113
|
+
logger.setLogFile(resolveLogFilePath());
|
|
36
114
|
console.info = logger.info.bind(logger);
|
|
37
115
|
console.error = logger.error.bind(logger);
|
|
38
116
|
console.warn = logger.warn.bind(logger);
|
|
@@ -161,13 +161,7 @@ export const CommonSchemas = {
|
|
|
161
161
|
/** File path */
|
|
162
162
|
filePath: z.string().min(1).refine((path) => !path.includes('..'), 'File path cannot contain ".."'),
|
|
163
163
|
/** Tool name */
|
|
164
|
-
toolName: z.string().regex(/^[a-z][a-z0-9-]*[a-z0-9]$/, 'Tool name must be lowercase, start with letter, and contain only letters, numbers, and hyphens')
|
|
165
|
-
/** API key */
|
|
166
|
-
apiKey: z.string().min(10, 'API key must be at least 10 characters'),
|
|
167
|
-
/** Temperature parameter */
|
|
168
|
-
temperature: z.number().min(0).max(2, 'Temperature must be between 0 and 2'),
|
|
169
|
-
/** Maximum token count */
|
|
170
|
-
maxTokens: z.number().int().min(1).max(4096, 'Max tokens must be between 1 and 4096')
|
|
164
|
+
toolName: z.string().regex(/^[a-z][a-z0-9-]*[a-z0-9]$/, 'Tool name must be lowercase, start with letter, and contain only letters, numbers, and hyphens')
|
|
171
165
|
};
|
|
172
166
|
/**
|
|
173
167
|
* Tool parameter validation schema builder
|
|
@@ -202,12 +196,3 @@ export class ToolSchemaBuilder {
|
|
|
202
196
|
return z.object(this.schema);
|
|
203
197
|
}
|
|
204
198
|
}
|
|
205
|
-
/**
|
|
206
|
-
* Global validator instance
|
|
207
|
-
*/
|
|
208
|
-
export const validator = RuntimeValidator;
|
|
209
|
-
/**
|
|
210
|
-
* Convenient validation functions
|
|
211
|
-
*/
|
|
212
|
-
export const validate = RuntimeValidator.validate.bind(RuntimeValidator);
|
|
213
|
-
export const safeValidate = RuntimeValidator.safeValidate.bind(RuntimeValidator);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@z_ai/mcp-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14-beta.0",
|
|
4
4
|
"description": "MCP Server for Z.AI - A Model Context Protocol server that provides AI capabilities",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -14,15 +14,20 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "tsc && chmod 755 build/index.js",
|
|
16
16
|
"start": "node build/index.js",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
17
|
+
"prepare": "npm run build",
|
|
18
|
+
"prerelease": "npm version prerelease --preid=beta",
|
|
19
|
+
"publish-beta": "npm publish --tag beta",
|
|
20
|
+
"publish": "npm publish"
|
|
20
21
|
},
|
|
21
22
|
"keywords": [
|
|
22
23
|
"zai",
|
|
23
|
-
"mcp"
|
|
24
|
+
"mcp",
|
|
25
|
+
"vision"
|
|
24
26
|
],
|
|
25
27
|
"author": "Z.AI",
|
|
28
|
+
"contributors": [
|
|
29
|
+
"Chao Gong (https://github.com/tomsun28)"
|
|
30
|
+
],
|
|
26
31
|
"license": "Apache-2.0",
|
|
27
32
|
"files": [
|
|
28
33
|
"build",
|
|
@@ -30,15 +35,14 @@
|
|
|
30
35
|
"README.md"
|
|
31
36
|
],
|
|
32
37
|
"engines": {
|
|
33
|
-
"node": ">=
|
|
38
|
+
"node": ">=18.0.0"
|
|
34
39
|
},
|
|
35
40
|
"publishConfig": {
|
|
36
41
|
"access": "public"
|
|
37
42
|
},
|
|
38
43
|
"dependencies": {
|
|
39
44
|
"zod": "^3.23.8",
|
|
40
|
-
"@modelcontextprotocol/sdk": "1.17.5"
|
|
41
|
-
"dotenv": "17.2.2"
|
|
45
|
+
"@modelcontextprotocol/sdk": "1.17.5"
|
|
42
46
|
},
|
|
43
47
|
"devDependencies": {
|
|
44
48
|
"@types/node": "24.3.1",
|
|
File without changes
|