返回 MCP 目录
public公开dns本地运行

ble-mcp-server

一个状态化的蓝牙低功耗(BLE)模型上下文协议(MCP)服务器,为开发工具和AI代理提供与真实BLE硬件交互的能力,支持扫描、连接、读写、订阅通知等操作,并可扩展设备协议规范和插件。

article

README

🚀 BLE MCP 服务器

这是一个有状态的蓝牙低功耗 (BLE) 模型上下文协议 (MCP) 服务器,专为开发工具和 AI 代理设计。它可直接与 Claude Code、带有 Copilot 的 VS Code 以及任何兼容 MCP 的运行时配合使用。该服务器通过 标准输入输出(无 HTTP,无开放端口)进行通信,并使用 bleak 库实现跨平台 BLE 功能,支持 macOS、Windows 和 Linux 系统。

示例:让 Claude Code 扫描附近的 BLE 设备,连接到其中一个,读取特征值,并从真实硬件接收通知流。

演示

7 分钟视频演示 — 扫描真实的 BLE 设备,发现服务,读取值,并将流程提升为插件。

🚀 快速开始

快速启动(Claude Code)

pip install ble-mcp-server

# 向 Claude Code 注册 MCP 服务器(默认只读)
claude mcp add ble -- ble_mcp

然后在 Claude Code 中尝试:

"扫描附近的 BLE 设备,并连接到名称以 Arduino 开头的设备。"

服务器 默认只读。写入操作和插件可以控制真实硬件并执行代码,可通过环境变量进行选择启用。详情请参阅 安全说明

✨ 主要特性

为何开发此项目

如果你有一个 BLE 设备,并且希望 AI 代理与之交互,如扫描、连接、读取传感器数据、发送命令、流式传输数据,那么这个服务器就能实现这些功能。

它为任何兼容 MCP 的代理提供了一套完整的 BLE 工具,包括扫描、连接、读取、写入、订阅通知等,同时还提供协议规范和设备插件,使代理能够理解更高级别的设备行为,而不仅仅是原始的 UUID 和字节数据。

代理调用这些工具后,会得到结构化的 JSON 数据,并据此决定下一步操作,无需人工干预每个 BLE 操作。

代理可以利用它做什么:

  • 开发与调试:连接到设备,探索其服务,读取特征值,测试命令,并以对话方式诊断问题。例如,你可以询问 “为什么这个传感器返回零值?”
  • 迭代新硬件:正在开发 BLE 设备?添加协议规范,让代理随着设备的发展理解你的命令和数据格式。
  • 自动化测试:编写特定于设备的插件,暴露高级操作(如 device.start_stream、device.run_self_test),然后让代理运行测试序列:启用传感器、收集样本、验证值、报告结果。
  • 探索:让代理指向一个你从未见过的设备。它会发现服务、探测特征值,并从头开始构建协议文档。
  • 构建 BLE 自动化:让代理控制真实硬件完成实际任务,如按计划读取环境传感器数据、管理一组 BLE 信标、根据条件触发执行器。

适用人群

  • 嵌入式工程师:更快地迭代 BLE 协议,进行对话式调试,实现自动化测试序列。
  • 爱好者和创客:无需编写样板代码即可探索 BLE 设备;让代理帮助逆向工程简单协议。
  • QA 和测试工程师:使用插件工具构建可重复的 BLE 测试套件,并从 CI 或代理会话中运行它们。
  • 支持和现场工程师:无需专业工具即可交互式诊断 BLE 设备问题。
  • 研究人员:自动从 BLE 传感器收集数据,系统地探索设备功能。

代理的功能

连接后,代理具备完整的 BLE 功能:

  • 扫描:扫描附近的设备,可选择按名称或服务 UUID 进行过滤。
  • 连接:连接到设备并发现其服务和特征值。
  • 读写:读取和写入特征值(写入操作需要 BLE_MCP_ALLOW_WRITES 权限)。
  • 订阅通知:订阅通知并收集流式数据,支持单事件、轮询或批量读取。
  • 附加协议规范:附加协议规范以理解特定设备的命令和数据格式。
  • 使用插件:使用插件进行高级设备操作(如 sensortag.read_temp),而不是进行原始的读写操作。
  • 创建规范和插件:为新设备创建规范和插件,在不同会话中积累可重复使用的知识。

