Dr. Dabber Switch 2 MCP
A Model Context Protocol (MCP) server for controlling a Dr. Dabber Switch 2 vaporizer over Bluetooth LE.
README
Dr. Dabber Switch 2 MCP
A Model Context Protocol (MCP) server for controlling a Dr. Dabber Switch 2 vaporizer over Bluetooth LE. It exposes every safe user-facing control as a typed MCP tool, so any MCP-connected LLM or automation can discover, connect, and operate the device without touching the official app.
Problem it solves
The Switch 2 ships with a mobile/web Bluetooth app. This server bridges the device into the MCP ecosystem so you can drive it from Claude, Codex, or any other MCP client on your laptop or over a Raspberry Pi BLE proxy, keeping the device always reachable even when your phone app is not connected.
Install
Option A: run from GitHub (no clone needed)
npx -y github:nidamen/drdabber-switch2-mcp
Option B: local clone
git clone https://github.com/nidamen/drdabber-switch2-mcp.git
cd drdabber-switch2-mcp
npm install
npm run build
Node 20+ is required.
MCP client configuration
Direct BLE (laptop)
The server opens its own Bluetooth connection. The Switch 2 must be on, nearby, and not connected to another client.
Claude Desktop / claude_desktop_config.json:
{
"mcpServers": {
"drdabber-switch2": {
"command": "npx",
"args": ["-y", "github:nidamen/drdabber-switch2-mcp"],
"env": {
"DRDABBER_SWITCH2_TARGET": "My Switch 2"
}
}
}
}
Or with a local build:
{
"mcpServers": {
"drdabber-switch2": {
"command": "node",
"args": ["/path/to/drdabber-switch2-mcp/dist/src/index.js"],
"env": {
"DRDABBER_SWITCH2_TARGET": "My Switch 2"
}
}
}
}
Pi BLE proxy (always-on headless path)
When DRDABBER_PROXY_URL is set, the MCP forwards every command to the web control running on the Pi instead of opening its own BLE link. The Pi becomes the single BLE owner and multiple clients can share it without GATT contention.
{
"mcpServers": {
"drdabber-switch2": {
"command": "node",
"args": ["/path/to/drdabber-switch2-mcp/dist/src/index.js"],
"env": {
"DRDABBER_PROXY_URL": "http://192.168.1.44:4477"
}
}
}
}
TOML style (Codex / Autohand):
[mcp_servers.drdabber-switch2]
command = "node"
args = ["/path/to/drdabber-switch2-mcp/dist/src/index.js"]
env = { DRDABBER_SWITCH2_TARGET = "My Switch 2" }
Environment variables
| Variable | Required | Description |
|---|---|---|
DRDABBER_SWITCH2_TARGET |
No | BLE id or exact advertised name to prefer during scan. Omit to connect to the first Switch 2 found. |
DRDABBER_PROXY_URL |
No | Base URL of the Pi web control (e.g. http://192.168.1.44:4477). When set, all commands are proxied; BLE is not opened locally. |
Transport
The server uses stdio MCP transport. It does not open any network ports itself. BLE communication runs via @abandonware/noble on the host machine, or via HTTP POST to the Pi proxy when DRDABBER_PROXY_URL is set.
Complete tool reference
Connection
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
discover_switch2 |
Scan for nearby Switch 2 devices advertising the fee7 BLE service |
timeoutMs (int, optional, 1000-60000) |
Array of { id, name, rssi, services, connectable } |
connect_switch2 |
Connect to the Switch 2 and read device information | target (string, optional) BLE id or exact advertised name |
Switch2DeviceInfo: { id, name, model, serial, hardwareRevision, softwareRevision, manufacturer, rssi } |
disconnect_switch2 |
Disconnect from the current Switch 2 | none | { disconnected: true } |
Device state
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
get_device_info |
Return cached model, serial, firmware, and manufacturer info | none | Switch2DeviceInfo |
get_status |
Sync clock, request analytics, and return decoded device status | waitMs (int, optional, 0-10000, default 3000) ms to wait for BLE notifications |
Full Switch2State: status + presets + analytics + raw notifications |
get_presets |
Return cached presets for all 5 vapor profiles | none | Array of Switch2Preset: { preset, tempF, tempC, holdTime, heatingProfile, heatingProfileLabel, customProfile } |
Preset configuration
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
set_active_preset |
Switch the active vapor profile | preset (int, required, 1-5) |
Switch2Status |
set_preset_temperature |
Set a preset's target temperature | preset (int, required, 1-5); tempF (int, optional, 250-650) OR tempC (int, optional, 121-343). At least one is required. |
Updated Switch2Preset |
set_preset_hold_time |
Set a preset's hold time | preset (int, required, 1-5); holdTime (int, required, 10-90 seconds) |
Updated Switch2Preset |
set_heating_profile |
Set a preset's heating curve | preset (int, required, 1-5); heatingProfile (int, required): 161 Steady, 177 Ascent, 193 Descent, 209 Valley, 225 Hill, 241 Custom |
Updated Switch2Preset |
Session control
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
start_session |
Start the active heating session | none | Switch2Status |
stop_session |
Stop the active heating session | none | Switch2Status |
extend_session |
Set the session extension value | minutes (int, required, 0-9) |
Switch2Status |
Device settings
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
set_light_mode |
Set the LED pattern | lightMode (int, required, 0-17). 0=Stealth, 1=Calm, 2=Purple, 3=Blue, 4=Cyan, 5=Green, 6=Yellow, 7=Orange, 8=Red, 9=Pink, 10=Cali Sunset, 11=Purple Haze, 12=Northern Lights, 13=Vegas Nights, 14=Blue Dream, 15=Strawberry Cough, 16=Florida Groves, 17=Lime Light |
Switch2Status |
set_light_brightness |
Set LED brightness | brightness (int, required, 0-100) |
Switch2Status |
set_temp_unit |
Set displayed temperature unit | tempUnit (string, required): "F" or "C" |
Switch2Status |
set_haptic_feedback |
Enable or disable haptic feedback | enabled (boolean, required) |
Switch2Status |
set_auto_shutoff |
Set idle auto-shutoff timer. Use 0 to disable. | minutes (int, required, 0-60) |
Switch2Status |
set_device_name |
Rename the Switch 2 (persisted on device) | name (string, required, 1-29 printable ASCII chars 0x20-0x7E) |
Switch2DeviceInfo |
Cleaning
| Tool | Purpose | Parameters | Returns |
|---|---|---|---|
start_cleaning_assist |
Start the cleaning assist cycle | none | Switch2Status |
stop_cleaning_assist |
Stop the cleaning assist cycle | none | Switch2Status |
Total: 21 tools.
Quick usage examples
Check device state and battery:
"Connect to my Switch 2 and tell me the battery level, current temperature, and active preset." The LLM calls
connect_switch2thenget_statusand reports back.
Change light and set temperature:
"Set preset 3 to 480F and switch the light to Purple Haze." The LLM calls
set_preset_temperaturewith{ preset: 3, tempF: 480 }andset_light_modewith{ lightMode: 11 }.
Automated session:
"Start a session on preset 2, then stop it after I say done." The LLM calls
set_active_presetwith{ preset: 2 }, thenstart_session, and waits for the next instruction to callstop_session.
Desktop control panel
A local web control panel is included under app/. It reuses Switch2Controller directly (no MCP layer) and serves a single-page UI at http://localhost:4477 over HTTP + Server-Sent Events. Controls mirror the official app: live temperature dial, preset editor, light mode and brightness, session start/stop/extend, cleaning assist, device rename, and all device settings.
# Real device
npm run app
# open http://localhost:4477
# Mock device (no hardware needed)
npm run app:mock
BLE protocol notes
Primary control surface:
| Purpose | UUID |
|---|---|
| Demo service | 0000fee7-0000-1000-8000-00805f9b34fb |
| Write characteristic | 0000fec1-0000-1000-8000-00805f9b34fb |
| Notify characteristic | 0000fec2-0000-1000-8000-00805f9b34fb |
| Device information service | 0000180a-0000-1000-8000-00805f9b34fb |
Intentionally excluded UUIDs:
| Purpose | UUID |
|---|---|
| OTA service | e5c7a653-7e52-4b06-af32-960455084ae3 |
| OTA write | 4cbbd40d-f1fa-4dbd-9bb5-36ec99d99a08 |
| OTA notify | 739cb17a-1aec-4232-a01a-a250d4c35f0d |
Safety boundaries
This server intentionally does NOT expose:
- Firmware update or OTA writes
- Factory reset
- Arbitrary raw BLE writes
All state-changing tools validate input ranges before writing to the device. These boundaries are permanent design decisions, not omissions.
Verified device
Live verified on May 29, 2026:
| Field | Value |
|---|---|
| BLE name | My Switch 2 |
| Advertised service | fee7 |
| Model | Switch 2 |
| Serial | SN-EXAMPLE-0000 |
| Hardware | V2.0.0 |
| Firmware | SW2-260322-010 |
| Manufacturer | Dr.Dabber |
Development
npm test # unit tests (21 tests)
npm run build # compile TypeScript
npm run qa # build + test
npm run probe # BLE scan (requires hardware)
npm run live:status -- "My Switch 2" # read-only live status
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。