mcpField
B
Bluetooth Low Energy (BLE) MCP server -- scan, connect and interact with BLE peripherals

Bluetooth Low Energy (BLE) MCP server -- scan, connect and interact with BLE peripherals

本地服务
github.com/stass开发工具2522 周前更新

关于 Bluetooth Low Energy (BLE) MCP server -- scan, connect and interact with BLE peripherals

blew 是适用于 macOS 的蓝牙低功耗(BLE)命令行工具,可扫描设备、检查 GATT 结构、读写特征值并订阅通知。适合需要调试 BLE 设备的开发者和嵌入式工程师,也可以在命令行中完成这些操作。

主要功能

  1. 01扫描附近 BLE 设备并显示信号强度
  2. 02打印设备 GATT 服务与特征树
  3. 03读写特征值并订阅通知
  4. 04以 kv 格式输出便于脚本处理
  5. 05支持将 Mac 配置为虚拟 BLE 外设

适用场景

  1. 01调试 BLE 外设的服务与特征
  2. 02将传感器数据实时记录到日志文件
  3. 03在脚本或 CI 中执行多步骤 BLE 测试

MCP 相关

该项目提供 mcp 子命令,将所有 BLE 操作以 MCP 工具的形式暴露给 AI Agent。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

blew —— 适用于 Mac OS X 的 BLE 扫描器和命令行工具

无需再折腾图形界面应用来调试低功耗蓝牙设备。blew 让你在 macOS 命令行中全面控制 BLE:扫描周围设备、深入查看任意设备的 GATT 树、读取和写入特征、实时接收通知,甚至启动一个其他设备可以连接的虚拟外围设备。

BLE 扫描

GATT 树 UART

为什么选择 blew
  • 一个工具,操作简单。 扫描、连接、检查、读取、写入、订阅——每项操作都只需一条命令。自动连接意味着你无需手动配对即可开始实际操作。
  • 需要时可交互操作。 启动 REPL,开展探索式会话,享受 Tab 补全、持久化历史记录,以及在你继续输入时打印内容的后台订阅。
  • 需要时可编写脚本。 使用 exec 串联命令,将机器可读的 kv 输出传递给 awk 或日志文件,并在 CI 或监控脚本中使用确定性的退出码。
  • 全面查看 GATT。 一次性打印任意设备的服务/特征树。直接在树中读取所有值。即使不连接,也能查询 Bluetooth SIG 特征的字段级规范。
  • 外围设备模式。 将 Mac 变成虚拟 BLE 设备。通过 JSON 配置定义 GATT 服务端,或克隆真实设备的完整服务树并重放。
  • 默认易于阅读。 标准 Bluetooth SIG UUID 在各处都会解析为对应名称,包括扫描结果、GATT 树和通知;数据来源为官方 Bluetooth SIG 数据库。
操作模式
  • 命令模式 —— 运行单条命令后退出:blew [global-options] <command> [command-options]
  • 交互式 REPL —— 不带命令运行 blew,进入支持历史记录和 Tab 补全的 readline 风格 Shell
  • 脚本模式 —— 运行以分号分隔、共享同一连接的命令序列:blew exec "connect -n Sensor; gatt tree; read -f uint8 2A19"
  • MCP 服务模式 —— 将所有 BLE 操作作为 MCP 工具提供给 AI Agent:blew mcp

需要 macOS 13+ 和蓝牙权限。

可以做什么

克隆真实设备并冒充它。 走到心率监测器旁,克隆其完整 GATT 树,Mac 就会开始以该设备的身份广播。其他应用可以像连接真实设备一样连接克隆设备:

% blew periph clone -n "Heart Rate Monitor" --save hr.json

实时监控 BLE 周边设备。 查看附近的每台设备及其信号强度条,并实时更新。按名称、服务或信号强度下限筛选,在拥挤场所快速找到所需设备:

% blew scan -w -R -70

一次性透视设备信息。 连接设备、发现所有服务、读取每个可读特征,并以树状结构打印全部内容,包括名称、属性、描述符和实时值:

