Skip to main content
Glama

ofaudio-mcp

An agent-first MCP server for any audio an AI agent needs — generate (music, sound effects, speech, multi-speaker dialogue) and transform (transcribe, caption, isolate/denoise, voice-convert/dub) — behind one intent-shaped tool surface. It wraps ElevenLabs (speech, dialogue, SFX, voice library/design/cloning, music, transcription, isolation, speech-to-speech) and Mureka (music, lyrics), does the work in-process, and writes files to the local filesystem. Games, audiobooks, podcasts, video, ads, accessibility, localization — all one MCP.

Built to be driven by an agent, never a human clicking a UI. Every generation call returns a job_id instantly and runs in the background, so an agent can fan out many variants without blocking, then collect them with check_jobs.

Install

# from a checkout
pip install -e .
ofaudio-mcp            # or:  python -m ofaudio_mcp

Only hard dependency is the mcp SDK. Python 3.10+.

Related MCP server: minimax-omni

Configure (environment)

Copy .env.example to .env and fill in your keys (.env is gitignored). Set at least one provider's key. Keys accept a singular or plural form; the plural is comma-separated and becomes a multi-account pool (see Parallelism).

Env var

Default

Purpose

ELEVENLABS_API_KEY / ELEVENLABS_API_KEYS

ElevenLabs key(s) — voice + SFX. Works with a subscription tier or pure pay-as-you-go.

MUREKA_API_KEY / MUREKA_API_KEYS

Mureka key(s) — music. Prepaid API credits.

OFAUDIO_OUT_DIR

./ofaudio-out

Where audio files are written.

OFAUDIO_STATE_DIR

<OUT_DIR>/.state

Job records (JSON) + presets.json.

OFAUDIO_ELEVENLABS_LANES

3

Concurrent requests per ElevenLabs key.

OFAUDIO_MUREKA_LANES

1

Concurrent requests per Mureka key (Mureka caps at 1/account).

OFAUDIO_POLL_INTERVAL

5

Seconds between polls for async (Mureka) jobs.

OFAUDIO_JOB_TIMEOUT

300

Max seconds to wait for one generation.

OFAUDIO_MUREKA_MODEL

auto

Pin a Mureka model (e.g. the V9 flagship string) once confirmed on a live key.

OFAUDIO_ELEVENLABS_MODEL

eleven_v3

TTS model; drop to eleven_multilingual_v2 if v3 isn't on the key's tier.

OFAUDIO_ELEVENLABS_VOICE

Rachel

Default voice id when a call doesn't specify one.

ELEVENLABS_BASE_URL / MUREKA_BASE_URL

official

Override API base URLs.

A key entry may be label:key to name the lane in logs and job results (e.g. MUREKA_API_KEYS="acct-a:ak_...,acct-b:ak_...").

Tools

Tool

What it does

generate_music(prompt, duration?, instrumental?, reference?, lyrics?, engine?, format?, count?, composition_plan?, store_for_inpainting?, respect_sections_durations?)

Themes, BGM, songs, instrumentals. Soft-defaults to Mureka (prompt→song writes its own lyrics; pass lyrics for your own; reference = local/URL track → vibe-match; format defaults to lossless flac; count 1–3). engine="elevenlabs" = Eleven Music (composition_plan replaces prompt; store_for_inpaintingsong_id) → {job_id}

generate_lyrics(prompt)

Write song lyrics from a theme (Mureka) — synchronous {title, lyrics}; review/edit before spending song credits

transcribe(audio, language?, diarize?, captions?)

Speech-to-text (ElevenLabs Scribe). audio = local path or a URL (YouTube/TikTok); diarize labels speakers; captions="srt"/"vtt" writes a subtitle file → {text, language_code, words, captions_path?}

forced_alignment(audio, text, captions?)

Align a known script to existing audio → exact per-word timings (+ optional SRT/VTT) — for captioning recordings you already have the transcript for

isolate_audio(audio)

Remove background noise / isolate the voice → {path}

convert_voice(audio, voice, remove_background_noise?, format?, seed?)

Speech-to-speech: re-voice a recording onto another voice, keeping delivery (dubbing/ADR) → {path}

generate_sfx(prompt, duration_seconds?, loop?, prompt_influence?, model?, engine?, format?)

