Text to Speech MCP: Murmur in Claude Code and Codex
Connect a text to speech MCP server to Claude Code or Codex. Pin the workspace, discover installed voices, track jobs, and troubleshoot setup.
Direct answer: To connect a text to speech MCP server to Claude Code or Codex, point the client at Murmur’s bundled helper, enable automation in the app, and start the server in your voiceover project. Then discover a usable speech model and voice, submit a short job, and poll its ID until it succeeds. This guide is for Mac creators and developers who want an assistant to produce local narration files in a known folder.
The connection has three separate checks: the client can discover Murmur’s tools, the app is ready to generate, and a submitted job produces usable audio. A saved server configuration proves only the first setup step. Download the MCP setup and recovery checklist for the launcher, commands, request examples, and an acceptance record.
Jump to Locate the helper and enable the app · Pin the server to your voiceover project · Connect Claude Code or Codex · Find a usable model for text to speech MCP · Submit one take and poll the job · Recover from common setup and job failures · Keep local speech and assistant privacy distinct · Frequently asked questions.
Locate the helper and enable the app
Murmur requires an Apple Silicon Mac running macOS 15 or later. Open the app, finish setup, activate the license, and enable Settings → Automation → Allow local automation. The optional Install CLI button links ~/.local/bin/murmur to that app’s helper. MCP can use the helper’s absolute path directly, so it does not need a package manager or a shell PATH change.
The usual helper path is /Applications/Murmur.app/Contents/Helpers/murmur, provided that your app is installed there and that build includes the helper. Locate the app you actually opened in Finder, then check its Contents/Helpers/murmur executable. If the file is missing, stop and obtain a build that includes automation; do not register a nonexistent path. An old CLI symlink can point to a different app. The automation documentation explains the in-app controls.
MURMUR_APP="/Applications/Murmur.app"
MURMUR_HELPER="$MURMUR_APP/Contents/Helpers/murmur"
# Change MURMUR_APP to the actual app location before continuing.
ls -l "$MURMUR_HELPER"
# Run only if that helper exists and is executable:
"$MURMUR_HELPER" --help
"$MURMUR_HELPER" status --jsonA completed status response contains status.appRunning, setupComplete, licensed, automationEnabled, and appVersion. Status can explain missing setup while automation is disabled. Listing models, listing voices, and generation require setup, a license, and enabled automation. Record the app version reported by status rather than treating an MCP server version as the app release.
Pin the server to your voiceover project
In the current implementation, Murmur takes its workspace from the server process’s starting directory. Input and output paths must resolve inside that directory. Adding another directory to the assistant does not extend Murmur’s root: this server does not implement MCP roots discovery. A small launcher makes the boundary explicit for either client.
Create murmur-mcp-launcher.sh in the project folder where you want narration. Copy the launcher below and set MURMUR_APP to your verified app location. Register the launcher through its absolute path. It changes into its own folder, checks the helper, and starts stdio MCP. Diagnostics go to stderr, keeping stdout available for protocol messages.
#!/bin/sh
set -eu
MURMUR_APP="/Applications/Murmur.app"
MURMUR_HELPER="$MURMUR_APP/Contents/Helpers/murmur"
if [ ! -x "$MURMUR_HELPER" ]; then
printf '%s\n' "Murmur helper missing or not executable: $MURMUR_HELPER" >&2
exit 1
fi
MURMUR_PROJECT="$(CDPATH= cd "$(dirname "$0")" && pwd -P)"
cd "$MURMUR_PROJECT"
exec "$MURMUR_HELPER" mcp serveOur isolated check invoked this launcher from outside a folder named “Project With Spaces.” With the app path changed to the development fixture, the server’s working directory matched that folder and discovery succeeded. With the default missing helper, it exited with code 1 and a clear diagnostic. This checks launcher behavior; it does not establish a connection inside either assistant.
Connect Claude Code or Codex
Choose the client you use and run its registration command from the project folder. Inspect an existing server named murmur before adding another definition. These commands change the client’s configuration; the checklist keeps them separate from preflight checks.
# Claude Code: private configuration for this project
claude mcp add --transport stdio --scope local murmur -- /bin/sh "$PWD/murmur-mcp-launcher.sh"
claude mcp get murmur
# Or Codex: adds to the current Codex host configuration
codex mcp add murmur -- /bin/sh "$PWD/murmur-mcp-launcher.sh"
codex mcp get murmurClaude Code’s local scope keeps this definition private to the project where you add it. Start a new Claude Code session there and inspect /mcp. The current Claude Code MCP reference documents scopes and connection status. An “Added” message confirms configuration was saved; check the connection and make a real tool call before treating setup as complete.
For Codex, inspect the saved command with codex mcp get murmur, restart the client, and inspect /mcp in the terminal UI. The OpenAI MCP reference covers stdio configuration. The launcher remains tied to this project even if you open Codex elsewhere. Use a separate server name for another project. A browser chat does not automatically gain access to a local Mac helper.
Find a usable model for text to speech MCP
- Call
murmur_statuswith{}. Confirm setup, license, and automation are ready. - Call
murmur_list_modelswith{}. Choose a returned model ID whoseinstallationStateisbundledorinstalled, and whose capabilities match the task. - Call
murmur_list_voiceswith{"model_id":"YOUR_MODEL_ID"}. Choose a returned preset voice ID from that model. - Pass both IDs explicitly in the speech request. Keep the same pair while testing, so a changed default cannot silently select another engine.
The other installation states are notInstalled, installing, removing, and failed. A listed model is part of the catalog, not proof that it can generate. If you need a missing model, review its download size and install it in the app, or deliberately call murmur_install_model with the returned ID. Poll that installation job, then refresh model discovery. Use an already usable preset model for the first connection check.
Voice discovery distinguishes kind: "preset" from kind: "reference-profile". A saved reference profile uses its UUID in reference_profile_id, rather than the preset voice_id field, and requires a compatible model. Start with a preset to establish the connection before adding cloning or model-specific directions.
Submit one take and poll the job
The example below uses placeholders: replace the model and voice IDs with values from your own discovery response. Send this object as arguments to murmur_generate_speech in the assistant, not as a Terminal command. The output path is relative to the launcher’s project folder, and force: false preserves existing takes.
{
"text": "This is a short connection check for local narration.",
"model_id": "YOUR_MODEL_ID",
"voice_id": "YOUR_PRESET_VOICE_ID",
"output_path": "audio/mcp-connection-take-01.wav",
"force": false,
"wait": false
}Long operations return a job snapshot by default. Copy structuredContent.id, then call murmur_get_job with {"job_id":"THE_RETURNED_UUID"}. Poll at a modest interval, such as every 2 seconds, rather than immediately resubmitting speech. Read state, message, error, and artifacts in each snapshot.
| State | Next action |
|---|---|
| queued or running | Keep the same job ID and poll. A submitted request is not finished audio. |
| succeeded | Use the returned artifact path, check that the file exists, and listen to it. |
| failed | Read error and message, fix the stated cause, then create a new take. |
| cancelled | Do not treat the take as complete. Review any listed artifacts before restarting. |
Inspect the snapshot’s state even when the MCP envelope says isError: false. A failed job retrieved by murmur_get_job can still arrive in a successful tool response. Malformed UUIDs instead return a tool error. If you need to stop a queued or running job, call murmur_cancel_job with its UUID and continue polling until a terminal state appears.
Success is the point to inspect the actual artifact. Record its path, model ID, voice, and durationSeconds; open the file and listen for the correct words and performance. If FFmpeg is already available, ffprobe and a full decode add a file-integrity check. They do not replace listening. After the connection works, the promo-reel workflow shows how to use narration in a video.
Recover from common setup and job failures
| Symptom | Check and recovery |
|---|---|
| Helper missing or client cannot launch | Verify the actual app path and executable. Recheck the launcher path after moving either the app or project. |
| Tools appear, readiness fails | Read murmur_status. Finish setup, activate the license, and enable automation in the app. |
| Model missing or installing | Use discovery, wait for installation completion, and refresh the model list. Do not infer readiness from a file in the cache. |
| Voice or language rejected | Refresh voices for that model and check its listed capabilities and languages. |
| Workspace path rejected | Put input and output inside the launcher folder. A symlink to an outside directory does not grant access. |
| Output already exists | Choose take-02 or another new name. Use force:true only for an intentional replacement. |
| Polling error or prolonged queue | Use the exact returned UUID and check that the intended app is open. Preserve the job ID before diagnosing or retrying. |
If the app stopped during work, inspect the old job before restarting it. A failed or interrupted job needs a new request after the cause is fixed. Keep completed audio and error information so a retry is deliberate. For broader batch design, the existing CLI and MCP architecture guide covers the surrounding job contract.
Keep local speech and assistant privacy distinct
Murmur performs speech generation on your Mac. Its current MCP implementation restricts generation input and output paths to the server’s workspace. That restriction is not a sandbox around the whole assistant, and job metadata is persisted in Murmur’s Application Support directory. A hosted assistant can receive the script, filenames, discovered voice names, and tool results through its conversation. Review that client’s data settings before supplying private material.
After model setup, local speech can run without a cloud TTS API. Model downloads and hosted assistant usage can still need a network connection and have their own costs or limits. Keep credentials out of scripts and shared configuration, use material you can authorize, and review saved reference voices before using them. Begin with the neutral test sentence in the checklist, then move to a real project once the artifact checks pass.
Frequently asked questions
Does installing an MCP server also install a speech model?
No. Client registration stores a launch command for Murmur’s server. Speech models remain managed by the Mac app. Call murmur_list_models after readiness checks, select a bundled or installed model, and explicitly install a missing one before asking it to generate audio.
Why is Murmur connected but unable to generate?
Tool discovery only proves that the helper can speak MCP. Generation also needs the app’s setup, license, automation permission, and a usable model. Call murmur_status, then inspect the model list. If a speech job fails, read its error field rather than submitting another identical request.
Can I use the same Murmur MCP launcher in every project?
The launcher fixes its workspace to the folder where the script is saved. Reusing that server elsewhere still routes relative paths to that original folder. Make a separate launcher and server name for another project, or use your client’s documented configuration to pin its starting directory deliberately.
Does isError:false mean my voiceover is complete?
No. It describes the tool response, while the job snapshot describes speech work. A queued, running, or failed snapshot can arrive in a valid response. Require state:succeeded and a returned artifact, then verify the actual file before using it in an editor.
Can ordinary ChatGPT web call this local stdio server?
A local Mac helper needs a client or executor that can launch local processes. This guide configures Claude Code or Codex on the Mac. A browser conversation does not read local Codex configuration automatically. Confirm tool access in the exact host where you plan to run the workflow.
Sources
- Murmur: CLI and MCP automation documentationAccessed 2026-10-09
- Anthropic: Claude Code MCP installation, scopes, and connection statusAccessed 2026-10-09
- OpenAI: local Codex MCP configuration and stdio supportAccessed 2026-10-09
- Murmur: Mac requirements, website-edition pricing, and purchase policyAccessed 2026-10-09