% blew -n "Thingy" gatt tree -dr

无需设备即可查询任意 Bluetooth SIG 特征。 即时查看任意标准特征的字段级结构,例如字节布局、类型和条件字段:

% blew gatt info 2A37    # Heart Rate Measurement spec

将传感器数据直接写入日志。 订阅某个特征,将值格式化为键值对,并传递到文件或其他工具。可在无头模式下运行,并在超时后正常退出:

% blew -o kv sub -n "Sensor" -f uint16le -d 3600 fff1 >> hourly.log

从 JSON 文件启动虚拟 BLE 设备。 在配置文件中定义服务、特征、属性和初始值,并通过一条命令开始广播:

% blew periph adv --config health-thermometer.json

用一条命令运行多步骤测试序列。 依次连接、检查、读取、写入、等待、再次读取或订阅通知:

% blew exec -k "connect -n Sensor; gatt tree; write -f uint8 fff2 01; sleep 2; read -f uint16le fff1"

安装

Homebrew
brew install stass/tap/blew
要求
  • macOS 14(Sonoma)或更高版本
  • Xcode 16 或更高版本(Swift 6.0+ 工具链)

MCP 服务(blew mcp 子命令)依赖 MCP swift-sdk,该 SDK 要求使用 Swift 6.1 工具链(Xcode 16.3+)。为确保 blew 能在较旧的工具链上构建,MCP 支持采用条件编译:使用 Swift 6.1 或更高版本构建时,mcp 子命令可用;使用 Swift 6.0.x(Xcode 16.0–16.2)构建时,会省略 MCP 服务,其他所有命令均保持不变。无需任何标志——Package.swift 会自动检测。

从源代码构建
git clone --recurse-submodules https://github.com/stass/blew.git
swift build -c release
cp .build/release/blew /usr/local/bin/blew

必须使用 --recurse-submodules——Bluetooth SIG 名称和特征数据库以 git 子模块的形式包含在 Vendor/ 下。Swift 构建会根据子模块数据自动生成所有数据文件。

首次运行时,macOS 会提示你授予蓝牙权限。请在系统设置 → 隐私与安全性 → 蓝牙中授予权限。


快速开始

# Scan for nearby devices
% blew scan

# Print the GATT tree of a device (connects automatically)
% blew -n "Thingy" gatt tree

# Read a characteristic (battery level)
% blew -n "Thingy" read -f uint8 2A19

# Subscribe to notifications for 10 seconds
% blew -n "Thingy" sub -d 10 fff1

# Run a multi-step procedure in one invocation
% blew -n "Thingy" -x "gatt tree; read -f uint8 2A19"

# Start the interactive REPL
% blew

全局选项

这些选项适用于所有命令,必须放在子命令名称之前:

% blew [global-options] <command> [command-options]
标志说明
-v, --verbose提高日志详细程度。可重复使用:-vv 可显示调试级别的详细信息。
-o, --out <format>结果的输出格式:text(默认,便于阅读)或 kv(key=value,每行一条记录,更易于解析)。
-t, --timeout <sec>BLE 操作的超时时间,单位为秒。
-h, --help显示帮助并退出。
--version显示版本并退出。

设备定位选项

连接设备的命令(scan、connect、gatt、read、write、sub、periph clone)接受这些选项来指定目标。请将它们放在子命令名称之后。

使用 --id 指定明确的设备,或组合多个筛选条件,让 blew 自动查找匹配设备。

标志说明
-i, --id <device-id>通过设备标识符指定目标设备。
-n, --name <substring>按设备名称筛选(匹配子字符串)。
-S, --service <uuid>按广播的服务 UUID 筛选。可重复使用。
-m, --manufacturer <id>按制造商 ID 筛选。
-R, --rssi-min <dBm>RSSI 最低阈值(例如 -R -70)。
-p, --pick <strategy>多个设备匹配时的选择方式:strongest(默认,RSSI 最高)、first(最先发现)或 only(匹配多个时出错)。

