Model Context Protocol (MCP)

Connect AI assistants directly to TTS generation via the MCP standard.

Overview

MCP (Model Context Protocol) lets AI agents call TTS tools without custom HTTP integration. The server exposes 35 tools covering generation, voices, jobs, shares, library management, and storage — the same capabilities as the REST API.

Two connection methods are available: a local stdio CLI for desktop AI apps, and a remote HTTP endpoint for server-side agents.

Connection Methods

Local stdio (recommended for desktop)

Add this to your MCP client config (Claude Desktop, Cursor, etc.):

MCP client config
{
  "mcpServers": {
    "aittsm": {
      "command": "npx",
      "args": ["@theproductivepixel/aittsm"],
      "env": { "AITTSM_API_KEY": "tts_YOUR_KEY" }
    }
  }
}

Set AITTSM_API_KEY to your API key. Optionally set AITTSM_BASE_URL to override the default API base URL.

Remote HTTP (server-to-server)

Send JSON-RPC messages directly to POST /api/v1/mcp. Stateless — no session tracking required.

Remote HTTP
# Remote HTTP — single request
curl -X POST https://aitts.theproductivepixel.com/api/v1/mcp \
  -H "Authorization: Bearer tts_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Available Tools (35)

Each tool requires specific API key permissions. Tools are grouped by function:

Voice & Generation

Permissions: tts:generate, tts:status, voices:list

search_voicesget_voice_detailsgenerate_speechget_job_statusget_audio_link

Jobs

Permissions: jobs:read, jobs:write

list_jobsget_job_textupdate_job_metadatadelete_job_audio

Shares

Permissions: shares:read, shares:write

create_sharelist_sharesget_shareupdate_sharerevoke_sharebulk_revoke_sharestoggle_share_permanentupdate_track_order

Access Codes & QR

Permissions: shares:read, shares:write

create_access_codeslist_access_codesupdate_access_codedelete_access_codeexport_access_codesget_qr_code

Library

Permissions: library:read, library:write

list_collectionsmanage_collectionlist_tagscreate_bookmarklist_bookmarksdelete_bookmarkmanage_bookmark_collection

Storage & Usage

Permissions: storage:read, storage:write, usage:read, pricing:estimate

get_storagelist_storage_itemsbulk_delete_storageget_usageestimate_cost

Patterns

Pagination

Paginated tools accept page_size (1–100, default 20) and page_token (opaque cursor). Results include next_page_token (null when done).

Delivery Mode

generate_speech supports two modes:

  • async (default): Returns job_id. Poll get_job_status until completed, then get_audio_link.
  • stream: Returns one-time stream_url for real-time audio. URL expires and is single-use. Durable artifact saved after stream completes.

Stream supports all 7 formats (wav, mp3, ogg_opus, pcm, mulaw, alaw, ogg_vorbis). Async supports wav, mp3, ogg_opus only.

Idempotency

Pass idempotency_key to generate_speech for safe retries. Same key + same body returns cached result. Same key + different body returns IDEMPOTENCY_KEY_REUSE (409). Key still processing returns REQUEST_IN_PROGRESS (409).

Rate Limiting

Tools use two buckets: read (higher limits, queries) and generate (lower limits, mutations). Limits are per-account. HTTP 429 with Retry-After header when exceeded.

Permissions

PermissionTools
voices:listsearch_voices, get_voice_details
tts:generategenerate_speech
tts:statusget_job_status, get_audio_link
jobs:readlist_jobs, get_job_text
jobs:writedelete_job_audio, update_job_metadata
shares:readlist_shares, get_share, list_access_codes, export_access_codes
shares:writecreate_share, update_share, revoke_share, bulk_revoke_shares, toggle_share_permanent, update_track_order, create_access_codes, update_access_code, delete_access_code, get_qr_code
library:readlist_collections, list_tags, list_bookmarks
library:writemanage_collection, create_bookmark, delete_bookmark, manage_bookmark_collection
storage:readget_storage, list_storage_items
storage:writebulk_delete_storage
pricing:estimateestimate_cost
usage:readget_usage

Examples