One-shots, ambience, seamless loops → {job_id}

generate_speech(text, voice?, profile?, model?, stability?, style?, speed?, similarity_boost?, use_speaker_boost?, seed?, previous_text?, next_text?, language_code?, with_timestamps?, variants?, engine?, format?)

Dialogue / character VO. Shape delivery with a profile and/or precision knobs; inline v3 tags like [whispers] work; with_timestamps=True emits a per-character alignment sidecar (lip-sync/captions); variants=N fans out N takes to audition → {job_id} (or {job_ids})

generate_dialogue(lines=[{voice, text}], model?, seed?, language_code?, apply_text_normalization?, engine?, format?)

Multi-speaker scene in one call (≤10 voices, ~2000 chars) with natural turn-taking → {job_id}

save_profile(name, voice?, model?, stability?, style?, speed?, …, tag?, seed?, description?)

Save a reusable persona/mood preset (a preset over the speech knobs)

list_profiles()

Built-in delivery presets (neutral, narrator, calm, whisper, sad, angry, excited, shout, steady, dynamic) + your saved ones

save_speaker(name, voice, workspace?, model?, stability?, …, seed?, description?)

Save a speaker (pinned voice + base delivery) under a workspace

speak(speaker, text, mood?, workspace?, …, with_timestamps?, variants?)

Speak as a saved speaker, layering a mood profile → {job_id}

preview_voices(query?, gender?, age?, accent?, use_case?, n?)

Search the library, return candidates with preview_urls — no generation, no slots

add_speaker_from_library(name, public_owner_id, voice_id, workspace?, seed?)

Add a library voice and save it as a speaker in one step

list_speakers(workspace?) / list_workspaces()

Saved speakers (optionally by workspace) / workspace namespaces

search_voice_library(query?, gender?, age?, accent?, use_case?, category?, descriptives?, page_size?)

Search ElevenLabs' shared library of thousands of voices

add_library_voice(public_owner_id, voice_id, name)

Add a library voice to the account and save it under name (uses a voice slot)

design_voice(description, save_as?, text?, model?, guidance_scale?, loudness?, seed?)

Synthesize a custom voice from a text description; returns previews to audition

save_voice(name, generated_voice_id, description?)

Keep a designed preview as a permanent, reusable voice (uses a voice slot)

clone_voice(name, audio_paths, description?, remove_background_noise?)

Instant Voice Cloning from your audio file(s) → saved, reusable voice (uses a slot)

delete_voice(voice, confirm=False)

Delete a custom voice and free its slot (fresh name→id, blocks premade, warns on profile/speaker refs)

account_status()

Both providers, one call — ElevenLabs (tier, char quota, voice slots, cloning, + quality/formats the tier allows) and Mureka (credit balance, concurrency limit). Check before fan-out

list_models()

ElevenLabs models available on the account + capability flags

check_jobs(job_ids)

Batch-poll — returns status + file path per id

list_jobs(status?, limit?)

Recent jobs, newest first

create_pronunciation_dictionary(name, rules, description?)

Lock how words/lore-names are said — rules = {word: say_as} map or EL rule objects. Apply via generate_speech/speak pronunciation= or save_speaker(pronunciation=)

add_pronunciation_rules(dictionary, rules) / list_pronunciation_dictionaries()

Extend / list saved dictionaries

list_voices()

ElevenLabs voices on the account ({account, profiles}) — resolve a voice by name or id

get_voice(voice)

One voice's details (category, labels, description, preview_url)

list_presets()

Everything saved: voices, music identities, profiles, speakers, pronunciation

Each generate_* has a soft-pinned provider (music→Mureka, SFX/speech→ElevenLabs) and an optional engine= override. A result is {job_id, status, path, duration, format, seed, provider} once succeeded.

Voices, speakers & delivery

The voice is the speaker's identity — pick or make one, don't dial it out of parameters. Three ways to get a voice, all reusable by name afterwards:

  1. Use one of ElevenLabs' manysearch_voice_library(query="warm narrator", age="middle aged")add_library_voice(public_owner_id, voice_id, "narrator"). Thousands of ready-made voices.

  2. Design a custom onedesign_voice("warm, measured audiobook narrator, clear articulation", save_as="narrator"). Describe it, audition the previews, keep the best.

  3. Reuse what's on the accountlist_voices() shows the premade voices already there.

