ble-mcp-server — Claude Code MCP server: BLE hardware from chat
Hands an agent the tools to scan for BLE devices, connect, read and write characteristics, and subscribe to notifications. Useful when you debug firmware or pull sensor data without doing every step by hand.
claude mcp add --env BLE_MCP_ALLOW_WRITES=<BLE_MCP_ALLOW_WRITES> --env BLE_MCP_WRITE_ALLOWLIST=<BLE_MCP_WRITE_ALLOWLIST> --env BLE_MCP_PLUGINS=<BLE_MCP_PLUGINS> --env BLE_MCP_TOOL_SEPARATOR=<BLE_MCP_TOOL_SEPARATOR> --env BLE_MCP_MAX_SESSIONS=<BLE_MCP_MAX_SESSIONS> --transport stdio ble-mcp-server -- uvx ble-mcp-serverWhat ble-mcp-server does
Under the hood it uses bleak, so Bluetooth Low Energy works on macOS, Windows and Linux alike. The default transport is stdio: no HTTP, no listening ports. SSE and Streamable HTTP are available too, for remote access or when several sessions share one server.
The agent gets a toolset and chains the calls itself: it finds a device by name or service UUID, connects, walks the services and characteristics, then reads values. Incoming notifications arrive as single events, by polling, or drained in batches. Everything comes back as structured JSON, and the model picks the next step from there.
Writes stay off until you set BLE_MCP_ALLOW_WRITES. To narrow them down, put the allowed UUIDs in BLE_MCP_WRITE_ALLOWLIST so ble.write touches only those. Device plugins are opt-in as well through BLE_MCP_PLUGINS; they give the agent named actions instead of raw bytes.
What it helps with
- scan for a board and match it by name or service UUID
- read a sensor characteristic and find out why it returns zeros
- subscribe to notifications and collect a batch of readings
- run a test sequence of commands against a new prototype
- write down a device protocol as a spec and reuse it later
Example prompts for the agent
- Read the temperature from my SensorTag and tell me the current value
- Subscribe to this characteristic and drain the first hundred notifications
How to install ble-mcp-server
Platform CLI
claude mcp add --env BLE_MCP_ALLOW_WRITES=<BLE_MCP_ALLOW_WRITES> --env BLE_MCP_WRITE_ALLOWLIST=<BLE_MCP_WRITE_ALLOWLIST> --env BLE_MCP_PLUGINS=<BLE_MCP_PLUGINS> --env BLE_MCP_TOOL_SEPARATOR=<BLE_MCP_TOOL_SEPARATOR> --env BLE_MCP_MAX_SESSIONS=<BLE_MCP_MAX_SESSIONS> --transport stdio ble-mcp-server -- uvx ble-mcp-serverReplace <…> with your own values. 1 more environment variable is in the server README. uvx runs the command named after the package; if the README names another one, use uvx --from ble-mcp-server <command>
Platform CLI
codex mcp add ble-mcp-server --env BLE_MCP_ALLOW_WRITES=<BLE_MCP_ALLOW_WRITES> --env BLE_MCP_WRITE_ALLOWLIST=<BLE_MCP_WRITE_ALLOWLIST> --env BLE_MCP_PLUGINS=<BLE_MCP_PLUGINS> --env BLE_MCP_TOOL_SEPARATOR=<BLE_MCP_TOOL_SEPARATOR> --env BLE_MCP_MAX_SESSIONS=<BLE_MCP_MAX_SESSIONS> -- uvx ble-mcp-serverReplace <…> with your own values. 1 more environment variable is in the server README. uvx runs the command named after the package; if the README names another one, use uvx --from ble-mcp-server <command>
Config file
{
"mcpServers": {
"ble-mcp-server": {
"command": "uvx",
"args": [
"ble-mcp-server"
],
"env": {
"BLE_MCP_ALLOW_WRITES": "<BLE_MCP_ALLOW_WRITES>",
"BLE_MCP_WRITE_ALLOWLIST": "<BLE_MCP_WRITE_ALLOWLIST>",
"BLE_MCP_PLUGINS": "<BLE_MCP_PLUGINS>",
"BLE_MCP_TOOL_SEPARATOR": "<BLE_MCP_TOOL_SEPARATOR>",
"BLE_MCP_MAX_SESSIONS": "<BLE_MCP_MAX_SESSIONS>"
}
}
}
}Replace <…> with your own values. 1 more environment variable is in the server README. uvx runs the command named after the package; if the README names another one, use uvx --from ble-mcp-server <command>
Config file
{
"servers": {
"ble-mcp-server": {
"type": "stdio",
"command": "uvx",
"args": [
"ble-mcp-server"
],
"env": {
"BLE_MCP_ALLOW_WRITES": "<BLE_MCP_ALLOW_WRITES>",
"BLE_MCP_WRITE_ALLOWLIST": "<BLE_MCP_WRITE_ALLOWLIST>",
"BLE_MCP_PLUGINS": "<BLE_MCP_PLUGINS>",
"BLE_MCP_TOOL_SEPARATOR": "<BLE_MCP_TOOL_SEPARATOR>",
"BLE_MCP_MAX_SESSIONS": "<BLE_MCP_MAX_SESSIONS>"
}
}
}
}Replace <…> with your own values. 1 more environment variable is in the server README. uvx runs the command named after the package; if the README names another one, use uvx --from ble-mcp-server <command>
Platform CLI
gemini mcp add -e BLE_MCP_ALLOW_WRITES=<BLE_MCP_ALLOW_WRITES> -e BLE_MCP_WRITE_ALLOWLIST=<BLE_MCP_WRITE_ALLOWLIST> -e BLE_MCP_PLUGINS=<BLE_MCP_PLUGINS> -e BLE_MCP_TOOL_SEPARATOR=<BLE_MCP_TOOL_SEPARATOR> -e BLE_MCP_MAX_SESSIONS=<BLE_MCP_MAX_SESSIONS> ble-mcp-server uvx ble-mcp-serverReplace <…> with your own values. 1 more environment variable is in the server README. uvx runs the command named after the package; if the README names another one, use uvx --from ble-mcp-server <command>
Step by step, with commands for each platform: How to add an MCP server to Claude Code, Codex, Cursor, VS Code, Gemini CLI and more
Questions about ble-mcp-server
How do I install ble-mcp-server in Claude Code?
Run claude mcp add ble-mcp-server -- uvx ble-mcp-server. For writes and plugins, use the variant with environment variables: `claude mcp add --env BLE_MCP_ALLOW_WRITES=<BLE_MCP_ALLOW_WRITES> --env BLE_MCP_WRITE_ALLOWLIST=<BLE_MCP_WRITE_ALLOWLIST> --env BLE_MCP_PLUGINS=<BLE_MCP_PLUGINS> --env BLE_MCP_TOOL_SEPARATOR=<BLE_MCP_TOOL_SEPARATOR> --env BLE_MCP_MAX_SESSIONS=<BLE_MCP_MAX_SESSIONS> --transport stdio ble-mcp-server -- uvx ble-mcp-server`.
What does ble-mcp-server do?
It turns BLE operations into agent-callable tools: scanning, connecting, reading and writing characteristics, subscribing to notifications. Protocol specs and device plugins sit on top of that.
Why does the agent fail to write a characteristic?
Writes are disabled out of the box. Turn them on with BLE_MCP_ALLOW_WRITES, and if only some characteristics may be written, list their UUIDs in BLE_MCP_WRITE_ALLOWLIST.