Initialize
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": { "name": "my-app", "version": "1.0.0" }
  }
}
List tools
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}
Generate speech
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "generate_speech",
    "arguments": {
      "text": "Hello from MCP!",
      "voice_id": "google:en-US-Chirp3HD-Charon"
    }
  }
}
Generate speech (stream)
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "generate_speech",
    "arguments": {
      "text": "Stream this audio in real time.",
      "voice_id": "google:en-US-Chirp3HD-Charon",
      "delivery_mode": "stream",
      "idempotency_key": "my-unique-key-123"
    }
  }
}
Search voices
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "search_voices",
    "arguments": { "language": "en-US", "gender": "female" }
  }
}

Tool Reference

Complete parameter tables, response shapes, and error codes for every tool.

Voice & Generation

search_voicesvoices:list · read

Search available TTS voices with optional filters.

ParamTypeReqDescription
languagestringLanguage code (e.g. en-US)
providerstringgoogle, polly, or kokoro
model_typeenum: premium | ultraFilter by model type
genderenum: male | female | neutral | unknownFilter by gender
voice_idstringExact voice_id filter (case-insensitive)
Response:{ voices: ApiV1Voice[], count: number }
get_voice_detailsvoices:list · read

Get full capability details for a voice (streaming, formats, limits, speed, prompt).

ParamTypeReqDescription
voice_idstringVoice ID (provider:language-Family-Name)
modelstringModel ID for ultra voices with model selection
Response:{ voice_id: string, provider: string, language: string, family: string, name: string, model_type: string, gender: string, characteristics: object, sample_url: string | null, capabilities: VoiceCapabilities, available_models?: string[], default_model?: string, model?: string, model_overrides?: Record<string, ModelOverride> }
Errors:
INVALID_VOICE_IDVOICE_NOT_FOUNDMODEL_SELECTION_NOT_AVAILABLEINVALID_MODEL
generate_speechtts:generate · generate

Generate TTS audio. Returns job_id for async or stream_url for real-time.

ParamTypeReqDescription
textstring (1–500000)Text to synthesize
voice_idstringsingle onlyVoice ID (provider:lang-Family-Name). Required for single-speaker, forbidden for multi-speaker.
delivery_modeenum: async | streamDefault: async. stream returns one-time URL.
model_typeenum: premium | ultraModel type
modelstringSpecific model ID
speednumber (0.25–4)Speaking rate multiplier
formatenum: text | ssml | markupInput format
speaker_typeenum: single | multiSpeaker type
voice_id_speaker_1stringmulti onlySpeaker 1 voice ID. Required for multi-speaker only.
voice_id_speaker_2stringmulti onlySpeaker 2 voice ID. Required for multi-speaker only.
output_formatenum: wav | mp3 | ogg_opus | pcm | mulaw | alaw | ogg_vorbisAsync: wav/mp3/ogg_opus. Stream: all 7.
promptstringUltra model guidance prompt
webhook_urlstring (URL)Completion webhook (enterprise)
metadataobjectCustom metadata
sample_rate_hertzintegerOutput sample rate
output_bitrate_kbpsintegerBitrate (async only)
languagestringLanguage override
tagsstring[]Library tags
collection_idstringCollection assignment
idempotency_keystring (max 256)Safe retry key (no line breaks)
Response:Async: { job_id, status, poll_url, audio_endpoint, chars_charged } Stream: { job_id, status, poll_url, audio_endpoint, stream_url?, transport_format, transport_mime_type, transport_sample_rate_hertz, chars_charged, cache? }
Errors:
VALIDATION_ERRORINVALID_VOICEPROVIDER_DISABLEDINSUFFICIENT_CREDITSSTORAGE_CAP_EXCEEDEDFORBIDDENINVALID_WEBHOOK_URLENTERPRISE_TIER_REQUIREDSTREAM_NOT_SUPPORTEDSPEED_OUT_OF_RANGESTREAM_BITRATE_NOT_SUPPORTEDSTREAM_FORMAT_MISMATCHMAINTENANCEIDEMPOTENCY_KEY_REUSEREQUEST_IN_PROGRESS
get_job_statustts:status · read

Get status and metadata of a TTS job.

ParamTypeReqDescription
job_idstringJob ID
Response:{ job_id, status, created_at?, provider?, model_requested?, model_effective?, output_format?, sample_rate_hertz?, output_bitrate_kbps?, duration_seconds?, estimated_duration_seconds?, prompt_bytes, chars_charged, audio_endpoint, audio_available, retention_tier?, retained_until?, voice_id?, model_type?, audio_bytes?, tags, collection_id?, source?, is_expired, audio_url?, audio_url_expires_at?, error?, metadata? }
Errors:
JOB_NOT_FOUND
get_audio_linktts:status · read