命令

scan — 扫描 BLE 设备
blew scan [-n <name>] [-S <uuid>] [-R <dBm>] [-i <id>] [-m <id>] [-p <strategy>] [-w]

扫描正在广播的 BLE 外围设备,并以表格形式显示发现的设备。默认超时时间为 5 秒。

标志:

标志说明
-n, --name按设备名称子字符串筛选结果。
-S, --service按广播的服务 UUID 筛选。可重复使用。
-R, --rssi-minRSSI 最低阈值(例如 -R -70)。
-i, --id仅显示具有此标识符的设备。
-m, --manufacturer按制造商 ID 筛选。
-p, --pick选择方式:strongest、first、only。
-w, --watch持续扫描并实时更新设备列表。运行至 Ctrl-C 或 -t 超时为止。文本模式下需要 TTY;若要通过管道传递输出,请使用 -o kv。

输出列(文本): ID、名称、RSSI、信号(可视化条形图)、服务

“服务”列中的标准 Bluetooth SIG 服务 UUID 会显示其易读名称,例如:180F (Battery Service), 180A (Device Information)。

示例:

% blew scan                          # Scan for 5 seconds
% blew -t 10 scan                    # Scan for 10 seconds
% blew scan -w                       # Continuously scan until Ctrl-C
% blew -t 30 scan -w                 # Watch for 30 seconds then stop
% blew scan -n "Heart" -w            # Watch for Heart Rate devices
% blew scan -S 180D -R -65           # Heart Rate service, RSSI ≥ -65 dBm
% blew -o kv scan                    # Machine-readable output
% blew -o kv scan -w                 # Stream device updates (piping-friendly)

connect — 连接设备
blew connect [-n <name>] [-S <uuid>] [-i <id>] [<device-id>]

显式连接到 BLE 设备后退出。可用于测试连接,或在 exec 脚本中预先建立连接。可通过位置参数、--id 或设备定位筛选条件指定设备(工具会进行短暂扫描来确定目标)。

对于 gatt、read、write 和 sub,无需先运行 connect——这些命令会使用相同的设备定位选项自动连接。

退出时会自动关闭连接。

示例:

% blew connect F3C2A1B0-...          # Test connectivity to an explicit ID
% blew connect -n "Thingy"           # Test connectivity by name
% blew connect -S 180F               # Connect to device advertising Battery Service

gatt — 检查 GATT 结构

如果当前没有活动连接,gatt 会自动连接。使用 --id、--name 或其他设备指定选项指定目标设备。

所有 UUID 输出都包含 Bluetooth SIG 标准 UUID 的易读名称。自定义或厂商 UUID 将按原样显示。

gatt svcs — 列出服务
blew gatt svcs [-n <name>] [-i <id>]

列出所有已发现的服务。输出列:UUID、名称、是否为主服务。

UUID   Name                  Primary
------------------------------------
180F   Battery Service       yes
180A   Device Information    yes
FFF0                         yes
gatt tree — 显示完整的 GATT 树
blew gatt tree [-n <name>] [-i <id>] [-d] [-r]

输出服务及其特征,并显示属性(读取 / 写入 / 通知 / 指示)。标准 UUID 会同时显示其易读名称。

Service 180F  Battery Service
├── 2A19  Battery Level  [read, notify]
│   └── 2902  Client Characteristic Configuration
└── FFF1  [read, write-without-response, notify]

Service FFF0
└── FFF1  [read, write-without-response, notify]
标志描述
-d, --descriptors同时显示每个特征的描述符。
-r, --read读取并内联显示所有可读特征的值。对于已知的 Bluetooth SIG 特征,会将其解码为自然类型(例如,将电池电量显示为整数,将制造商名称显示为字符串);其他特征则以十六进制显示。

使用 -r 时:

Service 180F  Battery Service
└── 2A19  Battery Level  [read, notify]  = 85

