TTS2Mic MCP Server
FreeNot checkedGo MCP server for end-to-end testing of browser voice applications by synthesizing text-to-speech audio into simulated microphone input.
About
Go MCP server for end-to-end testing of browser voice applications by synthesizing text-to-speech audio into simulated microphone input.
README
tts2mic-mcp is a Go-based MCP server for end-to-end testing browser voice applications by injecting TTS-generated audio into a simulated microphone.
The intended flow is:
MCP client / test runner
↓
speak(target, text, voice)
↓
TTS cache lookup
↓
TTS provider only on cache miss
↓
PCM / WAV audio
↓
Virtual microphone backend
↓
Browser app using getUserMedia / WebRTC / STT
The main use case is testing browser apps where Playwright or another automation tool clicks around normally and selects a simulated microphone device, for example BlackHole 2ch on macOS.
Status
This is an early scaffold. It currently includes:
- Go CLI entrypoint
- MCP server over stdio using
mcp-go speaktool- pluggable TTS provider interface
- deterministic local TTS stub
- ElevenLabs provider
- filesystem PCM cache
- WAV encoding
- macOS BlackHole backend with direct device-targeted playback
- Linux PipeWire/PulseAudio backend
- Chrome fake-audio-file backend
- setup scripts
- GitHub Actions CI
It is still intentionally small, but the core MCP transport is already in place.
Install / build
go test ./...
go build -o bin/tts2mic-mcp ./cmd/tts2mic-mcp
Run the CLI directly:
go run ./cmd/tts2mic-mcp speak \
--target chrome-file \
--text "hello world" \
--out /tmp/tts2mic.wav
How to use as an MCP server
The server runs over stdio using mcp-go and currently exposes a single tool, speak.
Start the server:
go run ./cmd/tts2mic-mcp
Then send one JSON request per line on stdin:
{"name":"speak","arguments":{"target":"macos-blackhole","text":"hello world","voice":"default"}}
Example using printf:
printf '%s\n' '{"name":"speak","arguments":{"target":"macos-blackhole","text":"hello world","voice":"default"}}' \
| go run ./cmd/tts2mic-mcp
Successful response:
{"ok":true}
Error response:
{"error":"unknown backend"}
MCP tool: speak
Input schema
{
"type": "object",
"required": ["target", "text"],
"properties": {
"target": {
"type": "string",
"description": "Injection backend to use: macos-blackhole, pipewire, or chrome-file"
},
"text": {
"type": "string",
"description": "Text to synthesize and inject into the simulated microphone"
},
"voice": {
"type": "string",
"description": "Provider-specific voice id. Defaults to default. Used in the cache key."
}
}
}
Go type
type SpeakInput struct {
Target string `json:"target"`
Text string `json:"text"`
Voice string `json:"voice,omitempty"`
}
Example request
{
"name": "speak",
"arguments": {
"target": "macos-blackhole",
"text": "hello world",
"voice": "en-US-JennyNeural"
}
}
macOS: simulated microphone with BlackHole
For browser E2E testing on macOS, use BlackHole so the browser sees a real selectable microphone device.
The macos-blackhole backend now opens a playback device directly through CoreAudio via malgo, so it does not need the current macOS system output to be switched just to inject speech.
Install/setup:
./scripts/setup-macos-blackhole.sh
Then:
- Open Audio MIDI Setup.
- Confirm
BlackHole 2chexists. - In your browser app, select
BlackHole 2chas the microphone. - Inject speech (sine test without provider):
go run ./cmd/tts2mic-mcp speak \
--target macos-blackhole \
--text "hello world"
By default the backend looks for the first playback device whose name contains BlackHole.
You can override that lookup if needed:
export TTS2MIC_MACOS_OUTPUT_DEVICE="BlackHole 2ch"
As a use case, in Playwright, your app can select the mic the same way a user would. For apps that expose an input selector, select BlackHole 2ch. For apps using navigator.mediaDevices.enumerateDevices(), choose the audio input whose label contains BlackHole after microphone permission is granted.
Linux: simulated microphone with PipeWire/PulseAudio (not tested yet)
Create a virtual sink and monitor source:
./scripts/setup-pipewire-virtual-mic.sh
Route playback into the virtual sink:
export PULSE_SINK=tts2mic_sink
Inject speech:
go run ./cmd/tts2mic-mcp speak \
--target pipewire \
--text "hello world"
Then select the monitor source as the microphone in the browser.
Chrome fake-audio-file mode
This mode does not create a normal selectable microphone. It is useful for deterministic Chromium automation but is intentionally less realistic than BlackHole/PipeWire.
Generate a WAV file:
go run ./cmd/tts2mic-mcp speak \
--target chrome-file \
--text "hello world" \
--out /tmp/tts2mic.wav
Run Chromium with fake media flags:
./scripts/run-chrome-fake-audio.sh /tmp/tts2mic.wav https://example.com
TTS cache
Before calling the TTS provider, the TTS layer checks a filesystem cache.
Logical cache key:
lang:voice_id:provider:sha256(text)
Default cache directory:
.tts2mic-cache/
The cache stores raw little-endian int16 PCM files and is gitignored.
Example layout:
.tts2mic-cache/
stub/
und/
default/
und__default__stub__<sha256>.pcm
Environment variables:
export TTS_CACHE_DIR=.tts2mic-cache
export TTS_PROVIDER_NAME=stub
export TTS_LANG=en-US
Current behavior:
first speak call → cache miss → provider called → PCM stored
next same call → cache hit → provider skipped
When real providers are added, the cache key should also include any options that affect output audio, such as sample rate, speaking rate, pitch, style, and output format.
TTS providers
The project currently supports two providers:
- Default test provider: a deterministic local sine-wave stub used when
TTS_PROVIDERis unset or set to anything other thanelevenlabs - Real provider: ElevenLabs, selected with
TTS_PROVIDER=elevenlabs
Default local test setup:
unset TTS_PROVIDER
export TTS_PROVIDER_NAME=stub
export TTS_LANG=en-US
ElevenLabs setup:
export TTS_PROVIDER=elevenlabs
export ELEVENLABS_API_KEY=...
export ELEVENLABS_VOICE_ID=...
export ELEVENLABS_MODEL_ID=eleven_multilingual_v2
export ELEVENLABS_OUTPUT_FORMAT=pcm_16000
Notes:
ELEVENLABS_OUTPUT_FORMATdefaults topcm_16000.- If no
voiceis passed tospeak, the ElevenLabs backend falls back toELEVENLABS_VOICE_ID. TTS_PROVIDER_NAMEis used as part of the cache key and defaults tostubor the value ofTTS_PROVIDER.
Roadmap
- Add additional real TTS providers beyond ElevenLabs, such as Azure or OpenAI.
- Add richer device controls for the macOS CoreAudio backend, such as explicit device listing and selection helpers.
- Add 48 kHz resampling for browser/STT realism.
- Add Playwright-oriented helpers for browser E2E flows, such as selecting the simulated microphone and asserting setup state.
- Add transcript assertion helpers.
- Add higher-level MCP/testing ergonomics on top of the existing server, such as richer tool metadata and reusable test helpers.
- Add audio fixtures for noise, silence, barge-in, long utterances, and multi-turn flows.
Installing TTS2Mic MCP Server
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/jacarte/tts2mic-mcpFAQ
Is TTS2Mic MCP Server MCP free?
Yes, TTS2Mic MCP Server MCP is free — one-click install via Unyly at no cost.
Does TTS2Mic MCP Server need an API key?
No, TTS2Mic MCP Server runs without API keys or environment variables.
Is TTS2Mic MCP Server hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install TTS2Mic MCP Server in Claude Desktop, Claude Code or Cursor?
Open TTS2Mic MCP Server on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Playwright
Browser automation, scraping, screenshots
by MicrosoftPuppeteer
Browser automation and web scraping.
by modelcontextprotocolopentabs-dev/opentabs
Plugin-based MCP server + Chrome extension that gives AI agents access to web applications through the user's authenticated browser session. 100+ plugins with a
by opentabs-devrobhunter/agentdeals
1,500+ developer infrastructure deals, free tiers, and startup programs across 54 categories. Search deals, compare vendors, plan stacks, and track pricing chan
by robhunterCompare TTS2Mic MCP Server with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All browse MCPs
