引言
MiniMax MCP JS 是 MiniMax 官方提供的 Model Context Protocol (MCP) JavaScript 实现,它将 MiniMax 强大的 AI 能力(图像生成、视频生成、语音合成、声音克隆等)封装为标准的 MCP 工具,供 Claude Desktop、Cursor 等 MCP 客户端调用。本文将深入源码,剖析其从初始化到工具调用的完整技术链路。
一、MCP 服务初始化流程
1.1 入口点与启动逻辑
MiniMax MCP 的入口文件是 src/index.ts,它通过 startMiniMaxMCP 函数启动服务:
**
ts
export async function startMiniMaxMCP(customConfig?: Partial<Config>): Promise<void> {
try {
const config = ConfigManager.getConfig(customConfig);
const mode = config.server?.mode || DEFAULT_TRANSPORT_MODE;
switch (mode) {
case TRANSPORT_MODE_REST:
return new MCPRestServer(config).start();
case TRANSPORT_MODE_SSE:
return new MCPSSEServer(config).start();
case TRANSPORT_MODE_STDIO:
default:
return new MCPServer(config).start();
}
} catch (err) {
process.exit(1);
}
}
核心设计要点:
- 支持三种传输模式:STDIO(默认)、REST、SSE
- 通过
ConfigManager实现多层级配置管理 - 根据不同模式实例化对应的服务器类
1.2 配置管理机制
ConfigManager 实现了一套完善的配置优先级系统(从高到低):
**
ts
// 配置优先级:
// 1. 请求级配置(meta.auth)- 最高优先级
// 2. 命令行参数
// 3. 环境变量
// 4. 配置文件
// 5. 默认值 - 最低优先级
static getConfig(requestConfig: Partial<Config> = {}, defaultConfig: Partial<Config> = {}): Config {
const config: Config = {
apiKey: '',
apiHost: DEFAULT_API_HOST,
basePath: DesktopPath,
resourceMode: RESOURCE_MODE_URL,
server: {
port: DEFAULT_SERVER_PORT,
endpoint: DEFAULT_SERVER_ENDPOINT,
mode: TRANSPORT_MODE_STDIO,
},
};
// 按优先级依次应用配置
this.applyConfigFile(config); // 优先级 4
this.applyEnvVars(config); // 优先级 3
this.applyCliArgs(config); // 优先级 2
Object.assign(config, requestConfig); // 优先级 1
return config;
}
设计亮点:
- 支持多租户场景:每个请求可通过
meta.auth使用独立配置 - 灵活的配置方式:适配本地开发、云端部署等多种场景
- 命令行参数解析支持 kebab-case 和 camelCase 两种风格
1.3 服务器实例化
以 STDIO 模式的 MCPServer 为例,其构造函数完成了核心组件的初始化:
**
ts
constructor(config: Config) {
this.config = config;
// 创建 MCP 服务器实例
this.server = new McpServer({
name: 'minimax-mcp-js',
version: '0.0.17',
});
// 初始化 API 客户端
this.api = new MiniMaxAPI(this.config);
// 初始化各个功能 API
this.ttsApi = new TTSAPI(this.api);
this.imageApi = new ImageAPI(this.api);
this.videoApi = new VideoAPI(this.api);
this.voiceCloneApi = new VoiceCloneAPI(this.api);
this.musicApi = new MusicAPI(this.api);
this.voiceDesignApi = new VoiceDesignAPI(this.api);
// 注册所有工具
this.registerTools();
}
架构特点:
- 使用
@modelcontextprotocol/sdk提供的McpServer作为底层框架 - 采用分层设计:API 层(MiniMaxAPI)→ 功能层(TTSAPI、ImageAPI 等)→ 工具层
- 通过依赖注入方式传递配置和 API 实例
二、对外暴露的三种连接方式
2.1 STDIO 模式(本地集成)
适用场景: Claude Desktop、Cursor 等本地 MCP 客户端
实现原理:
**
ts
public async startStdioServer(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
STDIO 模式通过标准输入输出流进行通信,是最简单直接的方式:
- 优势: 零配置、低延迟、适合本地开发
- 限制: 仅支持本地进程间通信,无法跨网络访问
配置示例(Claude Desktop):
**
json
{
"mcpServers": {
"minimax-mcp-js": {
"command": "npx",
"args": ["-y", "minimax-mcp-js"],
"env": {
"MINIMAX_API_KEY": "<your-api-key>",
"MINIMAX_API_HOST": "https://api.minimaxi.chat"
}
}
}
}
2.2 REST 模式(HTTP API)
适用场景: 云端部署、跨语言调用、API 服务
实现原理:
**
ts
public async start(): Promise<void> {
const port = this.config.server?.port || 3000;
const endpoint = this.config.server?.endpoint || '/mcp';
// 创建 REST 传输层
this.transport = new RestServerTransport({
endpoint: endpoint,
port: port
});
await this.server.connect(this.transport);
await this.transport.startServer();
}
REST 模式提供标准的 HTTP 接口:
- 请求处理: 通过 Express 框架处理 HTTP 请求
- 工具调用: 客户端通过 POST 请求调用工具
- 配置提取: 支持从请求参数中提取
meta.auth配置
核心请求处理逻辑:
**
ts
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const toolName = request.params.tool;
const toolParams = request.params.params || {};
// 从请求中提取配置
const requestConfig = this.getRequestConfig(request);
const requestApi = new MiniMaxAPI(requestConfig);
// 根据工具名称分发到对应的处理函数
switch (toolName) {
case 'text_to_audio':
return await this.handleTextToAudio(toolParams, requestApi, mediaService);
case 'text_to_image':
return await this.handleTextToImage(toolParams, requestApi, mediaService);
// ... 其他工具
}
});
2.3 SSE 模式(服务器推送)
适用场景: 需要服务器主动推送、长连接场景
实现原理:
SSE 模式是最复杂的实现,包含连接管理、心跳机制、会话管理等:
**
ts
// 1. SSE 连接建立
app.get('/sse', async (req, res) => {
const transport = new SSEServerTransport(endpoint, res);
const sessionId = transport.sessionId || `session-${Date.now()}-${Math.random()}`;
// 设置 SSE 响应头
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// 启动心跳机制
const heartbeatInterval = setInterval(() => {
res.write(`event: heartbeat\ndata: ${Date.now()}\n\n`);
}, HEARTBEAT_INTERVAL);
// 保存连接信息
this.connections.set(sessionId, {
transport,
heartbeatInterval,
lastActivityTime: Date.now()
});
await this.mcpServer.connect(transport);
});
// 2. 消息处理端点
app.post(endpoint, async (req, res) => {
const sessionId = req.query.sessionId as string;
const connectionInfo = this.connections.get(sessionId);
if (connectionInfo) {
connectionInfo.lastActivityTime = Date.now();
await this.handleClientMessage(connectionInfo.transport, req, res);
}
});
SSE 模式的关键特性:
- 连接管理: 维护
connectionsMap 存储所有活跃连接 - 心跳机制: 每 30 秒发送心跳,保持连接活跃
- 超时清理: 定期检查并清理 5 分钟无活动的连接
- 重试机制: 失败请求自动重试,指数退避策略
三、工具调用完整链路
3.1 工具注册机制
所有工具通过 registerTools() 方法统一注册:
**
kotlin
TypeScript
private registerTools(): void {
this.registerTextToAudioTool();
this.registerListVoicesTool();
this.registerPlayAudioTool();
this.registerVoiceCloneTool();
this.registerTextToImageTool();
this.registerGenerateVideoTool();
this.registerImageToVideoTool();
this.registerQueryVideoGenerationTool();
this.registerMusicGenerationTool();
this.registerVoiceDesignTool();
}
以 text_to_audio 工具为例,注册过程包含三个核心部分:
**
ts
private registerTextToAudioTool(): void {
this.server.tool(
// 1. 工具名称
'text_to_audio',
// 2. 工具描述
'Convert text to speech audio file...',
// 3. 参数 Schema(使用 Zod 进行类型验证)
{
text: z.string().describe('Text to convert'),
model: z.string().optional().default('speech-02-hd'),
voiceId: z.string().optional().default('male-qn-qingse'),
speed: z.number().optional().default(1.0),
// ... 更多参数
},
// 4. 工具处理函数
async (params) => {
try {
const result = await this.ttsApi.generateSpeech(params);
return {
content: [{
type: 'text',
text: `Audio saved: ${result.audio}`
}]
};
} catch (error) {
return {
content: [{
type: 'text',
text: `Failed: ${error.message}`
}]
};
}
}
);
}
设计要点:
- 使用 Zod 进行参数验证,确保类型安全
- 统一的错误处理和响应格式
- 支持可选参数和默认值
3.2 API 调用层
MiniMaxAPI 类封装了与 MiniMax API 的所有交互:
**
ts
export class MiniMaxAPI {
private config: Config;
private baseURL: string;
private session: ReturnType<typeof axios.create>;
constructor(config: Config) {
this.config = config;
this.baseURL = config.apiHost || 'https://api.minimax.chat';
this.session = axios.create({
headers: {
'Authorization': `Bearer ${this.config.apiKey}`,
'MM-API-Source': 'Minimax-MCP-JS'
}
});
}
async makeRequest<T>(endpoint: string, data: any, method: string = 'POST'): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
const hasFiles = !!data.files;
const config: AxiosRequestConfig = {
method,
url,
headers: this.getHeaders(hasFiles),
};
// 处理文件上传
if (hasFiles) {
const formData = new FormData();
// ... FormData 构建逻辑
config.data = formData;
} else {
config.data = data;
}
try {
const response = await this.session.request(config);
// 检查业务错误码
const baseResp = response.data?.base_resp;
if (baseResp && baseResp.status_code !== 0) {
if (baseResp.status_code === 1004) {
throw new MinimaxAuthError(`API Error: ${baseResp.status_msg}`);
} else {
throw new MinimaxRequestError(`API Error: ${baseResp.status_msg}`);
}
}
return response.data;
} catch (error) {
// 统一错误处理
// ...
}
}
}
关键特性:
- 认证管理: 自动添加 Bearer Token
- 错误分类: 区分认证错误(1004)和其他业务错误
- 文件上传: 支持 FormData 方式上传文件
- 请求追踪: 通过 Trace ID 追踪请求
3.3 功能 API 层
以 TTSAPI 为例,展示功能层的实现:
**
ts
export class TTSAPI {
private api: MiniMaxAPI;
constructor(api: MiniMaxAPI) {
this.api = api;
}
async generateSpeech(request: TTSRequest): Promise<any> {
// 1. 参数验证
if (!request.text || request.text.trim() === '') {
throw new MinimaxRequestError(ERROR_TEXT_REQUIRED);
}
// 2. 构建请求数据(嵌套结构)
const requestData: Record<string, any> = {
model: this.ensureValidModel(request.model),
text: request.text,
voice_setting: {
voice_id: request.voiceId || 'male-qn-qingse',
speed: request.speed || 1.0,
vol: request.vol || 1.0,
pitch: request.pitch || 0,
emotion: this.ensureValidEmotion(request.emotion, request.model)
},
audio_setting: {
sample_rate: this.ensureValidSampleRate(request.sampleRate),
bitrate: this.ensureValidBitrate(request.bitrate),
format: this.ensureValidFormat(request.format),
channel: this.ensureValidChannel(request.channel)
}
};
// 3. 过滤 undefined 字段
const filteredData = this.removeUndefinedFields(requestData);
// 4. 发送请求
const response = await this.api.post<any>('/v1/t2a_v2', filteredData);
// 5. 处理响应
const audioData = response?.data?.audio;
if (request.outputFormat === RESOURCE_MODE_URL) {
return { audio: audioData };
} else {
// 解码并保存文件
const audioBuffer = Buffer.from(audioData, 'hex');
fs.writeFileSync(outputFile, audioBuffer);
return { audio: outputFile };
}
}
// 参数验证辅助方法
private ensureValidModel(model?: string): string {
const validModels = ['speech-02-hd', 'speech-02-turbo', ...];
return validModels.includes(model) ? model : 'speech-02-hd';
}
}
设计模式:
- 参数规范化: 确保所有参数在有效范围内
- 嵌套数据结构: 符合 MiniMax API 的请求格式
- 资源模式切换: 支持 URL 模式和本地文件模式
- 错误传播: 将底层错误向上传递
3.4 完整调用链路示例
以用户调用 text_to_audio 工具为例,完整链路如下:
**
PlainText
1. 客户端(Claude Desktop)
↓ 通过 STDIO 发送 MCP 请求
2. MCPServer.registerTextToAudioTool()
↓ 接收请求,提取参数
3. TTSAPI.generateSpeech()
↓ 参数验证和规范化
4. MiniMaxAPI.post('/v1/t2a_v2', data)
↓ 构建 HTTP 请求
5. MiniMax API 服务器
↓ 处理请求,返回音频数据
6. TTSAPI
↓ 解码音频数据,保存文件
7. MCPServer
↓ 构建 MCP 响应
8. 客户端
↓ 接收结果
四、核心技术亮点
4.1 多租户支持
通过请求级配置实现多租户:
**
ts
// REST 模式下,每个请求可以携带独立配置
private getRequestConfig(request: any): Config {
const metaAuth = request.params?._meta?.auth;
const requestConfig = ConfigManager.extractConfigFromMetaAuth(metaAuth);
return ConfigManager.getConfig(requestConfig, this.config);
}
4.2 资源模式切换
支持两种资源返回模式:
**
ts
// URL 模式:返回资源 URL(适合云端部署)
if (this.config.resourceMode === RESOURCE_MODE_URL) {
return { content: [{ type: 'text', text: `Video URL: ${result.video_url}` }] };
}
// Local 模式:下载并保存到本地(适合本地使用)
else {
await this.api.downloadFile(result.video_url, outputPath);
return { content: [{ type: 'text', text: `Video saved: ${outputPath}` }] };
}
4.3 异步任务支持
视频生成等耗时任务支持异步模式:
**
ts
if (params.asyncMode) {
const result = await this.videoApi.generateVideo(params);
return {
content: [{
type: 'text',
text: `Task submitted: ${result.task_id}. Use query_video_generation to check status.`
}]
};
}
4.4 重试机制
REST 和 SSE 模式实现了自动重试:
**
ts
private async handleTextToAudio(args: any, api: MiniMaxAPI, mediaService: MediaService, attempt = 1): Promise<any> {
try {
return await mediaService.generateSpeech(args);
} catch (error) {
if (attempt < MAX_RETRY_ATTEMPTS) {
await new Promise(resolve => setTimeout(resolve, RETRY_DELAY * Math.pow(2, attempt - 1)));
return this.handleTextToAudio(args, api, mediaService, attempt + 1);
}
throw error;
}
}
五、总结
MiniMax MCP JS 通过精心设计的架构,实现了:
- 灵活的部署方式:支持 STDIO、REST、SSE 三种传输模式
- 完善的配置管理:五层优先级配置系统,适配多种场景
- 清晰的分层架构:传输层 → 服务层 → API 层 → 功能层
- 健壮的错误处理:统一的错误分类和重试机制
- 多租户支持:请求级配置实现资源隔离
这套架构不仅为 MiniMax AI 能力提供了标准化的 MCP 接口,也为其他 AI 服务的 MCP 集成提供了优秀的参考实现。