Service 180A  Device Information
├── 2A29  Manufacturer Name String  [read]  = Apple Inc.
└── 2A24  Model Number String  [read]  = MacBookPro18,3
gatt chars — 列出服务的特征
blew gatt chars [-n <name>] [-i <id>] [-r] <service-uuid>

输出列:UUID、名称、属性。

标志描述
-r, --read读取并显示所有可读特征的值。在表格中添加“值”列;不可读特征对应的单元格为空。
gatt desc — 列出特征的描述符
blew gatt desc [-n <name>] [-i <id>] <char-uuid>

输出列:UUID、名称。

gatt info — 显示特征的 Bluetooth SIG 规范
blew gatt info <char-uuid>

显示任何标准特征 UUID 的 Bluetooth SIG 名称、描述和字段级结构。无需连接设备——该命令会直接从生成的特征数据库中读取信息。

$ blew gatt info 2A37
Heart Rate Measurement (2A37)

The Heart Rate Measurement characteristic is used to represent data related to a heart rate measurement.

Structure:
  Flags                                             boolean[8]  1 byte
  Heart Rate Measurement Value (8 bit resolution)   uint8       1 byte  [present if bit 0 of Flags is 0]
  Heart Rate Measurement Value (16 bit resolution)  uint16      2 bytes  [present if bit 0 of Flags is 1]
  Energy Expended                                   uint16      2 bytes  [present if bit 3 of Flags is 1]
  RR-interval                                       opaque      variable (array)  [present if bit 4 of Flags is 1]

结构体类型的字段(例如嵌入的 Date Time)会递归内联显示,并使用点分隔名称:

$ blew gatt info 2A0A
Day Date Time (2A0A)

The Day Date Time characteristic is used to represent weekday, date, and time.

Structure:
  Date Time.Year           uint16  2 bytes
  Date Time.Month          uint8   1 byte
  Date Time.Day            uint8   1 byte
  Date Time.Hours          uint8   1 byte
  Date Time.Minutes        uint8   1 byte
  Date Time.Seconds        uint8   1 byte
  Day of Week.Day of Week  uint8   1 byte

使用 -o kv 时,会为每个字段输出一条记录(适用于脚本处理)。

示例:

% blew gatt tree -n "Thingy"
% blew gatt tree -n "Thingy" -d        # Include descriptors
% blew gatt tree -n "Thingy" -r        # Read values for readable characteristics
% blew gatt tree -n "Thingy" -dr       # Descriptors + values
% blew gatt chars -n "Thingy" 180F
% blew gatt chars -n "Thingy" -r 180A  # Read values for Device Information
% blew gatt desc -n "Thingy" 2A19

read — 读取特征值
blew read [-n <name>] [-i <id>] [-f <format>] <char-uuid>

读取特征值,并以指定格式输出。如果当前没有活动连接,则自动连接。

标志描述
-f, --format <fmt>输出格式(参见下表)。默认值:hex。

格式:

格式描述
hex十六进制字符串(默认)
utf8UTF-8 字符串
base64Base64 编码字符串
uint8无符号 8 位整数
uint16le小端序无符号 16 位整数
uint32le小端序无符号 32 位整数
float32le小端序 32 位浮点数
raw原始字节

示例:

% blew read -n "Thingy" -f uint8 2A19     # Battery level as integer
% blew read -n "Thingy" -f utf8 2A29      # Manufacturer name string
% blew read -n "Thingy" fff1              # Raw characteristic as hex

write — 向特征写入数据
blew write [-n <name>] [-i <id>] [-f <format>] [-r|-w] <char-uuid> <data>

向特征写入数据。如果当前没有活动连接,则自动连接。除非另行指定,否则会根据特征的属性自动选择写入模式(有响应或无响应)。

标志描述
-f, --format <fmt>数据格式(与 read 相同)。默认值:hex。
-r, --with-response强制使用有响应写入。
-w, --without-response强制使用无响应写入。

示例:

% blew write -n "Thingy" fff1 "deadbeef"           # Write hex bytes
% blew write -n "Thingy" -f uint8 -r 2A06 1        # Write uint8 with response
% blew write -n "Thingy" -f utf8 fff2 "hello"      # Write a UTF-8 string

