MCP server
Built-in Model Context Protocol server. Any MCP-capable AI agent can drive your microphone and speak through your speakers.
Three tools
| Tool | What it does |
|---|---|
| transcribe_voice | Opens the mic, records the user, returns the transcript |
| speak_text | Queues text for TTS playback through the current voice |
| get_status | Returns whether the mic is open and TTS is playing |
Transport
Unix domain socket at /tmp/voxctrl-mcp.sock (Linux) or named pipe
\\.\pipe\voxctrl-mcp (Windows). Each connection is spawned as its own async tokio
task. Newline-delimited
JSON-RPC 2.0 — one JSON object per line, terminated with \n. Follows MCP spec
2024-11-05.
Enabling
Settings → General → MCP Server section → toggle Enable MCP Server. Or set directly in
~/.config/voxctrl/config.json under the mcp key:
{
"mcp": {
"server_enabled": true,
"record_timeout": 15.0,
"visual_feedback": true
}
}
The server starts automatically when the app launches if server_enabled is true.
Claude Desktop
Add the bridge config to ~/.config/claude/claude_desktop_config.json manually — voxctrl must
already be running before Claude Desktop connects. On Linux, the bridge uses socat to pipe
stdio to the Unix socket:
{
"mcpServers": {
"voxctrl": {
"command": "socat",
"args": [
"STDIO",
"UNIX-CONNECT:/tmp/voxctrl-mcp.sock"
]
}
}
}
Protocol handshake
- Send
initialize— receiveprotocolVersion 2024-11-05and capability list - Send
notifications/initialized(no response expected) - Send
tools/list— receive the three tool definitions - Call any tool with
tools/call
Error codes
| Code | Meaning |
|---|---|
| -32700 | Parse error (malformed JSON) |
| -32601 | Method not found |
| -32603 | Internal error (unknown tool name, missing required argument, callback exception) |
Behaviour notes
- While
transcribe_voicerecords, the recording overlay is always shown — the user always has a visual indicator that the mic is live - The mic is released automatically once VAD detects silence or
timeout_seconds(default15.0) elapses - voxctrl's full post-processing pipeline (including OpenAI API LLM formatting/cleaning, if enabled) is applied before the transcript is returned
- If no speech is captured,
transcribe_voicereturns the literal text(no speech detected) speak_textreturns as soon as the text is queued — does not block until playback finishes. Ifpiperisn't installed or its voice files are missing, playback falls back toespeak-ngautomaticallyget_statusreturns a JSON-encoded object as its text content:{"recording": false, "speaking": false}
Response loopback (FIFO)
For agents that generate responses to a named FIFO, set response_pipe on the target in
targets.toml. voxctrl spawns an async run_fifo_responder task that watches the
FIFO; when the agent writes a line to it, voxctrl reads it and pushes it straight to the TTS worker queue —
no speak_text call required. The listener automatically handles agent disconnects (EOF) and
reconnects on the next session without restarting voxctrl.
[[target]] id = "my-agent" label = "My Agent" delivery = "pipe" pipe_path = "/tmp/my-agent.in" response_pipe = "/tmp/my-agent.out" # agent writes responses here append_newline = true