Local Voice MCP Server for Claude Code — file-based transcription and speech synthesis powered by Whisper (STT) and OpenAI-compatible TTS (Kokoro/Piper). Self-hosted, zero API cost. Supports primary + fallback endpoints.
Three tools with complete schemas and descriptions, but significant gaps in parameter documentation and error handling. Tool names are action-oriented (transcribe, speak, health) and descriptions are present (avg 150 chars). However, many parameters lack descriptions or constraints. The 'speak' tool has good parameter coverage, but 'transcribe' and 'health' are minimal. No output schemas documented. Error handling is absent, no recovery guidance, no categorization of retryable vs fatal errors. No tool annotations (readOnlyHint/destructiveHint). Circuit breaker logic is implemented server-side but not exposed to the LLM.
Check the status of Whisper STT and TTS services.
Convert text to speech using local TTS. Returns the path to the generated audio file (MP3). Language is auto-detected from text (zh, ja, en). You can override the voice with the voice parameter.
Transcribe an audio file to text using local Whisper. Supports wav, mp3, m4a, ogg, webm, flac, aac, and more. Pass the absolute file path to the audio file.
Missing output schemas. No documentation of what transcribe(), speak(), or health() return. LLMs cannot plan downstream tool calls or extract required fields without knowing response structure.
No error handling guidance. Tools fail silently or return raw HTTP errors with no recovery hints. E.g., if Whisper endpoint is down, the LLM gets no suggestion to check health() or retry with fallback.
Missing parameter descriptions. 'language' in transcribe has a description, but 'voice' in speak lacks detail on valid values (lists 'af_sky, af_bella, am_adam' in description but no enum constraint). 'speed' lacks min/max bounds.
No tool annotations. 'speak' is destructive (writes MP3 files) and 'transcribe' is read-only, but inputSchema lacks readOnlyHint/destructiveHint annotations. LLMs cannot infer safety properties.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
health() description is vague ('Check the status of Whisper STT and TTS services'). Does it return a boolean, a status object, or a detailed report? What fields? When should the LLM call it?