韦氏词典
48.02M · 2026-03-25
MiniMax MCP JS 是 MiniMax 官方提供的 Model Context Protocol (MCP) JavaScript 实现,它将 MiniMax 强大的 AI 能力(图像生成、视频生成、语音合成、声音克隆等)封装为标准的 MCP 工具,供 Claude Desktop、Cursor 等 MCP 客户端调用。本文将深入源码,剖析其从初始化到工具调用的完整技术链路。
MiniMax MCP 的入口文件是 src/index.ts,它通过 startMiniMaxMCP 函数启动服务:
**
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);
}
}
核心设计要点:
ConfigManager 实现多层级配置管理ConfigManager 实现了一套完善的配置优先级系统(从高到低):
**
// 配置优先级:
// 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 使用独立配置以 STDIO 模式的 MCPServer 为例,其构造函数完成了核心组件的初始化:
**
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 作为底层框架适用场景: Claude Desktop、Cursor 等本地 MCP 客户端
实现原理:
**
public async startStdioServer(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
STDIO 模式通过标准输入输出流进行通信,是最简单直接的方式:
配置示例(Claude Desktop):
**
{
"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"
}
}
}
}
适用场景: 云端部署、跨语言调用、API 服务
实现原理:
**
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 接口:
meta.auth 配置核心请求处理逻辑:
**
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);
// ... 其他工具
}
});
适用场景: 需要服务器主动推送、长连接场景
实现原理:
SSE 模式是最复杂的实现,包含连接管理、心跳机制、会话管理等:
**
// 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: heartbeatndata: ${Date.now()}nn`);
}, 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 模式的关键特性:
connections Map 存储所有活跃连接所有工具通过 registerTools() 方法统一注册:
**
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 工具为例,注册过程包含三个核心部分:
**
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}`
}]
};
}
}
);
}
设计要点:
MiniMaxAPI 类封装了与 MiniMax API 的所有交互:
**
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) {
// 统一错误处理
// ...
}
}
}
关键特性:
以 TTSAPI 为例,展示功能层的实现:
**
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';
}
}
设计模式:
以用户调用 text_to_audio 工具为例,完整链路如下:
**
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. 客户端
↓ 接收结果
通过请求级配置实现多租户:
**
// REST 模式下,每个请求可以携带独立配置
private getRequestConfig(request: any): Config {
const metaAuth = request.params?._meta?.auth;
const requestConfig = ConfigManager.extractConfigFromMetaAuth(metaAuth);
return ConfigManager.getConfig(requestConfig, this.config);
}
支持两种资源返回模式:
**
// 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}` }] };
}
视频生成等耗时任务支持异步模式:
**
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.`
}]
};
}
REST 和 SSE 模式实现了自动重试:
**
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 通过精心设计的架构,实现了:
这套架构不仅为 MiniMax AI 能力提供了标准化的 MCP 接口,也为其他 AI 服务的 MCP 集成提供了优秀的参考实现。