MCP cho agent
SaiTTS có MCP server để AI agent (Claude Code, Claude Desktop, Cursor…) tự chọn giọng và đọc văn bản. Có hai cách kết nối:
| Cách | Khi nào dùng | Audio nhận được |
|---|---|---|
HTTP trực tiếp tới http://saitts.supermeo.com/api/mcp | Cài nhanh, không cần tải gì | Base64 trong kết quả tool (bản nhỏ) hoặc link tải có chữ ký |
Proxy stdio saitts-mcp.mjs (Node 18+) | Agent chạy trên máy bạn, text dài | Proxy lưu file audio vào thư mục trên máy và trả đường dẫn file |
Chuẩn bị
- Gói của bạn phải có quyền MCP (xem bảng giá). Không có → MCP server trả
403 MCP_DISABLED. - Vào Hồ sơ › API tạo API key với scope
tts:generatevàtts:read(cần cả hai để đọc và lấy lại kết quả). Xem REST API. - MCP server chỉ nhận API key (
Authorization: Bearer sk-saitts-…); token đăng nhập web bị từ chối.
Trong các ví dụ, thay sk-saitts-YOUR_KEY bằng key của bạn.
Claude Code
HTTP trực tiếp:
claude mcp add --transport http saitts http://saitts.supermeo.com/api/mcp --header "Authorization: Bearer sk-saitts-YOUR_KEY"Qua proxy (audio lưu thành file trong ./saitts-audio):
curl -o saitts-mcp.mjs http://saitts.supermeo.com/api/mcp/client/saitts-mcp.mjs
claude mcp add saitts --env SAITTS_API_KEY=sk-saitts-YOUR_KEY --env SAITTS_URL=http://saitts.supermeo.com --env SAITTS_OUTPUT_DIR=./saitts-audio -- node ./saitts-mcp.mjsKiểm tra bằng claude mcp list, hoặc gõ /mcp trong Claude Code.
Claude Desktop
Mở Settings › Developer › Edit Config (claude_desktop_config.json), thêm vào mcpServers rồi khởi động lại Claude Desktop.
File cấu hình của Claude Desktop không gửi được header cho server từ xa, nên HTTP đi qua mcp-remote (cần Node):
{
"mcpServers": {
"saitts": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://saitts.supermeo.com/api/mcp", "--header", "Authorization: Bearer sk-saitts-YOUR_KEY"]
}
}
}Hoặc dùng proxy đã tải về (ghi đường dẫn tuyệt đối, vì Claude Desktop không chạy trong thư mục dự án):
{
"mcpServers": {
"saitts": {
"command": "node",
"args": ["/duong/dan/toi/saitts-mcp.mjs"],
"env": {
"SAITTS_API_KEY": "sk-saitts-YOUR_KEY",
"SAITTS_URL": "http://saitts.supermeo.com",
"SAITTS_OUTPUT_DIR": "/duong/dan/toi/saitts-audio"
}
}
}
}Cursor
Thêm vào ~/.cursor/mcp.json (mọi dự án) hoặc .cursor/mcp.json (một dự án):
{
"mcpServers": {
"saitts": {
"url": "http://saitts.supermeo.com/api/mcp",
"headers": { "Authorization": "Bearer sk-saitts-YOUR_KEY" }
}
}
}Muốn dùng proxy thì thay bằng "command": "node", "args": ["./saitts-mcp.mjs"] và khối env như ví dụ Claude Desktop.
Proxy saitts-mcp.mjs
Tải tại http://saitts.supermeo.com/api/mcp/client/saitts-mcp.mjs (không cần đăng nhập). Một file, không cần cài thư viện, chạy bằng Node 18 trở lên. Proxy tự báo khi server có bản mới.
| Biến môi trường | Mặc định | Ý nghĩa |
|---|---|---|
SAITTS_API_KEY | — (bắt buộc) | API key sk-saitts-… |
SAITTS_URL | https://saitts.supermeo.com | Địa chỉ máy chủ — với máy chủ này: http://saitts.supermeo.com |
SAITTS_OUTPUT_DIR | ./saitts-output | Thư mục lưu file audio |
SAITTS_TOOLSETS | (tất cả) | Chỉ hiện một số nhóm tool, ví dụ catalog,tts |
SAITTS_TIMEOUT | 150 | Số giây chờ tối đa mỗi lệnh gọi |
Với tts_speak và tts_get, proxy ghi audio vào SAITTS_OUTPUT_DIR và trả về đường dẫn file thay cho dữ liệu audio — agent không phải đọc base64. Tham số output_path của tts_speak chọn tên file (phải nằm trong SAITTS_OUTPUT_DIR).
Các tool
| Tool | Làm gì | Scope cần |
|---|---|---|
account_usage | Gói và số ký tự còn lại | (key hợp lệ) |
list_models | Model bạn được dùng, ngôn ngữ, định dạng, giới hạn | (key hợp lệ) |
list_voices | Giọng của một model (lọc lang, gender, q) | (key hợp lệ) |
tts_speak | Đọc văn bản: model, voice, text, format (mp3/opus/wav/flac), wait_seconds (≤ 60) | tts:generate |
tts_get | Kết quả của một job trước (job_id) | tts:read |
history_list | Tìm các văn bản đã đọc trước đây | tts:read |
Server còn có resource saitts://guide (hướng dẫn ngắn cho agent) và saitts://voices/{model}.
Kết quả của tts_speak:
- Xong trong
wait_secondsvà file nhỏ (≤ 8 MB) → audio base64 ngay trong kết quả. - File lớn hơn →
download_urlcó chữ ký (tải không cần key, hết hạn sau tối đa 1 giờ). - Chưa xong →
job_id+status; agent gọitts_get(job_id)sau. Đừng gọi lạitts_speakcho cùng text khi job còn chạy — mỗi lần gọi đều tính ký tự.
Lỗi nghiệp vụ trả trong kết quả tool (isError: true, structuredContent.error = {code, message}), ví dụ QUOTA_EXCEEDED, TEXT_TOO_LONG, FORBIDDEN_MODEL, VOICE_NOT_FOUND, SCOPE_MISSING, CONCURRENCY_LIMIT, NO_WORKER.
Ví dụ prompt
- "Dùng SaiTTS liệt kê các giọng nữ miền Nam của model mặc định."
- "Đọc đoạn sau bằng giọng minh-triet, định dạng mp3, lưu tên
chao-mung.mp3: Xin chào các bạn…" - "Kiểm tra tôi còn bao nhiêu ký tự hôm nay trên SaiTTS."
- "Tìm trong lịch sử SaiTTS bản đọc có chữ 'khuyến mãi' và lấy lại audio nếu còn."
MCP for agents
SaiTTS runs an MCP server so AI agents (Claude Code, Claude Desktop, Cursor…) can pick a voice and read text aloud on their own. There are two ways to connect:
| Way | When | Audio you get |
|---|---|---|
Direct HTTP to http://saitts.supermeo.com/api/mcp | Quick setup, nothing to download | Base64 inside the tool result (small files) or a signed download link |
stdio proxy saitts-mcp.mjs (Node 18+) | The agent runs on your machine, long texts | The proxy saves the audio to a local folder and returns the file path |
Before you start
- Your plan must include MCP (see pricing). Without it the MCP server answers
403 MCP_DISABLED. - Create an API key under Profile › API with the scopes
tts:generateandtts:read(both, to speak and to fetch results later). See REST API. - The MCP server accepts only API keys (
Authorization: Bearer sk-saitts-…); website sign-in tokens are refused.
In the examples, replace sk-saitts-YOUR_KEY with your key.
Claude Code
Direct HTTP:
claude mcp add --transport http saitts http://saitts.supermeo.com/api/mcp --header "Authorization: Bearer sk-saitts-YOUR_KEY"Through the proxy (audio saved as files in ./saitts-audio):
curl -o saitts-mcp.mjs http://saitts.supermeo.com/api/mcp/client/saitts-mcp.mjs
claude mcp add saitts --env SAITTS_API_KEY=sk-saitts-YOUR_KEY --env SAITTS_URL=http://saitts.supermeo.com --env SAITTS_OUTPUT_DIR=./saitts-audio -- node ./saitts-mcp.mjsCheck with claude mcp list, or type /mcp inside Claude Code.
Claude Desktop
Open Settings › Developer › Edit Config (claude_desktop_config.json), add the server under mcpServers, then restart Claude Desktop.
The Claude Desktop config file cannot send headers to a remote server, so HTTP goes through mcp-remote (needs Node):
{
"mcpServers": {
"saitts": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://saitts.supermeo.com/api/mcp", "--header", "Authorization: Bearer sk-saitts-YOUR_KEY"]
}
}
}Or use the downloaded proxy (use absolute paths: Claude Desktop does not run inside your project folder):
{
"mcpServers": {
"saitts": {
"command": "node",
"args": ["/path/to/saitts-mcp.mjs"],
"env": {
"SAITTS_API_KEY": "sk-saitts-YOUR_KEY",
"SAITTS_URL": "http://saitts.supermeo.com",
"SAITTS_OUTPUT_DIR": "/path/to/saitts-audio"
}
}
}
}Cursor
Add to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):
{
"mcpServers": {
"saitts": {
"url": "http://saitts.supermeo.com/api/mcp",
"headers": { "Authorization": "Bearer sk-saitts-YOUR_KEY" }
}
}
}To use the proxy instead, put "command": "node", "args": ["./saitts-mcp.mjs"] and the env block from the Claude Desktop example.
The saitts-mcp.mjs proxy
Download it from http://saitts.supermeo.com/api/mcp/client/saitts-mcp.mjs (no sign-in needed). One file, no dependencies, runs on Node 18 or later. The proxy tells you when the server has a newer version.
| Environment variable | Default | Meaning |
|---|---|---|
SAITTS_API_KEY | — (required) | The sk-saitts-… API key |
SAITTS_URL | https://saitts.supermeo.com | Server address — for this server: http://saitts.supermeo.com |
SAITTS_OUTPUT_DIR | ./saitts-output | Folder for audio files |
SAITTS_TOOLSETS | (all) | Show only some tool groups, for example catalog,tts |
SAITTS_TIMEOUT | 150 | Maximum seconds per call |
For tts_speak and tts_get the proxy writes the audio into SAITTS_OUTPUT_DIR and returns the file path instead of the audio data — the agent never has to handle base64. The output_path argument of tts_speak picks the file name (it must stay inside SAITTS_OUTPUT_DIR).
Tools
| Tool | What it does | Scope |
|---|---|---|
account_usage | Your plan and characters left | (any valid key) |
list_models | Models you may use, languages, formats, limits | (any valid key) |
list_voices | Voices of a model (filter by lang, gender, q) | (any valid key) |
tts_speak | Speak text: model, voice, text, format (mp3/opus/wav/flac), wait_seconds (≤ 60) | tts:generate |
tts_get | Result of an earlier job (job_id) | tts:read |
history_list | Find texts you read before | tts:read |
The server also offers the resources saitts://guide (a short guide for agents) and saitts://voices/{model}.
What tts_speak returns:
- Done within
wait_secondsand small (≤ 8 MB) → base64 audio right in the result. - Larger → a signed
download_url(no key needed, expires within 1 hour at most). - Not done yet →
job_id+status; the agent callstts_get(job_id)later. Do not calltts_speakagain for the same text while the job runs — every call spends characters.
Business errors come back inside the tool result (isError: true, structuredContent.error = {code, message}), for example QUOTA_EXCEEDED, TEXT_TOO_LONG, FORBIDDEN_MODEL, VOICE_NOT_FOUND, SCOPE_MISSING, CONCURRENCY_LIMIT, NO_WORKER.
Example prompts
- "Use SaiTTS to list the female Southern voices of the default model."
- "Read this with the voice minh-triet as mp3 and save it as
welcome.mp3: Hello everyone…" - "Check how many SaiTTS characters I have left today."
- "Find the SaiTTS reading that mentions 'discount' in my history and fetch its audio if it is still available."