The Atlas MCP (atlascloud-mcp) currently ships 9 tools covering image / video /
chat / upload / prediction — but no audio-generation tool. Every audio model
(xai/tts-v1, minimax/music-2.6, bytedance/seed-audio-1.0) is submitted to
POST /api/v1/model/generateAudio, which none of the existing tools reach.
This skill's pipeline works without the MCP (its scripts call the HTTP API directly), so this is not required to ship the explainer flow. But adding an audio tool makes the MCP itself complete for interactive/agent use — e.g. "generate a voiceover" or "make background music" straight from the MCP.
Below is a ready-to-adapt tool. It mirrors the existing atlas_generate_video
handler pattern (same submit → poll contract, just a different endpoint). Drop it
into the MCP's tool registry alongside the others and adjust imports/helpers to
match the repo's actual structure.
// tools/atlas_generate_audio.ts
import { z } from "zod";
const BASE = "https://api.atlascloud.ai/api/v1/model";
const UA =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"; // Cloudflare blocks default UA
// Reuse the MCP's existing poll helper if it has one; this is the shape it needs.
async function pollPrediction(id: string, apiKey: string, timeoutMs = 600_000) {
const t0 = Date.now();
while (Date.now() - t0 < timeoutMs) {
const r = await fetch(`${BASE}/prediction/${id}`, {
headers: { "User-Agent": UA, Authorization: `Bearer ${apiKey}` },
});
const data = (await r.json()).data ?? {};
const status = (data.status ?? "").toLowerCase();
if (["completed", "succeeded"].includes(status)) {
const out = data.outputs ?? data.output ?? [];
return Array.isArray(out) ? out : [out];
}
if (["failed", "canceled", "cancelled", "error"].includes(status)) {
throw new Error(`audio generation failed: ${JSON.stringify(data).slice(0, 500)}`);
}
await new Promise((res) => setTimeout(res, 3000));
}
throw new Error(`prediction ${id} timed out`);
}
export const atlasGenerateAudio = {
name: "atlas_generate_audio",
description:
"Generate audio (text-to-speech, music, or sound effects) with an Atlas Cloud " +
"audio model. Submits to the generateAudio endpoint and polls to completion. " +
"Use for narration/voiceover (xai/tts-v1), background music (minimax/music-2.6), " +
"or SFX/ambient/Chinese speech (bytedance/seed-audio-1.0). Verify the exact model " +
"id and params first with atlas_search_docs / atlas_get_model_info.",
inputSchema: {
model: z
.string()
.describe('Exact audio model id, e.g. "xai/tts-v1", "minimax/music-2.6", "bytedance/seed-audio-1.0"'),
params: z
.record(z.any())
.describe(
'Model-specific params. xai/tts-v1: {text, language, voice_id, codec:"mp3"}. ' +
'minimax/music-2.6: {prompt, is_instrumental:true, format:"mp3"}. ' +
'seed-audio: {text, format:"mp3", references:[{speaker:"..."}]}. ' +
"Pull the schema from atlas_get_model_info before building this."
),
},
async handler(
{ model, params }: { model: string; params: Record<string, unknown> },
apiKey: string
) {
const submit = await fetch(`${BASE}/generateAudio`, {
method: "POST",
headers: {
"User-Agent": UA,
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({ model, ...params }),
});
const body = await submit.json();
const data = body.data ?? body;
const id = data.id ?? data.prediction_id ?? data.request_id;
if (!id) throw new Error(`no prediction id: ${JSON.stringify(body).slice(0, 300)}`);
const urls = await pollPrediction(id, apiKey);
return {
content: [{ type: "text", text: JSON.stringify({ prediction_id: id, outputs: urls }) }],
};
},
};Wherever the MCP lists its tools (e.g. ListTools handler + the CallTool
switch), add atlas_generate_audio next to atlas_generate_video. If the repo
already factors out submit/poll into a shared client, call that instead of the
inline fetch/pollPrediction above — the contract is identical to video, only
the endpoint (generateAudio) and default poll interval differ.
atlas_generate_audio(
model="xai/tts-v1",
params={ "text": "Hello from Atlas Cloud.", "language": "en", "voice_id": "leo", "codec": "mp3" }
)
Expect a prediction_id + one output mp3 URL within a few seconds.
Note:
atlas_quick_generatecurrently acceptstype: "Image" | "Video". If you want one-step audio too, extend that enum to include"Audio"and route it togenerateAudiothe same way.