mcp-ai-music 1.0.3 → 1.0.6

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.
Files changed (3) hide show
  1. package/README.md +260 -260
  2. package/dist/index.js +210 -45
  3. package/package.json +40 -40
package/README.md CHANGED
@@ -1,260 +1,260 @@
1
- # AI作曲 MCP 服务
2
-
3
- **版本 (Version):** 1.0.0
4
-
5
- ## 描述 (Description)
6
-
7
- `mcp-ai-music` 是一个基于 Suno4.5 API 的 AI 作曲 MCP 服务,提供音乐生成、翻唱、扩展和进度查询功能。该服务支持多种音乐风格,可以生成原创音乐、对现有音乐进行翻唱转换,以及扩展音乐长度。
8
-
9
- ## 功能特点
10
-
11
- - **原创音乐生成**:根据提示词和风格生成全新的音乐作品
12
- - **音乐翻唱**:将现有音乐转换为不同风格,保留核心旋律
13
- - **音乐扩展**:在保持原始风格的基础上延长音乐时长
14
- - **实时进度查询**:支持轮询查询任务进度,实时了解生成状态
15
- - **多模型支持**:支持 V3_5、V4、V4_5 多个AI模型版本
16
- - **纯音乐模式**:支持生成无歌词的纯音乐版本
17
-
18
- ## 环境配置
19
-
20
- > **重要**:请配置以下必填环境变量:
21
- > - `SUNO_API_KEY`:Suno API 密钥
22
- > - `SUNO_SERVICE_BASE`:服务网关地址,默认 `https://www.mcpcn.cc`
23
-
24
- ### 费用说明
25
- - 生成音乐:¥0.438/次
26
- - 翻唱音乐:¥0.438/次
27
- - 扩展音乐:¥0.438/次
28
- - 查询进度:免费
29
-
30
- ## 使用方法
31
-
32
- ```json
33
- {
34
- "mcpServers": {
35
- "mcp-ai-music": {
36
- "command": "node",
37
- "args": [
38
- "dist/index.js"
39
- ],
40
- "env": {
41
- "SUNO_API_KEY": "您的Suno API密钥",
42
- "SUNO_SERVICE_BASE": "https://www.mcpcn.cc/api"
43
- },
44
- "autoApprove": [
45
- "generate_music",
46
- "cover_music",
47
- "extend_music",
48
- "query_progress"
49
- ]
50
- }
51
- }
52
- }
53
- ```
54
-
55
- ## 可用工具 (Available Tools)
56
-
57
- 该服务提供以下4个工具:
58
-
59
- ### 1. `generate_music` - 生成音乐
60
-
61
- 生成原创音乐作品。
62
-
63
- **输入参数:**
64
- - `prompt` (必需): 音乐描述提示词,详细描述想要的音乐风格、情感、乐器等
65
- - V3_5/V4 模型:最多 3000 字符
66
- - V4_5 模型:最多 5000 字符
67
- - `style` (可选): 音乐风格,如"古典"、"流行"、"摇滚"等
68
- - V3_5/V4 模型:最多 200 字符
69
- - V4_5 模型:最多 1000 字符
70
- - `title` (可选): 音乐标题,最多 80 字符
71
- - `instrumental` (可选): 是否生成纯音乐(无歌词),默认 false
72
- - `model` (可选): AI模型版本,可选 "V3_5"、"V4"、"V4_5",默认 "V4_5"
73
- - `negativeTags` (可选): 负面标签,描述不想要的音乐元素
74
-
75
- **调用示例:**
76
- ```json
77
- {
78
- "name": "generate_music",
79
- "arguments": {
80
- "prompt": "一段平静舒缓的钢琴曲,带有柔和的旋律,适合冥想和放松",
81
- "style": "古典",
82
- "title": "宁静钢琴冥想",
83
- "instrumental": true,
84
- "model": "V4_5",
85
- "negativeTags": "重金属, 强节奏鼓点"
86
- }
87
- }
88
- ```
89
-
90
- ### 2. `cover_music` - 翻唱音乐
91
-
92
- 将现有音乐转换为新的风格,保留核心旋律。
93
-
94
- **输入参数:**
95
- - `uploadUrl` (必需): 要翻唱的音频文件URL,音频长度不超过2分钟
96
- - `prompt` (必需): 翻唱风格描述
97
- - `style` (可选): 目标音乐风格
98
- - `title` (可选): 翻唱版本标题
99
- - `instrumental` (可选): 是否生成纯音乐版本,默认 false
100
- - `model` (可选): AI模型版本,默认 "V4_5"
101
- - `negativeTags` (可选): 负面标签
102
-
103
- **调用示例:**
104
- ```json
105
- {
106
- "name": "cover_music",
107
- "arguments": {
108
- "uploadUrl": "https://example.com/audio.mp3",
109
- "prompt": "将这首歌转换为爵士风格",
110
- "style": "爵士",
111
- "title": "爵士翻唱版",
112
- "instrumental": false
113
- }
114
- }
115
- ```
116
-
117
- ### 3. `extend_music` - 扩展音乐
118
-
119
- 在保留原始音频风格的同时扩展音轨长度。
120
-
121
- **输入参数:**
122
- - `uploadUrl` (必需): 要扩展的音频文件URL,音频长度不超过2分钟
123
- - `prompt` (必需): 扩展描述,如"用更多舒缓的音符延长音乐"
124
- - `continueAt` (必需): 从音频的第几秒开始扩展,必须大于0且小于音频总时长
125
- - `style` (可选): 保持的音乐风格
126
- - `title` (可选): 扩展版本标题
127
- - `instrumental` (可选): 是否生成纯音乐版本,默认 false
128
- - `model` (可选): AI模型版本,必须与源音乐保持一致,默认 "V4_5"
129
- - `negativeTags` (可选): 负面标签
130
-
131
- **调用示例:**
132
- ```json
133
- {
134
- "name": "extend_music",
135
- "arguments": {
136
- "uploadUrl": "https://example.com/audio.mp3",
137
- "prompt": "用更多舒缓的音符延长音乐,保持原有的宁静氛围",
138
- "continueAt": 60,
139
- "style": "古典",
140
- "title": "宁静钢琴延长版",
141
- "instrumental": true
142
- }
143
- }
144
- ```
145
-
146
- ### 4. `query_progress` - 查询进度
147
-
148
- 查询音乐生成任务的进度状态。
149
-
150
- > **重要提示**:由于AI生成音乐需要时间,大模型需要轮询此接口来获取任务状态和结果。建议每10-30秒查询一次,直到状态为'complete'或'failed'。
151
-
152
- **输入参数:**
153
- - `taskId` (必需): 音乐生成任务的ID(从其他工具的返回结果中获取)
154
-
155
- **调用示例:**
156
- ```json
157
- {
158
- "name": "query_progress",
159
- "arguments": {
160
- "taskId": "task_12345"
161
- }
162
- }
163
- ```
164
-
165
- **状态说明:**
166
- - `processing`: 正在处理中
167
- - `text`: 文本生成完成,正在生成音频
168
- - `first`: 第一首音乐生成完成
169
- - `complete`: 任务完成
170
- - `failed`: 任务失败
171
-
172
- ## 工作流程示例
173
-
174
- ### 生成原创音乐的完整流程:
175
-
176
- 1. **发起生成请求**
177
- ```json
178
- {
179
- "name": "generate_music",
180
- "arguments": {
181
- "prompt": "一首欢快的流行歌曲,适合夏天",
182
- "style": "流行",
183
- "title": "夏日阳光"
184
- }
185
- }
186
- ```
187
-
188
- 2. **获取任务ID**
189
- ```json
190
- {
191
- "taskId": "task_abc123",
192
- "status": "pending",
193
- "message": "音乐生成任务已提交,请使用query_progress工具查询进度。",
194
- "cost": "¥0.438"
195
- }
196
- ```
197
-
198
- 3. **轮询查询进度**
199
- ```json
200
- {
201
- "name": "query_progress",
202
- "arguments": {
203
- "taskId": "task_abc123"
204
- }
205
- }
206
- ```
207
-
208
- 4. **获取最终结果**
209
- 当状态变为'complete'时,会返回包含音乐文件信息的完整结果。
210
-
211
- ## 注意事项
212
-
213
- > 也需要设置 `SUNO_SERVICE_BASE`(默认 `https://www.mcpcn.cc`),否则将无法正常访问服务。
214
-
215
- 1. **API密钥安全**:请确保 `SUNO_API_KEY` 环境变量已正确设置,不要在代码中硬编码API密钥。
216
-
217
- 2. **文件大小限制**:上传的音频文件长度不得超过2分钟。
218
-
219
- 3. **文件保存期限**:生成的音乐文件在服务器上保留15天后会被删除。
220
-
221
- 4. **费用控制**:每次调用生成、翻唱、扩展功能都会产生¥0.438的费用,请合理使用。
222
-
223
- 5. **轮询间隔**:建议查询进度的间隔为10-30秒,避免过于频繁的请求。
224
-
225
- 6. **模型兼容性**:在扩展音乐时,使用的模型版本必须与源音乐的生成模型保持一致。
226
-
227
- 7. **字符限制**:请注意各个参数的字符长度限制,超出限制会导致请求失败。
228
-
229
- ## 错误处理
230
-
231
- 服务会返回详细的错误信息,包括:
232
- - 参数验证错误
233
- - API请求失败
234
- - 字符长度超限
235
- - 任务状态异常
236
-
237
- 所有错误都会在响应中通过 `isError` 字段标识,并在 `errorMessage` 字段中提供具体的错误描述。
238
-
239
- ## 技术实现
240
-
241
- - 基于 Model Context Protocol (MCP) SDK 构建
242
- - 使用 Suno4.5 API 进行音乐生成
243
- - 支持 TypeScript 开发
244
- - 提供完整的类型定义和输入验证
245
-
246
- ## 开发和构建
247
-
248
- ```bash
249
- # 安装依赖
250
- npm install
251
-
252
- # 开发模式运行
253
- npm run dev
254
-
255
- # 构建项目
256
- npm run build
257
-
258
- # 启动服务
259
- npm start
260
- ```
1
+ # AI作曲 MCP 服务
2
+
3
+ **版本 (Version):** 1.0.0
4
+
5
+ ## 描述 (Description)
6
+
7
+ `mcp-ai-music` 是一个基于 Suno4.5 API 的 AI 作曲 MCP 服务,提供音乐生成、翻唱、扩展和进度查询功能。该服务支持多种音乐风格,可以生成原创音乐、对现有音乐进行翻唱转换,以及扩展音乐长度。
8
+
9
+ ## 功能特点
10
+
11
+ - **原创音乐生成**:根据提示词和风格生成全新的音乐作品
12
+ - **音乐翻唱**:将现有音乐转换为不同风格,保留核心旋律
13
+ - **音乐扩展**:在保持原始风格的基础上延长音乐时长
14
+ - **实时进度查询**:支持轮询查询任务进度,实时了解生成状态
15
+ - **多模型支持**:支持 V3_5、V4、V4_5 多个AI模型版本
16
+ - **纯音乐模式**:支持生成无歌词的纯音乐版本
17
+
18
+ ## 环境配置
19
+
20
+ > **重要**:请配置以下必填环境变量:
21
+ > - `SUNO_API_KEY`:Suno API 密钥
22
+ > - `SUNO_SERVICE_BASE`:服务网关地址,默认 `https://www.mcpcn.cc`
23
+
24
+ ### 费用说明
25
+ - 生成音乐:¥0.438/次
26
+ - 翻唱音乐:¥0.438/次
27
+ - 扩展音乐:¥0.438/次
28
+ - 查询进度:免费
29
+
30
+ ## 使用方法
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "mcp-ai-music": {
36
+ "command": "node",
37
+ "args": [
38
+ "dist/index.js"
39
+ ],
40
+ "env": {
41
+ "SUNO_API_KEY": "您的Suno API密钥",
42
+ "SUNO_SERVICE_BASE": "https://www.mcpcn.cc/api"
43
+ },
44
+ "autoApprove": [
45
+ "generate_music",
46
+ "cover_music",
47
+ "extend_music",
48
+ "query_progress"
49
+ ]
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ## 可用工具 (Available Tools)
56
+
57
+ 该服务提供以下4个工具:
58
+
59
+ ### 1. `generate_music` - 生成音乐
60
+
61
+ 生成原创音乐作品。
62
+
63
+ **输入参数:**
64
+ - `prompt` (必需): 音乐描述提示词,详细描述想要的音乐风格、情感、乐器等
65
+ - V3_5/V4 模型:最多 3000 字符
66
+ - V4_5 模型:最多 5000 字符
67
+ - `style` (可选): 音乐风格,如"古典"、"流行"、"摇滚"等
68
+ - V3_5/V4 模型:最多 200 字符
69
+ - V4_5 模型:最多 1000 字符
70
+ - `title` (可选): 音乐标题,最多 80 字符
71
+ - `instrumental` (可选): 是否生成纯音乐(无歌词),默认 false
72
+ - `model` (可选): AI模型版本,可选 "V3_5"、"V4"、"V4_5",默认 "V4_5"
73
+ - `negativeTags` (可选): 负面标签,描述不想要的音乐元素
74
+
75
+ **调用示例:**
76
+ ```json
77
+ {
78
+ "name": "generate_music",
79
+ "arguments": {
80
+ "prompt": "一段平静舒缓的钢琴曲,带有柔和的旋律,适合冥想和放松",
81
+ "style": "古典",
82
+ "title": "宁静钢琴冥想",
83
+ "instrumental": true,
84
+ "model": "V4_5",
85
+ "negativeTags": "重金属, 强节奏鼓点"
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### 2. `cover_music` - 翻唱音乐
91
+
92
+ 将现有音乐转换为新的风格,保留核心旋律。
93
+
94
+ **输入参数:**
95
+ - `uploadUrl` (必需): 要翻唱的音频文件URL,音频长度不超过2分钟
96
+ - `prompt` (必需): 翻唱风格描述
97
+ - `style` (可选): 目标音乐风格
98
+ - `title` (可选): 翻唱版本标题
99
+ - `instrumental` (可选): 是否生成纯音乐版本,默认 false
100
+ - `model` (可选): AI模型版本,默认 "V4_5"
101
+ - `negativeTags` (可选): 负面标签
102
+
103
+ **调用示例:**
104
+ ```json
105
+ {
106
+ "name": "cover_music",
107
+ "arguments": {
108
+ "uploadUrl": "https://example.com/audio.mp3",
109
+ "prompt": "将这首歌转换为爵士风格",
110
+ "style": "爵士",
111
+ "title": "爵士翻唱版",
112
+ "instrumental": false
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### 3. `extend_music` - 扩展音乐
118
+
119
+ 在保留原始音频风格的同时扩展音轨长度。
120
+
121
+ **输入参数:**
122
+ - `uploadUrl` (必需): 要扩展的音频文件URL,音频长度不超过2分钟
123
+ - `prompt` (必需): 扩展描述,如"用更多舒缓的音符延长音乐"
124
+ - `continueAt` (必需): 从音频的第几秒开始扩展,必须大于0且小于音频总时长
125
+ - `style` (可选): 保持的音乐风格
126
+ - `title` (可选): 扩展版本标题
127
+ - `instrumental` (可选): 是否生成纯音乐版本,默认 false
128
+ - `model` (可选): AI模型版本,必须与源音乐保持一致,默认 "V4_5"
129
+ - `negativeTags` (可选): 负面标签
130
+
131
+ **调用示例:**
132
+ ```json
133
+ {
134
+ "name": "extend_music",
135
+ "arguments": {
136
+ "uploadUrl": "https://example.com/audio.mp3",
137
+ "prompt": "用更多舒缓的音符延长音乐,保持原有的宁静氛围",
138
+ "continueAt": 60,
139
+ "style": "古典",
140
+ "title": "宁静钢琴延长版",
141
+ "instrumental": true
142
+ }
143
+ }
144
+ ```
145
+
146
+ ### 4. `query_progress` - 查询进度
147
+
148
+ 查询音乐生成任务的进度状态。
149
+
150
+ > **重要提示**:由于AI生成音乐需要时间,大模型需要轮询此接口来获取任务状态和结果。建议每10-30秒查询一次,直到状态为'complete'或'failed'。
151
+
152
+ **输入参数:**
153
+ - `taskId` (必需): 音乐生成任务的ID(从其他工具的返回结果中获取)
154
+
155
+ **调用示例:**
156
+ ```json
157
+ {
158
+ "name": "query_progress",
159
+ "arguments": {
160
+ "taskId": "task_12345"
161
+ }
162
+ }
163
+ ```
164
+
165
+ **状态说明:**
166
+ - `processing`: 正在处理中
167
+ - `text`: 文本生成完成,正在生成音频
168
+ - `first`: 第一首音乐生成完成
169
+ - `complete`: 任务完成
170
+ - `failed`: 任务失败
171
+
172
+ ## 工作流程示例
173
+
174
+ ### 生成原创音乐的完整流程:
175
+
176
+ 1. **发起生成请求**
177
+ ```json
178
+ {
179
+ "name": "generate_music",
180
+ "arguments": {
181
+ "prompt": "一首欢快的流行歌曲,适合夏天",
182
+ "style": "流行",
183
+ "title": "夏日阳光"
184
+ }
185
+ }
186
+ ```
187
+
188
+ 2. **获取任务ID**
189
+ ```json
190
+ {
191
+ "taskId": "task_abc123",
192
+ "status": "pending",
193
+ "message": "音乐生成任务已提交,请使用query_progress工具查询进度。",
194
+ "cost": "¥0.438"
195
+ }
196
+ ```
197
+
198
+ 3. **轮询查询进度**
199
+ ```json
200
+ {
201
+ "name": "query_progress",
202
+ "arguments": {
203
+ "taskId": "task_abc123"
204
+ }
205
+ }
206
+ ```
207
+
208
+ 4. **获取最终结果**
209
+ 当状态变为'complete'时,会返回包含音乐文件信息的完整结果。
210
+
211
+ ## 注意事项
212
+
213
+ > 也需要设置 `SUNO_SERVICE_BASE`(默认 `https://www.mcpcn.cc`),否则将无法正常访问服务。
214
+
215
+ 1. **API密钥安全**:请确保 `SUNO_API_KEY` 环境变量已正确设置,不要在代码中硬编码API密钥。
216
+
217
+ 2. **文件大小限制**:上传的音频文件长度不得超过2分钟。
218
+
219
+ 3. **文件保存期限**:生成的音乐文件在服务器上保留15天后会被删除。
220
+
221
+ 4. **费用控制**:每次调用生成、翻唱、扩展功能都会产生¥0.438的费用,请合理使用。
222
+
223
+ 5. **轮询间隔**:建议查询进度的间隔为10-30秒,避免过于频繁的请求。
224
+
225
+ 6. **模型兼容性**:在扩展音乐时,使用的模型版本必须与源音乐的生成模型保持一致。
226
+
227
+ 7. **字符限制**:请注意各个参数的字符长度限制,超出限制会导致请求失败。
228
+
229
+ ## 错误处理
230
+
231
+ 服务会返回详细的错误信息,包括:
232
+ - 参数验证错误
233
+ - API请求失败
234
+ - 字符长度超限
235
+ - 任务状态异常
236
+
237
+ 所有错误都会在响应中通过 `isError` 字段标识,并在 `errorMessage` 字段中提供具体的错误描述。
238
+
239
+ ## 技术实现
240
+
241
+ - 基于 Model Context Protocol (MCP) SDK 构建
242
+ - 使用 Suno4.5 API 进行音乐生成
243
+ - 支持 TypeScript 开发
244
+ - 提供完整的类型定义和输入验证
245
+
246
+ ## 开发和构建
247
+
248
+ ```bash
249
+ # 安装依赖
250
+ npm install
251
+
252
+ # 开发模式运行
253
+ npm run dev
254
+
255
+ # 构建项目
256
+ npm run build
257
+
258
+ # 启动服务
259
+ npm start
260
+ ```
package/dist/index.js CHANGED
@@ -85,17 +85,22 @@ const PROGRESS_QUERY_OUTPUT_SCHEMA = {
85
85
  // 工具定义
86
86
  const GENERATE_MUSIC_TOOL = {
87
87
  name: "generate_music",
88
- description: "生成音乐。根据提示词和风格生成原创音乐,支持自定义模式和纯音乐模式。\n\n注意:生成需要时间,请每10-30秒轮询调用query_progress查询进度工具,直到状态为'complete'或'failed'。\n\n参数行为说明:\n- customMode: 是否启用自定义模式(默认 true)。\n- instrumental: 是否为纯音乐。\n- 当 customMode=true 且 instrumental=false 时,prompt 将作为精确歌词使用;\n 当 customMode=false 且 instrumental=false 时,将自动生成歌词;\n 当 instrumental=true 时,始终为纯音乐(不含歌词)。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
88
+ description: "生成音乐。根据提示词和风格生成原创音乐,支持自定义模式和纯音乐模式。\n\n注意:\n- 生成需要时间,请每10-30秒轮询调用 query_progress 查询进度工具,直到状态为 'complete' 'failed'。\n- 平台仅保存音频与封面文件 15 天,请及时下载保存。\n\n参数行为说明:\n- customMode: 是否启用自定义模式(默认 true)。\n- instrumental: 是否为纯音乐。\n- 当 customMode=true 且 instrumental=false 时,可以同时提供 prompt(音乐描述)和 lyrics(精确歌词);\n 当 customMode=false 且 instrumental=false 时,只需 prompt,将自动生成歌词;\n 当 instrumental=true 时,始终为纯音乐(不含歌词),只需提供 prompt。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
89
89
  inputSchema: {
90
90
  type: "object",
91
91
  properties: {
92
92
  prompt: {
93
93
  type: "string",
94
- description: "音乐描述提示词,详细描述想要的音乐风格、情感、乐器等。长度限制:V3_5和V4模型3000字符,V4_5模型5000字符。注意:当 customMode=true 且 instrumental=false 时,prompt 将作为精确歌词使用。",
94
+ description: "音乐描述提示词,详细描述想要的音乐风格、情感、乐器等。长度限制:V3_5和V4模型3000字符,V4_5模型5000字符。当 instrumental=false 时,可与 lyrics 字段配合使用。",
95
+ },
96
+ lyrics: {
97
+ type: "string",
98
+ description: "精确歌词内容,用于 customMode=true 且 instrumental=false 时。当提供此字段时,AI将按照此歌词演唱。长度限制:V3_5和V4模型3000字符,V4_5模型5000字符。",
99
+ default: "",
95
100
  },
96
101
  style: {
97
102
  type: "string",
98
- description: "音乐风格,如'古典'、'流行'、'摇滚'等。长度限制:V3_5和V4模型200字符,V4_5模型1000字符。",
103
+ description: "音乐风格,如'古典'、'流行'、'摇滚'、'电子'等。长度限制:V3_5和V4模型200字符,V4_5模型1000字符。",
99
104
  default: "",
100
105
  },
101
106
  title: {
@@ -105,12 +110,12 @@ const GENERATE_MUSIC_TOOL = {
105
110
  },
106
111
  customMode: {
107
112
  type: "boolean",
108
- description: "是否启用自定义模式。为 true 时:如果 instrumental=true,仅需提供 style 和 title;如果 instrumental=false,需要提供 style、title prompt(prompt 作为精确歌词)。为 false 时:只需 prompt,若 instrumental=false 将自动生成歌词。",
113
+ description: "是否启用自定义模式。为 true 时:如果 instrumental=true,仅需提供 style 和 title;如果 instrumental=false,需要提供 style、title,可选择提供 prompt(音乐描述)和/或 lyrics(精确歌词)。为 false 时:只需 prompt,若 instrumental=false 将自动生成歌词。",
109
114
  default: true,
110
115
  },
111
116
  instrumental: {
112
117
  type: "boolean",
113
- description: "是否生成纯音乐(无歌词)。当 customMode=true 且该值=false 时,需要提供精确歌词(使用 prompt 作为歌词);当 customMode=false 且该值=false,将自动生成歌词。",
118
+ description: "是否生成纯音乐(无歌词)。当 customMode=true 且该值=false 时,可以同时提供 prompt(音乐描述)和 lyrics(精确歌词);当 customMode=false 且该值=false,将自动生成歌词。",
114
119
  default: false,
115
120
  },
116
121
  model: {
@@ -131,7 +136,7 @@ const GENERATE_MUSIC_TOOL = {
131
136
  };
132
137
  const COVER_MUSIC_TOOL = {
133
138
  name: "cover_music",
134
- description: "翻唱音乐。上传音频文件并转换为新的风格,保留核心旋律。\n\n注意:生成需要时间,请每10-30秒轮询调用query_progress工具,直到状态为'complete'或'failed'。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
139
+ description: "翻唱音乐。上传音频文件并转换为新的风格,保留核心旋律。\n\n注意:\n- 生成需要时间,请每10-30秒轮询调用 query_progress 工具,直到状态为 'complete' 'failed'。\n- 平台仅保存音频与封面文件 15 天,请及时下载保存。\n- 当 instrumental=false 时,可以同时提供 prompt(风格描述)和 lyrics(精确歌词)。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
135
140
  inputSchema: {
136
141
  type: "object",
137
142
  properties: {
@@ -141,11 +146,16 @@ const COVER_MUSIC_TOOL = {
141
146
  },
142
147
  prompt: {
143
148
  type: "string",
144
- description: "翻唱风格描述。",
149
+ description: "翻唱风格描述,描述想要的音乐风格、情感、乐器等。当 instrumental=false 时,可与 lyrics 字段配合使用。",
150
+ },
151
+ lyrics: {
152
+ type: "string",
153
+ description: "精确歌词内容,用于 instrumental=false 时。当提供此字段时,AI将按照此歌词演唱。长度限制:V3_5和V4模型3000字符,V4_5模型5000字符。",
154
+ default: "",
145
155
  },
146
156
  style: {
147
157
  type: "string",
148
- description: "目标音乐风格。",
158
+ description: "目标音乐风格,如'古典'、'流行'、'摇滚'、'电子'等。",
149
159
  default: "",
150
160
  },
151
161
  title: {
@@ -155,7 +165,7 @@ const COVER_MUSIC_TOOL = {
155
165
  },
156
166
  instrumental: {
157
167
  type: "boolean",
158
- description: "是否生成纯音乐版本。",
168
+ description: "是否生成纯音乐版本。当该值=false 时,可以同时提供 prompt(风格描述)和 lyrics(精确歌词)。",
159
169
  default: false,
160
170
  },
161
171
  model: {
@@ -166,7 +176,7 @@ const COVER_MUSIC_TOOL = {
166
176
  },
167
177
  negativeTags: {
168
178
  type: "string",
169
- description: "负面标签。",
179
+ description: "负面标签,描述不想要的音乐元素。",
170
180
  default: "",
171
181
  },
172
182
  },
@@ -176,7 +186,7 @@ const COVER_MUSIC_TOOL = {
176
186
  };
177
187
  const EXTEND_MUSIC_TOOL = {
178
188
  name: "extend_music",
179
- description: "扩展音乐。在保留原始音频风格的同时扩展音轨长度。\n\n注意:生成需要时间,请每10-30秒轮询调用query_progress工具,直到状态为'complete'或'failed'。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
189
+ description: "扩展音乐。在保留原始音频风格的同时扩展音轨长度。\n\n注意:\n- 生成需要时间,请每10-30秒轮询调用 query_progress 工具,直到状态为 'complete' 'failed'。\n- 平台仅保存音频与封面文件 15 天,请及时下载保存。\n- 当 instrumental=false 时,可以同时提供 prompt(扩展描述)和 lyrics(精确歌词)。\n\n返回字段说明:\n- taskId: 任务ID,用于查询进度\n- status: 任务状态 (pending)\n- message: 状态描述",
180
190
  inputSchema: {
181
191
  type: "object",
182
192
  properties: {
@@ -186,11 +196,16 @@ const EXTEND_MUSIC_TOOL = {
186
196
  },
187
197
  prompt: {
188
198
  type: "string",
189
- description: "扩展描述,如'用更多舒缓的音符延长音乐'",
199
+ description: "扩展描述,如'用更多舒缓的音符延长音乐'。当 instrumental=false 时,可与 lyrics 字段配合使用。",
200
+ },
201
+ lyrics: {
202
+ type: "string",
203
+ description: "精确歌词内容,用于 instrumental=false 时。当提供此字段时,AI将按照此歌词演唱扩展部分。长度限制:V3_5和V4模型3000字符,V4_5模型5000字符。",
204
+ default: "",
190
205
  },
191
206
  style: {
192
207
  type: "string",
193
- description: "保持的音乐风格。",
208
+ description: "保持的音乐风格,如'古典'、'流行'、'摇滚'、'电子'等。",
194
209
  default: "",
195
210
  },
196
211
  title: {
@@ -205,7 +220,7 @@ const EXTEND_MUSIC_TOOL = {
205
220
  },
206
221
  instrumental: {
207
222
  type: "boolean",
208
- description: "是否生成纯音乐版本。",
223
+ description: "是否生成纯音乐版本。当该值=false 时,可以同时提供 prompt(扩展描述)和 lyrics(精确歌词)。",
209
224
  default: false,
210
225
  },
211
226
  model: {
@@ -216,7 +231,7 @@ const EXTEND_MUSIC_TOOL = {
216
231
  },
217
232
  negativeTags: {
218
233
  type: "string",
219
- description: "负面标签。",
234
+ description: "负面标签,描述不想要的音乐元素。",
220
235
  default: "",
221
236
  },
222
237
  },
@@ -345,34 +360,96 @@ async function handleGenerateMusic(input) {
345
360
  errorMessage: "输入参数格式错误,预期为包含prompt字段的对象。",
346
361
  };
347
362
  }
348
- const { prompt, style = "", title = "", customMode = true, instrumental = false, model = "V4_5", negativeTags = "" } = input;
349
- if (!prompt || typeof prompt !== 'string') {
350
- return {
351
- content: [],
352
- isError: true,
353
- errorMessage: "prompt字段是必需的,且必须为字符串类型。",
354
- };
363
+ const { prompt, lyrics = "", style = "", title = "", customMode = true, instrumental = false, model = "V4_5", negativeTags = "" } = input;
364
+ // 根据API文档,当customMode=false时,只需要prompt
365
+ // 当customMode=true且instrumental=true时,只需要style和title
366
+ // 当customMode=true且instrumental=false时,需要style和title,可以选择提供prompt和/或lyrics
367
+ if (!customMode) {
368
+ // 非自定义模式:只需要prompt
369
+ if (!prompt || typeof prompt !== 'string') {
370
+ return {
371
+ content: [],
372
+ isError: true,
373
+ errorMessage: "非自定义模式下,prompt字段是必需的,且必须为字符串类型。",
374
+ };
375
+ }
355
376
  }
356
- // 验证prompt长度
357
- const maxPromptLength = model === "V4_5" ? 5000 : 3000;
358
- if (prompt.length > maxPromptLength) {
359
- return {
360
- content: [],
361
- isError: true,
362
- errorMessage: `prompt长度超过限制。${model}模型最大允许${maxPromptLength}字符。`,
363
- };
377
+ else if (instrumental) {
378
+ // 自定义模式且为纯音乐:只需要style和title
379
+ if (!style || typeof style !== 'string') {
380
+ return {
381
+ content: [],
382
+ isError: true,
383
+ errorMessage: "自定义纯音乐模式下,style字段是必需的,且必须为字符串类型。",
384
+ };
385
+ }
386
+ if (!title || typeof title !== 'string') {
387
+ return {
388
+ content: [],
389
+ isError: true,
390
+ errorMessage: "自定义纯音乐模式下,title字段是必需的,且必须为字符串类型。",
391
+ };
392
+ }
364
393
  }
365
- // 验证style长度
366
- const maxStyleLength = model === "V4_5" ? 1000 : 200;
367
- if (style.length > maxStyleLength) {
368
- return {
369
- content: [],
370
- isError: true,
371
- errorMessage: `style长度超过限制。${model}模型最大允许${maxStyleLength}字符。`,
372
- };
394
+ else {
395
+ // 自定义模式且有歌词:需要style和title,可以选择提供prompt和/或lyrics
396
+ if (!style || typeof style !== 'string') {
397
+ return {
398
+ content: [],
399
+ isError: true,
400
+ errorMessage: "自定义有歌词模式下,style字段是必需的,且必须为字符串类型。",
401
+ };
402
+ }
403
+ if (!title || typeof title !== 'string') {
404
+ return {
405
+ content: [],
406
+ isError: true,
407
+ errorMessage: "自定义有歌词模式下,title字段是必需的,且必须为字符串类型。",
408
+ };
409
+ }
410
+ if (!prompt && !lyrics) {
411
+ return {
412
+ content: [],
413
+ isError: true,
414
+ errorMessage: "自定义有歌词模式下,至少需要提供prompt(音乐描述)或lyrics(精确歌词)中的一个。",
415
+ };
416
+ }
373
417
  }
374
- // 验证title长度
375
- if (title.length > 80) {
418
+ // 验证prompt长度(如果提供)
419
+ if (prompt) {
420
+ const maxPromptLength = model === "V4_5" ? 5000 : 3000;
421
+ if (prompt.length > maxPromptLength) {
422
+ return {
423
+ content: [],
424
+ isError: true,
425
+ errorMessage: `prompt长度超过限制。${model}模型最大允许${maxPromptLength}字符。`,
426
+ };
427
+ }
428
+ }
429
+ // 验证lyrics长度(如果提供)
430
+ if (lyrics) {
431
+ const maxLyricsLength = model === "V4_5" ? 5000 : 3000;
432
+ if (lyrics.length > maxLyricsLength) {
433
+ return {
434
+ content: [],
435
+ isError: true,
436
+ errorMessage: `lyrics长度超过限制。${model}模型最大允许${maxLyricsLength}字符。`,
437
+ };
438
+ }
439
+ }
440
+ // 验证style长度(如果提供)
441
+ if (style) {
442
+ const maxStyleLength = model === "V4_5" ? 1000 : 200;
443
+ if (style.length > maxStyleLength) {
444
+ return {
445
+ content: [],
446
+ isError: true,
447
+ errorMessage: `style长度超过限制。${model}模型最大允许${maxStyleLength}字符。`,
448
+ };
449
+ }
450
+ }
451
+ // 验证title长度(如果提供)
452
+ if (title && title.length > 80) {
376
453
  return {
377
454
  content: [],
378
455
  isError: true,
@@ -381,8 +458,9 @@ async function handleGenerateMusic(input) {
381
458
  }
382
459
  const callbackUrl = buildCallbackUrl("generate");
383
460
  console.error(`使用回调地址: ${callbackUrl}`);
461
+ // 构建请求体,根据API文档,当customMode=true且instrumental=false时,
462
+ // 如果提供了lyrics,则使用lyrics作为prompt字段发送给API
384
463
  const requestBody = {
385
- prompt,
386
464
  style,
387
465
  title,
388
466
  customMode,
@@ -391,6 +469,14 @@ async function handleGenerateMusic(input) {
391
469
  negativeTags,
392
470
  callBackUrl: callbackUrl, // 必需的参数
393
471
  };
472
+ // 根据Suno API文档,当customMode=true且instrumental=false时,
473
+ // 如果提供了精确歌词,应该将其作为prompt字段发送
474
+ if (customMode && !instrumental && lyrics) {
475
+ requestBody.prompt = lyrics;
476
+ }
477
+ else if (prompt) {
478
+ requestBody.prompt = prompt;
479
+ }
394
480
  const result = await makeApiRequest('/generate', 'POST', requestBody);
395
481
  const taskData = {
396
482
  taskId: result.data?.taskId || result.taskId || result.id || result.task_id || "unknown",
@@ -428,7 +514,7 @@ async function handleCoverMusic(input) {
428
514
  errorMessage: "输入参数格式错误,预期为包含uploadUrl和prompt字段的对象。",
429
515
  };
430
516
  }
431
- const { uploadUrl, prompt, style = "", title = "", instrumental = false, model = "V4_5", negativeTags = "" } = input;
517
+ const { uploadUrl, prompt, lyrics = "", style = "", title = "", instrumental = false, model = "V4_5", negativeTags = "" } = input;
432
518
  if (!uploadUrl || typeof uploadUrl !== 'string') {
433
519
  return {
434
520
  content: [],
@@ -443,9 +529,30 @@ async function handleCoverMusic(input) {
443
529
  errorMessage: "prompt字段是必需的,且必须为字符串类型。",
444
530
  };
445
531
  }
532
+ // 验证prompt长度
533
+ if (prompt) {
534
+ const maxPromptLength = model === "V4_5" ? 5000 : 3000;
535
+ if (prompt.length > maxPromptLength) {
536
+ return {
537
+ content: [],
538
+ isError: true,
539
+ errorMessage: `prompt长度超过限制。${model}模型最大允许${maxPromptLength}字符。`,
540
+ };
541
+ }
542
+ }
543
+ // 验证lyrics长度(如果提供)
544
+ if (lyrics) {
545
+ const maxLyricsLength = model === "V4_5" ? 5000 : 3000;
546
+ if (lyrics.length > maxLyricsLength) {
547
+ return {
548
+ content: [],
549
+ isError: true,
550
+ errorMessage: `lyrics长度超过限制。${model}模型最大允许${maxLyricsLength}字符。`,
551
+ };
552
+ }
553
+ }
446
554
  const requestBody = {
447
555
  uploadUrl,
448
- prompt,
449
556
  style,
450
557
  title,
451
558
  customMode: true,
@@ -454,6 +561,13 @@ async function handleCoverMusic(input) {
454
561
  negativeTags,
455
562
  callBackUrl: buildCallbackUrl("upload-cover"), // 必需的参数
456
563
  };
564
+ // 根据Suno API文档,当instrumental=false且提供了lyrics时,使用lyrics作为prompt字段发送给API
565
+ if (!instrumental && lyrics) {
566
+ requestBody.prompt = lyrics;
567
+ }
568
+ else {
569
+ requestBody.prompt = prompt;
570
+ }
457
571
  const result = await makeApiRequest('/generate/upload-cover', 'POST', requestBody);
458
572
  const taskData = {
459
573
  taskId: result.data?.taskId || result.taskId || result.id || result.task_id || "unknown",
@@ -491,7 +605,7 @@ async function handleExtendMusic(input) {
491
605
  errorMessage: "输入参数格式错误,预期为包含uploadUrl、prompt和continueAt字段的对象。",
492
606
  };
493
607
  }
494
- const { uploadUrl, prompt, style = "", title = "", continueAt, instrumental = false, model = "V4_5", negativeTags = "" } = input;
608
+ const { uploadUrl, prompt, lyrics = "", style = "", title = "", continueAt, instrumental = false, model = "V4_5", negativeTags = "" } = input;
495
609
  if (!uploadUrl || typeof uploadUrl !== 'string') {
496
610
  return {
497
611
  content: [],
@@ -513,11 +627,32 @@ async function handleExtendMusic(input) {
513
627
  errorMessage: "continueAt字段是必需的,且必须为大于0的数字。",
514
628
  };
515
629
  }
630
+ // 验证prompt长度
631
+ if (prompt) {
632
+ const maxPromptLength = model === "V4_5" ? 5000 : 3000;
633
+ if (prompt.length > maxPromptLength) {
634
+ return {
635
+ content: [],
636
+ isError: true,
637
+ errorMessage: `prompt长度超过限制。${model}模型最大允许${maxPromptLength}字符。`,
638
+ };
639
+ }
640
+ }
641
+ // 验证lyrics长度(如果提供)
642
+ if (lyrics) {
643
+ const maxLyricsLength = model === "V4_5" ? 5000 : 3000;
644
+ if (lyrics.length > maxLyricsLength) {
645
+ return {
646
+ content: [],
647
+ isError: true,
648
+ errorMessage: `lyrics长度超过限制。${model}模型最大允许${maxLyricsLength}字符。`,
649
+ };
650
+ }
651
+ }
516
652
  const requestBody = {
517
653
  uploadUrl,
518
654
  defaultParamFlag: true,
519
655
  instrumental,
520
- prompt,
521
656
  style,
522
657
  title,
523
658
  continueAt,
@@ -525,6 +660,13 @@ async function handleExtendMusic(input) {
525
660
  negativeTags,
526
661
  callBackUrl: buildCallbackUrl("upload-extend"), // 必需的参数
527
662
  };
663
+ // 根据Suno API文档,当instrumental=false且提供了lyrics时,使用lyrics作为prompt字段发送给API
664
+ if (!instrumental && lyrics) {
665
+ requestBody.prompt = lyrics;
666
+ }
667
+ else {
668
+ requestBody.prompt = prompt;
669
+ }
528
670
  const result = await makeApiRequest('/generate/upload-extend', 'POST', requestBody);
529
671
  const taskData = {
530
672
  taskId: result.data?.taskId || result.taskId || result.id || result.task_id || "unknown",
@@ -668,6 +810,29 @@ async function handleQueryProgress(input) {
668
810
  rawData: result
669
811
  } : null,
670
812
  };
813
+ // 如果任务失败,按要求返回格式化数据,并透传后端错误信息到顶层 errorMessage
814
+ if (status === 'failed') {
815
+ const failureReason = result.errorMessage || result.msg || "";
816
+ const messageText = failureReason ? `任务失败: ${failureReason}` : "任务失败";
817
+ return {
818
+ content: [
819
+ {
820
+ type: "text",
821
+ text: JSON.stringify([
822
+ {
823
+ taskId,
824
+ status: "failed",
825
+ progress: 0,
826
+ message: messageText,
827
+ result: null,
828
+ },
829
+ ]),
830
+ },
831
+ ],
832
+ isError: false,
833
+ errorMessage: failureReason,
834
+ };
835
+ }
671
836
  // 检查是否来自自定义服务端且返回错误
672
837
  if (result.code !== undefined) {
673
838
  // 自定义服务端格式:code 0=成功,其他=失败
package/package.json CHANGED
@@ -1,40 +1,40 @@
1
- {
2
- "name": "mcp-ai-music",
3
- "version": "1.0.3",
4
- "description": "AI作曲MCP服务 - 基于Suno4.5 API的音乐生成、翻唱、扩展和进度查询工具",
5
- "main": "dist/index.js",
6
- "scripts": {
7
- "build": "tsc",
8
- "start": "node dist/index.js",
9
- "dev": "ts-node src/index.ts",
10
- "test": "echo \"Error: no test specified\" && exit 1"
11
- },
12
- "keywords": [
13
- "AI",
14
- "music",
15
- "composition",
16
- "suno",
17
- "mcp",
18
- "audio",
19
- "generation"
20
- ],
21
- "author": "",
22
- "license": "ISC",
23
- "bin": {
24
- "mcp-ai-music": "dist/index.js"
25
- },
26
- "files": [
27
- "dist",
28
- "README.md"
29
- ],
30
- "dependencies": {
31
- "@modelcontextprotocol/sdk": "^1.10.0",
32
- "node-fetch": "^2.7.0"
33
- },
34
- "devDependencies": {
35
- "@types/node": "^22.14.1",
36
- "@types/node-fetch": "^2.6.12",
37
- "typescript": "^5.8.3",
38
- "ts-node": "^10.9.2"
39
- }
40
- }
1
+ {
2
+ "name": "mcp-ai-music",
3
+ "version": "1.0.6",
4
+ "description": "AI作曲MCP服务 - 基于Suno4.5 API的音乐生成、翻唱、扩展和进度查询工具",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "start": "node dist/index.js",
9
+ "dev": "ts-node src/index.ts",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "AI",
14
+ "music",
15
+ "composition",
16
+ "suno",
17
+ "mcp",
18
+ "audio",
19
+ "generation"
20
+ ],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "bin": {
24
+ "mcp-ai-music": "dist/index.js"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.10.0",
32
+ "node-fetch": "^2.7.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.14.1",
36
+ "@types/node-fetch": "^2.6.12",
37
+ "typescript": "^5.8.3",
38
+ "ts-node": "^10.9.2"
39
+ }
40
+ }