MCP Setup
Connect MCP clients to local speech, speakers, and model generation.
Setup
Works with any MCP client that supports stdio. Install and activate edgespeak-cli first, then register EdgeSpeak. For Claude Code:
claude mcp add edgespeak -- edgespeak-cli mcpTransports
stdio is recommended: when the desktop app is running, it reuses loaded models through the local gateway; when it is not running, stdio starts the bundled local engine and downloads missing models on demand. HTTP /mcp is the alternative, served by the running desktop app and by the headless service, and follows that gateway’s authentication setting. The shared selector also updates the HTTP examples; stdio needs no API key.
edgespeak-cli mcp # stdio
POST http://127.0.0.1:1117/mcp # HTTP (desktop app running)
POST http://127.0.0.1:1118/mcp # HTTP (edgespeak-cli serve)Call MCP over HTTP
POST /mcp is a JSON-RPC transport at the server root, not /v1/mcp. Reuse the quickstart environment. This service uses stateless HTTP with JSON responses; there is no session ID to save. MCP clients handle initialization and discovery for you. To inspect it manually, send an initialize request first (requires jq):
Request:
MCP_URL="${EDGESPEAK_BASE_URL%/v1}/mcp"
curl --fail-with-body "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"docs-example","version":"1.0"}}}' \
-o mcp-init.json
jq '{id, server: .result.serverInfo.name, protocolVersion: .result.protocolVersion}' mcp-init.json
MCP_PROTOCOL=$(jq -er '.result.protocolVersion' mcp-init.json)Example output (jq projection; the negotiated protocol version may differ):
{"id":1,"server":"edgespeak","protocolVersion":"2025-03-26"}Notify initialization, then call a tool. The notification returns 202 with an empty body; the tool request returns a JSON-RPC result. Reuse the negotiated version:
curl --fail-with-body "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $MCP_PROTOCOL" \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
curl --fail-with-body "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $MCP_PROTOCOL" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"edgespeak_segment_sentences","arguments":{"text":"Hello world. Let us begin."}}}' \
-o mcp-result.json
jq '.result.structuredContent' mcp-result.jsonExample output (the structuredContent projection; model boundaries may differ):
{
"metadata": {"sentence_count": 2},
"result": [{"text":"Hello world.","start":0.0,"end":0.0},{"text":"Let us begin.","start":0.0,"end":0.0}],
"truncated": false
}For plain-text MCP segmentation, zero start and end values are placeholders, not measured audio timing. The HTTP text segmentation API omits these fields.
To retrieve the complete tool schemas, send {"jsonrpc":"2.0","id":3,"method":"tools/list","params":{}} with the same headers; the response has result.tools[] entries containing name, description, and inputSchema. Tool call failures may still return HTTP 200: inspect JSON-RPC error and result.isError before reading structured content.
File paths accepted by MCP are on the service host; they do not automatically upload files from a remote client. For remote transcription, pass inline audio or use the multipart HTTP API instead. Returned artifact paths also belong to the service host and are not download links.
Tools
Twelve tools, nine of them read-only. Voice creation, deletion, and Broadcast only modify managed local files. The product capability is called Broadcast, but tool identifiers keep the developer-contract term speech.
edgespeak_transcribe_file required: path (absolute)
optional: model, language, diarize, timestamps (none|word|segment),
min_chars, max_chars, start_margin, end_margin
edgespeak_transcribe required: audio_base64 (decoded ≤ 50MB)
optional: same as transcribe_file
edgespeak_diarize_file required: path (absolute)
optional: num_speakers (1..32)
edgespeak_align required: text + exactly one of path | audio_base64
optional: language, protected_terms
result: words, plus task, text, segments, usage
shaped like POST /v1/audio/alignments
edgespeak_segment_sentences required: text or segments[]
optional: threshold (default 0.35), min_chars, max_chars,
start_margin, end_margin
edgespeak_speech_examples optional: model, mode, language, id, recipe
returns model-specific speech examples and applicability
edgespeak_list_models no parameters → {models: [{id, owned_by, locality}]}
edgespeak_create_response required: model, and input or images
optional: max_output_tokens, temperature, reasoning, translation
(same shape as top-level translation on /v1/responses:
target_language, language_pair, source_language, style)
images: at most 4; decoded total ≤ 20MB
edgespeak_list_voices no parameters → {voices: [...]}
edgespeak_add_voice required: audio_path (absolute), ref_text, name,
consent=true
optional: language, speaker_description
edgespeak_delete_voice required: voice_id (user:<uuid>)
built-in voices cannot be deleted
edgespeak_create_speech required: model, input, voice
models: select from the current edgespeak_list_models catalog
optional: instructions, disable_style, clone_mode, speed, language, seed,
guidance_scale, inference_steps, retry_badcase, clone_recipe,
temperature, top_p, top_k, repetition_penalty,
user_marks, phonetic_spans, control_policy
instructions: omitted / "" / null keeps the voice's saved style,
non-empty text uses that style for this request
disable_style: true speaks without any style;
cannot be combined with non-empty instructions
clone_mode: quick | ultimate; omitted uses the model default
voice=builtin:design designs a voice from the instructions
description (required)
qwen3-tts-voice-design requires instructions
with voice=builtin:auto or builtin:design
output: managed local WAV artifactEvery language argument uses the same codes as the HTTP API; see Languages. MCP edgespeak_segment_sentences currently exposes sentence parameters. Use the HTTP API or CLI segment --paragraph-threshold for paragraphs. Speech controls vary by model; check the model catalog and edgespeak_speech_examples before calling. For instructions, clone_mode, and builtin:design, see Style instructions, clone modes, and voice design; for translation, see Set the translation direction.
Tool request and result examples
Use each row’s tool name and arguments in the tools/call request shown above: params:{name,arguments}. Output cells are excerpts of result.structuredContent, with unrelated fields and extra array items omitted; they are not complete JSON-RPC envelopes. When calling, replace example file paths, base64 data, model IDs, and voice IDs with actual values. All paths correspond to the service host. Adding/deleting voices and creating speech write managed local files; execute those only when needed.
| Tool name | Example arguments | Example structured result (excerpt) |
|---|---|---|
edgespeak_list_models | {} | {"models":[{"id":"Qwen/Qwen3.5-4B","owned_by":"EdgeSpeak","locality":"local"}]} |
edgespeak_transcribe_file | {"path":"/absolute/path/hello.wav"} | {"result":{"text":"Hello world."},"truncated":false} |
edgespeak_transcribe | {"audio_base64":"<base64 audio file bytes>"} | {"result":{"text":"Hello world."},"truncated":false} |
edgespeak_diarize_file | {"path":"/absolute/path/meeting.wav","num_speakers":2} | {"result":{"speakers":["SPEAKER_00","SPEAKER_01"],"segments":[{"start":0.4,"end":3.2,"speaker":"SPEAKER_00"}]},"truncated":false} |
edgespeak_align | {"path":"/absolute/path/hello.wav","text":"Hello world."} | {"result":{"words":[{"word":"Hello","start":0.2,"end":0.6,"score":0.98}],"task":"align","text":"Hello world.","segments":[{"id":0,"start":0.2,"end":1.1,"text":"Hello world.","words":[{"word":"Hello","start":0.2,"end":0.6,"score":0.98}]}],"usage":{"type":"duration","seconds":1.2}},"truncated":false} |
edgespeak_segment_sentences | {"text":"Hello world. Let us begin."} | {"metadata":{"sentence_count":2},"result":[{"text":"Hello world.","start":0.0,"end":0.0}],"truncated":false} |
edgespeak_speech_examples | {} | {"examples":[{"model":"openbmb/VoxCPM2","mode":"voice-design","applicable":true,"reason":null}]} |
edgespeak_create_response | {"model":"Qwen/Qwen3.5-4B","input":"我们下周一开会。","translation":{"target_language":"en"}} | {"output":[{"type":"message","role":"assistant","content":[{"type":"output_text","text":"We have a meeting next Monday."}]}]} |
edgespeak_list_voices | {} | {"voices":[{"id":"builtin:bright-girl","available":true}]} |
edgespeak_add_voice | {"audio_path":"/absolute/path/reference.wav","ref_text":"Hello world.","name":"My voice","language":"en-US","consent":true} | {"voice":{"id":"user:00000000-0000-4000-8000-000000000001"}} |
edgespeak_create_speech | {"model":"Qwen/Qwen3-TTS-0.6B-Base","voice":"builtin:bright-girl","input":"Hello world.","clone_mode":"quick"} | {"artifact_path":"/service/artifacts/speech-example.wav","format":"wav","sample_rate":24000,"duration":1.2} |
edgespeak_delete_voice | {"voice_id":"user:00000000-0000-4000-8000-000000000001"} | {"deleted":{"id":"user:00000000-0000-4000-8000-000000000001","name":"My voice"}} |
For complete voice and model records, see voice fields and model discovery. The MCP model catalog uses models[] with locality; the HTTP API uses data[] with execution_location. Do not mix the two response formats. For oversized results, see Results.
Results
Text results are returned inline up to 2000 characters; output exceeding 2000 characters spills to a local artifact with an inline preview. Broadcast always returns a managed local WAV artifact path plus generation diagnostics.
≤ 2000 chars → { "metadata": …, "result": …, "truncated": false }
> 2000 chars → { "metadata": …, "preview": { "head": …, "tail": … },
"artifact_path": …, "artifact_json_path": …, "truncated": true }
Broadcast → { "artifact_path": …, "format": "wav", "sample_rate": …,
"duration": …, "seed_used": …, "warnings": […] }Privacy
Speech workflows and installed local models keep source audio, voices, generated audio, transcripts, prompts, and images on this device. Only when you explicitly select a model reported as execution_location=remote is that request sent to its configured provider.
Generate with a local model
Start the desktop app, download and load a local model, then use Responses, Chat Completions, the CLI, or MCP.
Call edgespeak_create_response with the following arguments; replace the image placeholder with base64-encoded PNG bytes:
{
"model": "Qwen/Qwen3.5-4B",
"input": "Describe the attached image",
"images": [{ "mime_type": "image/png", "data_base64": "<base64>" }]
}