MCP Server
Run and use the SimpleAIBLE MCP server.
The SimpleAIBLE MCP server provides local BLE tools to MCP-capable clients. It is designed for development, debugging, and AI-assisted workflows that need direct access to BLE hardware on the host machine.
Note
This server runs locally using STDIO transport. The local setup uses uv (recommended) or Python/pip.
Installation
uv tool install simpleaiblepip install simpleaibleOn Python 3.11+ (most modern macOS and Linux systems), pip install may fail with an "externally-managed-environment" error (PEP 668). Add the --break-system-packages flag:
pip install --break-system-packages simpleaible
# or
python3 -m pip install --break-system-packages simpleaibleInstall in Cursor
Go to: Settings -> Cursor Settings -> MCP -> Add new global MCP server
Pasting the following configuration into your Cursor ~/.cursor/mcp.json file is the recommended approach. You may also install in a specific project by creating .cursor/mcp.json in your project folder. See Cursor MCP docs for more info.
Cursor Local Server Connection
{
"mcpServers": {
"simpleaible": {
"command": "simpleaible"
}
}
}Install in Claude Code
Run this command. See Claude Code MCP docs for more info.
Claude Code Local Server Connection
claude mcp add simpleaible -- simpleaibleInstall in Opencode
Add this to your Opencode configuration file. See Opencode MCP docs for more info.
Opencode Local Server Connection
{
"mcp": {
"simpleaible": {
"type": "local",
"command": ["simpleaible"],
"enabled": true
}
}
}Tool catalog
All tool inputs/outputs are JSON-serializable.
General Tools
bluetooth_enabled
Check if Bluetooth is enabled on the host system. By default, assume Bluetooth is enabled. Use this tool only when troubleshooting failed operations.
- Response:
{"enabled": true}
get_adapters
List all available Bluetooth adapters on the system.
- Response: List of objects containing
identifierandaddress.[ { "identifier": "hci0", "address": "AA:BB:CC:DD:EE:FF" } ]
scan_for
Scan for nearby BLE devices using the first available adapter.
- Parameters:
timeout_ms(default:5000) - Duration of the scan in milliseconds. - Response: List of found devices.
[ { "identifier": "Nordic_HRM", "address": "AA:BB:CC:DD:EE:FF", "rssi": -55, "connectable": true, "manufacturer_data": {"76": "0215..."} } ]
Device Connection
connect
Establish a connection to a specific device found in the last scan.
- Parameters:
address- Device address (UUID on macOS, MAC on Linux/Windows). - Response:
{"message": "Connected to Nordic_HRM", "address": "AA:BB:CC:DD:EE:FF"}
disconnect
Disconnect from a connected device.
- Parameters:
address - Response:
{"message": "Disconnected from AA:BB:CC:DD:EE:FF"}
services
Retrieve services and characteristics for a connected device.
- Parameters:
address - Response:
{ "identifier": "Nordic_HRM", "address": "AA:BB:CC:DD:EE:FF", "connected": true, "mtu": 23, "services": [ { "uuid": "0000180d-0000-1000-8000-00805f9b34fb", "characteristics": ["00002a37-0000-1000-8000-00805f9b34fb"] } ] }
Characteristic Interaction
read
Read the current value of a characteristic.
- Parameters:
address,service_uuid,char_uuid - Response:
{"service_uuid": "0000180d-0000-1000-8000-00805f9b34fb", "char_uuid": "00002a37-0000-1000-8000-00805f9b34fb", "data_hex": "00aabb", "data_utf8": "..."} - Note:
data_utf8is a convenience field. If the data is not valid UTF-8, invalid bytes are silently skipped, so it may be incomplete or empty for binary data. Usedata_hexfor reliable binary representation.
write_request
Write a value to a characteristic (Write with Response).
- Parameters:
address,service_uuid,char_uuid,data(hex string, e.g."001122") - Response:
{"message": "Write successful"}
write_command
Write a value to a characteristic without expecting a response (Write Command).
- Parameters:
address,service_uuid,char_uuid,data(hex string, e.g."001122") - Response:
{"message": "Write command successful"}
Notifications and Indications
notify
Subscribe to notifications for a specific characteristic. Data is buffered in the background.
- Parameters:
address,service_uuid,char_uuid - Response:
{"message": "Subscribed to notifications"}
indicate
Subscribe to indications for a specific characteristic. Data is buffered in the background.
- Parameters:
address,service_uuid,char_uuid - Response:
{"message": "Subscribed to indications"}
unsubscribe
Stop receiving notifications or indications for a characteristic.
- Parameters:
address,service_uuid,char_uuid - Response:
{"message": "Unsubscribed"}
get_notifications
Retrieve all received notifications and indications for a device. This call clears the internal notification buffer for that device.
- Parameters:
address - Response: List of notification objects.
[ { "service": "0000180d-0000-1000-8000-00805f9b34fb", "characteristic": "00002a37-0000-1000-8000-00805f9b34fb", "data_hex": "163c00", "data_utf8": "...", "type": "notification" } ] - Note:
data_utf8is a convenience field. If the data is not valid UTF-8, invalid bytes are silently skipped, so it may be incomplete or empty for binary data. Usedata_hexfor reliable binary representation.
Recommended flow
scan_forconnectservicesreadorwrite_request/write_commandfor one-time operations, ornotify/indicate+get_notifications+unsubscribefor streaming datadisconnect
get_adapters is only needed when you want to list available Bluetooth adapters, not as a prerequisite for other operations.
Platform notes
- On macOS/iOS, device
addressis a randomized UUID (e.g.,5E2A...) instead of a hardware MAC address. These UUIDs are temporary and may change between sessions or device restarts. On Linux/Windows, standard MAC addresses are used (e.g.,AA:BB:CC:DD:EE:FF). - Advertisement fields (RSSI, manufacturer data, service UUIDs) can vary by OS and device.
- Some characteristics require pairing or may be restricted by the OS.
MCP client example (FastMCP via HTTP)
If you are running the server manually using the HTTP transport (simpleaible --transport http), you can connect to it using a FastMCP client:
import asyncio
from fastmcp import Client
async def main():
# Connect to the server running on the default port 8000
async with Client("http://127.0.0.1:8000/mcp") as client:
adapters = await client.call_tool("get_adapters", {})
# ...Note: FastMCP returns structured results under structured_content rather than data for some tool outputs.
Running the server manually
While MCP clients handle starting the server automatically, you can also run it manually for testing.
STDIO Transport (Default):
simpleaibleHTTP Transport:
simpleaible --transport http --host 127.0.0.1 --port 8000