sub — 订阅通知或指示
blew sub [-n <name>] [-i <id>] [-f <format>] [-d <sec>] [-c <count>] [-b] <char-uuid>

订阅特征,并将收到的值逐行写入标准输出。若当前没有活动连接,则会自动连接。按 Ctrl-C 停止,或在达到持续时间/数量上限时停止。

标志说明
-f, --format <fmt>值格式(与 read 的可选值相同)。默认值:hex。
-d, --duration <sec>在指定秒数后停止。
-c, --count <n>收到指定数量的通知后停止。
-b, --bg在后台运行(仅限 REPL 和 exec 模式)。立即返回提示符;通知到达时会打印。使用 sub stop 取消。

使用 --out kv 时,每行包含 ts=、char= 和 value= 字段。

后台模式(-b)在 REPL 和 exec 脚本中可用。可以同时订阅多个特征。后台通知会通过 stderr 和 ANSI 光标控制打印,因此能够清晰地显示在提示符上方:

blew> sub -b -f uint8 2A19
Subscribing to 2A19 (Battery Level) in background. Use 'sub stop 2A19' to stop.
blew> sub -b fff1
Subscribing to fff1 in background. Use 'sub stop fff1' to stop.
blew> sub status
Active background subscriptions:
  2A19 (Battery Level)
  fff1
blew> sub stop 2A19
Stopped subscription for 2A19 (Battery Level).
blew> sub stop
Stopped all background subscriptions.

示例:

% blew sub -n "Thingy" fff1                        # Stream indefinitely (Ctrl-C to stop)
% blew sub -n "Thingy" -f uint16le -d 30 fff1      # 30-second capture as uint16
% blew -o kv sub -n "Thingy" -c 100 2A37           # Capture 100 events, kv output
% blew -o kv sub -n "Thingy" fff1 >> data.log      # Append to a log file

交互式 REPL

不带参数(或仅带全局选项但不带子命令)运行 blew,即可启动交互式 REPL:

% blew
% blew -v           # Start verbose REPL

REPL 提供:

  • 行编辑 — 光标移动、Ctrl-A/E、Ctrl-W 等。
  • 持久化历史记录 — 会在各会话间保存到 ~/.config/blew/history
  • Tab 补全 — 命令、GATT 发现后的已知 UUID,以及格式名称
REPL 命令
命令说明
scan [options]扫描设备
connect [<id>]连接设备
disconnect断开连接
status显示连接状态
gatt svcs|tree|chars|desc|info检查 GATT
read [-f <fmt>] <uuid>读取特征
write [-f <fmt>] [-r|-w] <uuid> <data>写入特征
sub [-f <fmt>] [-d <s>] [-c <n>] <uuid>订阅通知(按 Ctrl-C 停止)
sub [-b] [-f <fmt>] [-d <s>] [-c <n>] <uuid>在后台订阅;提示符仍可使用
sub stop [<uuid>]停止一个或所有后台订阅
sub status列出活动的后台订阅
periph adv [-n <n>] [-S <uuid>] [--config <f>]以虚拟外围设备身份开始广播
periph clone [--save <f>]克隆真实设备的 GATT
periph stop停止广播
periph set [-f <fmt>] <uuid> <val>更新特征值
periph notify [-f <fmt>] <uuid> <val>向订阅者推送通知
periph status显示外围设备的广播状态
help显示可用命令
quit / exit退出 REPL

会话示例:

blew> scan -t 3 -n Thingy
ID                                    NAME    RSSI  Signal    Services
-------------------------------------------------------------------------------------------
F3C2A1B0-1234-5678-ABCD-000000000001  Thingy  -58   ████████  180F (Battery Service), 180A (Device Information)

blew> connect F3C2A1B0-1234-5678-ABCD-000000000001

blew> gatt tree
Service 180F  Battery Service
└── 2A19  Battery Level  [read, notify]