Then just generate_speech("...", voice="narrator") — the voice stays consistent.

Make it a first-class Speaker, grouped by workspace. For a whole cast across several projects, save_speaker("narrator", voice, workspace="projectA", ...) saves the identity (pinned voice + base delivery), and speak("narrator", text, mood="calm", workspace="projectA") speaks it — the mood layers over the speaker (a speaker is who; a profile is what mood). preview_voices(query) samples library candidates by preview (no slots), and add_speaker_from_library(...) adds + saves in one step. variants=N on speak/generate_speech fans out N takes so a human picks the best.

Delivery (mood/tone) is a separate layer on top. Shape it with a profile and/or the precision knobs. Built-in profiles: neutral, narrator, calm, whisper, sad, angry, excited, shout (v3, emotion via audio tags) and steady, dynamic (v2, consistency axis). Save your own persona/mood presets with save_profile.

Two facts worth knowing (both handled for you, but they explain the design):

  • Eleven v3 (default for speech) does emotion via inline audio tags ([whispers], [angry], [snorts], …) and a 3-mode stability (creative/natural/robust) — it ignores the numeric style slider. Tags only land on an expressive voice; a flat narration voice mutes them.

  • Eleven v2 uses the numeric sliders, but those control consistency (dynamic ↔ steady), not a specific emotion. Use it via the steady/dynamic profiles.

Parallelism

Mureka caps concurrency at 1 request per prepaid account and it doesn't stack, so the way to run music generation in parallel is multiple accounts. This server treats keys as a pool: supply N keys and it runs N jobs in parallel, one per key, automatically routing around a key that hits its rate limit (back-off) or runs out of balance. Supplying one key is just the N=1 case. (ElevenLabs scales concurrency within a single key by tier, so a lane count > 1 per key is the norm there.)

Mount it

Claude Code

claude mcp add ofaudio \
  --env ELEVENLABS_API_KEY=xi_... --env MUREKA_API_KEY=ak_... \
  -- python -m ofaudio_mcp

Cursor.cursor/mcp.json:

{
  "mcpServers": {
    "ofaudio": {
      "command": "python",
      "args": ["-m", "ofaudio_mcp"],
      "env": { "ELEVENLABS_API_KEY": "xi_...", "MUREKA_API_KEY": "ak_..." }
    }
  }
}

Self-hosted / server — add the server to your MCP client's config and put the keys in a .env next to it (they stay on the box):

ELEVENLABS_API_KEYS=xi_...
MUREKA_API_KEYS=acct-a:ak_...,acct-b:ak_...
OFAUDIO_OUT_DIR=/var/audio/ofaudio-out

The intended usage pattern is fan-out: fire many generate_* calls, then check_jobs.

Status

Both providers work end-to-end. ElevenLabs: speech (+ timestamps, mood profiles, variants), multi-speaker dialogue, SFX, Eleven Music, voice library / design / instant cloning, voice lifecycle, account introspection, the speaker/workspace layer, and the transform tools (transcribe, forced alignment, isolate, voice-convert). Mureka: instrumental + song, prompt→song (easy-generate), user-supplied lyrics, standalone generate_lyrics, reference-track vibe-match, and lossless flac-default output.

Design

See CLAUDE.md for the architecture, module map, tool surface, and the verified provider facts that shape the design.

License

Source-available under PolyForm Noncommercial 1.0.0, with a licensor carve-out that draws the line at the tool, not the audio:

  • Run it freely for any purpose — including to generate audio you use commercially. This MCP is only a client; it claims no rights in what you generate. Your rights to the generated audio are governed by ElevenLabs' and Mureka's terms and your own accounts with them.

  • Don't commercialize the tool itself — you may not sell this software, host it as a paid service, or turn it (or a derivative) into a commercial product.

In short: make whatever audio you want, sell it if your provider terms allow — just don't sell the MCP. See LICENSE for the full terms.

Install Server
F
license - not found
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for Producer/Riffusion AI music generation

  • MCP server exposing the AceDataCloud Fish Audio API (text-to-speech with voice conditioning)

  • MCP server for AI dialogue using various LLM models via AceDataCloud

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DuragonYama/ofaudio-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server