ofaudio-mcp

ofaudio-mcp

An agent-first MCP server for generating and transforming audio (music, speech, sound effects) via ElevenLabs and Mureka, providing tools for transcription, voice cloning, and multi-speaker dialogue.

Category
访问服务器

README

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+.

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.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选