Get a signed download URL for completed audio.

ParamTypeReqDescription
job_idstringJob ID
Response:{ audio_endpoint, signed_url?, expires_at?, job_id }
Errors:
JOB_NOT_FOUND

Jobs

get_job_textjobs:read · read

Retrieve the input text of a completed TTS job.

ParamTypeReqDescription
job_idstringJob ID
Response:{ text }
Errors:
JOB_NOT_FOUNDTEXT_UNAVAILABLE
list_jobsjobs:read · read

List TTS jobs with pagination and filters.

ParamTypeReqDescription
page_sizeinteger (1–100)Default 20
page_tokenstringPagination cursor
sourceenum: api | uiFilter by source
statusenum: completed | failed | pending | processingFilter by status
Response:{ jobs: JobSummary[], next_page_token }
delete_job_audiojobs:write · generate

Delete stored audio for a completed job.

ParamTypeReqDescription
job_idstringJob ID
Response:{ shares_revoked, storage? }
Errors:
JOB_NOT_FOUNDJOB_IN_PROGRESS
update_job_metadatajobs:write · generate

Update tags and/or collection for a job.

ParamTypeReqDescription
job_idstringJob ID
tagsstring[]Replace tags
collection_idstring | nullSet or clear collection
Response:{ job_id, tags, collection_id }
Errors:
JOB_NOT_FOUNDVALIDATION_ERROR

Shares

create_shareshares:write · generate

Create a shareable link. Provide job_ids (snapshot) or source_type+source_id (source-based).

ParamTypeReqDescription
job_idsstring[]Job IDs for snapshot
source_typeenum: collection | tagSource type
source_idstringSource ID
share_modeenum: snapshot | liveDefault: snapshot
auth_modeenum: none | password | access_codeAuth mode
passwordstringRequired if auth_mode=password
titlestringShare title
allow_downloadbooleanAllow download
include_textbooleanInclude text excerpts
show_voicebooleanShow voice info
show_modelbooleanShow model info
show_providerbooleanShow provider
show_languagebooleanShow language
show_expirybooleanShow expiry
show_track_metabooleanShow track metadata
track_titlesRecord<string, string>{ jobId: title }
track_orderstring[]Custom track order
Response:{ code, url, item_count }
Errors:
AMBIGUOUS_SHARE_INPUTVALIDATION_ERRORINVALID_SHARE_SOURCEPASSWORD_REQUIREDINVALID_AUTH_MODE_PASSWORD_COMBO
list_sharesshares:read · read

List active shares with pagination.

ParamTypeReqDescription
page_sizeinteger (1–100)Default 20
page_tokenstringPagination cursor
Response:{ shares: ShareSummary[], next_page_token }
get_shareshares:read · read

Get full share details including job metadata.

ParamTypeReqDescription
codestringShare code
Response:{ code, title?, share_mode, auth_mode, source_type?, source_id?, created_at, expires_at?, revoked, views, permanent, allow_download, include_text, show_*, track_titles?, track_order?, item_count, jobs: [{ job_id, voice_id, model_type, created_at, audio_bytes?, output_format?, duration_seconds?, estimated_duration_seconds?, duration_source?, duration_confidence?, audio_sample_rate_hertz?, sample_rate_hertz?, output_bitrate_kbps? }] }
Errors:
SHARE_NOT_FOUND
update_shareshares:write · generate

Update share settings.

ParamTypeReqDescription
codestringShare code
titlestringNew title
auth_modeenum: none | password | access_codeAuth mode
passwordstringPassword
allow_downloadbooleanAllow download
share_modeenum: snapshot | liveShare mode
include_textbooleanInclude text
show_voicebooleanShow voice
show_modelbooleanShow model
show_providerbooleanShow provider
show_languagebooleanShow language
show_expirybooleanShow expiry
show_track_metabooleanShow track meta
track_titlesRecord<string, string>Track titles
track_orderstring[] | nullTrack order or null
source_typeenum: collection | tagSource type
source_idstringSource ID
Response:(Same shape as get_share)
Errors:
SHARE_NOT_FOUNDINVALID_SHARE_SOURCESOURCE_IMMUTABLEPASSWORD_REQUIREDINVALID_AUTH_MODE_PASSWORD_COMBO
revoke_shareshares:write · generate

Revoke a share, disabling access.

