Skip to content

Self-hosted MCP setup ​

Run VoiceLab MCP with your own API key, locally over stdio or remotely over HTTP.

Prerequisites ​

Installation ​

Build from the source repository:

bash
git clone https://github.com/voicelab-uz/mcp.git
cd mcp
npm ci
npm run build

Configuration ​

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.js

The 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:http

Binds 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:http

Put nginx or another TLS proxy in front of HTTP mode for remote access.

Environment variables ​

VariableDefaultPurpose
VOICELAB_API_KEY(required)VoiceLab API key used by tools
VOICELAB_BASE_URLhttps://api.voicelab.uzAPI 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_BYTES10485760Max request body size (10 MiB)
RATE_LIMIT_MAX120Max requests per window per IP
RATE_LIMIT_WINDOW_MS60000Rate limit window (60 seconds)
HOST127.0.0.1HTTP listen address (keep loopback in production)
PORT3100HTTP 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:http

Clients 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-mcp

VPS with nginx ​

  1. Install Node.js 20+ on your VPS
  2. Clone and build the MCP server
  3. Start HTTP mode with a process manager (pm2, systemd, etc.)
  4. 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.log

For Cloudflare Workers, stream logs with wrangler tail:

bash
wrangler tail

Troubleshooting ​

"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 ​

Report bugs or submit changes on GitHub.

Next steps ​