代理可以自动处理多步骤流程。例如,“从我的 SensorTag 读取温度” 可能涉及扫描、连接、发现服务、附加规范、启用传感器和读取值,而无需你指定每个步骤。

从高层次来看: 原始 BLE → 协议规范 → 插件

你可以从原始 BLE 工具开始,随着对设备协议的理解和重复使用,逐步提升到更高层次。有关各部分如何协同工作的详细信息,请参阅 概念

📦 安装指南

开发环境安装

# 从仓库根目录进行可编辑安装
pip install -e .

# 或者使用 uv
uv pip install -e .

MCP 是一种协议,此服务器可与任何兼容 MCP 的客户端配合使用。以下是最常见客户端的设置说明。

添加到 Claude Code

# 最小化安装(只读)
claude mcp add ble -- ble_mcp

# 或者作为模块运行
claude mcp add ble -- python -m ble_mcp_server

# 启用写入操作
claude mcp add ble -e BLE_MCP_ALLOW_WRITES=true -- ble_mcp

# 启用写入操作并设置特征 UUID 白名单
claude mcp add ble \
  -e BLE_MCP_ALLOW_WRITES=true \
  -e BLE_MCP_WRITE_ALLOWLIST="2a00,12345678-1234-1234-1234-123456789abc" \
  -- ble_mcp

# 启用所有插件
claude mcp add ble -e BLE_MCP_PLUGINS=all -- ble_mcp

# 仅启用特定插件
claude mcp add ble -e BLE_MCP_PLUGINS=sensortag,hello -- ble_mcp

# 启用调试日志
claude mcp add ble -e BLE_MCP_LOG_LEVEL=DEBUG -- ble_mcp

添加到 VS Code / Copilot

将以下内容添加到项目的 .vscode/mcp.json 文件中(如果文件不存在则创建):

{
  "servers": {
    "ble": {
      "type": "stdio",
      "command": "ble_mcp",
      "args": [],
      "env": {
        "BLE_MCP_ALLOW_WRITES": "true",
        "BLE_MCP_PLUGINS": "all"
      }
    }
  }
}

根据需要调整 env 参数:移除 BLE_MCP_ALLOW_WRITES 可设置为只读模式,或设置 BLE_MCP_PLUGINS 为特定插件名称。

添加到 Cursor

将以下内容添加到项目的 .cursor/mcp.json 文件中(如果文件不存在则创建)。由于 Cursor 不支持工具名称中包含点号,因此必须将 BLE_MCP_TOOL_SEPARATOR 设置为 _

{
  "mcpServers": {
    "ble": {
      "command": "ble_mcp",
      "args": [],
      "env": {
        "BLE_MCP_ALLOW_WRITES": "true",
        "BLE_MCP_PLUGINS": "all",
        "BLE_MCP_TOOL_SEPARATOR": "_"
      }
    }
  }
}

环境变量

| 变量 | 默认值 | 描述 | |------|------|------| | BLE_MCP_ALLOW_WRITES | 禁用 | 设置为 true1yes 以启用 ble.write 操作。 | | BLE_MCP_WRITE_ALLOWLIST | 空 | 可写入特征的 UUID 白名单,以逗号分隔(仅在启用写入操作时检查)。 | | BLE_MCP_PLUGINS | 禁用 | 插件策略:all 表示允许所有插件,或使用 name1,name2 允许特定插件。未设置则禁用。 | | BLE_MCP_LOG_LEVEL | WARNING | Python 日志级别(DEBUGINFOWARNINGERROR)。日志输出到标准错误输出。 | | BLE_MCP_TRACE | 启用 | 对每个工具调用进行 JSONL 跟踪。设置为 0falseno 可禁用。 | | BLE_MCP_TRACE_PAYLOADS | 禁用 | 在跟踪参数中包含 value_b64/value_hex(默认情况下会去除)。 | | BLE_MCP_TRACE_MAX_BYTES | 16384 | 截断前的最大有效负载字符数(仅在 TRACE_PAYLOADS 启用时适用)。 | | BLE_MCP_TOOL_SEPARATOR | . | 用于分隔工具名称段的字符。对于不允许工具名称中包含点号的 MCP 客户端(如 Cursor),设置为 _。 |

💻 使用示例

基础用法