Service 180A  Device Information
└── 2A29  Manufacturer Name String  [read]

blew> read -f uint8 2A19
87

blew> sub -f uint8 -c 5 2A19
87
86
86
85
85

blew> quit

脚本执行(exec)

exec 子命令会在单个进程中运行以分号分隔的命令序列,并共享同一连接生命周期。命令的解析方式与 REPL 完全相同。第一个需要连接的命令会触发自动连接;后续命令会复用该连接。

% blew exec "connect -n Thingy; gatt tree; read -f uint8 2A19"

标志:

标志说明
-k, --keep-going命令出错后继续;退出时返回遇到的第一个非零代码。
--dry-run打印解析后的步骤,但不执行。

exec 和 REPL 中可用的其他命令:

命令说明
sleep <seconds>暂停指定秒数。0 表示无限期暂停(直到按 Ctrl-C)。

示例:

# Connect by name, read a value
% blew exec "connect -n Thingy; read -f uint8 2A19"

# Wait 2 seconds between operations
% blew exec "connect -n Thingy; sleep 2; read -f uint8 2A19"

# Keep going after errors
% blew exec -k "read fff1; read fff9"

# Preview what would run
% blew exec --dry-run "connect -n Thingy; gatt tree; read -f uint8 2A19"

输出与日志

stdout 与 stderr
流内容
stdout命令结果 — 表格、值、通知行
stderr操作消息(错误、详细信息、调试信息)
日志格式(stderr)

始终打印错误:

Error: timeout waiting for connection

使用 -v 时,也会显示信息性消息:

connecting to F3C2A1B0-...
connected to F3C2A1B0-...

使用 -vv 时,会添加调试级别的消息:

[debug] discovered service 180F
[debug] discovered characteristic 2A19
键值输出(--out kv)

传入 -o kv 可获取机器可解析的输出。每条记录占一行,包含以空格分隔的 key=value 键值对(含空格的值会加引号)。便于使用 awk、grep 或任何日志解析器处理:

id=F3C2A1B0-... name=Thingy rssi=-58 services=180F,180A
char=2A19 name="Battery Level" value=57 fmt=uint8
ts=2026-02-21T12:34:56.789Z char=fff1 value=deadbeef

当 UUID 是已知的 Bluetooth SIG UUID 时,会包含 name= 字段。对于自定义 UUID 或厂商 UUID,则省略该字段。

% blew -n "Thingy" -o kv sub -d 60 fff1 | awk -F'value=' '{print $2}'

退出代码

代码含义
0成功
2未找到/没有匹配的设备
3Bluetooth 不可用或权限被拒绝
4超时
5操作失败(连接/GATT/读取/写入/订阅)
6参数无效

periph — 外设(GATT 服务端)模式

periph 可将 Mac 变为虚拟 BLE 外设,附近的设备可以连接到它、读取/写入数据并订阅。

CoreBluetooth 外设限制: 只能广播本地设备名称和服务 UUID。无法通过外设 API 设置厂商数据和其他 ADV 载荷字段。ADV 间隔、TX 功率和连接参数由操作系统控制。

广播名称与主机名: macOS 始终将计算机主机名用作 GAP(通用访问配置文件)设备名称。此前连接过该 Mac 的 iOS 扫描器会在设备列表中显示缓存的 GAP 名称(主机名),而不是通过 -n 设置的广播名称。广播名称仍会出现在原始广播数据(kCBAdvDataLocalName)中,并且点按设备后可在 LightBlue 的“Advertisement Data”下查看。

大多数标准 Bluetooth SIG 服务 UUID 都支持短格式(例如 180D、1809、181A)。不过,macOS 自身作为外设公开的服务无法使用短格式——CBPeripheralManager 会对 1800(通用访问)、1801(通用属性)、1805(当前时间)、180A(设备信息)、180F(电池)、1812(HID)和 181E(绑定管理)返回“The specified UUID is not allowed for this operation.”。使用完整的 128 位 Bluetooth 基础 UUID 格式(例如 0000180F-0000-1000-8000-00805F9B34FB)可绕过此检查,但注册后会成为原始 128 位 UUID,因此中心设备无法将其识别为标准服务。

