An audio playback control MCP service based on Tuya MCP SDK and FastMCP, supporting both WebSocket and Streamable HTTP transport modes.
- Features
- Architecture
- Requirements
- Quick Start
- Configuration
- AI Client Integration
- MCP Tools
- Testing
- Documentation
- Troubleshooting
- Contributing
- License
📖 Quick Start: See doc/QUICKSTART.md for installation and service management
✅ 9 Playback Intents:
play- Play audiostop- Stop playbackresume- Resume playbackreplay- Replay current audionext- Next trackprev- Previous tracksingle_loop- Single track loopsequential_loop- Sequential loopno_loop- Cancel loop
✅ Tech Stack:
- MCP Framework: FastMCP (class-based mode)
- Transport Modes: WebSocket (Tuya Cloud) + Streamable HTTP (Direct clients)
- Authentication: URL Parameter API Key + Tuya OpenAPI (HMAC-SHA256)
- State Storage: Redis (playback state + playlist + token cache)
- File Platform: Tuya File Platform API integration
- Message Queue: Tuya MCP SDK WebSocket connection
- Context Handling: Dual-mode context extraction (WebSocket meta + HTTP headers)
Tuya Cloud (WebSocket with meta)
↓
SDK Runner (src/sdk_runner.py)
↓ HTTP POST (meta auto-forwarded)
MCP Server (src/mcp_server.py) + API Key Auth
├─> Tool 1: query_tags
└─> Tool 2: music_play_control
├─> play_handler (play/next/prev)
├─> control_handler (stop/resume/replay)
└─> mode_handler (loop modes)
↓
┌──────────┴───────────┐
↓ ↓
Redis File Platform API
(State+Token) (Audio Resources)
AI Client (Claude/Cline/Continue)
↓ HTTPS + API Key + X-Mcp-Context Header
Reverse Proxy (Caddy/Nginx)
↓ HTTP
MCP Server (src/mcp_server.py)
├─> URL Key Authentication
├─> X-Mcp-Context Header Parsing
└─> Tools Execution
↓
Redis + File Platform API
- SDK Runner: Maintains WebSocket connection with Tuya Cloud (WebSocket mode only)
- MCP Server: FastMCP-based server supporting both WebSocket and Streamable HTTP
- Authentication: URL parameter API key validation for secure access
- Context Extraction: Dual-mode support (WebSocket meta + HTTP headers)
- Redis: Required for token caching and playback state storage
- File Platform API: Tuya cloud service for audio file search and tag queries
This service integrates with the following Tuya Cloud APIs:
- Endpoint:
/v1.0/token - Method: GET
- Purpose: Obtain access token with HMAC-SHA256 signature
- Token Cache: Tokens are cached in Redis with automatic refresh
- Endpoint:
/v1.0/cloud/agent/file/box/user/tags - Method: POST
- Purpose: Query available music/content tags
- Request Body:
{ "params": "{\"pageNo\": 1, \"pageSize\": 100}" } - Response: List of tags with
tagKeyandtagKeyDesc - Cache: 5 minutes in-memory cache
- Endpoint:
/v1.0/cloud/agent/file/box/user/list/search - Method: POST
- Purpose: Search audio files by tags, language, and weights
- Request Body:
{ "params": "{ \"tag\": [[{\"key\":\"artist\",\"value\":\"Jay Chou\"}]], \"searchTag\": [{\"key\":\"lang\",\"value\":\"zh\"}], \"textWeight\": 0.5, \"vectorWeight\": 0.5, \"topK\": 10, \"filterScore\": 0.2 }" } - Response: List of audio files with metadata (name, URL, artist, album, etc.)
- Protocol: WebSocket with message framing
- Features:
- Automatic reconnection
- Message metadata (
meta) extraction and forwarding - Bidirectional communication for tool invocation
tuya-audio-controller-mcp/
├── src/
│ ├── mcp_server.py # FastMCP service entry
│ ├── sdk_runner.py # Tuya SDK WebSocket connector
│ ├── services/
│ │ ├── tuya_openapi.py # Tuya OpenAPI client (Redis token cache)
│ │ ├── tag_service.py # Tag query service
│ │ ├── file_platform.py # File Platform audio search
│ │ └── redis_playback_service.py # Redis playback state management
│ ├── handlers/
│ │ ├── play_handler.py # Play intent handlers (play/next/prev)
│ │ ├── control_handler.py # Control intent handlers (stop/resume/replay)
│ │ └── mode_handler.py # Mode intent handlers (loop modes)
│ └── utils/
│ ├── constants.py # Constants and enums
│ ├── i18n.py # TTS/Tips text templates
│ ├── card_builder.py # Playback card builder
│ ├── intent_registry.py # Intent handler registry
│ ├── skill_context.py # Skill context extraction
│ ├── redis_config.py # Redis configuration management
│ └── redis_lock.py # Redis distributed lock
├── scripts/
│ ├── check_services.py # Service status check script
│ ├── manage_services.py # Service management script
│ ├── verify_config.py # Configuration verification script
│ └── query_endpoint_cache_sync.py # Redis cache query script
├── tests/ # Test directory (to be added)
└── doc/
└── QUICKSTART.md # Installation and service management
- Python >= 3.10 (3.12+ recommended)
- pip >= 21.3
- Redis (required for token cache and playback state storage)
- Tuya MCP SDK credentials (access ID and secret)
- Tuya OpenAPI credentials for File Platform
See doc/QUICKSTART.md for:
- Installation instructions
- Environment configuration
- Service management (start/stop/restart)
- Troubleshooting guide
- Advanced deployment options
# 1. Configure environment
cp .env.example .env
# Edit .env with your credentials
# 2. Install dependencies
pip install -r requirements.txt
# 3. Start services
python scripts/manage_services.py start
# 4. Check status
python scripts/manage_services.py statusKey environment variables in .env:
# ===== Transport Mode =====
# Options: "websocket" (Tuya Cloud) or "streamable-http" (Direct clients)
MCP_TRANSPORT_MODE=websocket
FASTMCP_TRANSPORT=streamable-http
# ===== Authentication =====
MCP_AUTH_ENABLED=true
MCP_API_KEY=your-secret-key-here # Generate with: python -c "import secrets; print(secrets.token_urlsafe(32))"
# ===== MCP SDK (WebSocket Mode) =====
# Choose endpoint based on your Tuya account region:
# - China: https://mcp.tuyacn.com
# - Europe: https://mcp.iot-eu.com
# - US: https://mcp.iot-us.com
TUYA_ENDPOINT=https://mcp.tuyacn.com
TUYA_ACCESS_ID=your_mcp_access_id
TUYA_ACCESS_SECRET=your_mcp_access_secret
# ===== File Platform Configuration =====
# Choose endpoint based on your Tuya account region:
# - China: https://openapi.tuyacn.com
# - Europe: https://openapi.tuyaeu.com
# - US: https://openapi.tuyaus.com
TUYA_OPENAPI_ENDPOINT=https://openapi.tuyacn.com
TUYA_FILE_ACCESS_ID=your_file_platform_access_id
TUYA_FILE_ACCESS_SECRET=your_file_platform_access_secret
# ===== Redis (Required) =====
REDIS_URL=redis://localhost:6379/0
# ===== MCP Server =====
MCP_SERVER_HOST=localhost
MCP_SERVER_PORT=8765This service supports two transport modes:
WebSocket Mode (for Tuya Cloud integration):
- Starts both SDK Runner and MCP Server
- Used for Tuya IoT platform integration
- Receives requests via WebSocket from Tuya Cloud
Streamable HTTP Mode (for direct AI clients):
- Starts MCP Server only
- Used for direct integration with AI clients (Claude, Cline, etc.)
- Requires HTTPS reverse proxy and API key authentication
- Note: Reverse proxy configuration examples not included (use Caddy/Nginx with HTTPS)
Switch modes by setting MCP_TRANSPORT_MODE in .env.
For AI clients like Claude Desktop, Cline, or Continue.dev:
-
Deploy with Streamable HTTP mode:
# Set in .env MCP_TRANSPORT_MODE=streamable-http FASTMCP_TRANSPORT=streamable-http MCP_AUTH_ENABLED=true MCP_API_KEY=your-generated-key -
Configure reverse proxy (Caddy or Nginx):
- Configure your reverse proxy to forward to
http://localhost:8765/mcp - Ensure HTTPS is enabled
- Example Caddy config:
your-domain.com { reverse_proxy /mcp* localhost:8765 } - Example Nginx config:
location /mcp { proxy_pass http://localhost:8765; }
- Configure your reverse proxy to forward to
-
Configure your AI client:
{ "mcpServers": { "tuya-audio-controller": { "url": "https://your-domain.com/mcp?key=your-api-key" } } } -
Send context with requests (for music_play_control):
- Include
X-Mcp-Contextheader with device context (URL-encoded JSON) - Required fields:
endpointId,endpointType - Header format example:
{ "bizAttachments": { "skillcontext": { "endpointId": "your-device-id", "endpointType": 2, "requestId": "optional-request-id" } } } - Note: This is typically used in Tuya Cloud integration via WebSocket mode. For direct AI client integration, context handling may vary by client implementation.
- Include
For detailed client setup instructions, see doc/QUICKSTART.md.
Query available music/content tags from File Platform.
Usage: Called by AI to discover available tags before searching audio.
Execute playback control intents with tag-based audio search.
Parameters:
intent: One of 9 playback intentstags: Optional tag filters (key-value pairs)language: Optional language filter (ISO 639-1 code)
Returns: Skill card with TTS text and audio metadata.
# Test framework is configured (pytest)
# Test directory structure to be added
# pytest tests/ -v- Quick Start Guide: doc/QUICKSTART.md - Installation and service management
Common issues and solutions are available in doc/QUICKSTART.md.
Quick checks:
- Verify Redis is running:
redis-cli ping - Check service logs:
tail -f logs/*.log - Validate configuration:
python scripts/verify_config.py - Test services:
python scripts/check_services.py
Manage Tuya OpenAPI token cache manually when needed:
# Refresh token (force fetch new token from Tuya OpenAPI)
python scripts/refresh_token_cache.py refresh
# View current cached token information
python scripts/refresh_token_cache.py view
# Verify token validity
python scripts/refresh_token_cache.py verify
# Clear token cache (next connect will fetch new token)
python scripts/refresh_token_cache.py clear
# JSON output for script integration
python scripts/refresh_token_cache.py view --jsonUse cases:
- Force refresh token before service restart
- Troubleshoot token expiration issues
- Clear invalid token from cache
- Verify token validity and remaining time
See CONTRIBUTING.md for contribution guidelines.
MIT License - see LICENSE file for details.
Tuya Audio Controller MCP Service Contributors