Brings Web Bluetooth to iPhone Safari by wrapping the WebBLE extension SDK. Lets Claude scan for BLE devices, connect to them, and read or write GATT characteristics directly from chat. You'd use this when building iOS web apps that talk to heart rate monitors, fitness trackers, or any Bluetooth LE peripheral, and you want AI help writing the scanning filters, connection logic, or characteristic parsing code. Handles the iOS Safari quirks and extension detection automatically. The underlying SDK is 4KB gzipped and supports typed profiles for common devices, React hooks, and proper error codes with suggestions. Good for prototyping BLE integrations or debugging why your device won't pair.
Web Bluetooth SDK for iOS Safari. Scan, connect, and talk to BLE devices from any web app.
| Package | Purpose | Size |
|---|---|---|
@ios-web-bluetooth/core | BLE scanning, connecting, GATT read/write/subscribe | ~4KB gzip |
@ios-web-bluetooth/detect | iOS extension detection + install banner | ~2KB gzip |
@ios-web-bluetooth/profiles | Typed BLE profiles (heart rate, battery, etc.) | Optional |
@ios-web-bluetooth/react | React hooks (useDevice, useCharacteristic) | Optional |
@ios-web-bluetooth/cli | CLI tooling | Optional |
@ios-web-bluetooth/mcp | MCP server for AI coding agents | Optional |
npm install @ios-web-bluetooth/core @ios-web-bluetooth/detect
import { initIOSWebBLE, isIOSSafari } from '@ios-web-bluetooth/detect';
import { WebBLE, WebBLEError } from '@ios-web-bluetooth/core';
// 1. On iOS Safari, detect the extension and prompt install if missing
if (isIOSSafari()) {
await initIOSWebBLE({
operatorName: 'MyApp',
banner: { mode: 'sheet' },
onReady: () => console.log('Extension ready'),
});
}
// 2. Scan and connect (works on iOS Safari + Chrome + Edge)
const ble = new WebBLE();
const device = await ble.requestDevice({
filters: [{ services: ['heart_rate'] }],
});
await device.connect();
// 3. Read a value
const value = await device.read('heart_rate', 'heart_rate_measurement');
console.log('Heart rate:', value.getUint8(1));
// 4. Subscribe to notifications
const unsub = device.subscribe('heart_rate', 'heart_rate_measurement', (v) => {
console.log('Heart rate:', v.getUint8(1));
});
// 5. Clean up
unsub();
await device.disconnect();
For plain HTML (no bundler):
<script src="https://ioswebble.com/webble.js"></script>
All errors are WebBLEError instances with a typed code and a human-readable suggestion:
try {
const device = await ble.requestDevice({
filters: [{ services: ['heart_rate'] }],
});
await device.connect();
} catch (err) {
if (err instanceof WebBLEError) {
console.log(err.code); // e.g. 'DEVICE_NOT_FOUND'
console.log(err.suggestion); // 'No matching devices in range'
}
}
MCP server for coding agents (Claude Code, Cursor, Copilot):
npx -y @ios-web-bluetooth/mcp
Full SDK reference for LLM context: https://ioswebble.com/llms-full.txt
Each package has its own README with full API reference:
@ios-web-bluetooth/core README -- scanning, connecting, GATT operations, error codes@ios-web-bluetooth/detect README -- extension detection, install banners, React provider@ios-web-bluetooth/react README -- React hooks, provider setup, and UI componentsProprietary. See individual package licenses.
inditextech/mcp-server-simulator-ios-idb
mobile-next/mobile-mcp
alexgladkov/claude-in-mobile
srmorete/mobile-device-mcp