ParamTypeReqDescription
codestringShare code
Response:{ code, revoked: true }
Errors:
SHARE_NOT_FOUND
bulk_revoke_sharesshares:write · generate

Revoke multiple shares (max 100).

ParamTypeReqDescription
codesstring[] (1–100)Share codes
Response:{ revoked_count, skipped: string[] }
Errors:
VALIDATION_ERROR
toggle_share_permanentshares:write · generate

Toggle permanent status on a share.

ParamTypeReqDescription
codestringShare code
Response:{ code, permanent, expires_at? }
Errors:
SHARE_NOT_FOUND
update_track_ordershares:write · generate

Reorder tracks. Pass null to reset.

ParamTypeReqDescription
codestringShare code
track_orderstring[] | nullOrdered job IDs or null
Response:{ code, track_order }
Errors:
SHARE_NOT_FOUNDVALIDATION_ERROR

Access Codes & QR

create_access_codesshares:write · generate

Create access codes for a share. Raw codes returned once only.

ParamTypeReqDescription
codestringParent share code
countinteger (1–100)Default 1
labelstringLabel or prefix
expires_atstring (ISO date)Expiration
max_usesinteger (≥1)Max uses per code
Response:count=1: { id, code, code_prefix, label?, active, created_at, expires_at?, max_uses? } count>1: [ { id, code }, ... ]
Errors:
SHARE_NOT_FOUNDVALIDATION_ERROR
list_access_codesshares:read · read

List access codes for a share (no raw codes).

ParamTypeReqDescription
codestringShare code
Response:[ { id, code_prefix, label?, active, created_at, expires_at?, max_uses?, uses, last_used_at? }, ... ]
Errors:
SHARE_NOT_FOUND
update_access_codeshares:write · generate

Update an access code.

ParamTypeReqDescription
codestringShare code
access_code_idstringAccess code ID
labelstringNew label
activebooleanActive status
expires_atstring | nullNew expiry or null
max_usesinteger | nullNew max uses or null
Response:{ id, code_prefix, label?, active, created_at, expires_at?, max_uses?, uses, last_used_at? }
Errors:
SHARE_NOT_FOUNDACCESS_CODE_NOT_FOUND
delete_access_codeshares:write · generate

Permanently delete an access code.

ParamTypeReqDescription
codestringShare code
access_code_idstringAccess code ID
Response:{ deleted: true }
Errors:
SHARE_NOT_FOUNDACCESS_CODE_NOT_FOUND
export_access_codesshares:read · read

Export access codes in CSV-compatible format.

ParamTypeReqDescription
codestringShare code
Response:[ { id, code_prefix, label?, active, created_at, expires_at?, max_uses?, uses }, ... ]
Errors:
SHARE_NOT_FOUND
get_qr_codeshares:write · generate

Generate a QR code image for a share link.

ParamTypeReqDescription
codestringShare code
formatenum: svg | pngImage format
presetenum: clean | brandedVisual preset
include_access_codebooleanEmbed code in URL
access_codestringCode to embed
Response:{ data_uri, format }
Errors:
SHARE_NOT_FOUND

Library & Storage

list_collectionslibrary:read · read

List all audio collections.

Response:{ collections: [ { id, name, created_at, updated_at } ] }
manage_collectionlibrary:write · generate

Create, rename, or delete a collection.

ParamTypeReqDescription
actionenum: create | rename | deleteOperation
namestringRequired for create/rename
collection_idstringRequired for rename/delete
Response:create/rename: { id, name, created_at, updated_at } delete: { deleted: true }
Errors:
VALIDATION_ERRORCOLLECTION_NOT_FOUND
list_tagslibrary:read · read

List all tags with usage counts.

Response:{ tags: [ { tag, count } ] }
create_bookmarklibrary:write · generate

Bookmark a shared audio link.

ParamTypeReqDescription
share_codestringShare code
Response:{ created: true }
Errors:
VALIDATION_ERRORALREADY_EXISTS
list_bookmarkslibrary:read · read

List bookmarks with pagination.

ParamTypeReqDescription
page_sizeinteger (1–100)Default 20
page_tokenstringPagination cursor
Response:{ bookmarks: [ { id, share_code, title, personal_title?, collection_id?, created_at, last_opened_at?, effective_status } ], next_page_token }
delete_bookmarklibrary:write · generate

Delete a bookmark.

ParamTypeReqDescription
bookmark_idstringBookmark ID (share code)
Response:{ deleted: true }
Errors:
BOOKMARK_NOT_FOUND
manage_bookmark_collectionlibrary:write · generate

