mcp-ble-bridge
Provides tools for controlling Bluetooth Low Energy devices, including sending vibration, licking, suction, pulse, and stop commands to compatible BLE toys via a phone browser bridge.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-ble-bridgevibrate my toy at medium intensity for 10 seconds"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP → BLE Bridge
Control Bluetooth Low Energy (BLE) toys from AI assistants over the cloud.
This is a working reference implementation that bridges the Model Context Protocol (MCP) to BLE devices via Web Bluetooth, letting an AI chatbot send commands to a physical device in real time.
Tested with: SVAKOM "Bera" (ST462A) / "口口甜" — but the architecture works for any BLE device you can write bytes to.
Architecture
AI Assistant (Claude, AstrBot, etc.)
│ MCP (Streamable HTTP or SSE)
▼
Cloud Server (Node.js, HTTPS)
│ WebSocket
▼
Phone Browser (Bluefy on iOS / Chrome on Android)
│ Web Bluetooth API
▼
BLE DeviceWhy this stack?
iOS has no native Web Bluetooth in Safari. Bluefy is a third-party browser that supports it.
Claude mobile / claude.ai has no local MCP support — you need a cloud relay.
Most BLE toys use proprietary protocols. buttplug.io covers some, but many (like SVAKOM's newer models) need manual reverse engineering.
This approach needs zero native apps on the phone beyond a BLE-capable browser. No Intiface, no custom iOS app, no jailbreak.
Related MCP server: Lovense Cloud MCP
Prerequisites
A VPS with a public IP (any cloud provider, 1 CPU / 512MB RAM is enough)
A domain pointing to your VPS (or use DuckDNS for free)
HTTPS certificate (Let's Encrypt via acme.sh)
Node.js 18+ and pm2
iOS: Bluefy browser ($2.99) / Android: Chrome (free, Web Bluetooth built-in)
Quick Start
1. Get a domain and certificate
# Install acme.sh if you haven't
curl https://get.acme.sh | sh
# Example with DuckDNS (replace with your token and subdomain)
export DuckDNS_Token="your-duckdns-token"
acme.sh --issue --dns dns_duckdns -d yourdomain.duckdns.org --keylength ec-256
# Note where certs are stored, e.g.:
# ~/.acme.sh/yourdomain.duckdns.org_ecc/2. Clone and configure
git clone https://github.com/kumavulp/mcp-ble-bridge.git
cd mcp-ble-bridge
npm installEdit config.js:
module.exports = {
domain: 'yourdomain.duckdns.org',
port: 8443,
certDir: '/home/youruser/.acme.sh/yourdomain.duckdns.org_ecc',
keyFile: 'yourdomain.duckdns.org.key',
certFile: 'fullchain.cer'
};3. Open firewall
sudo ufw allow 8443/tcp
# Also open it in your cloud provider's security group if applicable4. Start server
# With pm2 (recommended)
npm install -g pm2
pm2 start server.js --name mcp-ble-bridge
pm2 save
# Or directly
node server.js5. Connect from phone
Open Bluefy (iOS) or Chrome (Android):
https://yourdomain.duckdns.org:8443/bridgeTap Connect Server, then Connect Device → pick your BLE toy from the popup.
6. Connect your AI assistant
AstrBot (recommended — works now):
{
"transport": "streamable_http",
"url": "https://yourdomain.duckdns.org:8443/mcp",
"headers": {},
"timeout": 120,
"sse_read_timeout": 300
}claude.ai Custom Connector:
The server includes a full OAuth stub at /.well-known/oauth-*, /register, /authorize, /token. Add as a custom connector with URL https://yourdomain.duckdns.org:8443/sse.
⚠️ Known Issue (as of Sep 2026): claude.ai custom connectors have a bug where OAuth completes successfully but no SSE connection is ever established afterward. This has been reported since March 2026 (GitHub issues #600+) and remains unresolved. The server code is ready — it will work the day Anthropic fixes it.
Claude Desktop (local): If your computer has Bluetooth and the BLE device is in range, you can skip the cloud relay entirely — add the MCP server to Claude Desktop's config pointing to localhost.
Server Endpoints
Path | Method | Purpose |
| POST | Streamable HTTP MCP endpoint |
| GET | SSE MCP transport |
| POST | SSE message endpoint |
| WS | WebSocket relay to phone bridge |
| GET | Serves bridge.html |
| GET | Health check JSON |
| GET | OAuth discovery (for claude.ai) |
| POST | OAuth client registration |
| GET | OAuth authorization |
| POST | OAuth token exchange |
MCP Tools
The server exposes these tools to the AI:
Tool | Parameters | Description |
|
| Tongue licking patterns |
|
| Vibration patterns |
|
| Suction |
|
| Alternating pulse |
| — | Stop everything |
| — | Connection status |
| — | Check beg count (see below) |
duration: seconds before auto-stop. The controlling AI decides how long, not the user.
reason: why the AI is doing this — logged server-side, visible in the bridge UI.
check: the bridge page has a "beg" button. Pressing it doesn't stop the device — it sends a signal back to the server that the AI can query. The AI decides whether to show mercy.
SVAKOM BLE Protocol (Bera / ST462A / 口口甜)
Reverse-engineered protocol for SVAKOM's newer Bera-series devices.
BLE Service: 0000ffe0-0000-1000-8000-00805f9b34fb
Characteristic: 0000ffe1-0000-1000-8000-00805f9b34fb
⚠️ Never write to the AE00 characteristic — it can brick the device.
Command format (7 bytes)
55 [cmd] 00 00 [mode] [intensity] [suffix]Function | cmd byte | mode | intensity | suffix | Example |
Vibrate |
| 1-10 (pattern) | 1-5 |
|
|
Tongue lick |
| 1-10 (pattern) | 1-5 |
|
|
Suction |
| — | 0-255 |
|
|
Important notes
Intensity 1-5 is the device's native range. The bridge maps 0.0-1.0 from the AI to 1-5 for vibrate/lick, and 0-255 for suction.
Tongue lick below intensity 4 (0.8 in 0-1 scale) is very slow. Intensity 5 (1.0) matches the normal speed in the official app.
Keepalive required: the device auto-stops after ~2 seconds of silence. The bridge re-sends the last command every 1.5 seconds.
Modes 1-10 are different rhythm patterns. Most are unexplored — experiment.
Suction combines tongue + vibration + rhythmic sucking. It's its own thing, not "stronger vibration."
How we figured this out
Started with buttplug.io's generic SVAKOM 6-byte format (
55 03 00 XX XX XX) — didn't work on Bera.Tried 7-byte format
55 04 00 00 01 [0-255] AA— vibration responded.Found a Chinese reverse-engineering post (小红书) confirming the full protocol for Bera-series:
03= vibrate,14= tongue lick,04= suctionMode byte and intensity byte positions differ from older SVAKOM models
Verified all three functions work through the bridge.
If you're working with a different SVAKOM model, the raw tool (in older versions of the server) lets you send arbitrary hex bytes for protocol probing.
Bridge Page Features
The bridge page (bridge.html) runs in the phone browser and:
Connects to the cloud server via WebSocket
Connects to the BLE device via Web Bluetooth
Translates MCP tool calls into BLE writes
Sends keepalive packets every 1.5s
Has a "beg" button — doesn't stop the device, just signals back to the AI
Has a long-press emergency stop (3 seconds) — actually stops everything, overrides all commands
Auto-stops after
durationseconds when specifiedRequests a wake lock to prevent the screen from turning off
Adapting for Other Devices
To use this with a different BLE toy:
Find the BLE service/characteristic UUIDs — use a BLE scanner app (nRF Connect, LightBlue)
Figure out the command protocol — check buttplug.io's device config, search for teardowns, or probe with raw hex bytes
Edit
bridge.html— changeSVC,CHR, and thetx()command buildersEdit
server.js— update tool names and descriptions to match your device's capabilities
The server ↔ bridge WebSocket protocol is device-agnostic. The server sends {requestId, tool, args}, the bridge sends back {requestId, result, error}. All device-specific logic lives in bridge.html.
Troubleshooting
AstrBot says "Failed to test MCP connection"
→ Check curl -sk https://localhost:8443/health returns valid JSON with "tools":7. If the schema is malformed, AstrBot can't parse it.
BLE scan shows nothing in Bluefy → Make sure the device is powered on and not connected to another app. Only one thing can hold a BLE connection at a time.
Device stops after 2 seconds
→ Keepalive isn't running. Check the bridge console log — it should show TX lines every 1.5 seconds while a command is active.
claude.ai connector completes OAuth but never sends requests → Known Anthropic bug. Use AstrBot or Claude Desktop instead.
WebSocket connects but tool calls timeout → Check if the bridge page is in the foreground. iOS suspends JS in background tabs. Bluefy must stay visible.
Security Note
This server has no authentication beyond HTTPS. Anyone who knows the URL can send commands. For personal use on an obscure subdomain this is fine. For anything more, add auth middleware.
The OAuth endpoints are stubs that accept anything — they exist solely to satisfy claude.ai's connector flow.
License
MIT. Do whatever you want with it.
Credits
SVAKOM BLE protocol info: community reverse engineering efforts
buttplug.io for pioneering open-source toy control
Bluefy for making Web Bluetooth possible on iOS
MCP for the protocol spec
Related MCP Connectors
Turns a phone into a camera+Bluetooth remote so AI assistants can see and control any PC.
OAuth 2.1 short-link tools for AI agents with scoped tokens, approvals, audit logs, and revocation.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables external tool registration and execution through WebSocket-based communication, providing a unified interface for real-time tool management within SillyTavern.27-
- AlicenseNot gradedqualityCmaintenanceEnables remote control of Lovense toys through Claude using natural language commands. Supports vibration patterns, presets, and intensity control from any device via Cloudflare Workers.5Apache 2.0
- FlicenseCqualityFmaintenanceEnables AI assistants to control Godot game engine projects through a WebSocket bridge. Supports scene editing, node manipulation, script management, and project introspection via 163 registered tools.1001-
- AlicenseAqualityCmaintenanceA stateful Bluetooth Low Energy (BLE) MCP server that enables AI agents to scan, connect, read/write characteristics, and subscribe to notifications on BLE devices.3517MIT