Theme
Self-hosted MCP setup
Run VoiceLab MCP with your own API key, locally over stdio or remotely over HTTP.
Prerequisites
- Node.js 20.0.0 or later and npm
- A VoiceLab API key from voicelab.uz/app
Installation
Build from the source repository:
bash
git clone https://github.com/voicelab-uz/mcp.git
cd mcp
npm ci
npm run buildConfiguration
Set the VoiceLab API key via environment variable:
bash
export VOICELAB_API_KEY='vlk_your_api_key_here'Optional base URL override (uses https://api.voicelab.uz by default):
bash
export VOICELAB_BASE_URL='https://api.voicelab.uz'Keep keys out of version control. Load them into the process environment from a secret manager. The Node entry point does not load .env files automatically.
Running the server
Stdio mode (local Cursor, Claude Desktop)
bash
node dist/index.jsThe server reads JSON-RPC messages from stdin and writes responses to stdout. Use this mode for local MCP clients like Cursor and Claude Desktop.
Configure your client with command: "node", an absolute path to dist/index.js in args, and your VOICELAB_API_KEY in env. See Connect clients for Cursor and Claude Desktop examples.
HTTP mode (remote agents, web clients)
bash
npm run start:httpBinds to 127.0.0.1:3100 by default. Override with HOST and PORT environment variables.
To change the port:
bash
HOST=127.0.0.1 PORT=8080 npm run start:httpPut nginx or another TLS proxy in front of HTTP mode for remote access.
Environment variables
| Variable | Default | Purpose |
|---|---|---|
VOICELAB_API_KEY | (required) | VoiceLab API key used by tools |
VOICELAB_BASE_URL | https://api.voicelab.uz | API origin (must be HTTPS) |
MCP_AUTH_TOKEN | (empty) | If set, /mcp requires Authorization: Bearer <token> |
ALLOWED_ORIGINS | (empty) | Comma-separated browser origins for CORS |
MAX_BODY_BYTES | 10485760 | Max request body size (10 MiB) |
RATE_LIMIT_MAX | 120 | Max requests per window per IP |
RATE_LIMIT_WINDOW_MS | 60000 | Rate limit window (60 seconds) |
HOST | 127.0.0.1 | HTTP listen address (keep loopback in production) |
PORT | 3100 | HTTP listen port |
Gateway authentication (HTTP mode)
To require a Bearer token for /mcp requests, set MCP_AUTH_TOKEN:
bash
export MCP_AUTH_TOKEN='your-secret-gateway-token'
npm run start:httpClients must include the token:
bash
curl -fS 'http://localhost:3100/mcp' \
-H "Authorization: Bearer your-secret-gateway-token" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Without MCP_AUTH_TOKEN, anyone who can reach the MCP process can invoke tools using its configured VoiceLab account. Set a gateway token before exposing HTTP mode to other users.
Health check and discovery
Health check, no authentication required:
bash
curl -fS 'http://localhost:3100/health'Returns server status and version.
Discovery, no authentication required:
bash
curl -fS 'http://localhost:3100/v1'
curl -fS 'http://localhost:3100/.well-known/mcp.json'Return MCP transport, authentication, and endpoint metadata. Use an MCP client to discover the tool list.
Deployment options
Cloudflare Workers
The repository includes a Cloudflare Worker. Check src/worker.ts for its transport and authentication settings. Node's MCP_AUTH_TOKEN, CORS, and rate limits do not automatically apply to the Worker.
Docker
Create a Dockerfile:
dockerfile
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY dist ./dist
ENV HOST=0.0.0.0
CMD ["node", "dist/index.js", "--http"]Build and run:
bash
npm run build
docker build -t voicelab-mcp .
# Export both credentials in your shell before starting the container.
docker run -e VOICELAB_API_KEY -e MCP_AUTH_TOKEN -p 127.0.0.1:3100:3100 voicelab-mcpVPS with nginx
- Install Node.js 20+ on your VPS
- Clone and build the MCP server
- Start HTTP mode with a process manager (pm2, systemd, etc.)
- Configure nginx as a reverse proxy with TLS:
nginx
server {
listen 443 ssl http2;
server_name mcp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3100;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Monitoring and logs
In stdio mode, read logs in your MCP client's console.
In HTTP mode, logs go to stdout. To write them to a file:
bash
npm run start:http 2>&1 | tee voicelab-mcp.logFor Cloudflare Workers, stream logs with wrangler tail:
bash
wrangler tailTroubleshooting
"VOICELAB_API_KEY environment variable is required"
Set the key before starting:
bash
export VOICELAB_API_KEY='vlk_...'
node dist/index.js"401 invalid_api_key"
- Check that your key is correct and not expired
- Verify the key is enabled in the VoiceLab dashboard
- Ensure the key has required permissions (
tts:write,stt:write, etc.)
"EADDRINUSE: address already in use"
Another process is using port 3100. Change the port:
bash
PORT=8080 npm run start:http"Failed to fetch tools from VoiceLab MCP"
- Verify the server is running:
curl http://localhost:3100/health - Check client configuration syntax (Cursor/Claude config)
- Restart the MCP client after config changes
- Review client logs for connection errors
Source code and contributions
- GitHub: github.com/voicelab-uz/mcp
- Grok plugin: github.com/voicelab-uz/grok-plugin
Report bugs or submit changes on GitHub.