示例会话: 仓库中包含一个模拟的 BLE 外设,你可以在第二台机器(如树莓派)上运行它,进行端到端测试,无需真实硬件。设置方法请参阅 examples/demo-device/

"扫描 BLE 设备并连接到 DemoDevice。读取电池电量,然后开始数据收集。"

代理将执行以下操作:

  1. 扫描附近的设备并找到 DemoDevice。
  2. 连接并发现其服务。
  3. 检查是否有匹配的协议规范 — 如果存在,则附加该规范以理解设备协议。
  4. 检查是否有匹配的插件 — 如果存在,则使用其快捷工具。
  5. 如果没有规范或插件,则使用原始 BLE 工具探索设备,或向你寻求指导。
  6. 读取电池电量,配置数据服务,并开始收集数据。

该示例包含预构建的 协议规范插件 — 将它们复制到 .ble_mcp/specs/.ble_mcp/plugins/ 中可跳过探索阶段,也可以让代理从头开始创建自己的规范和插件。

高级用法

你可以在不使用代理的情况下,使用 MCP Inspector 交互式测试服务器:

npx @modelcontextprotocol/inspector python -m ble_mcp_server

打开终端输出中带有认证令牌的 URL。Inspector 提供一个 Web UI,可调用任何工具,查看响应,并实时观察 MCP 通知(如断开连接警报)。

📚 详细文档

工具

有关各部分如何协同工作的详细信息,请参阅 概念,有关详细的输入输出模式,请参阅 工具参考

| 类别 | 工具 | |------|------| | BLE 核心 | ble.scan_startble.scan_get_resultsble.scan_stopble.connectble.disconnectble.connection_statusble.discoverble.mtuble.readble.writeble.read_descriptorble.write_descriptorble.subscribeble.unsubscribeble.wait_notificationble.poll_notificationsble.drain_notifications | | 自省 | ble.connections.listble.subscriptions.listble.scans.list | | 协议规范 | ble.spec.templateble.spec.registerble.spec.listble.spec.attachble.spec.getble.spec.readble.spec.search | | 跟踪 | ble.trace.statusble.trace.tail | | 插件 | ble.plugin.templateble.plugin.listble.plugin.reloadble.plugin.load |

协议规范

协议规范是描述 BLE 设备协议的 Markdown 文件,包括服务、特征值、命令和数据格式。它们存储在 .ble_mcp/specs/ 目录中,可帮助代理理解设备的功能,而不仅仅是原始的 UUID 和字节数据。

如果没有规范,代理仍然可以发现服务并读取特征值。但有了规范,它就能理解这些值的含义并知道要发送的命令。

你可以通过向代理描述设备来创建规范,例如粘贴数据手册、描述协议,或者让代理自行探索并记录它发现的内容。代理会生成规范文件,注册它,并在后续会话中引用。你也可以手动编写规范。

有关规范格式和代理如何使用它们的详细信息,请参阅 概念

插件

插件为服务器添加特定于设备的快捷工具。代理无需编写原始的读写序列,插件可以提供高级操作,如 sensortag.read_tempota.upload_firmware

代理还可以 创建 插件(需经你批准)。它会探索设备,根据所学内容编写插件,后续会话即可使用这些快捷工具,无需手动编码。

要启用插件:

# 启用所有插件
claude mcp add ble -e BLE_MCP_PLUGINS=all -- ble_mcp

# 仅启用特定插件
claude mcp add ble -e BLE_MCP_PLUGINS=sensortag,ota -- ble_mcp

编辑已加载的插件只需使用 ble.plugin.reload,无需重启服务器。

有关插件契约、元数据匹配以及规范和插件如何协同工作的详细信息,请参阅 概念

跟踪

每个工具调用都会被跟踪到 .ble_mcp/traces/trace.jsonl 和内存中的环形缓冲区(最后 2000 个事件)。跟踪 默认开启,设置 BLE_MCP_TRACE=0 可禁用。

事件格式

每个工具调用会产生两个事件:

{"ts":"2025-01-01T00:00:00.000Z","event":"tool_call_start","tool":"ble.read","args":{"connection_id":"c1","char_uuid":"2a00"},"connection_id":"c1"}
{"ts":"2025-01-01T00:00:00.050Z","event":"tool_call_end","tool":"ble.read","ok":true,"error_code":null,"duration_ms":50,"connection_id":"c1"}
  • connection_id 会在参数中存在时被提取。
  • value_b64value_hex 默认会从跟踪参数中去除(可通过 BLE_MCP_TRACE_PAYLOADS=1 启用)。