Create, rename, or delete a bookmark collection.

ParamTypeReqDescription
actionenum: create | rename | deleteOperation
namestringRequired for create/rename
collection_idstringRequired for rename/delete
Response:create/rename: { id, name, color?, created_at, updated_at } delete: { deleted: true }
Errors:
VALIDATION_ERRORBOOKMARK_NOT_FOUND
get_storagestorage:read · read

Get storage usage summary.

Response:{ used_bytes, cap_bytes, remaining_bytes, pending_reclaim_bytes, sync_status }
list_storage_itemsstorage:read · read

List stored audio items with pagination.

ParamTypeReqDescription
page_sizeinteger (1–100)Default 20
page_tokenstringPagination cursor
Response:{ items: [ { job_id, status, audio_bytes?, output_format?, created_at?, storage_tier? } ], next_page_token }
bulk_delete_storagestorage:write · generate

Bulk delete stored audio (max 100 jobs).

ParamTypeReqDescription
job_idsstring[] (1–100)Job IDs to delete
Response:{ deleted_count, skipped_count, skipped: [ { job_id, reason } ] }
Errors:
VALIDATION_ERROR
estimate_costpricing:estimate · read

Estimate TTS cost without generating.

ParamTypeReqDescription
textstring (1–500000)Text to estimate
model_typeenum: premium | ultraModel type
voice_idstringVoice ID
output_formatenum: wav | mp3 | ogg_opusFormat
Response:{ estimated_cost, chars_charged, model_type, provider, output_format }
Errors:
VALIDATION_ERRORENTERPRISE_TIER_REQUIRED
get_usageusage:read · read

Get API usage and credit balance.

Response:{ account_type, credits_balance }

Error Codes

Tool errors are returned as text content with isError: true and a JSON payload: { error: "message", code: "ERROR_CODE", status: 400 }. Protocol-level errors (invalid JSON-RPC, unknown method) use standard JSON-RPC 2.0 error format.

Protocol Errors

CodeMeaning
-32700Parse error — malformed JSON body
-32600Invalid request — bad method or params
-32001Authentication failed — missing or invalid API key
-32603Internal server error

Tool-Level Errors

CodeStatusDescription
VALIDATION_ERROR400Invalid input parameters
INVALID_VOICE400Voice ID not found or invalid format
PROVIDER_DISABLED400Provider unknown or disabled
INSUFFICIENT_CREDITS402Not enough credits for generation
STORAGE_CAP_EXCEEDED403Storage quota full
FORBIDDEN403Enterprise-only feature or ownership check failed
INVALID_WEBHOOK_URL400Webhook URL validation failed
ENTERPRISE_TIER_REQUIRED400Enterprise pricing without tier
STREAM_NOT_SUPPORTED400Voice/provider doesn't support streaming
SPEED_OUT_OF_RANGE400Speaking rate exceeds stream limit
STREAM_BITRATE_NOT_SUPPORTED400Bitrate selection in stream mode
STREAM_FORMAT_MISMATCH400Format not supported for stream transport
MAINTENANCE503API in maintenance mode
IDEMPOTENCY_KEY_REUSE409Key reused with different request body
REQUEST_IN_PROGRESS409Key still processing
JOB_NOT_FOUND404Job doesn't exist or not owned by caller
JOB_IN_PROGRESS409Cannot delete pending/processing job
TEXT_UNAVAILABLE410Job expired or text not stored
SHARE_NOT_FOUND404Share doesn't exist or not owned
AMBIGUOUS_SHARE_INPUT400Both job_ids and source provided
INVALID_SHARE_SOURCE400Invalid source configuration
PASSWORD_REQUIRED400auth_mode=password without password
INVALID_AUTH_MODE_PASSWORD_COMBO400auth_mode and password combination invalid
SOURCE_IMMUTABLE400Cannot change source on source-backed share
ACCESS_CODE_NOT_FOUND404Access code doesn't exist
COLLECTION_NOT_FOUND404Collection doesn't exist or not owned
BOOKMARK_NOT_FOUND404Bookmark or collection doesn't exist
ALREADY_EXISTS409Bookmark already exists for this share
FREE_TIER_LIMIT_EXCEEDED403Free tier limit reached (>1000 characters per request)
Back to Documentation

© 2026 AI TTS Microservice. All rights reserved.