Skip to content

Latest commit

 

History

History
117 lines (103 loc) · 4.78 KB

File metadata and controls

117 lines (103 loc) · 4.78 KB

Adding atlas_generate_audio to the Atlas MCP

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.

Tool definition (TypeScript, MCP SDK style)

// 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 }) }],
    };
  },
};

Register it

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.

Sanity test

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_generate currently accepts type: "Image" | "Video". If you want one-step audio too, extend that enum to include "Audio" and route it to generateAudio the same way.