ble-fleet-mcp
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., "@ble-fleet-mcp Read temperature from all sensors in the warehouse"
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.
ble-fleet-mcp
An MCP server that lets an AI agent manage a fleet of constrained-connection devices — 10, 100, or 1000+ of them — without ever having to know or reason about how many the underlying radio can actually hold open at once.
BLE radios typically support somewhere between 3 and 7 simultaneous connections.
Existing BLE-to-MCP bridges expose scan / connect / read / write / subscribe
as direct tools and leave connection management to the agent. That breaks down the
moment a task involves more devices than the radio can hold open: "check the
temperature on all 40 sensors in the warehouse" turns into forty manual
connect/read/disconnect cycles, with the agent doing the bookkeeping itself — wasted
tokens, wasted latency, and a real failure mode when it gets the bookkeeping wrong.
ble-fleet-mcp hides all of that. The agent asks for fleet-level outcomes — "read
all sensors", "set brightness on every light in Zone 2" — and the server handles
connection pooling, scheduling, retries, and partial failures underneath, inside a
hard concurrency cap it enforces itself.
Agent ──MCP──▶ fleet_read("warehouse", "temperature_c")
│
▼
[ scheduler batches 40 devices behind a 4-connection pool,
retries failures with backoff, circuit-breaks the
unresponsive ones, evicts idle connections to make room ]
│
▼
{ "SIM:0001": 21.4, "SIM:0002": "unreachable", ... }Safety
Read-only by default.
fleet_writerefuses to run unless the server is started withFLEET_ALLOW_WRITES=1— same posture asble-mcp-server.Verify-after-write. Every write is followed by a readback; the result reports both
acknowledged(the device accepted the write) andconverged(the readback actually matches what was requested) rather than trusting the ack alone.Risk tiering. Devices registered as
safety_critical(e.g. a lock, in a fleet that also has light bulbs) are excluded fromfleet_writebatches by default and reported asconfirmation_required, unless their address is explicitly listed inconfirm_addresseson that call. A bulk write to "everything in Zone 2" can never silently include a lock.Nothing is silently dropped. Every device in a fleet operation resolves to
success, a specific error (unreachable,timeout,write_rejected), orstill_queued(pollable viafleet_operation_status) — never just missing.One bad device can't take down the fleet. Per-device timeouts and a circuit breaker isolate unresponsive devices; see docs/architecture.md.
Related MCP server: BLE MCP Server
Quick start
pip install ble-fleet-mcpOr with uv:
uv add ble-fleet-mcpRun it directly to sanity-check your BLE setup:
fleet-mcpIt speaks MCP over stdio, so in practice it's launched by your MCP client (see below), not run standalone. A minimal session, once connected from an agent:
fleet_register(name="warehouse", name_pattern="sensor")
-> {"fleet": "warehouse", "device_count": 40, "addresses": [...]}
fleet_read(fleet="warehouse", resource="temperature_c")
-> {"operation_id": "…", "status": "completed", "total": 40, "completed": 40,
"results": {"AA:BB:...:01": {"status": "success", "value": 21.4}, ...}}No BLE hardware handy? examples/simulated_fleet/ runs
the exact same tool layer against a simulated fleet of virtual peripherals:
uv run python examples/simulated_fleet/demo.py --devices 50 --cap 4Registering 50 simulated sensors (radio cap: 4)...
Reading temperature_c across the whole fleet...
Done in 1.64s over 50 devices with only 4 connections.
Status breakdown: {
"success": 50
}Adding it to your client
ble-fleet-mcp speaks standard MCP over stdio, so it works with any MCP-compatible
client. Writes stay off unless you explicitly set FLEET_ALLOW_WRITES=1.
Claude Code
claude mcp add fleet-mcp -- fleet-mcpOr add it to .mcp.json directly:
{
"mcpServers": {
"fleet-mcp": {
"command": "fleet-mcp",
"env": {
"FLEET_MAX_CONNECTIONS": "4",
"FLEET_ALLOW_WRITES": "0"
}
}
}
}Claude Desktop
Add to your claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"fleet-mcp": {
"command": "fleet-mcp",
"env": {
"FLEET_MAX_CONNECTIONS": "4",
"FLEET_ALLOW_WRITES": "0"
}
}
}
}Cursor
Add to .cursor/mcp.json in your project (or the global ~/.cursor/mcp.json):
{
"mcpServers": {
"fleet-mcp": {
"command": "fleet-mcp",
"env": {
"FLEET_MAX_CONNECTIONS": "4",
"FLEET_ALLOW_WRITES": "0"
}
}
}
}VS Code (Copilot)
Add to .vscode/mcp.json:
{
"servers": {
"fleet-mcp": {
"type": "stdio",
"command": "fleet-mcp",
"env": {
"FLEET_MAX_CONNECTIONS": "4",
"FLEET_ALLOW_WRITES": "0"
}
}
}
}Tools
Tool | Purpose |
| Register a device or group (address list, name pattern, or service UUIDs) into a named fleet. |
| Discover devices matching a filter, without connecting or registering. |
| Read one resource across a fleet (or subset). Per-device results, not all-or-nothing. |
| Write one resource across a fleet. Requires |
| Subscribe to / unsubscribe from / poll buffered, debounced notifications for a resource across a fleet. |
| Per-device health: healthy/unhealthy, consecutive failures, connected. |
| Connection pool telemetry: active/idle/evicting counts, queue depth, per-device wait times. |
| Poll a |
Full input/output schemas: docs/tools.md. Design rationale for the pool manager, scheduler, and circuit breaker: docs/architecture.md.
Environment variables
Variable | Default | Meaning |
|
| Hard cap on simultaneous BLE connections. Match this to what you measured for your adapter — see docs/hardware-validation.md. |
|
| Set to |
|
| Whether |
|
| Per-device timeout (connect + operation) before it's treated as a failure. |
|
| Default overall timeout for a |
|
| Initial per-device retry backoff. |
|
| Cap on per-device retry backoff. |
|
| Exponential backoff multiplier. |
|
| Consecutive failures before a device is marked unhealthy and stops being retried. |
|
| How long an unhealthy device is skipped before a single probe attempt is allowed through. |
|
| Structured JSONL tracing of pool/scheduler events. |
|
| Where trace events are written. |
|
| Log level; logs always go to stderr so stdout stays clean for the MCP stdio transport. |
| unset (disabled) | Set to a port number to serve the web dashboard on that port. Off by default — see below. |
|
| Dashboard bind address. Localhost only unless you explicitly widen it — there's no authentication. |
Web dashboard
A minimal, read-only dashboard over the same telemetry fleet_pool_status/fleet_status
already expose: live connection pool gauges, per-device health, recent operations, and
active watches. It's a stdlib http.server running in a background thread — no extra
dependency, and it reads straight from the running server's in-memory state, so it's
always exactly in sync.
Off by default. Enable it by setting FLEET_DASHBOARD_PORT:
FLEET_DASHBOARD_PORT=8765 fleet-mcp
# open http://127.0.0.1:8765No hardware or MCP client needed to see it in action —
examples/simulated_fleet/dashboard_demo.py
runs the dashboard against a lively simulated fleet:
uv run python examples/simulated_fleet/dashboard_demo.py --devices 30 --cap 4
# open http://127.0.0.1:8765Transports
Transport | Status |
BLE (via | v1, shipped |
Zigbee coordinator | Roadmap, not started |
Thread border router | Roadmap, not started |
The pool manager, scheduler, and MCP tool layer never import anything transport-specific — a new transport is a plugin, not a rewrite. See CONTRIBUTING.md.
Roadmap (not blocking 1.0.0)
A second transport plugin (Zigbee or Thread) to prove the plugin interface generalizes beyond BLE.
A "fleet template" registry for shareable configs of common device populations.
Development
git clone https://github.com/JephinJose/ble-fleet-mcp.git
cd ble-fleet-mcp
uv sync --extra dev
uv run pre-commit install
uv run pytest tests/unitSee CONTRIBUTING.md for the full workflow and how to add a transport plugin.
License
MIT — see LICENSE.
Available Tools
8 toolsfleet_operation_statusA
Poll a fleet_read/fleet_write batch by operation_id for partial or complete results. Never returns a silently-dropped device: every device resolves to success, a specific error, or still_queued.
Inputs: operation_id (required). Returns: object
fleet_pool_statusA
Connection pool telemetry: active/idle/evicting connection counts, queue depth, and per-device wait times. The live debugging surface for the pool.
Inputs: no named parameters. Returns: object
fleet_readA
Read one resource across every device in a fleet, or a subset by address. Returns per-device results (success / unreachable / timeout / still_queued) as an operation snapshot keyed by operation_id.
Inputs: fleet (required), resource (required), priority, addresses, +1 more. Returns: object
fleet_registerA
Register a device or group (by explicit address list, or by name pattern / service UUIDs discovery filter) into a named fleet. risk_tier is one of read_only, low_risk_actuator, or safety_critical; safety_critical devices are excluded from fleet_write batches unless explicitly confirmed.
Inputs: name (required), addresses, risk_tier, name_pattern, +2 more. Returns: object
fleet_scanA
Discover devices matching a filter, without connecting to or registering them. Use this to see what's out there before fleet_register.
Inputs: addresses, timeout_s, name_pattern, service_uuids. Returns: object
fleet_statusC
Health of every device in a fleet: healthy/unhealthy, consecutive failure count, and whether it's currently connected.
Inputs: fleet (required). Returns: object
fleet_watchA
Subscribe to (action="subscribe"), stop watching (action="unsubscribe"), or drain buffered notifications for (action="poll") a resource across a fleet. Watching a device pins one pool connection slot for as long as it's watched.
Inputs: fleet (required), resource (required), action, addresses, +1 more. Returns: object
fleet_writeA
Write one resource across a fleet. Requires the server to have been started
with FLEET_ALLOW_WRITES=1. Every write is verified with a readback; the result
reports both acknowledged and converged. Devices tiered safety_critical are
skipped (status confirmation_required) unless their address is passed in
confirm_addresses.
Inputs: fleet (required), value (required), resource (required), priority, +3 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool has a distinct role: register, scan, read, write, watch, status, pool_status, and operation_status. The three 'status' tools are differentiated by scope (device health vs. pool telemetry vs. batch progress), though the naming overlap could cause minor confusion.
All tools share the 'fleet_' prefix and use consistent snake_case. Actions are verbs (register, scan, read, write, watch), while queries are nouns (status, pool_status, operation_status), forming a predictable pattern.
Eight tools is well-scoped for a fleet management server, covering core operations without unnecessary bloat. Each tool serves a clear purpose in the lifecycle.
The set covers discovery, registration, read/write, watching, device health, pool telemetry, and operation tracking. Missing a deregister or fleet deletion operation is a minor gap, but the primary workflows are fully supported.
Maintenance
Related MCP Connectors
Remote MCP server for The Colony — a social network for AI agents (posts, DMs, search, marketplace).
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server for building and testing AI agents with multi-model experimentation and insights.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceBluetooth Low Energy (BLE) MCP server that allows AI agents to scan, connect to and communicated with BLE devices, as well as simulate BLE perhipherals.26BSD 2-Clause "Simplified"
- AlicenseAqualityDmaintenanceA stateful Bluetooth Low Energy (BLE) MCP server that enables AI agents to scan, connect, read/write characteristics, and subscribe to notifications on BLE devices.3569 PyPI19MIT
- AlicenseAqualityDmaintenanceMCP server for multi-agent AI systems providing mailbox messaging, A2A task delegation, resource coordination, and a web dashboard.2114 npm1MIT
- AlicenseNot gradedqualityBmaintenanceMCP server enabling real-time communication, task delegation, and acknowledgment among multiple AI agents through a single local endpoint.117 npm6MIT