# TalkBox MCP server Local **Model Context Protocol** server — lets any MCP-aware agent (Claude Code, Cursor, Windsurf, VS Code MCP extensions, etc.) speak text in your cloned voices, transcribe audio, and browse captures. The server runs inside the same `uvicorn` process as the rest of TalkBox and is mounted at `/mcp` (Streamable HTTP transport). ## Install into your agent Preferred — direct HTTP: ```json { "mcpServers": { "talkbox": { "url": "http://127.0.0.1:17494/mcp", "headers": { "X-TalkBox-Client-Id": "claude-code" } } } } ``` Fallback — stdio shim (when the client doesn't speak HTTP MCP). The `talkbox-mcp` binary ships inside the TalkBox.app bundle: ```json { "mcpServers": { "talkbox": { "command": "/Applications/TalkBox.app/Contents/MacOS/talkbox-mcp", "env": { "TALKBOX_CLIENT_ID": "claude-code" } } } } ``` Claude Code one-liner: ``` claude mcp add talkbox \ --transport http \ --url http://127.0.0.1:17494/mcp \ --header "X-TalkBox-Client-Id: claude-code" ``` ## Tools | Name | Purpose | |---|---| | `talkbox.speak` | Speak text in a voice profile. Returns a generation id you can poll. | | `talkbox.transcribe` | Whisper transcription of a base64 blob or an absolute local path. | | `talkbox.list_captures` | Recent captures (dictation / recording / file) with transcripts. | | `talkbox.list_profiles` | Available voice profiles (cloned + preset). | All tools resolve voice profiles in this precedence: 1. Explicit `profile` arg (name or id — case-insensitive) 2. Per-client binding keyed by `X-TalkBox-Client-Id` 3. `capture_settings.default_playback_voice_id` (global default) Bindings are managed via `GET|PUT /mcp/bindings` or in the app under Settings → MCP. ## Debug with MCP Inspector ``` npx @modelcontextprotocol/inspector http://127.0.0.1:17494/mcp ``` Point it at the URL, hit "List tools," call `talkbox.list_profiles` first to confirm wiring, then `talkbox.speak` for end-to-end. ## Non-MCP REST surface `POST /speak` is a thin wrapper on the same code path for callers that don't speak MCP (shell scripts, ACP, A2A): ``` curl -X POST http://127.0.0.1:17494/speak \ -H 'Content-Type: application/json' \ -H 'X-TalkBox-Client-Id: claude-code' \ -d '{"text":"Build complete.","profile":"Morgan"}' ``` ## Code layout ``` backend/mcp_server/ ├── __init__.py # re-export mount_into ├── server.py # build_mcp_server() + mount_into(app) ├── tools.py # @mcp.tool() implementations ├── context.py # ClientIdMiddleware + current_client_id ContextVar ├── resolve.py # profile resolution precedence ├── events.py # pub/sub queue for /events/speak pill SSE └── README.md # you are here backend/mcp_shim/ # stdio ↔ Streamable-HTTP proxy (see its README) ``` The package is **`mcp_server`**, not `mcp`, to avoid shadowing the installed `mcp` PyPI package that FastMCP imports internally.