检查跟踪信息

使用 ble.trace.status 检查配置和事件数量,使用 ble.trace.tail 获取最近的事件,无需直接读取文件。

平台 BLE 权限

macOS

大多数情况下无需特殊设置。在 macOS 12+ 系统中,终端应用程序(或你使用的任何终端)必须具有 蓝牙 权限。转到 系统设置 > 隐私与安全 > 蓝牙,确保你的终端已列出并启用。如果从 IDE 运行,IDE 本身可能也需要此权限。

Windows

需要 Windows 10 版本 1709(秋季创意者更新)或更高版本。无需额外驱动程序,bleak 使用原生 WinRT 蓝牙 API。只需确保在设置中打开蓝牙。

Linux

需要 BlueZ 5.43+ 版本。你的用户必须有权限访问 D-Bus 蓝牙接口。最简单的方法是:

# 将你的用户添加到 bluetooth 组
sudo usermod -aG bluetooth $USER
# 然后注销并重新登录

如果你在容器或无头环境中运行,请确保 dbusbluetoothd 正在运行。

🔧 技术细节

架构

  • 标准输入输出 MCP 传输:无 HTTP,无网络端口。
  • 有状态:连接和订阅信息保存在内存中。
  • 默认安全:写入操作由环境标志和白名单控制。
  • 对代理友好:结构化输出,缓冲通知。
  • 优雅关闭:退出时断开所有客户端连接。

已知限制

  • 真实硬件是异步的,而代理运行时大多不是:设备可能会断开连接,通知可能会异步到达,并且在代理思考时状态可能会发生变化。大多数代理运行时针对干净的请求/响应循环进行了优化。服务器通过轮询工具、缓冲通知队列和 MCP 日志通知(用于断开连接和传入数据)来解决这个问题,但 MCP 日志通知依赖于客户端(它们在 MCP Inspector 中有效;Claude Code 目前忽略它们)。代理始终可以在下次工具调用时检测到断开连接并显式轮询通知 — 日志消息只是尽力提供的提醒,并非保证。
  • 仅支持单客户端:服务器一次处理一个 MCP 会话(标准输入输出传输)。后续可能会添加多客户端传输(HTTP/SSE)功能。

📄 许可证

本项目采用 MIT 许可证 — 详情请参阅 LICENSE

致谢

本项目基于优秀的 bleak 库构建,该库用于 Python 中的跨平台 BLE 功能。

⚠️ 安全说明

此服务器将 AI 代理连接到真实硬件。这既是其目的,也意味着风险比纯软件工具更高。

  • 插件会执行任意代码:启用插件后,代理可以在你的机器上创建并运行具有完整服务器权限的 Python 代码。在加载代理生成的插件之前,请仔细审查。使用 BLE_MCP_PLUGINS=name1,name2 仅允许特定插件,而不是 all
  • 写入操作会影响真实设备:错误地写入错误的特征值可能会损坏设备、触发意外行为或干扰其他连接的系统。除非需要,否则请保持写入操作禁用。使用 BLE_MCP_WRITE_ALLOWLIST 限制可写入的特征值。
  • 谨慎使用工具批准:当你的 MCP 客户端提示你批准工具调用时,请考虑是允许一次还是始终允许。“始终允许” 很方便,但意味着代理可以在无需进一步确认的情况下重复该操作。

本软件按 “原样” 提供,遵循 MIT 许可证。你应对代理对硬件的操作负责。

help

运行方式说明

cloud

托管运行

托管运行通常表示这个 MCP Server 由服务方环境承载,用户一般按页面提供的连接方式或授权流程接入,不需要在本地长期启动一个 MCP 进程

  1. 打开服务方连接页
  2. 完成授权或复制端点
  3. 在 MCP 客户端中连接
terminal

本地运行 / 其它方式

本地运行通常需要用户在自己的电脑或服务器上安装依赖,把 server_config 复制到 MCP 客户端,并按 env_schema 补齐环境变量、密钥或其它配置

  1. 复制 server_config
  2. 安装所需依赖
  3. 补齐环境变量后重启客户端