periph adv — 广播并托管 GATT 服务端
blew periph adv [-n <name>] [-S <uuid>] [--config <file>]

开始广播并持续运行,直到收到中断信号(Ctrl-C)。事件(读取、写入、订阅)会记录到 stdout。

标志说明
-n, --name <name>广播的设备名称。默认为 blew。
-S, --service <uuid>要广播的服务 UUID,可重复指定。
-c, --config <file>定义服务和特征的 JSON 配置文件。

配置文件格式:

{
  "name": "My Device",
  "services": [
    {
      "uuid": "180F",
      "primary": true,
      "characteristics": [
        {
          "uuid": "2A19",
          "properties": ["read", "notify"],
          "value": "55",
          "format": "uint8"
        }
      ]
    }
  ]
}

properties 可包含:read、write、writeWithoutResponse、notify、indicate。 format 接受与 read/write 中 --format 相同的值:hex(默认)、utf8、uint8、uint16le、uint32le、float32le、base64、raw。

示例:

# Advertise a name + service UUID (scanner-visible, no GATT characteristics)
% blew periph adv -n "My Sensor" -S 180F

# Multiple service UUIDs
% blew periph adv -n "My Sensor" -S 180F -S 180A

# Full GATT server from a config file
% blew periph adv --config device.json

# Config file with name override
% blew periph adv -n "Override Name" --config device.json

Examples/ 目录中提供了示例配置文件:

文件说明
health-thermometer.json健康温度计(1809)——指示温度测量值(2A1C)、读取温度类型(2A1D)、读取/写入/通知测量间隔(2A21)
environmental-sensing.json环境感测(181A)——读取/通知温度(2A6E)、湿度(2A6F)和气压(2A6D)
blood-pressure.json血压(1810)——指示测量值(2A35)、读取特征标志(2A49)
custom-sensor.json完全自定义的厂商服务,使用 128 位 UUID——读取/通知数值、读取/写入配置寄存器、仅写入命令端点

输出(文本模式):

Advertising "My Sensor" [180F (Battery Service)]
  Service 180F (Battery Service)
  +-- 2A19 (Battery Level) [read, notify]

[12:34:56] central A1B2C3D4 connected
[12:34:56] read 2A19 (Battery Level) by A1B2C3D4
[12:34:57] subscribe 2A19 (Battery Level) by A1B2C3D4
[12:35:01] write 2A19 (Battery Level) by A1B2C3D4 <- 2a
^C
Stopped advertising.

输出(kv 模式):

event=connected ts=12:34:56 central=A1B2C3D4-...
event=read ts=12:34:56 central=A1B2C3D4-... char=2A19
event=subscribe ts=12:34:57 central=A1B2C3D4-... char=2A19
event=write ts=12:35:01 central=A1B2C3D4-... char=2A19 value=2a
periph clone — 克隆真实设备
blew periph clone [-n <name>] [-i <id>] [--save <file>]

连接到目标设备,发现其完整 GATT 树,读取所有可读特征值,然后断开连接并开始以克隆设备的身份广播。

标志描述
-n, --name目标设备名称筛选条件。
-i, --id目标设备标识符。
-o, --save <file>将克隆的 GATT 结构保存到 JSON 配置文件,以便日后复用。

克隆范围:

  • 已克隆:广播名称、服务 UUID、完整 GATT 结构、初始特征值(适用于可读特征)。
  • 未克隆:制造商数据、ADV 负载中的服务数据、ADV 时序。

示例:

% blew periph clone -n "Heart Rate Monitor"
% blew periph clone -i F3C2A1B0-... --save hr-monitor.json
仅限 REPL 的 periph 命令

在 REPL 和 exec 模式下,periph adv 和 periph clone 分两个阶段运行。启动阶段(配置 + 开始广播)为同步操作,并确认外设已启动。确认广播后,事件循环会作为后台任务运行,并立即返回提示符。这样便可在同一会话中使用 periph stop、periph set 和 periph notify:

命令描述
periph stop停止广播并取消后台事件任务。
periph set [-f <fmt>] <char> <val>更新特征的存储值。
periph notify [-f <fmt>] <char> <val>更新值并向所有订阅者推送通知。
periph status显示广播状态、服务/特征数量和订阅者数量。
blew> periph adv --config device.json
Advertising "My Device" [180F]
Advertising in background. Use 'periph stop' to stop.
blew> periph notify -f uint8 2A19 42
blew> periph stop
Stopped advertising.

在 exec 模式下,同样采用非阻塞行为,因此可以运行如下脚本:

% blew exec "periph adv -n 'My Device' --config device.json; periph set 2A19 ff; periph notify 2A19 ff"

MCP 服务模式

blew mcp 会通过标准输入/输出启动 Model Context Protocol 服务,并将所有 BLE 操作作为独立的 MCP 工具提供。AI Agent(Cursor、Claude Desktop 等)可以发现并调用这些工具,以编程方式与 BLE 设备交互。

该服务具有状态:BLE 连接和外设状态会在工具调用之间保留,就像 REPL 一样。工具结果以结构化 JSON(structuredContent)形式返回,让 Agent 能够以类型化方式访问扫描结果、GATT 数据、读取值等。

Agent 配置

Cursor(.cursor/mcp.json):

{
  "mcpServers": {
    "blew": {
      "command": "/path/to/blew",
      "args": ["mcp"]
    }
  }
}

Claude Desktop(claude_desktop_config.json):

{
  "mcpServers": {
    "blew": {
      "command": "/path/to/blew",
      "args": ["mcp"]
    }
  }
}
可用工具
工具描述
ble_scan扫描附近的 BLE 设备
ble_connect按 ID、名称或筛选条件连接设备
ble_disconnect断开与当前设备的连接
ble_status显示连接状态
ble_gatt_services列出 GATT 服务
ble_gatt_tree完整 GATT 树,可选包含值
ble_gatt_chars列出服务的特征
ble_gatt_descriptors列出特征的描述符
ble_gatt_info查询 Bluetooth SIG 特征规范(无需设备)
ble_read读取特征值
ble_write写入特征值
ble_subscribe收集通知(返回批次)
ble_periph_advertise以外设身份开始广播
ble_periph_clone克隆真实设备的 GATT 结构
ble_periph_stop停止广播
ble_periph_set更新外设特征值
ble_periph_notify更新值并通知订阅者
ble_periph_status显示外设状态

所有与远程设备交互的工具都支持可选的目标参数(name、device_id、service、manufacturer、rssi_min、pick),并会在尚未连接时自动连接。

结构化输出示例

ble_scan 调用返回:

{
  "type": "devices",
  "devices": [
    {
      "id": "A1B2C3D4-...",
      "name": "Heart Rate Sensor",
      "rssi": -55,
      "serviceUUIDs": ["180D"],
      "serviceDisplayNames": ["Heart Rate"]
    }
  ]
}

ble_read 调用返回:

{
  "type": "readValue",
  "readValue": {
    "char": "2A19",
    "name": "Battery Level",
    "value": "85",
    "format": "uint8"
  }
}

用法示例

在拥挤环境中查找设备
% blew scan -n "Sensor" -S 180F -R -65 -t 10
将传感器数据捕获到文件
% blew -o kv sub -n "Sensor" -f uint16le -d 300 fff1 >> sensor.log
一行快速审查 GATT
% blew gatt tree -n "Thingy" -d
检查包含值的设备信息特征
% blew gatt chars -n "Thingy" -r 180A
使用脚本读取
% value=$(blew read -n "Thingy" -f uint8 2A19)
% echo "Battery: ${value}%"
使用 --pick only 防止意外匹配多个设备
% blew read -n "Thingy" -p only -f uint8 2A19
# Errors out if more than one "Thingy" is nearby

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。