Add Astro/Starlight documentation site
23-page docs site following diataxis principles with guides, reference, and explanation sections covering all 61 MCP tools. Bluetooth-themed design with Pagefind search.
This commit is contained in:
parent
e9f06173c5
commit
9d1c0f3e0f
21
docs-site/.gitignore
vendored
Normal file
21
docs-site/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
# generated types
|
||||||
|
.astro/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# environment variables
|
||||||
|
.env
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
||||||
49
docs-site/README.md
Normal file
49
docs-site/README.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Starlight Starter Kit: Basics
|
||||||
|
|
||||||
|
[](https://starlight.astro.build)
|
||||||
|
|
||||||
|
```
|
||||||
|
npm create astro@latest -- --template starlight
|
||||||
|
```
|
||||||
|
|
||||||
|
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||||
|
|
||||||
|
## 🚀 Project Structure
|
||||||
|
|
||||||
|
Inside of your Astro + Starlight project, you'll see the following folders and files:
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── public/
|
||||||
|
├── src/
|
||||||
|
│ ├── assets/
|
||||||
|
│ ├── content/
|
||||||
|
│ │ └── docs/
|
||||||
|
│ └── content.config.ts
|
||||||
|
├── astro.config.mjs
|
||||||
|
├── package.json
|
||||||
|
└── tsconfig.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name.
|
||||||
|
|
||||||
|
Images can be added to `src/assets/` and embedded in Markdown with a relative link.
|
||||||
|
|
||||||
|
Static assets, like favicons, can be placed in the `public/` directory.
|
||||||
|
|
||||||
|
## 🧞 Commands
|
||||||
|
|
||||||
|
All commands are run from the root of the project, from a terminal:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
| :------------------------ | :----------------------------------------------- |
|
||||||
|
| `npm install` | Installs dependencies |
|
||||||
|
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||||
|
| `npm run build` | Build your production site to `./dist/` |
|
||||||
|
| `npm run preview` | Preview your build locally, before deploying |
|
||||||
|
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||||
|
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||||
|
|
||||||
|
## 👀 Want to learn more?
|
||||||
|
|
||||||
|
Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).
|
||||||
85
docs-site/astro.config.mjs
Normal file
85
docs-site/astro.config.mjs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// @ts-check
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
import starlight from '@astrojs/starlight';
|
||||||
|
import icon from 'astro-icon';
|
||||||
|
|
||||||
|
// https://astro.build/config
|
||||||
|
export default defineConfig({
|
||||||
|
// Site URL for sitemap generation
|
||||||
|
site: 'https://mcbluetooth.example.com',
|
||||||
|
|
||||||
|
// Disable telemetry
|
||||||
|
telemetry: false,
|
||||||
|
|
||||||
|
// Disable devToolbar
|
||||||
|
devToolbar: { enabled: false },
|
||||||
|
|
||||||
|
integrations: [
|
||||||
|
icon(),
|
||||||
|
starlight({
|
||||||
|
title: 'mcbluetooth',
|
||||||
|
description: 'Give LLMs control of your Linux Bluetooth stack',
|
||||||
|
logo: {
|
||||||
|
light: './src/assets/logo-light.svg',
|
||||||
|
dark: './src/assets/logo-dark.svg',
|
||||||
|
replacesTitle: false,
|
||||||
|
},
|
||||||
|
social: [
|
||||||
|
{ icon: 'github', label: 'GitHub', href: 'https://github.com/yourusername/mcbluetooth' },
|
||||||
|
],
|
||||||
|
customCss: [
|
||||||
|
'./src/styles/custom.css',
|
||||||
|
],
|
||||||
|
head: [
|
||||||
|
// Favicon
|
||||||
|
{ tag: 'link', attrs: { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' } },
|
||||||
|
],
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
label: 'Getting Started',
|
||||||
|
items: [
|
||||||
|
{ label: 'Introduction', slug: 'getting-started/introduction' },
|
||||||
|
{ label: 'Installation', slug: 'getting-started/installation' },
|
||||||
|
{ label: 'Quick Start', slug: 'getting-started/quick-start' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Guides',
|
||||||
|
items: [
|
||||||
|
{ label: 'Adapter Management', slug: 'guides/adapters' },
|
||||||
|
{ label: 'Device Pairing', slug: 'guides/pairing' },
|
||||||
|
{ label: 'Audio Control', slug: 'guides/audio' },
|
||||||
|
{ label: 'BLE & GATT', slug: 'guides/ble' },
|
||||||
|
{ label: 'OBEX File Transfer', slug: 'guides/obex' },
|
||||||
|
{ label: 'Phonebook & Messages', slug: 'guides/phonebook-messages' },
|
||||||
|
{ label: 'Protocol Capture', slug: 'guides/capture' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Reference',
|
||||||
|
items: [
|
||||||
|
{ label: 'All Tools', slug: 'reference/tools' },
|
||||||
|
{ label: 'Adapter Tools', slug: 'reference/adapter-tools' },
|
||||||
|
{ label: 'Device Tools', slug: 'reference/device-tools' },
|
||||||
|
{ label: 'Audio Tools', slug: 'reference/audio-tools' },
|
||||||
|
{ label: 'BLE Tools', slug: 'reference/ble-tools' },
|
||||||
|
{ label: 'OBEX Tools', slug: 'reference/obex-tools' },
|
||||||
|
{ label: 'Monitor Tools', slug: 'reference/monitor-tools' },
|
||||||
|
{ label: 'MCP Resources', slug: 'reference/resources' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Explanation',
|
||||||
|
items: [
|
||||||
|
{ label: 'Architecture', slug: 'explanation/architecture' },
|
||||||
|
{ label: 'Pairing Agent', slug: 'explanation/pairing-agent' },
|
||||||
|
{ label: 'OBEX Profiles', slug: 'explanation/obex-profiles' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
editLink: {
|
||||||
|
baseUrl: 'https://github.com/yourusername/mcbluetooth/edit/main/docs-site/',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
6988
docs-site/package-lock.json
generated
Normal file
6988
docs-site/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
docs-site/package.json
Normal file
19
docs-site/package.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "docs-site",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"start": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview",
|
||||||
|
"astro": "astro"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@astrojs/starlight": "^0.37.6",
|
||||||
|
"@iconify-json/lucide": "^1.2.87",
|
||||||
|
"astro": "^5.6.1",
|
||||||
|
"astro-icon": "^1.1.5",
|
||||||
|
"sharp": "^0.34.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
docs-site/public/favicon.svg
Normal file
5
docs-site/public/favicon.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
||||||
|
<circle cx="16" cy="16" r="14" fill="#0066cc"/>
|
||||||
|
<path d="M16 6 L16 26 M16 6 L22 12 L16 16 L22 22 L16 26 M16 16 L10 10 M16 16 L10 22"
|
||||||
|
stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 329 B |
BIN
docs-site/src/assets/houston.webp
Normal file
BIN
docs-site/src/assets/houston.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
5
docs-site/src/assets/logo-dark.svg
Normal file
5
docs-site/src/assets/logo-dark.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
||||||
|
<circle cx="16" cy="16" r="14" fill="#3399ff"/>
|
||||||
|
<path d="M16 6 L16 26 M16 6 L22 12 L16 16 L22 22 L16 26 M16 16 L10 10 M16 16 L10 22"
|
||||||
|
stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 329 B |
5
docs-site/src/assets/logo-light.svg
Normal file
5
docs-site/src/assets/logo-light.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
||||||
|
<circle cx="16" cy="16" r="14" fill="#0066cc"/>
|
||||||
|
<path d="M16 6 L16 26 M16 6 L22 12 L16 16 L22 22 L16 26 M16 16 L10 10 M16 16 L10 22"
|
||||||
|
stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 329 B |
7
docs-site/src/content.config.ts
Normal file
7
docs-site/src/content.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineCollection } from 'astro:content';
|
||||||
|
import { docsLoader } from '@astrojs/starlight/loaders';
|
||||||
|
import { docsSchema } from '@astrojs/starlight/schema';
|
||||||
|
|
||||||
|
export const collections = {
|
||||||
|
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
||||||
|
};
|
||||||
275
docs-site/src/content/docs/explanation/architecture.md
Normal file
275
docs-site/src/content/docs/explanation/architecture.md
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
---
|
||||||
|
title: Architecture
|
||||||
|
description: How mcbluetooth integrates with BlueZ, D-Bus, and the Linux Bluetooth stack
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Understanding mcbluetooth's architecture helps you troubleshoot issues and extend functionality.
|
||||||
|
|
||||||
|
## System Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ MCP Client (Claude, etc.) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ mcbluetooth │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
||||||
|
│ │ MCP Tools │ │ MCP Resources│ │ Pairing Agent │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐│
|
||||||
|
│ │ D-Bus Clients (async) ││
|
||||||
|
│ │ ┌──────────────┐ ┌──────────────────────┐ ││
|
||||||
|
│ │ │ BlueZClient │ │ ObexClient │ ││
|
||||||
|
│ │ │ (system bus) │ │ (session bus) │ ││
|
||||||
|
│ │ └──────────────┘ └──────────────────────┘ ││
|
||||||
|
│ └─────────────────────────────────────────────────────────┘│
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────┼───────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||||
|
│ BlueZ │ │ obexd │ │ PipeWire/ │
|
||||||
|
│ (bluetoothd) │ │ (session) │ │ PulseAudio │
|
||||||
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||||
|
│ │ │
|
||||||
|
└───────────────┼───────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Linux Kernel │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
||||||
|
│ │ Bluetooth │ │ btusb │ │ HCI driver │ │
|
||||||
|
│ │ subsystem │ │ module │ │ │ │
|
||||||
|
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Bluetooth Hardware │
|
||||||
|
│ (USB dongle, built-in) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Component Responsibilities
|
||||||
|
|
||||||
|
### mcbluetooth (MCP Server)
|
||||||
|
|
||||||
|
The MCP server layer that exposes Bluetooth functionality:
|
||||||
|
|
||||||
|
| Component | Purpose |
|
||||||
|
|-----------|---------|
|
||||||
|
| **MCP Tools** | 61 tools for Bluetooth operations |
|
||||||
|
| **MCP Resources** | Live state queries via URIs |
|
||||||
|
| **Pairing Agent** | Handles PIN/passkey negotiation |
|
||||||
|
| **D-Bus Clients** | Async communication with BlueZ/obexd |
|
||||||
|
|
||||||
|
### BlueZ (bluetoothd)
|
||||||
|
|
||||||
|
The official Linux Bluetooth stack daemon:
|
||||||
|
|
||||||
|
- Manages adapter hardware
|
||||||
|
- Handles device discovery and pairing
|
||||||
|
- Implements Bluetooth profiles (A2DP, HFP, etc.)
|
||||||
|
- Exposes D-Bus API on **system bus**
|
||||||
|
|
||||||
|
### obexd
|
||||||
|
|
||||||
|
OBEX protocol daemon for file transfer:
|
||||||
|
|
||||||
|
- Runs per-user (session daemon)
|
||||||
|
- Implements OPP, FTP, PBAP, MAP profiles
|
||||||
|
- Exposes D-Bus API on **session bus**
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
obexd requires an active desktop session because it runs on the session D-Bus.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
### PipeWire/PulseAudio
|
||||||
|
|
||||||
|
Audio server integration:
|
||||||
|
|
||||||
|
- Receives audio streams from BlueZ
|
||||||
|
- Provides volume, mute, routing controls
|
||||||
|
- Handles codec negotiation
|
||||||
|
|
||||||
|
## D-Bus Architecture
|
||||||
|
|
||||||
|
mcbluetooth communicates with two D-Bus buses:
|
||||||
|
|
||||||
|
### System Bus (BlueZ)
|
||||||
|
|
||||||
|
```
|
||||||
|
Service: org.bluez
|
||||||
|
Paths: /org/bluez
|
||||||
|
/org/bluez/hci0
|
||||||
|
/org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF
|
||||||
|
|
||||||
|
Interfaces:
|
||||||
|
org.bluez.Adapter1 - Adapter control
|
||||||
|
org.bluez.Device1 - Device management
|
||||||
|
org.bluez.GattService1 - BLE services
|
||||||
|
org.bluez.GattCharacteristic1 - BLE characteristics
|
||||||
|
org.bluez.AgentManager1 - Pairing agent registration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Session Bus (OBEX)
|
||||||
|
|
||||||
|
```
|
||||||
|
Service: org.bluez.obex
|
||||||
|
Paths: /org/bluez/obex
|
||||||
|
/org/bluez/obex/client/session0
|
||||||
|
/org/bluez/obex/client/session0/transfer0
|
||||||
|
|
||||||
|
Interfaces:
|
||||||
|
org.bluez.obex.Client1 - Session management
|
||||||
|
org.bluez.obex.Session1 - Session properties
|
||||||
|
org.bluez.obex.ObjectPush1 - OPP file sending
|
||||||
|
org.bluez.obex.FileTransfer1 - FTP operations
|
||||||
|
org.bluez.obex.PhonebookAccess1 - PBAP
|
||||||
|
org.bluez.obex.MessageAccess1 - MAP
|
||||||
|
```
|
||||||
|
|
||||||
|
## Async Design
|
||||||
|
|
||||||
|
mcbluetooth uses **dbus-fast** for non-blocking D-Bus communication:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Singleton pattern ensures one connection
|
||||||
|
class BlueZClient:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get_instance(cls):
|
||||||
|
if cls._instance is None:
|
||||||
|
cls._instance = cls()
|
||||||
|
await cls._instance._connect()
|
||||||
|
return cls._instance
|
||||||
|
```
|
||||||
|
|
||||||
|
Benefits:
|
||||||
|
- Multiple concurrent operations
|
||||||
|
- No blocking the MCP event loop
|
||||||
|
- Efficient resource usage
|
||||||
|
|
||||||
|
## Tool Registration
|
||||||
|
|
||||||
|
Tools are organized by functional area:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# server.py
|
||||||
|
from mcbluetooth.tools import adapter, audio, ble, device, monitor, obex
|
||||||
|
|
||||||
|
def create_server():
|
||||||
|
mcp = FastMCP("mcbluetooth")
|
||||||
|
|
||||||
|
adapter.register_tools(mcp)
|
||||||
|
audio.register_tools(mcp)
|
||||||
|
ble.register_tools(mcp)
|
||||||
|
device.register_tools(mcp)
|
||||||
|
monitor.register_tools(mcp)
|
||||||
|
obex.register_tools(mcp)
|
||||||
|
|
||||||
|
return mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Each module follows the pattern:
|
||||||
|
```python
|
||||||
|
# tools/device.py
|
||||||
|
def register_tools(mcp: FastMCP) -> None:
|
||||||
|
@mcp.tool()
|
||||||
|
async def bt_connect(adapter: str, address: str) -> dict:
|
||||||
|
"""Connect to a paired device."""
|
||||||
|
client = await BlueZClient.get_instance()
|
||||||
|
return await client.connect_device(adapter, address)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
D-Bus errors are translated to user-friendly messages:
|
||||||
|
|
||||||
|
| D-Bus Error | mcbluetooth Response |
|
||||||
|
|-------------|---------------------|
|
||||||
|
| `org.bluez.Error.Failed` | `{"error": "Operation failed", ...}` |
|
||||||
|
| `org.bluez.Error.NotReady` | `{"error": "Device not ready", ...}` |
|
||||||
|
| `org.bluez.Error.AuthenticationFailed` | `{"error": "Authentication failed", ...}` |
|
||||||
|
| `org.freedesktop.DBus.Error.ServiceUnknown` | `{"error": "BlueZ not running", ...}` |
|
||||||
|
|
||||||
|
## State Management
|
||||||
|
|
||||||
|
### BlueZ State
|
||||||
|
|
||||||
|
mcbluetooth doesn't cache BlueZ state — each query goes to D-Bus:
|
||||||
|
|
||||||
|
- Ensures fresh data
|
||||||
|
- Avoids stale state issues
|
||||||
|
- BlueZ handles the caching
|
||||||
|
|
||||||
|
### OBEX Sessions
|
||||||
|
|
||||||
|
OBEX sessions are tracked locally:
|
||||||
|
|
||||||
|
```python
|
||||||
|
_active_sessions: dict[str, dict] = {}
|
||||||
|
# session_id -> {path, address, target, created}
|
||||||
|
|
||||||
|
def generate_session_id(address: str, target: str) -> str:
|
||||||
|
"""Generate friendly ID: ftp_C87B235568E8"""
|
||||||
|
clean_addr = address.replace(":", "")
|
||||||
|
return f"{target}_{clean_addr}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pairing Agent
|
||||||
|
|
||||||
|
The pairing agent registers with BlueZ and handles callbacks:
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Agent registers with AgentManager1
|
||||||
|
2. BlueZ calls agent methods for pairing events
|
||||||
|
3. Agent handles PIN/passkey based on pairing_mode
|
||||||
|
4. Results returned to BlueZ
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### D-Bus Call Overhead
|
||||||
|
|
||||||
|
Each tool call involves:
|
||||||
|
1. MCP request parsing
|
||||||
|
2. D-Bus method call (async)
|
||||||
|
3. Response serialization
|
||||||
|
|
||||||
|
Typical latency: 1-10ms per call.
|
||||||
|
|
||||||
|
### Scanning
|
||||||
|
|
||||||
|
Discovery is resource-intensive:
|
||||||
|
- `bt_scan` starts/stops discovery explicitly
|
||||||
|
- Avoids continuous scanning
|
||||||
|
- Timeout prevents runaway scans
|
||||||
|
|
||||||
|
### Large Transfers
|
||||||
|
|
||||||
|
OBEX transfers use polling for progress:
|
||||||
|
```python
|
||||||
|
while True:
|
||||||
|
status = await get_transfer_status(transfer_path)
|
||||||
|
if status["status"] in ("complete", "error"):
|
||||||
|
return status
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Model
|
||||||
|
|
||||||
|
| Layer | Security |
|
||||||
|
|-------|----------|
|
||||||
|
| MCP | Trust boundary at MCP client |
|
||||||
|
| D-Bus | PolicyKit for privileged ops |
|
||||||
|
| BlueZ | Pairing provides encryption |
|
||||||
|
| OBEX | Session-based access |
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
mcbluetooth inherits the permissions of its running user. System-level operations require appropriate D-Bus policies.
|
||||||
|
</Aside>
|
||||||
353
docs-site/src/content/docs/explanation/obex-profiles.md
Normal file
353
docs-site/src/content/docs/explanation/obex-profiles.md
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
---
|
||||||
|
title: OBEX Profiles
|
||||||
|
description: Understanding OPP, FTP, PBAP, and MAP — the OBEX family of Bluetooth profiles
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
OBEX (Object Exchange) is a protocol for transferring objects over Bluetooth. Four profiles build on OBEX for specific use cases.
|
||||||
|
|
||||||
|
## What is OBEX?
|
||||||
|
|
||||||
|
OBEX is a binary protocol originally designed for infrared (IrDA) that was adapted for Bluetooth. It provides:
|
||||||
|
|
||||||
|
- Session-based connections
|
||||||
|
- Request/response pattern
|
||||||
|
- Headers for metadata (name, type, length)
|
||||||
|
- Support for large object transfers
|
||||||
|
|
||||||
|
Think of it as "HTTP for Bluetooth" — a simple way to push and pull objects between devices.
|
||||||
|
|
||||||
|
## The Four OBEX Profiles
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
|
│ OBEX Protocol │
|
||||||
|
├──────────────────────────────────────────────────────────────┤
|
||||||
|
│ OPP │ FTP │ PBAP │ MAP │
|
||||||
|
│ (Push) │ (Files) │ (Contacts) │ (Messages) │
|
||||||
|
└──────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## OPP — Object Push Profile
|
||||||
|
|
||||||
|
**Purpose:** Simple file sending, like handing someone a file.
|
||||||
|
|
||||||
|
### Characteristics
|
||||||
|
|
||||||
|
- No session management needed
|
||||||
|
- One-shot transfers
|
||||||
|
- Receiver can accept or reject
|
||||||
|
- Minimal device interaction required
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
|
||||||
|
| Operation | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| Push | Send a file to device |
|
||||||
|
| Pull | Get device's business card |
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
|
||||||
|
- Send a photo to a friend
|
||||||
|
- Share a document
|
||||||
|
- Exchange contact cards
|
||||||
|
|
||||||
|
### mcbluetooth Tools
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="..." file_path="~/photo.jpg"
|
||||||
|
bt_obex_get_vcard address="..." save_path="~/contact.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
Almost universal — OPP is the most widely supported OBEX profile.
|
||||||
|
|
||||||
|
| Device | Support |
|
||||||
|
|--------|---------|
|
||||||
|
| Android | ✓ |
|
||||||
|
| iPhone | ✓ |
|
||||||
|
| Feature phones | ✓ |
|
||||||
|
| Windows | ✓ |
|
||||||
|
| macOS | ✓ |
|
||||||
|
|
||||||
|
## FTP — File Transfer Profile
|
||||||
|
|
||||||
|
**Purpose:** Browse and manage remote file systems.
|
||||||
|
|
||||||
|
### Characteristics
|
||||||
|
|
||||||
|
- Session-based (connect → browse → disconnect)
|
||||||
|
- Full file system operations
|
||||||
|
- Folder navigation
|
||||||
|
- Two-way transfers
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
|
||||||
|
| Operation | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| Connect | Create FTP session |
|
||||||
|
| List | Get folder contents |
|
||||||
|
| Get | Download file |
|
||||||
|
| Put | Upload file |
|
||||||
|
| Delete | Remove file/folder |
|
||||||
|
| Mkdir | Create folder |
|
||||||
|
| Setpath | Navigate folders |
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
|
||||||
|
- Backup phone photos
|
||||||
|
- Browse device storage
|
||||||
|
- Manage files on remote device
|
||||||
|
|
||||||
|
### mcbluetooth Tools
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_connect address="..." target="ftp"
|
||||||
|
bt_obex_browse session_id="ftp_..."
|
||||||
|
bt_obex_get session_id="..." remote_path="photo.jpg" local_path="~/photo.jpg"
|
||||||
|
bt_obex_put session_id="..." local_path="~/doc.pdf" remote_path="doc.pdf"
|
||||||
|
bt_obex_disconnect session_id="ftp_..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
More limited than OPP:
|
||||||
|
|
||||||
|
| Device | Support |
|
||||||
|
|--------|---------|
|
||||||
|
| Android | Varies by version/manufacturer |
|
||||||
|
| iPhone | ✗ |
|
||||||
|
| Feature phones | ✓ Usually |
|
||||||
|
| Windows | ✓ |
|
||||||
|
| macOS | ✗ |
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Android FTP support varies. Some versions require enabling "File Transfer" mode when connected via Bluetooth.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## PBAP — Phonebook Access Profile
|
||||||
|
|
||||||
|
**Purpose:** Read contacts from a phone.
|
||||||
|
|
||||||
|
### Characteristics
|
||||||
|
|
||||||
|
- Read-only access (mostly)
|
||||||
|
- Standardized folder structure
|
||||||
|
- vCard format output
|
||||||
|
- Search capabilities
|
||||||
|
|
||||||
|
### Folder Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
telecom/
|
||||||
|
├── pb/ ← Main phonebook
|
||||||
|
├── ich/ ← Incoming call history
|
||||||
|
├── och/ ← Outgoing call history
|
||||||
|
├── mch/ ← Missed call history
|
||||||
|
└── cch/ ← Combined call history
|
||||||
|
|
||||||
|
SIM1/
|
||||||
|
└── telecom/
|
||||||
|
└── pb/ ← SIM card contacts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
|
||||||
|
| Operation | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| PullAll | Download entire phonebook |
|
||||||
|
| List | Get contact handles |
|
||||||
|
| Pull | Get specific contact |
|
||||||
|
| Search | Find contacts by field |
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
|
||||||
|
- Sync contacts to car system
|
||||||
|
- Backup phone contacts
|
||||||
|
- Contact management applications
|
||||||
|
|
||||||
|
### mcbluetooth Tools
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_pull address="..." save_path="~/contacts.vcf"
|
||||||
|
bt_phonebook_list address="..." folder="telecom/pb"
|
||||||
|
bt_phonebook_search address="..." field="name" value="Smith"
|
||||||
|
bt_phonebook_count address="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
| Device | Support |
|
||||||
|
|--------|---------|
|
||||||
|
| Android | ✓ Full |
|
||||||
|
| iPhone | ✓ (when properly paired) |
|
||||||
|
| Feature phones | ✓ Usually |
|
||||||
|
| Car systems | ✓ Often |
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
PBAP is widely supported because car infotainment systems rely on it for contact syncing.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## MAP — Message Access Profile
|
||||||
|
|
||||||
|
**Purpose:** Access SMS/MMS messages.
|
||||||
|
|
||||||
|
### Characteristics
|
||||||
|
|
||||||
|
- Read messages from phone
|
||||||
|
- Some devices support sending
|
||||||
|
- Folder-based organization
|
||||||
|
- Notification of new messages
|
||||||
|
|
||||||
|
### Folder Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
telecom/
|
||||||
|
└── msg/
|
||||||
|
├── inbox/
|
||||||
|
├── outbox/
|
||||||
|
├── sent/
|
||||||
|
├── drafts/
|
||||||
|
└── deleted/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
|
||||||
|
| Operation | Description |
|
||||||
|
|-----------|-------------|
|
||||||
|
| GetFolderListing | List message folders |
|
||||||
|
| GetMessagesListing | List messages in folder |
|
||||||
|
| GetMessage | Download message content |
|
||||||
|
| PushMessage | Send message (if supported) |
|
||||||
|
| SetMessageStatus | Mark read/unread |
|
||||||
|
|
||||||
|
### Use Cases
|
||||||
|
|
||||||
|
- Read texts through car system
|
||||||
|
- Message backup
|
||||||
|
- SMS integration applications
|
||||||
|
|
||||||
|
### mcbluetooth Tools
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_messages_folders address="..."
|
||||||
|
bt_messages_list address="..." folder="inbox" unread_only=true
|
||||||
|
bt_messages_get address="..." handle="msg001" save_path="~/message.txt"
|
||||||
|
bt_messages_send address="..." recipient="+1555..." message="Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
Most limited of the OBEX profiles:
|
||||||
|
|
||||||
|
| Device | Read | Send |
|
||||||
|
|--------|------|------|
|
||||||
|
| Android | ✓ | Varies |
|
||||||
|
| iPhone | ✗ | ✗ |
|
||||||
|
| Car systems | ✓ (receive) | ✗ |
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
iPhone does not support MAP. Apple uses proprietary protocols for message sync.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Session Architecture
|
||||||
|
|
||||||
|
### OPP (Stateless)
|
||||||
|
|
||||||
|
```
|
||||||
|
Client Server
|
||||||
|
│ │
|
||||||
|
│────── CONNECT ─────────→│
|
||||||
|
│←───── SUCCESS ──────────│
|
||||||
|
│────── PUT file ────────→│
|
||||||
|
│←───── SUCCESS ──────────│
|
||||||
|
│────── DISCONNECT ──────→│
|
||||||
|
│ │
|
||||||
|
```
|
||||||
|
|
||||||
|
OPP creates temporary sessions for each transfer.
|
||||||
|
|
||||||
|
### FTP/PBAP/MAP (Session-Based)
|
||||||
|
|
||||||
|
```
|
||||||
|
Client Server
|
||||||
|
│ │
|
||||||
|
│────── CONNECT ─────────→│ ← Session created
|
||||||
|
│←───── SUCCESS ──────────│
|
||||||
|
│ │
|
||||||
|
│────── LIST ────────────→│
|
||||||
|
│←───── folder contents ──│
|
||||||
|
│ │
|
||||||
|
│────── GET file ────────→│
|
||||||
|
│←───── file data ────────│
|
||||||
|
│ │
|
||||||
|
│────── DISCONNECT ──────→│ ← Session closed
|
||||||
|
│ │
|
||||||
|
```
|
||||||
|
|
||||||
|
Sessions persist for multiple operations.
|
||||||
|
|
||||||
|
## obexd Architecture
|
||||||
|
|
||||||
|
mcbluetooth uses BlueZ's **obexd** daemon:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ mcbluetooth │
|
||||||
|
│ │ │
|
||||||
|
│ D-Bus (session) │
|
||||||
|
│ │ │
|
||||||
|
└────────────────────────┼────────────────────────────┘
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────┐
|
||||||
|
│ obexd │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||||
|
│ │ OPP │ │ FTP │ │ PBAP │ │ MAP │ │
|
||||||
|
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ RFCOMM/L2CAP │
|
||||||
|
└────────────────────────┼────────────────────────────┘
|
||||||
|
▼
|
||||||
|
Bluetooth Stack
|
||||||
|
```
|
||||||
|
|
||||||
|
obexd runs on the **session D-Bus** (not system bus), which means:
|
||||||
|
- Requires active desktop session
|
||||||
|
- Per-user isolation
|
||||||
|
- Integrates with user's file permissions
|
||||||
|
|
||||||
|
## Transfer Progress
|
||||||
|
|
||||||
|
OBEX transfers report progress via D-Bus properties:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Status": "active",
|
||||||
|
"Transferred": 52428800,
|
||||||
|
"Size": 104857600,
|
||||||
|
"Filename": "large_file.mp4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
mcbluetooth polls these properties to provide progress updates.
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Common OBEX errors:
|
||||||
|
|
||||||
|
| Error | Meaning |
|
||||||
|
|-------|---------|
|
||||||
|
| `NotSupported` | Profile not available on device |
|
||||||
|
| `NotAuthorized` | Permission denied |
|
||||||
|
| `NotFound` | File/folder doesn't exist |
|
||||||
|
| `Forbidden` | Operation not allowed |
|
||||||
|
| `Failed` | Generic failure |
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- OBEX uses Bluetooth encryption (if paired)
|
||||||
|
- Phone typically prompts for permission on first access
|
||||||
|
- Permission can be revoked in phone settings
|
||||||
|
- Sessions are tied to pairing relationship
|
||||||
276
docs-site/src/content/docs/explanation/pairing-agent.md
Normal file
276
docs-site/src/content/docs/explanation/pairing-agent.md
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
---
|
||||||
|
title: Pairing Agent
|
||||||
|
description: How mcbluetooth handles Bluetooth pairing with its smart agent
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Bluetooth pairing establishes trust between devices. mcbluetooth includes a pairing agent that handles all pairing methods automatically.
|
||||||
|
|
||||||
|
## What is a Pairing Agent?
|
||||||
|
|
||||||
|
In BlueZ, a **pairing agent** is a program that:
|
||||||
|
|
||||||
|
1. Registers with BlueZ's AgentManager
|
||||||
|
2. Receives callbacks during pairing
|
||||||
|
3. Responds to PIN/passkey requests
|
||||||
|
4. Confirms or rejects pairings
|
||||||
|
|
||||||
|
Without an agent, pairing requests fail because there's no program to handle the negotiation.
|
||||||
|
|
||||||
|
## Secure Simple Pairing (SSP)
|
||||||
|
|
||||||
|
Modern Bluetooth uses SSP with four association models:
|
||||||
|
|
||||||
|
### Just Works
|
||||||
|
|
||||||
|
**No user interaction required.**
|
||||||
|
|
||||||
|
- Used when one device has no display/keyboard
|
||||||
|
- Provides encryption but no MITM protection
|
||||||
|
- mcbluetooth auto-accepts these
|
||||||
|
|
||||||
|
**Example devices:** Simple speakers, mice, keyboards
|
||||||
|
|
||||||
|
### Numeric Comparison
|
||||||
|
|
||||||
|
**Both devices show 6-digit code; user confirms they match.**
|
||||||
|
|
||||||
|
```
|
||||||
|
Your device: 123456
|
||||||
|
Their device: 123456
|
||||||
|
Do they match? [Y/N]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Both devices have displays
|
||||||
|
- User verifies the numbers match
|
||||||
|
- Protects against MITM attacks
|
||||||
|
|
||||||
|
**Example devices:** Phones, computers, smart watches
|
||||||
|
|
||||||
|
### Passkey Entry
|
||||||
|
|
||||||
|
**One device displays code; user enters it on the other.**
|
||||||
|
|
||||||
|
```
|
||||||
|
Their device shows: 123456
|
||||||
|
Enter on your device: [______]
|
||||||
|
```
|
||||||
|
|
||||||
|
- One device has display, other has keyboard
|
||||||
|
- Code entry proves physical access
|
||||||
|
|
||||||
|
**Example devices:** Phone pairing with keyboard
|
||||||
|
|
||||||
|
### Legacy PIN
|
||||||
|
|
||||||
|
**Old-style 4-6 digit PIN entry.**
|
||||||
|
|
||||||
|
```
|
||||||
|
Enter PIN: [____]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Pre-SSP devices (Bluetooth 2.0 and earlier)
|
||||||
|
- Often uses "0000" or "1234"
|
||||||
|
|
||||||
|
**Example devices:** Older headsets, car systems
|
||||||
|
|
||||||
|
## mcbluetooth Pairing Modes
|
||||||
|
|
||||||
|
The `bt_pair` tool supports three modes:
|
||||||
|
|
||||||
|
### Interactive Mode (Default)
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="interactive"
|
||||||
|
```
|
||||||
|
|
||||||
|
1. mcbluetooth initiates pairing
|
||||||
|
2. Returns immediately with status
|
||||||
|
3. If confirmation needed, returns passkey/info
|
||||||
|
4. Use `bt_pair_confirm` to respond
|
||||||
|
|
||||||
|
**Flow:**
|
||||||
|
```
|
||||||
|
bt_pair → {"status": "awaiting_confirmation", "passkey": 123456}
|
||||||
|
↓
|
||||||
|
bt_pair_confirm passkey=123456 accept=true → {"status": "paired"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Best for: LLM-driven pairing where you want control over each step.
|
||||||
|
|
||||||
|
### Auto Mode
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="auto"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Automatically accepts all pairing requests
|
||||||
|
- No user confirmation required
|
||||||
|
- Just Works and auto-confirm numeric comparison
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Auto mode should only be used in trusted environments. It accepts pairings without verification.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
Best for: Automated testing, trusted lab environments.
|
||||||
|
|
||||||
|
### Elicit Mode
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="elicit"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Uses MCP elicitation to prompt user directly
|
||||||
|
- If MCP client supports elicitation, user sees prompt
|
||||||
|
- Falls back to interactive if not supported
|
||||||
|
|
||||||
|
Best for: Human-in-the-loop pairing with MCP clients that support elicitation.
|
||||||
|
|
||||||
|
## Agent Implementation
|
||||||
|
|
||||||
|
### Registration
|
||||||
|
|
||||||
|
mcbluetooth registers its agent at startup:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Register with BlueZ
|
||||||
|
agent_manager = await bus.get_proxy_object(
|
||||||
|
"org.bluez",
|
||||||
|
"/org/bluez"
|
||||||
|
).get_interface("org.bluez.AgentManager1")
|
||||||
|
|
||||||
|
await agent_manager.call_register_agent(
|
||||||
|
agent_path,
|
||||||
|
"KeyboardDisplay" # Capability
|
||||||
|
)
|
||||||
|
|
||||||
|
await agent_manager.call_request_default_agent(agent_path)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Capability Declaration
|
||||||
|
|
||||||
|
The agent declares "KeyboardDisplay" capability:
|
||||||
|
- Can display codes (for numeric comparison)
|
||||||
|
- Can accept input (for passkey entry)
|
||||||
|
- Maximizes pairing compatibility
|
||||||
|
|
||||||
|
### Callback Methods
|
||||||
|
|
||||||
|
The agent implements these D-Bus methods:
|
||||||
|
|
||||||
|
| Method | Called When |
|
||||||
|
|--------|-------------|
|
||||||
|
| `RequestPinCode` | Legacy PIN needed |
|
||||||
|
| `RequestPasskey` | Passkey entry needed |
|
||||||
|
| `DisplayPasskey` | Show passkey to user |
|
||||||
|
| `DisplayPinCode` | Show PIN to user |
|
||||||
|
| `RequestConfirmation` | Numeric comparison |
|
||||||
|
| `RequestAuthorization` | Just Works confirmation |
|
||||||
|
| `AuthorizeService` | Service-level auth |
|
||||||
|
| `Cancel` | Pairing cancelled |
|
||||||
|
| `Release` | Agent released |
|
||||||
|
|
||||||
|
## Handling Pending Requests
|
||||||
|
|
||||||
|
When pairing requires confirmation:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Store pending request
|
||||||
|
_pending_pairings[address] = {
|
||||||
|
"method": "numeric_comparison",
|
||||||
|
"passkey": 123456,
|
||||||
|
"timestamp": datetime.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return to bt_pair caller
|
||||||
|
return {
|
||||||
|
"status": "awaiting_confirmation",
|
||||||
|
"method": "numeric_comparison",
|
||||||
|
"passkey": 123456
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Later, `bt_pair_confirm` resolves it:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@mcp.tool()
|
||||||
|
async def bt_pair_confirm(adapter: str, address: str, accept: bool, passkey: int = None):
|
||||||
|
pending = _pending_pairings.get(address)
|
||||||
|
if pending:
|
||||||
|
if accept:
|
||||||
|
pending["resolve"](passkey)
|
||||||
|
else:
|
||||||
|
pending["reject"]()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting Pairing
|
||||||
|
|
||||||
|
### "No agent registered"
|
||||||
|
|
||||||
|
mcbluetooth's agent didn't register properly:
|
||||||
|
|
||||||
|
1. Check mcbluetooth is running
|
||||||
|
2. Verify D-Bus connectivity
|
||||||
|
3. Check for existing agents (some DEs register their own)
|
||||||
|
|
||||||
|
### "Authentication rejected"
|
||||||
|
|
||||||
|
The other device rejected pairing:
|
||||||
|
|
||||||
|
1. Device may have reached pairing limit
|
||||||
|
2. Try removing existing pairing on both sides
|
||||||
|
3. Restart Bluetooth on the other device
|
||||||
|
|
||||||
|
### Pairing timeout
|
||||||
|
|
||||||
|
No response within timeout period:
|
||||||
|
|
||||||
|
1. Extend timeout: `bt_pair ... timeout=120`
|
||||||
|
2. Check `bt_pairing_status` for pending requests
|
||||||
|
3. Other device may need user interaction
|
||||||
|
|
||||||
|
### Wrong passkey
|
||||||
|
|
||||||
|
For Passkey Entry mode:
|
||||||
|
|
||||||
|
1. Ensure you're entering the exact code shown
|
||||||
|
2. Some devices show passkey only briefly
|
||||||
|
3. Use `bt_pairing_status` to see expected passkey
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### MITM Protection
|
||||||
|
|
||||||
|
| Mode | MITM Protected |
|
||||||
|
|------|----------------|
|
||||||
|
| Just Works | ✗ No |
|
||||||
|
| Numeric Comparison | ✓ Yes |
|
||||||
|
| Passkey Entry | ✓ Yes |
|
||||||
|
| Legacy PIN | Partial |
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Just Works provides encryption but doesn't verify you're pairing with the intended device. An attacker could intercept the pairing (MITM).
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
1. **Prefer Numeric Comparison** - Verify codes match on both devices
|
||||||
|
2. **Avoid auto mode in production** - Human verification is important
|
||||||
|
3. **Check device identity** - Verify name/address before confirming
|
||||||
|
4. **Remove unused pairings** - Reduce attack surface
|
||||||
|
|
||||||
|
## Agent Conflicts
|
||||||
|
|
||||||
|
Desktop environments often register their own agents:
|
||||||
|
|
||||||
|
| Environment | Agent |
|
||||||
|
|-------------|-------|
|
||||||
|
| GNOME | gnome-shell |
|
||||||
|
| KDE | bluedevil |
|
||||||
|
| XFCE | blueman |
|
||||||
|
|
||||||
|
mcbluetooth requests to be the **default agent**, which usually works. If you have issues:
|
||||||
|
|
||||||
|
1. Temporarily stop the DE's Bluetooth applet
|
||||||
|
2. Or use mcbluetooth's agent alongside (may cause double prompts)
|
||||||
191
docs-site/src/content/docs/getting-started/installation.md
Normal file
191
docs-site/src/content/docs/getting-started/installation.md
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
title: Installation
|
||||||
|
description: Install mcbluetooth and configure permissions
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
## Install mcbluetooth
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="uvx (recommended)">
|
||||||
|
```bash
|
||||||
|
# Run directly without installing
|
||||||
|
uvx mcbluetooth
|
||||||
|
|
||||||
|
# Or install globally
|
||||||
|
uv tool install mcbluetooth
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="pip">
|
||||||
|
```bash
|
||||||
|
pip install mcbluetooth
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="From source">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/mcbluetooth
|
||||||
|
cd mcbluetooth
|
||||||
|
uv sync
|
||||||
|
uv run mcbluetooth
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Add to Claude Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using uvx
|
||||||
|
claude mcp add mcbluetooth -- uvx mcbluetooth
|
||||||
|
|
||||||
|
# From source
|
||||||
|
claude mcp add mcbluetooth -- uv run --directory /path/to/mcbluetooth mcbluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure Permissions
|
||||||
|
|
||||||
|
### BlueZ Access
|
||||||
|
|
||||||
|
mcbluetooth needs access to the BlueZ D-Bus interface. Most desktop Linux distributions allow this by default.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Add user to bluetooth group (requires re-login)
|
||||||
|
sudo usermod -aG bluetooth $USER
|
||||||
|
|
||||||
|
# Option 2: Verify polkit allows access (check for errors when running)
|
||||||
|
uvx mcbluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### HCI Packet Capture (Optional)
|
||||||
|
|
||||||
|
For `bt_capture_*` tools (btmon integration):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Allow btmon without sudo
|
||||||
|
sudo setcap cap_net_raw+ep /usr/bin/btmon
|
||||||
|
```
|
||||||
|
|
||||||
|
### OBEX Profiles (Optional)
|
||||||
|
|
||||||
|
For file transfer, phonebook, and message access:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="Arch Linux">
|
||||||
|
```bash
|
||||||
|
sudo pacman -S bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Debian/Ubuntu">
|
||||||
|
```bash
|
||||||
|
sudo apt install bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Fedora">
|
||||||
|
```bash
|
||||||
|
sudo dnf install bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
After installing, verify with:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
obexd runs as a user service on the session D-Bus. It requires an active desktop session (X11 or Wayland).
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Verify Installation
|
||||||
|
|
||||||
|
### Check the Server Starts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Should show startup banner and wait for MCP connections
|
||||||
|
uvx mcbluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output:
|
||||||
|
```
|
||||||
|
🔵 mcbluetooth v0.1.0
|
||||||
|
BlueZ MCP Server - Bluetooth management for LLMs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test with Claude Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In Claude Code, try:
|
||||||
|
bt_list_adapters
|
||||||
|
```
|
||||||
|
|
||||||
|
Should return your Bluetooth adapter(s):
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"discovering": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "org.bluez was not provided"
|
||||||
|
|
||||||
|
BlueZ daemon isn't running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
systemctl status bluetooth
|
||||||
|
|
||||||
|
# Start if stopped
|
||||||
|
sudo systemctl start bluetooth
|
||||||
|
sudo systemctl enable bluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Permission denied" on D-Bus
|
||||||
|
|
||||||
|
Add user to bluetooth group:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo usermod -aG bluetooth $USER
|
||||||
|
# Log out and back in
|
||||||
|
```
|
||||||
|
|
||||||
|
### No Bluetooth adapter found
|
||||||
|
|
||||||
|
Check if adapter is detected by the kernel:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List USB devices
|
||||||
|
lsusb | grep -i bluetooth
|
||||||
|
|
||||||
|
# Check kernel module
|
||||||
|
lsmod | grep btusb
|
||||||
|
|
||||||
|
# Check dmesg
|
||||||
|
dmesg | grep -i bluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### obexd not found
|
||||||
|
|
||||||
|
Install the bluez-obex package for your distribution (see OBEX section above).
|
||||||
|
|
||||||
|
## Tested Configurations
|
||||||
|
|
||||||
|
| Distribution | BlueZ | Audio | Status |
|
||||||
|
|--------------|-------|-------|--------|
|
||||||
|
| Arch Linux | 5.85 | PipeWire 1.4 | ✓ Full support |
|
||||||
|
| Ubuntu 22.04 | 5.64 | PulseAudio | ✓ Full support |
|
||||||
|
| Ubuntu 24.04 | 5.72 | PipeWire | ✓ Full support |
|
||||||
|
| Fedora 39 | 5.70 | PipeWire | ✓ Full support |
|
||||||
|
| Debian 12 | 5.66 | PipeWire | ✓ Full support |
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- [Quick Start Guide](/getting-started/quick-start/) — Try your first commands
|
||||||
|
- [Adapter Management](/guides/adapters/) — Control your Bluetooth hardware
|
||||||
103
docs-site/src/content/docs/getting-started/introduction.md
Normal file
103
docs-site/src/content/docs/getting-started/introduction.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: Introduction
|
||||||
|
description: What is mcbluetooth and why use it?
|
||||||
|
---
|
||||||
|
|
||||||
|
**mcbluetooth** is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that gives LLMs full control over the Linux Bluetooth stack via BlueZ.
|
||||||
|
|
||||||
|
## What Can You Do?
|
||||||
|
|
||||||
|
Ask Claude (or any MCP-compatible LLM) to:
|
||||||
|
|
||||||
|
- **"Turn on Bluetooth and make my computer discoverable"**
|
||||||
|
- **"Scan for devices and pair with my Sony headphones"**
|
||||||
|
- **"Connect my headphones and set volume to 80%"**
|
||||||
|
- **"Read the battery level from my fitness tracker"**
|
||||||
|
- **"Send this PDF to my phone via Bluetooth"**
|
||||||
|
- **"Download my phone's contacts"**
|
||||||
|
- **"Start capturing Bluetooth traffic for debugging"**
|
||||||
|
|
||||||
|
## Why mcbluetooth?
|
||||||
|
|
||||||
|
### Natural Language Control
|
||||||
|
|
||||||
|
Instead of memorizing `bluetoothctl` commands or navigating GUI menus, just describe what you want:
|
||||||
|
|
||||||
|
```
|
||||||
|
"My headphones disconnected, reconnect them and set them as the default audio output"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete BlueZ Coverage
|
||||||
|
|
||||||
|
mcbluetooth exposes the full power of BlueZ:
|
||||||
|
|
||||||
|
- **Adapters** — Power, discovery, pairing acceptance
|
||||||
|
- **Devices** — Scanning, pairing, connection management
|
||||||
|
- **Audio** — A2DP/HFP profiles, volume, routing
|
||||||
|
- **BLE/GATT** — Services, characteristics, notifications
|
||||||
|
- **OBEX** — File transfer, phonebook, messages
|
||||||
|
- **Monitoring** — HCI packet capture and analysis
|
||||||
|
|
||||||
|
### Smart Pairing
|
||||||
|
|
||||||
|
The built-in pairing agent handles all Bluetooth pairing methods:
|
||||||
|
|
||||||
|
| Method | Description | Agent Response |
|
||||||
|
|--------|-------------|----------------|
|
||||||
|
| Just Works | No user interaction | Auto-accept |
|
||||||
|
| Numeric Comparison | Confirm 6-digit code | Interactive or auto |
|
||||||
|
| Passkey Entry | Enter code from device | PIN prompt |
|
||||||
|
| Legacy PIN | 4-6 digit PIN | PIN prompt |
|
||||||
|
|
||||||
|
### MCP Resources
|
||||||
|
|
||||||
|
Live state queries without tool calls:
|
||||||
|
|
||||||
|
```
|
||||||
|
bluetooth://adapters → All Bluetooth adapters
|
||||||
|
bluetooth://paired → Paired devices
|
||||||
|
bluetooth://connected → Connected devices
|
||||||
|
bluetooth://device/AA:BB:CC:DD:EE:FF → Specific device
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Claude / LLM │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ MCP Protocol (stdio) │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ mcbluetooth (FastMCP) │
|
||||||
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||||
|
│ │ Adapter │ │ Device │ │ Audio │ │ OBEX │ ... │
|
||||||
|
│ │ Tools │ │ Tools │ │ Tools │ │ Tools │ │
|
||||||
|
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||||||
|
│ └──────────┬┴──────────┬┴───────────┘ │
|
||||||
|
│ ┌────────┴────────┐ │ │
|
||||||
|
│ │ BlueZ D-Bus │ │ PipeWire/Pulse │
|
||||||
|
│ │ (dbus-fast) │ │ (pulsectl-asyncio) │
|
||||||
|
│ └────────┬────────┘ └──────────────────────────────┤
|
||||||
|
├──────────────────┼──────────────────────────────────────────┤
|
||||||
|
│ │ │
|
||||||
|
│ BlueZ (bluetoothd) obexd │
|
||||||
|
│ │ │
|
||||||
|
│ Linux Kernel (Bluetooth subsystem) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
| Requirement | Version | Notes |
|
||||||
|
|-------------|---------|-------|
|
||||||
|
| Linux | Any | BlueZ is Linux-only |
|
||||||
|
| Python | 3.11+ | Async/await, type hints |
|
||||||
|
| BlueZ | 5.x | Bluetooth daemon |
|
||||||
|
| PipeWire or PulseAudio | Any | For audio features |
|
||||||
|
| bluez-obex | Any | For OBEX features (optional) |
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. [Install mcbluetooth](/getting-started/installation/)
|
||||||
|
2. [Try the quick start guide](/getting-started/quick-start/)
|
||||||
|
3. [Explore the tool reference](/reference/tools/)
|
||||||
150
docs-site/src/content/docs/getting-started/quick-start.md
Normal file
150
docs-site/src/content/docs/getting-started/quick-start.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
title: Quick Start
|
||||||
|
description: Get up and running with mcbluetooth in 5 minutes
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Steps, Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
This guide walks you through basic Bluetooth operations with mcbluetooth.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- mcbluetooth installed and added to Claude Code
|
||||||
|
- A Bluetooth adapter (built-in or USB dongle)
|
||||||
|
- A Bluetooth device to test with (headphones, phone, etc.)
|
||||||
|
|
||||||
|
## Basic Operations
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
1. **Check your adapter**
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_list_adapters
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see your Bluetooth adapter:
|
||||||
|
```json
|
||||||
|
[{"name": "hci0", "address": "...", "powered": true, ...}]
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Power on Bluetooth (if needed)**
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_power adapter="hci0" on=true
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Scan for devices**
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_scan adapter="hci0" timeout=10 mode="both"
|
||||||
|
```
|
||||||
|
|
||||||
|
This scans for 10 seconds and returns all discovered devices.
|
||||||
|
|
||||||
|
4. **Pair with a device**
|
||||||
|
|
||||||
|
Put your device in pairing mode, then:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
The agent handles PIN/passkey automatically for most devices.
|
||||||
|
|
||||||
|
5. **Connect to the paired device**
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Connect Headphones
|
||||||
|
|
||||||
|
```
|
||||||
|
# Scan for devices
|
||||||
|
bt_scan adapter="hci0"
|
||||||
|
|
||||||
|
# Pair (first time only)
|
||||||
|
bt_pair adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
|
||||||
|
# Connect
|
||||||
|
bt_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
|
||||||
|
# Set as default audio and adjust volume
|
||||||
|
bt_audio_set_default address="C8:7B:23:55:68:E8"
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=75
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read a BLE Sensor
|
||||||
|
|
||||||
|
```
|
||||||
|
# Scan for BLE devices
|
||||||
|
bt_ble_scan adapter="hci0" timeout=10
|
||||||
|
|
||||||
|
# Connect and discover services
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
bt_ble_services adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Read battery level (standard BLE service)
|
||||||
|
bt_ble_battery adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Read a specific characteristic
|
||||||
|
bt_ble_read adapter="hci0" address="AA:BB:CC:DD:EE:FF" char_uuid="00002a19-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Send a File to Your Phone
|
||||||
|
|
||||||
|
```
|
||||||
|
# Check OBEX is ready
|
||||||
|
bt_obex_status
|
||||||
|
|
||||||
|
# Send file (phone will show accept prompt)
|
||||||
|
bt_obex_send_file address="AA:BB:CC:DD:EE:FF" file_path="~/Documents/report.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Download Contacts from Phone
|
||||||
|
|
||||||
|
```
|
||||||
|
# Pull entire phonebook
|
||||||
|
bt_phonebook_pull address="AA:BB:CC:DD:EE:FF" save_path="~/contacts.vcf"
|
||||||
|
|
||||||
|
# Or search for specific contact
|
||||||
|
bt_phonebook_search address="AA:BB:CC:DD:EE:FF" field="name" value="John"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using MCP Resources
|
||||||
|
|
||||||
|
Resources provide live state without tool calls:
|
||||||
|
|
||||||
|
```
|
||||||
|
# In your MCP client, read these URIs:
|
||||||
|
bluetooth://adapters # All adapters
|
||||||
|
bluetooth://paired # Paired devices
|
||||||
|
bluetooth://connected # Connected devices
|
||||||
|
bluetooth://device/AA:BB:... # Specific device details
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
**Use device aliases**: Set friendly names with `bt_device_set_alias` so you don't have to remember MAC addresses.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
**Trust devices**: Use `bt_trust` to allow devices to auto-connect without explicit authorization.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
**Check OBEX first**: Before using file transfer or phonebook tools, run `bt_obex_status` to verify obexd is running.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- [Adapter Management](/guides/adapters/) — Control Bluetooth hardware
|
||||||
|
- [Device Pairing](/guides/pairing/) — Deep dive into pairing modes
|
||||||
|
- [Audio Control](/guides/audio/) — Master Bluetooth audio
|
||||||
|
- [Tool Reference](/reference/tools/) — Complete tool documentation
|
||||||
201
docs-site/src/content/docs/guides/adapters.md
Normal file
201
docs-site/src/content/docs/guides/adapters.md
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
---
|
||||||
|
title: Adapter Management
|
||||||
|
description: Control your Bluetooth hardware — power, discovery, and pairing modes
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Bluetooth adapters are the hardware interfaces that enable wireless communication. mcbluetooth provides full control over adapter configuration.
|
||||||
|
|
||||||
|
## List Adapters
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_list_adapters
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all Bluetooth adapters with their current state:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"alias": "My Laptop",
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"discoverable_timeout": 180,
|
||||||
|
"pairable": true,
|
||||||
|
"pairable_timeout": 0,
|
||||||
|
"discovering": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get Adapter Details
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_info adapter="hci0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns detailed information including supported features and UUIDs.
|
||||||
|
|
||||||
|
## Power Control
|
||||||
|
|
||||||
|
### Turn Bluetooth On
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_power adapter="hci0" on=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Turn Bluetooth Off
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_power adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Powering off disconnects all devices and stops any ongoing discovery.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Discovery Settings
|
||||||
|
|
||||||
|
### Make Discoverable
|
||||||
|
|
||||||
|
Allow other devices to see your computer:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=true timeout=180
|
||||||
|
```
|
||||||
|
|
||||||
|
- `timeout=0` means discoverable forever (use carefully)
|
||||||
|
- `timeout=180` means 3 minutes (default)
|
||||||
|
|
||||||
|
### Stop Being Discoverable
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pairing Acceptance
|
||||||
|
|
||||||
|
### Enable Pairing
|
||||||
|
|
||||||
|
Allow devices to pair with your computer:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_pairable adapter="hci0" on=true timeout=0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disable Pairing
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_pairable adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Leaving pairable enabled indefinitely (`timeout=0`) may be a security risk in public environments.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Set Adapter Name
|
||||||
|
|
||||||
|
Change the friendly name other devices see:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_set_alias adapter="hci0" alias="Ryan's Desktop"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Prepare for Incoming Connection
|
||||||
|
|
||||||
|
When you want another device to find and connect to your computer:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Make discoverable and pairable
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=true timeout=300
|
||||||
|
bt_adapter_pairable adapter="hci0" on=true timeout=300
|
||||||
|
```
|
||||||
|
|
||||||
|
This opens a 5-minute window for pairing.
|
||||||
|
|
||||||
|
### Secure Configuration
|
||||||
|
|
||||||
|
For everyday use with known devices:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Hidden but accepting connections from paired devices
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=false
|
||||||
|
bt_adapter_pairable adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adapter Properties Reference
|
||||||
|
|
||||||
|
| Property | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `name` | System name (e.g., `hci0`) |
|
||||||
|
| `address` | MAC address |
|
||||||
|
| `alias` | Friendly name |
|
||||||
|
| `powered` | On/off state |
|
||||||
|
| `discoverable` | Visible to other devices |
|
||||||
|
| `discoverable_timeout` | Seconds until auto-hidden (0=forever) |
|
||||||
|
| `pairable` | Accepting new pairings |
|
||||||
|
| `pairable_timeout` | Seconds until auto-disable (0=forever) |
|
||||||
|
| `discovering` | Currently scanning |
|
||||||
|
| `uuids` | Supported Bluetooth profiles |
|
||||||
|
| `modalias` | Hardware identifier |
|
||||||
|
|
||||||
|
## Multiple Adapters
|
||||||
|
|
||||||
|
If you have multiple Bluetooth adapters (e.g., built-in + USB dongle):
|
||||||
|
|
||||||
|
```
|
||||||
|
# List all adapters
|
||||||
|
bt_list_adapters
|
||||||
|
|
||||||
|
# Configure each separately
|
||||||
|
bt_adapter_power adapter="hci0" on=true
|
||||||
|
bt_adapter_power adapter="hci1" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
Use different adapters for different purposes — one for audio, one for BLE sensors.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Adapter Not Found
|
||||||
|
|
||||||
|
Check if the kernel sees your hardware:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List USB Bluetooth devices
|
||||||
|
lsusb | grep -i bluetooth
|
||||||
|
|
||||||
|
# Check kernel messages
|
||||||
|
dmesg | grep -i bluetooth
|
||||||
|
|
||||||
|
# Verify btusb module is loaded
|
||||||
|
lsmod | grep btusb
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adapter Won't Power On
|
||||||
|
|
||||||
|
BlueZ might be blocked by rfkill:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check rfkill status
|
||||||
|
rfkill list bluetooth
|
||||||
|
|
||||||
|
# Unblock if blocked
|
||||||
|
rfkill unblock bluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
### Discovery Stops Unexpectedly
|
||||||
|
|
||||||
|
Discovery has a default timeout. For continuous scanning:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_scan adapter="hci0" timeout=60 mode="both"
|
||||||
|
```
|
||||||
|
|
||||||
|
The `bt_scan` tool handles starting and stopping discovery automatically.
|
||||||
199
docs-site/src/content/docs/guides/audio.md
Normal file
199
docs-site/src/content/docs/guides/audio.md
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
---
|
||||||
|
title: Audio Control
|
||||||
|
description: Manage Bluetooth audio devices with PipeWire/PulseAudio integration
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
mcbluetooth integrates with PipeWire and PulseAudio to provide seamless Bluetooth audio control.
|
||||||
|
|
||||||
|
## List Audio Devices
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_audio_list
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all audio devices including Bluetooth:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sinks": [
|
||||||
|
{
|
||||||
|
"name": "bluez_sink.C8_7B_23_55_68_E8.a2dp_sink",
|
||||||
|
"description": "Bombay",
|
||||||
|
"bluetooth_address": "C8:7B:23:55:68:E8",
|
||||||
|
"volume": 65536,
|
||||||
|
"volume_percent": 75,
|
||||||
|
"muted": false,
|
||||||
|
"state": "running"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sources": [...],
|
||||||
|
"cards": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connect Audio
|
||||||
|
|
||||||
|
After pairing a device, connect its audio profiles:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_audio_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
This connects A2DP (high-quality audio) and/or HFP (hands-free) profiles.
|
||||||
|
|
||||||
|
## Audio Profiles
|
||||||
|
|
||||||
|
Bluetooth audio devices support different profiles:
|
||||||
|
|
||||||
|
| Profile | Quality | Microphone | Use Case |
|
||||||
|
|---------|---------|------------|----------|
|
||||||
|
| **A2DP** | High (stereo) | No | Music, videos |
|
||||||
|
| **HFP** | Low (mono) | Yes | Phone calls |
|
||||||
|
| **HSP** | Low (mono) | Yes | Legacy headsets |
|
||||||
|
|
||||||
|
### Switch Profiles
|
||||||
|
|
||||||
|
```
|
||||||
|
# High-quality stereo for music
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="a2dp"
|
||||||
|
|
||||||
|
# Hands-free for calls (enables microphone)
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="hfp"
|
||||||
|
|
||||||
|
# Disable audio (but stay connected for other profiles)
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="off"
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
Switch to HFP before a video call to enable the headset microphone, then back to A2DP for music.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Set Default Output
|
||||||
|
|
||||||
|
Make a Bluetooth device the default audio output:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_audio_set_default address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Volume Control
|
||||||
|
|
||||||
|
### Set Volume
|
||||||
|
|
||||||
|
```
|
||||||
|
# Set to 75%
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=75
|
||||||
|
|
||||||
|
# Boost to 120% (use carefully)
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=120
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Volume above 100% may cause distortion or hearing damage.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
### Mute/Unmute
|
||||||
|
|
||||||
|
```
|
||||||
|
# Mute
|
||||||
|
bt_audio_mute address="C8:7B:23:55:68:E8" muted=true
|
||||||
|
|
||||||
|
# Unmute
|
||||||
|
bt_audio_mute address="C8:7B:23:55:68:E8" muted=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Disconnect Audio
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_audio_disconnect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
This disconnects audio profiles but keeps the device connected for other services.
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Connect Headphones for Music
|
||||||
|
|
||||||
|
```
|
||||||
|
# Connect and set up for music
|
||||||
|
bt_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
bt_audio_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="a2dp"
|
||||||
|
bt_audio_set_default address="C8:7B:23:55:68:E8"
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=70
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prepare for Video Call
|
||||||
|
|
||||||
|
```
|
||||||
|
# Switch to HFP for microphone support
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="hfp"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Return to Music After Call
|
||||||
|
|
||||||
|
```
|
||||||
|
# Switch back to A2DP for high-quality audio
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="a2dp"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### No Sound from Device
|
||||||
|
|
||||||
|
1. Check the device is connected: `bt_device_info adapter="hci0" address="..."`
|
||||||
|
2. Verify audio profile is connected: `bt_audio_list`
|
||||||
|
3. Ensure it's set as default: `bt_audio_set_default address="..."`
|
||||||
|
4. Check volume isn't zero: `bt_audio_volume address="..." volume=70`
|
||||||
|
|
||||||
|
### Audio Cuts Out
|
||||||
|
|
||||||
|
- **Interference**: Move away from WiFi routers, microwaves
|
||||||
|
- **Distance**: Stay within 10 meters of the adapter
|
||||||
|
- **Battery**: Low battery can cause audio issues
|
||||||
|
- **Profile**: Try switching profiles and back
|
||||||
|
|
||||||
|
### Poor Audio Quality
|
||||||
|
|
||||||
|
```
|
||||||
|
# Ensure A2DP (not HFP) is active
|
||||||
|
bt_audio_set_profile address="..." profile="a2dp"
|
||||||
|
```
|
||||||
|
|
||||||
|
HFP is mono and lower quality — it's for calls, not music.
|
||||||
|
|
||||||
|
### Microphone Not Working
|
||||||
|
|
||||||
|
```
|
||||||
|
# Switch to HFP or HSP
|
||||||
|
bt_audio_set_profile address="..." profile="hfp"
|
||||||
|
```
|
||||||
|
|
||||||
|
A2DP doesn't support microphone input.
|
||||||
|
|
||||||
|
### Device Shows "Off" Profile
|
||||||
|
|
||||||
|
The device may need reconnection:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_audio_disconnect adapter="hci0" address="..."
|
||||||
|
bt_audio_connect adapter="hci0" address="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Audio Codecs
|
||||||
|
|
||||||
|
Audio quality depends on the codec negotiated between devices:
|
||||||
|
|
||||||
|
| Codec | Quality | Latency | Notes |
|
||||||
|
|-------|---------|---------|-------|
|
||||||
|
| SBC | Good | Medium | Universal, default |
|
||||||
|
| AAC | Better | Medium | Apple devices |
|
||||||
|
| aptX | Better | Low | Qualcomm devices |
|
||||||
|
| aptX HD | Best | Low | High-res audio |
|
||||||
|
| LDAC | Best | Medium | Sony devices |
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Codec selection is automatic based on device capabilities. mcbluetooth doesn't directly control codec selection — this is handled by BlueZ and PipeWire.
|
||||||
|
</Aside>
|
||||||
240
docs-site/src/content/docs/guides/ble.md
Normal file
240
docs-site/src/content/docs/guides/ble.md
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
---
|
||||||
|
title: BLE & GATT
|
||||||
|
description: Interact with Bluetooth Low Energy devices — sensors, fitness trackers, and IoT
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Bluetooth Low Energy (BLE) devices use GATT (Generic Attribute Profile) to expose services and characteristics. mcbluetooth provides tools to discover, read, write, and subscribe to BLE data.
|
||||||
|
|
||||||
|
## BLE Scanning
|
||||||
|
|
||||||
|
### Basic Scan
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_scan adapter="hci0" timeout=10
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filtered Scan
|
||||||
|
|
||||||
|
```
|
||||||
|
# Filter by name
|
||||||
|
bt_ble_scan adapter="hci0" name_filter="Fitness"
|
||||||
|
|
||||||
|
# Filter by service UUID
|
||||||
|
bt_ble_scan adapter="hci0" service_filter="0000180d-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
## GATT Structure
|
||||||
|
|
||||||
|
BLE devices organize data hierarchically:
|
||||||
|
|
||||||
|
```
|
||||||
|
Device
|
||||||
|
└── Service (UUID: 0000180d-...) ← Heart Rate Service
|
||||||
|
├── Characteristic (UUID: 00002a37-...) ← Heart Rate Measurement
|
||||||
|
│ └── Descriptor ← Client Configuration
|
||||||
|
└── Characteristic (UUID: 00002a38-...) ← Body Sensor Location
|
||||||
|
```
|
||||||
|
|
||||||
|
## Discover Services
|
||||||
|
|
||||||
|
After connecting:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_services adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"uuid": "0000180f-0000-1000-8000-00805f9b34fb",
|
||||||
|
"primary": true,
|
||||||
|
"description": "Battery Service"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid": "0000180d-0000-1000-8000-00805f9b34fb",
|
||||||
|
"primary": true,
|
||||||
|
"description": "Heart Rate Service"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## List Characteristics
|
||||||
|
|
||||||
|
```
|
||||||
|
# All characteristics
|
||||||
|
bt_ble_characteristics adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Filter by service
|
||||||
|
bt_ble_characteristics adapter="hci0" address="..." service_uuid="0000180f-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"uuid": "00002a19-0000-1000-8000-00805f9b34fb",
|
||||||
|
"flags": ["read", "notify"],
|
||||||
|
"description": "Battery Level"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Read Values
|
||||||
|
|
||||||
|
### Read Battery Level (Shortcut)
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_battery adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns battery percentage (0-100).
|
||||||
|
|
||||||
|
### Read Any Characteristic
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_read adapter="hci0" address="..." char_uuid="00002a19-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hex": "4b",
|
||||||
|
"decoded": 75,
|
||||||
|
"description": "Battery Level: 75%"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Write Values
|
||||||
|
|
||||||
|
```
|
||||||
|
# Write hex bytes
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="0102ff" value_type="hex"
|
||||||
|
|
||||||
|
# Write string
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="hello" value_type="string"
|
||||||
|
|
||||||
|
# Write integer
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="42" value_type="int"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Write with/without Response
|
||||||
|
|
||||||
|
```
|
||||||
|
# With response (default) - waits for acknowledgment
|
||||||
|
bt_ble_write ... with_response=true
|
||||||
|
|
||||||
|
# Without response (faster, less reliable)
|
||||||
|
bt_ble_write ... with_response=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
Subscribe to value changes:
|
||||||
|
|
||||||
|
### Enable Notifications
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_notify adapter="hci0" address="..." char_uuid="00002a37-..." enable=true
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
After enabling notifications, the device will send updates when values change. Currently, mcbluetooth enables the notification mode but doesn't provide a callback mechanism — use protocol capture to see the actual notifications.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
### Disable Notifications
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_ble_notify adapter="hci0" address="..." char_uuid="..." enable=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common UUIDs
|
||||||
|
|
||||||
|
### Standard Services
|
||||||
|
|
||||||
|
| Service | UUID | Description |
|
||||||
|
|---------|------|-------------|
|
||||||
|
| Generic Access | `0x1800` | Device name, appearance |
|
||||||
|
| Generic Attribute | `0x1801` | Service change indication |
|
||||||
|
| Battery | `0x180F` | Battery level |
|
||||||
|
| Device Information | `0x180A` | Manufacturer, model, etc. |
|
||||||
|
| Heart Rate | `0x180D` | Heart rate measurement |
|
||||||
|
| Health Thermometer | `0x1809` | Temperature |
|
||||||
|
| Blood Pressure | `0x1810` | Blood pressure |
|
||||||
|
|
||||||
|
### Standard Characteristics
|
||||||
|
|
||||||
|
| Characteristic | UUID | Service |
|
||||||
|
|----------------|------|---------|
|
||||||
|
| Battery Level | `0x2A19` | Battery |
|
||||||
|
| Heart Rate Measurement | `0x2A37` | Heart Rate |
|
||||||
|
| Temperature Measurement | `0x2A1C` | Health Thermometer |
|
||||||
|
| Manufacturer Name | `0x2A29` | Device Information |
|
||||||
|
| Model Number | `0x2A24` | Device Information |
|
||||||
|
|
||||||
|
<Aside type="tip">
|
||||||
|
Full UUIDs are `0000XXXX-0000-1000-8000-00805f9b34fb` where `XXXX` is the short UUID.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Example: Heart Rate Monitor
|
||||||
|
|
||||||
|
```
|
||||||
|
# Scan for heart rate monitors
|
||||||
|
bt_ble_scan adapter="hci0" service_filter="0000180d-0000-1000-8000-00805f9b34fb"
|
||||||
|
|
||||||
|
# Connect
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# List services
|
||||||
|
bt_ble_services adapter="hci0" address="..."
|
||||||
|
|
||||||
|
# Enable heart rate notifications
|
||||||
|
bt_ble_notify adapter="hci0" address="..." char_uuid="00002a37-0000-1000-8000-00805f9b34fb" enable=true
|
||||||
|
|
||||||
|
# Read body sensor location
|
||||||
|
bt_ble_read adapter="hci0" address="..." char_uuid="00002a38-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example: Smart Light Bulb
|
||||||
|
|
||||||
|
```
|
||||||
|
# Connect to bulb
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Find the control characteristic (vendor-specific)
|
||||||
|
bt_ble_characteristics adapter="hci0" address="..."
|
||||||
|
|
||||||
|
# Write command to turn on (example - actual commands vary by device)
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="01" value_type="hex"
|
||||||
|
|
||||||
|
# Set color (RGB example)
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="ff0000" value_type="hex"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "ServicesResolved: false"
|
||||||
|
|
||||||
|
Services aren't discovered yet. Wait a moment after connecting:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_connect adapter="hci0" address="..."
|
||||||
|
# Wait 2-3 seconds
|
||||||
|
bt_ble_services adapter="hci0" address="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Can't Read Characteristic
|
||||||
|
|
||||||
|
Check the characteristic flags:
|
||||||
|
- `read` must be present for reading
|
||||||
|
- `write` or `write-without-response` for writing
|
||||||
|
- `notify` for notifications
|
||||||
|
|
||||||
|
### Connection Drops Frequently
|
||||||
|
|
||||||
|
BLE has limited connection capacity. Try:
|
||||||
|
- Disconnecting other BLE devices
|
||||||
|
- Moving closer to the adapter
|
||||||
|
- Checking device battery level
|
||||||
278
docs-site/src/content/docs/guides/capture.md
Normal file
278
docs-site/src/content/docs/guides/capture.md
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
---
|
||||||
|
title: Protocol Capture
|
||||||
|
description: Capture and analyze Bluetooth HCI traffic for debugging
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
mcbluetooth can capture raw Bluetooth HCI (Host Controller Interface) traffic for protocol analysis and debugging.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
HCI captures record all communication between the Bluetooth stack and hardware adapter. This includes:
|
||||||
|
|
||||||
|
- Device discovery packets
|
||||||
|
- Pairing and authentication
|
||||||
|
- Connection management
|
||||||
|
- Audio streaming data
|
||||||
|
- BLE GATT operations
|
||||||
|
|
||||||
|
## Starting a Capture
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_start output_file="/tmp/bluetooth.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "started",
|
||||||
|
"capture_id": "capture_abc123",
|
||||||
|
"output_file": "/tmp/bluetooth.btsnoop"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Capture Options
|
||||||
|
|
||||||
|
```
|
||||||
|
# Capture from specific adapter
|
||||||
|
bt_capture_start output_file="/tmp/hci0.btsnoop" adapter="0"
|
||||||
|
|
||||||
|
# Include voice data (SCO)
|
||||||
|
bt_capture_start output_file="/tmp/calls.btsnoop" include_sco=true
|
||||||
|
|
||||||
|
# Include audio streaming (A2DP)
|
||||||
|
bt_capture_start output_file="/tmp/audio.btsnoop" include_a2dp=true
|
||||||
|
|
||||||
|
# Include LE Audio (ISO)
|
||||||
|
bt_capture_start output_file="/tmp/le_audio.btsnoop" include_iso=true
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Audio captures (`include_sco`, `include_a2dp`, `include_iso`) generate large files quickly.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Stopping a Capture
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_stop capture_id="capture_abc123"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "stopped",
|
||||||
|
"output_file": "/tmp/bluetooth.btsnoop",
|
||||||
|
"packets_captured": 1542,
|
||||||
|
"file_size": 245760
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Listing Active Captures
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_list_active
|
||||||
|
```
|
||||||
|
|
||||||
|
## Analyzing Captures
|
||||||
|
|
||||||
|
### Quick Parse
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_parse filepath="/tmp/bluetooth.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns packet summaries:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total_packets": 1542,
|
||||||
|
"packet_types": {
|
||||||
|
"HCI_CMD": 234,
|
||||||
|
"HCI_EVENT": 456,
|
||||||
|
"ACL_DATA": 852
|
||||||
|
},
|
||||||
|
"packets": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"timestamp": "2024-01-15T10:30:00.123456",
|
||||||
|
"type": "HCI_CMD",
|
||||||
|
"direction": "TX",
|
||||||
|
"summary": "Inquiry"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filtered Parse
|
||||||
|
|
||||||
|
```
|
||||||
|
# Only HCI commands
|
||||||
|
bt_capture_parse filepath="..." packet_type_filter="HCI_CMD"
|
||||||
|
|
||||||
|
# Only received packets
|
||||||
|
bt_capture_parse filepath="..." direction_filter="RX"
|
||||||
|
|
||||||
|
# Limit results
|
||||||
|
bt_capture_parse filepath="..." max_packets=100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Detailed Analysis
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_analyze filepath="/tmp/bluetooth.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns high-level statistics:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"duration_seconds": 45.2,
|
||||||
|
"total_packets": 1542,
|
||||||
|
"protocols": {
|
||||||
|
"L2CAP": 423,
|
||||||
|
"RFCOMM": 156,
|
||||||
|
"SDP": 34,
|
||||||
|
"ATT": 289
|
||||||
|
},
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"packets": 892,
|
||||||
|
"bytes": 45678
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Raw Packet Decoding
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_capture_read_raw filepath="/tmp/bluetooth.btsnoop" offset=0 count=50
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns btmon-style decoded output for detailed inspection.
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Debug Pairing Issues
|
||||||
|
|
||||||
|
```
|
||||||
|
# Start capture
|
||||||
|
bt_capture_start output_file="/tmp/pairing_debug.btsnoop"
|
||||||
|
|
||||||
|
# Attempt pairing
|
||||||
|
bt_pair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Stop and analyze
|
||||||
|
bt_capture_stop capture_id="..."
|
||||||
|
bt_capture_parse filepath="/tmp/pairing_debug.btsnoop" packet_type_filter="HCI_EVENT"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Investigate Audio Glitches
|
||||||
|
|
||||||
|
```
|
||||||
|
# Capture with A2DP data
|
||||||
|
bt_capture_start output_file="/tmp/audio_debug.btsnoop" include_a2dp=true
|
||||||
|
|
||||||
|
# Play audio for 30 seconds
|
||||||
|
|
||||||
|
# Stop and check for errors
|
||||||
|
bt_capture_stop capture_id="..."
|
||||||
|
bt_capture_analyze filepath="/tmp/audio_debug.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor BLE Sensor
|
||||||
|
|
||||||
|
```
|
||||||
|
# Start capture
|
||||||
|
bt_capture_start output_file="/tmp/ble_sensor.btsnoop"
|
||||||
|
|
||||||
|
# Connect and interact with sensor
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
bt_ble_read adapter="hci0" address="..." char_uuid="..."
|
||||||
|
|
||||||
|
# Analyze ATT/GATT traffic
|
||||||
|
bt_capture_stop capture_id="..."
|
||||||
|
bt_capture_parse filepath="/tmp/ble_sensor.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Format
|
||||||
|
|
||||||
|
Captures are saved in **btsnoop** format, compatible with:
|
||||||
|
|
||||||
|
| Tool | Usage |
|
||||||
|
|------|-------|
|
||||||
|
| **Wireshark** | Full GUI analysis |
|
||||||
|
| **btmon** | Command-line decode |
|
||||||
|
| **hcidump** | Legacy analysis |
|
||||||
|
|
||||||
|
### Open in Wireshark
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wireshark /tmp/bluetooth.btsnoop
|
||||||
|
```
|
||||||
|
|
||||||
|
Wireshark provides:
|
||||||
|
- Protocol dissection
|
||||||
|
- Conversation tracking
|
||||||
|
- Expert analysis
|
||||||
|
- Export options
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Capture requires elevated privileges (root or `CAP_NET_RAW`).
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
The capture functionality uses `btmon` which needs access to the Bluetooth monitor socket:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Run as root
|
||||||
|
sudo btmon
|
||||||
|
|
||||||
|
# Option 2: Add capability (one-time setup)
|
||||||
|
sudo setcap cap_net_raw+ep /usr/bin/btmon
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Permission Denied"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check btmon capability
|
||||||
|
getcap /usr/bin/btmon
|
||||||
|
|
||||||
|
# Add if missing
|
||||||
|
sudo setcap cap_net_raw+ep /usr/bin/btmon
|
||||||
|
```
|
||||||
|
|
||||||
|
### Capture File Empty
|
||||||
|
|
||||||
|
- Ensure adapter is active: `bt_adapter_power adapter="hci0" on=true`
|
||||||
|
- Verify Bluetooth activity is occurring
|
||||||
|
- Check btmon is running: `bt_capture_list_active`
|
||||||
|
|
||||||
|
### Very Large Files
|
||||||
|
|
||||||
|
Audio data generates significant traffic:
|
||||||
|
|
||||||
|
| Content | Approximate Size |
|
||||||
|
|---------|------------------|
|
||||||
|
| Discovery/pairing | ~10 KB/min |
|
||||||
|
| BLE sensors | ~50 KB/min |
|
||||||
|
| A2DP audio | ~2 MB/min |
|
||||||
|
| HFP calls | ~500 KB/min |
|
||||||
|
|
||||||
|
Use without audio flags for general debugging:
|
||||||
|
```
|
||||||
|
bt_capture_start output_file="..." include_sco=false include_a2dp=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Can't Open in Wireshark
|
||||||
|
|
||||||
|
Verify file format:
|
||||||
|
```bash
|
||||||
|
file /tmp/capture.btsnoop
|
||||||
|
# Should show: BTSnoop version 1, HCI UART (H4)
|
||||||
|
```
|
||||||
|
|
||||||
|
If corrupted, the capture may have been interrupted. Always use `bt_capture_stop` to properly close files.
|
||||||
270
docs-site/src/content/docs/guides/obex.md
Normal file
270
docs-site/src/content/docs/guides/obex.md
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
---
|
||||||
|
title: OBEX File Transfer
|
||||||
|
description: Send files, browse phone storage, and download data using OBEX profiles
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
OBEX (Object Exchange) enables file transfer over Bluetooth. mcbluetooth supports four OBEX profiles:
|
||||||
|
|
||||||
|
| Profile | Code | Purpose |
|
||||||
|
|---------|------|---------|
|
||||||
|
| **OPP** | Object Push | Simple file sending |
|
||||||
|
| **FTP** | File Transfer | Full file browsing |
|
||||||
|
| **PBAP** | Phonebook Access | Read contacts (see [Phonebook guide](/guides/phonebook-messages/)) |
|
||||||
|
| **MAP** | Message Access | Read SMS/MMS (see [Phonebook guide](/guides/phonebook-messages/)) |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
OBEX requires the `obexd` daemon:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="Arch Linux">
|
||||||
|
```bash
|
||||||
|
sudo pacman -S bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Debian/Ubuntu">
|
||||||
|
```bash
|
||||||
|
sudo apt install bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
Verify installation:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
If obexd isn't running:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_start_daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
obexd runs on the session D-Bus and requires an active desktop session.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Quick File Send (OPP)
|
||||||
|
|
||||||
|
The simplest way to send a file:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="AA:BB:CC:DD:EE:FF" file_path="~/Documents/report.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Creates a temporary OPP session
|
||||||
|
- Sends the file (recipient sees accept prompt)
|
||||||
|
- Waits for completion
|
||||||
|
- Closes the session
|
||||||
|
|
||||||
|
### Non-blocking Send
|
||||||
|
|
||||||
|
For large files, start transfer without waiting:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="..." file_path="large_video.mp4" wait=false
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns a `transfer_path` to monitor progress:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_transfer_status transfer_path="/org/bluez/obex/client/session0/transfer0"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pull Business Card (OPP)
|
||||||
|
|
||||||
|
Get the device's default vCard:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_get_vcard address="AA:BB:CC:DD:EE:FF" save_path="~/contact.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Browsing (FTP)
|
||||||
|
|
||||||
|
For full file system access, create an FTP session:
|
||||||
|
|
||||||
|
### Create Session
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_connect address="AA:BB:CC:DD:EE:FF" target="ftp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"session_id": "ftp_AABBCCDDEEFF",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"target": "ftp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Browse Folders
|
||||||
|
|
||||||
|
```
|
||||||
|
# List root
|
||||||
|
bt_obex_browse session_id="ftp_AABBCCDDEEFF" path="/"
|
||||||
|
|
||||||
|
# Navigate to folder
|
||||||
|
bt_obex_browse session_id="ftp_AABBCCDDEEFF" path="DCIM"
|
||||||
|
|
||||||
|
# Go up
|
||||||
|
bt_obex_browse session_id="ftp_AABBCCDDEEFF" path=".."
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"entries": [
|
||||||
|
{"name": "DCIM", "type": "folder"},
|
||||||
|
{"name": "Download", "type": "folder"},
|
||||||
|
{"name": "document.pdf", "type": "file", "size": 102400}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Download Files
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_get session_id="ftp_..." remote_path="photo.jpg" local_path="~/Downloads/photo.jpg"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload Files
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_put session_id="ftp_..." local_path="~/document.pdf" remote_path="document.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create Folder
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_mkdir session_id="ftp_..." folder_name="Backup"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete Files
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_delete session_id="ftp_..." remote_path="old_file.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Close Session
|
||||||
|
|
||||||
|
Always close when done:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_disconnect session_id="ftp_AABBCCDDEEFF"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Session Management
|
||||||
|
|
||||||
|
### List Active Sessions
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_sessions
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check OBEX Status
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ready",
|
||||||
|
"obexd_installed": true,
|
||||||
|
"obexd_running": true,
|
||||||
|
"dbus_accessible": true,
|
||||||
|
"active_sessions": [...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transfer Monitoring
|
||||||
|
|
||||||
|
### Check Progress
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_transfer_status transfer_path="/org/bluez/obex/client/session0/transfer0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "active",
|
||||||
|
"size": 104857600,
|
||||||
|
"transferred": 52428800,
|
||||||
|
"progress_percent": 50
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cancel Transfer
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_transfer_cancel transfer_path="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Backup Phone Photos
|
||||||
|
|
||||||
|
```
|
||||||
|
# Connect FTP session
|
||||||
|
bt_obex_connect address="..." target="ftp"
|
||||||
|
|
||||||
|
# Navigate to photos
|
||||||
|
bt_obex_browse session_id="ftp_..." path="/"
|
||||||
|
bt_obex_browse session_id="ftp_..." path="DCIM"
|
||||||
|
bt_obex_browse session_id="ftp_..." path="Camera"
|
||||||
|
|
||||||
|
# Download each photo
|
||||||
|
bt_obex_get session_id="ftp_..." remote_path="IMG_001.jpg" local_path="~/backup/"
|
||||||
|
bt_obex_get session_id="ftp_..." remote_path="IMG_002.jpg" local_path="~/backup/"
|
||||||
|
|
||||||
|
# Close session
|
||||||
|
bt_obex_disconnect session_id="ftp_..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Share Document
|
||||||
|
|
||||||
|
```
|
||||||
|
# Simple send
|
||||||
|
bt_obex_send_file address="..." file_path="~/report.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Device Compatibility
|
||||||
|
|
||||||
|
| Device Type | OPP | FTP |
|
||||||
|
|-------------|-----|-----|
|
||||||
|
| Android phones | ✓ | Varies |
|
||||||
|
| iPhones | ✓ | ✗ |
|
||||||
|
| Feature phones | ✓ | ✓ |
|
||||||
|
| Windows PCs | ✓ | ✓ |
|
||||||
|
| macOS | ✓ | ✗ |
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
FTP support varies by Android version and manufacturer. Some require enabling "File Transfer" mode in Bluetooth settings.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Device rejected connection"
|
||||||
|
|
||||||
|
- Ensure device is paired first
|
||||||
|
- Check device has OBEX enabled in Bluetooth settings
|
||||||
|
- Some devices require explicit file sharing permission
|
||||||
|
|
||||||
|
### "NotSupported"
|
||||||
|
|
||||||
|
The device doesn't support the requested profile. Try OPP instead of FTP.
|
||||||
|
|
||||||
|
### Transfer Stuck at 0%
|
||||||
|
|
||||||
|
The receiving device may be showing an accept prompt. Check its screen.
|
||||||
|
|
||||||
|
### Session Disappeared
|
||||||
|
|
||||||
|
Sessions are tied to obexd. If it restarts, create a new session.
|
||||||
237
docs-site/src/content/docs/guides/pairing.md
Normal file
237
docs-site/src/content/docs/guides/pairing.md
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
---
|
||||||
|
title: Device Pairing
|
||||||
|
description: Pair Bluetooth devices with automatic PIN and passkey handling
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Pairing establishes a trusted relationship between devices, enabling secure communication. mcbluetooth includes a smart pairing agent that handles all Bluetooth pairing methods.
|
||||||
|
|
||||||
|
## Scanning for Devices
|
||||||
|
|
||||||
|
Before pairing, discover available devices:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_scan adapter="hci0" timeout=10 mode="both"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Scan modes:**
|
||||||
|
- `classic` — Traditional Bluetooth (BR/EDR)
|
||||||
|
- `ble` — Bluetooth Low Energy only
|
||||||
|
- `both` — Both types (default)
|
||||||
|
|
||||||
|
## Initiating Pairing
|
||||||
|
|
||||||
|
### Basic Pairing
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pairing Modes
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="Interactive (default)">
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="interactive"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns immediately with status. If confirmation needed, use `bt_pair_confirm` to respond.
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Auto">
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="auto"
|
||||||
|
```
|
||||||
|
|
||||||
|
Automatically accepts all pairing requests. Use only in trusted environments.
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Elicit">
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="..." pairing_mode="elicit"
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses MCP elicitation to prompt the user directly (if the MCP client supports it).
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Pairing Methods
|
||||||
|
|
||||||
|
Bluetooth uses different pairing methods based on device capabilities:
|
||||||
|
|
||||||
|
| Method | Description | Agent Action |
|
||||||
|
|--------|-------------|--------------|
|
||||||
|
| **Just Works** | No user interaction | Auto-accepted |
|
||||||
|
| **Numeric Comparison** | Confirm 6-digit code matches | Show code, await confirmation |
|
||||||
|
| **Passkey Entry** | Enter code shown on other device | Prompt for passkey |
|
||||||
|
| **Legacy PIN** | Enter 4-6 digit PIN | Prompt for PIN |
|
||||||
|
|
||||||
|
### Handling Confirmation Requests
|
||||||
|
|
||||||
|
When pairing requires confirmation:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Check for pending requests
|
||||||
|
bt_pairing_status
|
||||||
|
|
||||||
|
# Confirm with passkey (if needed)
|
||||||
|
bt_pair_confirm adapter="hci0" address="..." passkey=123456 accept=true
|
||||||
|
|
||||||
|
# Or reject
|
||||||
|
bt_pair_confirm adapter="hci0" address="..." accept=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Managing Paired Devices
|
||||||
|
|
||||||
|
### List Paired Devices
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_list_devices adapter="hci0" filter="paired"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Remove Pairing
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_unpair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
This removes the device from known devices and deletes all pairing information.
|
||||||
|
|
||||||
|
## Connection Management
|
||||||
|
|
||||||
|
### Connect to Paired Device
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disconnect
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_disconnect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Disconnecting preserves the pairing. The device can reconnect later.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Trust and Security
|
||||||
|
|
||||||
|
### Trust a Device
|
||||||
|
|
||||||
|
Trusted devices can connect automatically without explicit authorization:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_trust adapter="hci0" address="..." trusted=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Untrust
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_trust adapter="hci0" address="..." trusted=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Block a Device
|
||||||
|
|
||||||
|
Prevent a device from connecting:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_block adapter="hci0" address="..." blocked=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unblock
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_block adapter="hci0" address="..." blocked=false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Device Information
|
||||||
|
|
||||||
|
### Get Device Details
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_device_info adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"alias": "My Headphones",
|
||||||
|
"paired": true,
|
||||||
|
"bonded": true,
|
||||||
|
"trusted": true,
|
||||||
|
"connected": true,
|
||||||
|
"uuids": ["0000110b-...", "0000110e-..."],
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Device Name
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_device_set_alias adapter="hci0" address="..." alias="My Headphones"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Pair New Headphones
|
||||||
|
|
||||||
|
```
|
||||||
|
# Put headphones in pairing mode first!
|
||||||
|
|
||||||
|
# Scan for them
|
||||||
|
bt_scan adapter="hci0" timeout=15
|
||||||
|
|
||||||
|
# Pair
|
||||||
|
bt_pair adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
|
||||||
|
# Trust for auto-reconnect
|
||||||
|
bt_trust adapter="hci0" address="C8:7B:23:55:68:E8" trusted=true
|
||||||
|
|
||||||
|
# Connect
|
||||||
|
bt_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pair a Phone for OBEX
|
||||||
|
|
||||||
|
```
|
||||||
|
# Scan and pair
|
||||||
|
bt_scan adapter="hci0"
|
||||||
|
bt_pair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Both devices may show confirmation prompts - accept on both
|
||||||
|
|
||||||
|
# After pairing, OBEX profiles become available
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Pairing Fails Immediately
|
||||||
|
|
||||||
|
- Ensure the device is in pairing mode
|
||||||
|
- Check device isn't already paired (try `bt_unpair` first)
|
||||||
|
- Verify adapter is powered and pairable
|
||||||
|
|
||||||
|
### "Authentication Rejected"
|
||||||
|
|
||||||
|
- Device may have reached its pairing limit
|
||||||
|
- Try resetting Bluetooth on the other device
|
||||||
|
- Delete the pairing on both sides and retry
|
||||||
|
|
||||||
|
### Pairing Stuck
|
||||||
|
|
||||||
|
```
|
||||||
|
# Check for pending requests
|
||||||
|
bt_pairing_status
|
||||||
|
|
||||||
|
# Cancel if stuck
|
||||||
|
bt_pair_confirm adapter="hci0" address="..." accept=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Device Connects Then Disconnects
|
||||||
|
|
||||||
|
- Profile incompatibility (e.g., device doesn't support expected audio profile)
|
||||||
|
- Check device UUIDs with `bt_device_info`
|
||||||
|
- Try connecting specific profile with `bt_connect_profile`
|
||||||
265
docs-site/src/content/docs/guides/phonebook-messages.md
Normal file
265
docs-site/src/content/docs/guides/phonebook-messages.md
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
---
|
||||||
|
title: Phonebook & Messages
|
||||||
|
description: Access contacts and SMS using PBAP and MAP profiles
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
PBAP (Phonebook Access Profile) and MAP (Message Access Profile) let you read contacts and messages from paired phones.
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Both profiles require the device to be paired first. See [Device Pairing](/guides/pairing/).
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
These profiles use OBEX. Ensure obexd is installed:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
If not ready:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="Arch Linux">
|
||||||
|
```bash
|
||||||
|
sudo pacman -S bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Debian/Ubuntu">
|
||||||
|
```bash
|
||||||
|
sudo apt install bluez-obex
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Phonebook Access (PBAP)
|
||||||
|
|
||||||
|
### Download Entire Phonebook
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_pull address="AA:BB:CC:DD:EE:FF" save_path="~/contacts.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
This downloads all contacts as a single vCard file.
|
||||||
|
|
||||||
|
### List Contacts
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_list address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"entries": [
|
||||||
|
{"handle": "1.vcf", "name": "Alice Smith"},
|
||||||
|
{"handle": "2.vcf", "name": "Bob Jones"},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"count": 150
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get Single Contact
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_get address="..." handle="1.vcf" save_path="~/alice.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Search Contacts
|
||||||
|
|
||||||
|
```
|
||||||
|
# Search by name
|
||||||
|
bt_phonebook_search address="..." field="name" value="Smith"
|
||||||
|
|
||||||
|
# Search by phone number
|
||||||
|
bt_phonebook_search address="..." field="number" value="+1555"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Count Contacts
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_count address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns total number of contacts without downloading them.
|
||||||
|
|
||||||
|
### Phonebook Folders
|
||||||
|
|
||||||
|
PBAP provides access to different phonebook locations:
|
||||||
|
|
||||||
|
| Folder | Contents |
|
||||||
|
|--------|----------|
|
||||||
|
| `telecom/pb` | Main phonebook (default) |
|
||||||
|
| `telecom/ich` | Incoming call history |
|
||||||
|
| `telecom/och` | Outgoing call history |
|
||||||
|
| `telecom/mch` | Missed call history |
|
||||||
|
| `telecom/cch` | Combined call history |
|
||||||
|
| `SIM1/telecom/pb` | SIM card contacts |
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_list address="..." folder="telecom/ich"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Message Access (MAP)
|
||||||
|
|
||||||
|
### List Message Folders
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_messages_folders address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{"name": "inbox"},
|
||||||
|
{"name": "sent"},
|
||||||
|
{"name": "drafts"},
|
||||||
|
{"name": "outbox"},
|
||||||
|
{"name": "deleted"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Messages
|
||||||
|
|
||||||
|
```
|
||||||
|
# All inbox messages
|
||||||
|
bt_messages_list address="..." folder="inbox"
|
||||||
|
|
||||||
|
# Unread only
|
||||||
|
bt_messages_list address="..." folder="inbox" unread_only=true
|
||||||
|
|
||||||
|
# Limit results
|
||||||
|
bt_messages_list address="..." folder="inbox" max_count=50
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"handle": "msg001",
|
||||||
|
"subject": "Meeting tomorrow",
|
||||||
|
"sender": "+15551234567",
|
||||||
|
"timestamp": "2024-01-15T10:30:00",
|
||||||
|
"read": false,
|
||||||
|
"type": "SMS"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Download Message
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_messages_get address="..." handle="msg001" save_path="~/message.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Send Message
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Message sending support varies by device. Many phones only allow read access.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_messages_send address="..." recipient="+15559876543" message="Hello from mcbluetooth!"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Backup All Contacts
|
||||||
|
|
||||||
|
```
|
||||||
|
# Download as vCard (can import into any contact app)
|
||||||
|
bt_phonebook_pull address="AA:BB:CC:DD:EE:FF" save_path="~/phone_backup_$(date +%Y%m%d).vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Export Call History
|
||||||
|
|
||||||
|
```
|
||||||
|
# Get incoming calls
|
||||||
|
bt_phonebook_list address="..." folder="telecom/ich"
|
||||||
|
|
||||||
|
# Get missed calls
|
||||||
|
bt_phonebook_list address="..." folder="telecom/mch"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Find Contact by Phone Number
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_search address="..." field="number" value="555-1234"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Archive Text Messages
|
||||||
|
|
||||||
|
```
|
||||||
|
# List all sent messages
|
||||||
|
bt_messages_list address="..." folder="sent"
|
||||||
|
|
||||||
|
# Download specific message
|
||||||
|
bt_messages_get address="..." handle="msg042" save_path="~/messages/msg042.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Device Compatibility
|
||||||
|
|
||||||
|
### PBAP Support
|
||||||
|
|
||||||
|
| Device | Support |
|
||||||
|
|--------|---------|
|
||||||
|
| Android phones | ✓ Full |
|
||||||
|
| iPhones | ✓ Full (when paired) |
|
||||||
|
| Feature phones | ✓ Usually |
|
||||||
|
| Car systems | ✓ Often (receive only) |
|
||||||
|
|
||||||
|
### MAP Support
|
||||||
|
|
||||||
|
| Device | Read | Send |
|
||||||
|
|--------|------|------|
|
||||||
|
| Android | ✓ | Varies |
|
||||||
|
| iPhone | ✗ | ✗ |
|
||||||
|
| Feature phones | Varies | Varies |
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
iPhone doesn't support MAP. Use iCloud or other sync methods for messages.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "NotAuthorized" Error
|
||||||
|
|
||||||
|
The phone is blocking access. Check:
|
||||||
|
1. Phone screen for permission prompt
|
||||||
|
2. Bluetooth settings → paired device → enable phonebook/message access
|
||||||
|
|
||||||
|
### Empty Phonebook
|
||||||
|
|
||||||
|
Some phones require explicit permission:
|
||||||
|
- **Android**: Settings → Apps → Bluetooth → Permissions → Contacts
|
||||||
|
- **iPhone**: Settings → Bluetooth → [device] → Allow Contact Access
|
||||||
|
|
||||||
|
### MAP Connection Fails
|
||||||
|
|
||||||
|
1. Verify device supports MAP: `bt_device_info adapter="hci0" address="..."`
|
||||||
|
2. Check for MAP UUID in the UUIDs list
|
||||||
|
3. Some devices need MAP enabled in Bluetooth settings
|
||||||
|
|
||||||
|
### Slow Downloads
|
||||||
|
|
||||||
|
Large phonebooks (1000+ contacts) take time:
|
||||||
|
- PBAP downloads are sequential
|
||||||
|
- Consider using `bt_phonebook_count` first to estimate
|
||||||
|
- vCard format is verbose
|
||||||
|
|
||||||
|
## Privacy Considerations
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
These tools access personal data. Use responsibly and only on devices you own or have explicit permission to access.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
- Phonebook and message access requires active pairing
|
||||||
|
- Devices typically prompt for permission on first access
|
||||||
|
- Permission can be revoked on the phone at any time
|
||||||
105
docs-site/src/content/docs/index.mdx
Normal file
105
docs-site/src/content/docs/index.mdx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
title: mcbluetooth
|
||||||
|
description: Give LLMs control of your Linux Bluetooth stack
|
||||||
|
template: splash
|
||||||
|
hero:
|
||||||
|
tagline: A comprehensive MCP server that exposes the Linux Bluetooth stack to LLMs. Control adapters, pair devices, manage audio, read BLE sensors, and transfer files — all through natural language.
|
||||||
|
image:
|
||||||
|
file: ../../assets/logo-dark.svg
|
||||||
|
actions:
|
||||||
|
- text: Get Started
|
||||||
|
link: /getting-started/introduction/
|
||||||
|
icon: right-arrow
|
||||||
|
- text: View on GitHub
|
||||||
|
link: https://github.com/yourusername/mcbluetooth
|
||||||
|
icon: external
|
||||||
|
variant: minimal
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
<CardGrid stagger>
|
||||||
|
<Card title="Full BlueZ Integration" icon="bluetooth">
|
||||||
|
Adapters, devices, pairing, audio profiles, and BLE/GATT — the complete Linux Bluetooth stack at your fingertips.
|
||||||
|
</Card>
|
||||||
|
<Card title="Smart Pairing Agent" icon="shield">
|
||||||
|
Handles PIN codes, passkeys, and numeric comparison automatically. Supports interactive, auto, and elicitation modes.
|
||||||
|
</Card>
|
||||||
|
<Card title="Audio Control" icon="headphones">
|
||||||
|
PipeWire and PulseAudio integration for seamless Bluetooth audio management. Switch profiles, adjust volume, set defaults.
|
||||||
|
</Card>
|
||||||
|
<Card title="OBEX Profiles" icon="folder">
|
||||||
|
File transfer (OPP/FTP), phonebook access (PBAP), and message access (MAP) for connected phones and devices.
|
||||||
|
</Card>
|
||||||
|
<Card title="BLE & GATT" icon="cpu">
|
||||||
|
Read sensors, write commands, subscribe to notifications. Full support for Bluetooth Low Energy devices.
|
||||||
|
</Card>
|
||||||
|
<Card title="Protocol Analysis" icon="magnifier">
|
||||||
|
Capture and analyze Bluetooth traffic with btmon integration. Debug connections and reverse engineer protocols.
|
||||||
|
</Card>
|
||||||
|
</CardGrid>
|
||||||
|
|
||||||
|
## Example Conversation
|
||||||
|
|
||||||
|
```
|
||||||
|
You: Scan for Bluetooth devices and connect to my Bose headphones
|
||||||
|
|
||||||
|
Claude: I'll scan for nearby Bluetooth devices.
|
||||||
|
|
||||||
|
[Calling bt_scan with adapter="hci0", timeout=10, mode="both"]
|
||||||
|
|
||||||
|
Found 5 devices:
|
||||||
|
• Bombay (C8:7B:23:55:68:E8) - Bose NCH700, paired
|
||||||
|
• DS18 BT-TWO (20:23:05:26:02:31) - Audio device
|
||||||
|
• iPhone (AA:BB:CC:DD:EE:FF) - Phone
|
||||||
|
...
|
||||||
|
|
||||||
|
I found your Bose headphones "Bombay". Connecting now...
|
||||||
|
|
||||||
|
[Calling bt_connect with adapter="hci0", address="C8:7B:23:55:68:E8"]
|
||||||
|
|
||||||
|
✓ Connected to Bombay! The headphones are ready. Would you like me
|
||||||
|
to set them as the default audio output?
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Install
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="uvx (recommended)">
|
||||||
|
```bash
|
||||||
|
# Run directly
|
||||||
|
uvx mcbluetooth
|
||||||
|
|
||||||
|
# Or install globally
|
||||||
|
uv tool install mcbluetooth
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="From source">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/mcbluetooth
|
||||||
|
cd mcbluetooth
|
||||||
|
uv sync
|
||||||
|
uv run mcbluetooth
|
||||||
|
```
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Add to Claude Code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude mcp add mcbluetooth -- uvx mcbluetooth
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tool Categories
|
||||||
|
|
||||||
|
| Category | Tools | Description |
|
||||||
|
|----------|-------|-------------|
|
||||||
|
| **Adapter** | 6 | Power, discoverable, pairable, alias |
|
||||||
|
| **Device** | 12 | Scan, pair, connect, trust, block |
|
||||||
|
| **Audio** | 7 | Profiles, volume, mute, default sink |
|
||||||
|
| **BLE** | 7 | GATT services, characteristics, notify |
|
||||||
|
| **Monitor** | 6 | HCI capture, parse, analyze |
|
||||||
|
| **OBEX** | 23 | File transfer, phonebook, messages |
|
||||||
|
| **Total** | **61** | Complete Bluetooth control |
|
||||||
217
docs-site/src/content/docs/reference/adapter-tools.md
Normal file
217
docs-site/src/content/docs/reference/adapter-tools.md
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
---
|
||||||
|
title: Adapter Tools
|
||||||
|
description: Reference for Bluetooth adapter management tools
|
||||||
|
---
|
||||||
|
|
||||||
|
Tools for managing Bluetooth hardware adapters.
|
||||||
|
|
||||||
|
## bt_list_adapters
|
||||||
|
|
||||||
|
List all Bluetooth adapters on the system.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"alias": "My Laptop",
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"discoverable_timeout": 180,
|
||||||
|
"pairable": true,
|
||||||
|
"pairable_timeout": 0,
|
||||||
|
"discovering": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_list_adapters
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_adapter_info
|
||||||
|
|
||||||
|
Get detailed information about a specific adapter.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name (e.g., "hci0") |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"alias": "My Laptop",
|
||||||
|
"class": 7995916,
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"discoverable_timeout": 180,
|
||||||
|
"pairable": true,
|
||||||
|
"pairable_timeout": 0,
|
||||||
|
"discovering": false,
|
||||||
|
"uuids": [
|
||||||
|
"0000110a-0000-1000-8000-00805f9b34fb",
|
||||||
|
"0000110c-0000-1000-8000-00805f9b34fb"
|
||||||
|
],
|
||||||
|
"modalias": "usb:v1D6Bp0246d0540"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_adapter_info adapter="hci0"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_adapter_power
|
||||||
|
|
||||||
|
Power an adapter on or off.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `on` | boolean | Yes | true to power on, false to power off |
|
||||||
|
|
||||||
|
**Returns:** Updated adapter info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_adapter_power adapter="hci0" on=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Powering off disconnects all devices
|
||||||
|
- Stops any ongoing discovery
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_adapter_discoverable
|
||||||
|
|
||||||
|
Set adapter discoverable (visible to other devices).
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `on` | boolean | Yes | - | Enable/disable discoverable |
|
||||||
|
| `timeout` | integer | No | 180 | Seconds until auto-hidden (0 = forever) |
|
||||||
|
|
||||||
|
**Returns:** Updated adapter info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Discoverable for 5 minutes
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=true timeout=300
|
||||||
|
|
||||||
|
# Discoverable forever (use carefully)
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=true timeout=0
|
||||||
|
|
||||||
|
# Hide from other devices
|
||||||
|
bt_adapter_discoverable adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_adapter_pairable
|
||||||
|
|
||||||
|
Set adapter pairable state.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `on` | boolean | Yes | - | Enable/disable pairing acceptance |
|
||||||
|
| `timeout` | integer | No | 0 | Seconds until auto-disable (0 = forever) |
|
||||||
|
|
||||||
|
**Returns:** Updated adapter info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Accept pairings for 5 minutes
|
||||||
|
bt_adapter_pairable adapter="hci0" on=true timeout=300
|
||||||
|
|
||||||
|
# Stop accepting pairings
|
||||||
|
bt_adapter_pairable adapter="hci0" on=false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_adapter_set_alias
|
||||||
|
|
||||||
|
Set adapter friendly name (alias).
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `alias` | string | Yes | New friendly name |
|
||||||
|
|
||||||
|
**Returns:** Updated adapter info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_adapter_set_alias adapter="hci0" alias="Ryan's Desktop"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_scan
|
||||||
|
|
||||||
|
Scan for nearby Bluetooth devices.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `timeout` | integer | No | 10 | Scan duration in seconds |
|
||||||
|
| `mode` | string | No | "both" | Scan mode: "classic", "ble", or "both" |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "My Device",
|
||||||
|
"alias": "My Device",
|
||||||
|
"paired": false,
|
||||||
|
"connected": false,
|
||||||
|
"rssi": -65,
|
||||||
|
"uuids": ["0000110a-..."],
|
||||||
|
"manufacturer_data": {...},
|
||||||
|
"service_data": {...}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Standard scan
|
||||||
|
bt_scan adapter="hci0" timeout=10
|
||||||
|
|
||||||
|
# BLE only
|
||||||
|
bt_scan adapter="hci0" timeout=15 mode="ble"
|
||||||
|
|
||||||
|
# Classic only (faster for headphones, speakers)
|
||||||
|
bt_scan adapter="hci0" timeout=10 mode="classic"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Starts discovery, waits for timeout, then stops
|
||||||
|
- BLE devices must be advertising to be found
|
||||||
|
- Returns devices discovered during the scan period
|
||||||
256
docs-site/src/content/docs/reference/audio-tools.md
Normal file
256
docs-site/src/content/docs/reference/audio-tools.md
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
---
|
||||||
|
title: Audio Tools
|
||||||
|
description: Reference for Bluetooth audio management tools
|
||||||
|
---
|
||||||
|
|
||||||
|
Tools for managing Bluetooth audio with PipeWire/PulseAudio integration.
|
||||||
|
|
||||||
|
## bt_audio_list
|
||||||
|
|
||||||
|
List all audio devices including Bluetooth.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sinks": [
|
||||||
|
{
|
||||||
|
"name": "bluez_sink.C8_7B_23_55_68_E8.a2dp_sink",
|
||||||
|
"description": "Bose Headphones",
|
||||||
|
"bluetooth_address": "C8:7B:23:55:68:E8",
|
||||||
|
"volume": 65536,
|
||||||
|
"volume_percent": 75,
|
||||||
|
"muted": false,
|
||||||
|
"state": "running"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "bluez_source.C8_7B_23_55_68_E8.hfp_ag",
|
||||||
|
"description": "Bose Headphones (Microphone)",
|
||||||
|
"bluetooth_address": "C8:7B:23:55:68:E8",
|
||||||
|
"volume": 65536,
|
||||||
|
"volume_percent": 100,
|
||||||
|
"muted": false,
|
||||||
|
"state": "idle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cards": [
|
||||||
|
{
|
||||||
|
"name": "bluez_card.C8_7B_23_55_68_E8",
|
||||||
|
"bluetooth_address": "C8:7B:23:55:68:E8",
|
||||||
|
"active_profile": "a2dp-sink",
|
||||||
|
"profiles": ["a2dp-sink", "hfp-hf", "off"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_audio_list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_connect
|
||||||
|
|
||||||
|
Connect audio profiles to a Bluetooth device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "connected",
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"profiles": ["a2dp-sink", "hfp-hf"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_audio_connect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Connects A2DP (high-quality audio) and/or HFP (hands-free) profiles
|
||||||
|
- Device must be paired first
|
||||||
|
- Automatically registers with PipeWire/PulseAudio
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_disconnect
|
||||||
|
|
||||||
|
Disconnect audio profiles from a Bluetooth device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "disconnected",
|
||||||
|
"address": "C8:7B:23:55:68:E8"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_audio_disconnect adapter="hci0" address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Disconnects audio profiles only
|
||||||
|
- Device remains connected for other services
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_set_profile
|
||||||
|
|
||||||
|
Switch audio profile for a Bluetooth device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `profile` | string | Yes | Profile: "a2dp", "hfp", or "off" |
|
||||||
|
|
||||||
|
**Profiles:**
|
||||||
|
| Profile | Quality | Microphone | Use Case |
|
||||||
|
|---------|---------|------------|----------|
|
||||||
|
| `a2dp` | High (stereo) | No | Music, videos |
|
||||||
|
| `hfp` | Low (mono) | Yes | Phone calls |
|
||||||
|
| `off` | - | - | Disable audio |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "profile_changed",
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"profile": "a2dp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# High-quality for music
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="a2dp"
|
||||||
|
|
||||||
|
# Enable microphone for calls
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="hfp"
|
||||||
|
|
||||||
|
# Disable audio (stay connected for other profiles)
|
||||||
|
bt_audio_set_profile address="C8:7B:23:55:68:E8" profile="off"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_set_default
|
||||||
|
|
||||||
|
Set a Bluetooth device as the default audio output.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "default_set",
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"sink": "bluez_sink.C8_7B_23_55_68_E8.a2dp_sink"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_audio_set_default address="C8:7B:23:55:68:E8"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- All system audio routes to this device
|
||||||
|
- Persists until changed or device disconnects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_volume
|
||||||
|
|
||||||
|
Set volume for a Bluetooth audio device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `volume` | integer | Yes | Volume level (0-100, can go up to 150) |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "volume_set",
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"volume": 75
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Normal volume
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=75
|
||||||
|
|
||||||
|
# Boost (may distort)
|
||||||
|
bt_audio_volume address="C8:7B:23:55:68:E8" volume=120
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- 0-100 is standard range
|
||||||
|
- 100-150 provides software amplification (may cause distortion)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_audio_mute
|
||||||
|
|
||||||
|
Mute or unmute a Bluetooth audio device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `muted` | boolean | Yes | true to mute, false to unmute |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "mute_changed",
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"muted": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Mute
|
||||||
|
bt_audio_mute address="C8:7B:23:55:68:E8" muted=true
|
||||||
|
|
||||||
|
# Unmute
|
||||||
|
bt_audio_mute address="C8:7B:23:55:68:E8" muted=false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Preserves volume level
|
||||||
|
- Faster than setting volume to 0
|
||||||
283
docs-site/src/content/docs/reference/ble-tools.md
Normal file
283
docs-site/src/content/docs/reference/ble-tools.md
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
---
|
||||||
|
title: BLE Tools
|
||||||
|
description: Reference for Bluetooth Low Energy and GATT tools
|
||||||
|
---
|
||||||
|
|
||||||
|
Tools for interacting with Bluetooth Low Energy devices — sensors, fitness trackers, IoT devices, and more.
|
||||||
|
|
||||||
|
## bt_ble_scan
|
||||||
|
|
||||||
|
Scan for BLE (Bluetooth Low Energy) devices.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `timeout` | integer | No | 10 | Scan duration in seconds |
|
||||||
|
| `name_filter` | string | No | - | Only devices with name containing this |
|
||||||
|
| `service_filter` | string | No | - | Only devices advertising this service UUID |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "Heart Rate Monitor",
|
||||||
|
"rssi": -65,
|
||||||
|
"uuids": ["0000180d-0000-1000-8000-00805f9b34fb"],
|
||||||
|
"manufacturer_data": {"76": "02150201..."},
|
||||||
|
"service_data": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Basic scan
|
||||||
|
bt_ble_scan adapter="hci0" timeout=10
|
||||||
|
|
||||||
|
# Filter by name
|
||||||
|
bt_ble_scan adapter="hci0" name_filter="Fitness"
|
||||||
|
|
||||||
|
# Filter by service (Heart Rate)
|
||||||
|
bt_ble_scan adapter="hci0" service_filter="0000180d-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_services
|
||||||
|
|
||||||
|
List GATT services for a connected BLE device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"uuid": "0000180f-0000-1000-8000-00805f9b34fb",
|
||||||
|
"primary": true,
|
||||||
|
"description": "Battery Service"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uuid": "0000180d-0000-1000-8000-00805f9b34fb",
|
||||||
|
"primary": true,
|
||||||
|
"description": "Heart Rate Service"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_ble_services adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Device must be connected first
|
||||||
|
- Wait 2-3 seconds after connecting for service discovery
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_characteristics
|
||||||
|
|
||||||
|
List GATT characteristics for a BLE device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `service_uuid` | string | No | - | Filter to this service only |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"uuid": "00002a19-0000-1000-8000-00805f9b34fb",
|
||||||
|
"service_uuid": "0000180f-0000-1000-8000-00805f9b34fb",
|
||||||
|
"flags": ["read", "notify"],
|
||||||
|
"description": "Battery Level"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# All characteristics
|
||||||
|
bt_ble_characteristics adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
|
||||||
|
# Filter by service
|
||||||
|
bt_ble_characteristics adapter="hci0" address="..." service_uuid="0000180f-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_read
|
||||||
|
|
||||||
|
Read a GATT characteristic value.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `char_uuid` | string | Yes | Characteristic UUID |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"uuid": "00002a19-0000-1000-8000-00805f9b34fb",
|
||||||
|
"hex": "4b",
|
||||||
|
"decoded": 75,
|
||||||
|
"description": "Battery Level: 75%"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_ble_read adapter="hci0" address="AA:BB:CC:DD:EE:FF" char_uuid="00002a19-0000-1000-8000-00805f9b34fb"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Characteristic must have `read` flag
|
||||||
|
- Device must be connected
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_write
|
||||||
|
|
||||||
|
Write a value to a GATT characteristic.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `char_uuid` | string | Yes | - | Characteristic UUID |
|
||||||
|
| `value` | string | Yes | - | Value to write |
|
||||||
|
| `value_type` | string | No | "hex" | How to interpret value: "hex", "string", "int" |
|
||||||
|
| `with_response` | boolean | No | true | Wait for write acknowledgment |
|
||||||
|
|
||||||
|
**Value Types:**
|
||||||
|
| Type | Example | Bytes Written |
|
||||||
|
|------|---------|---------------|
|
||||||
|
| `hex` | "0102ff" | 0x01, 0x02, 0xFF |
|
||||||
|
| `string` | "hello" | UTF-8 encoded |
|
||||||
|
| `int` | "42" | Single byte (0-255) |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "written",
|
||||||
|
"uuid": "...",
|
||||||
|
"bytes_written": 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Write hex bytes
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="0102ff" value_type="hex"
|
||||||
|
|
||||||
|
# Write string
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="hello" value_type="string"
|
||||||
|
|
||||||
|
# Write without waiting for response (faster)
|
||||||
|
bt_ble_write adapter="hci0" address="..." char_uuid="..." value="01" with_response=false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_notify
|
||||||
|
|
||||||
|
Enable or disable notifications for a characteristic.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `char_uuid` | string | Yes | Characteristic UUID |
|
||||||
|
| `enable` | boolean | Yes | true to enable, false to disable |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "notifications_enabled",
|
||||||
|
"uuid": "00002a37-0000-1000-8000-00805f9b34fb"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Enable heart rate notifications
|
||||||
|
bt_ble_notify adapter="hci0" address="..." char_uuid="00002a37-0000-1000-8000-00805f9b34fb" enable=true
|
||||||
|
|
||||||
|
# Disable notifications
|
||||||
|
bt_ble_notify adapter="hci0" address="..." char_uuid="..." enable=false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Characteristic must have `notify` flag
|
||||||
|
- Notifications are delivered via GATT protocol
|
||||||
|
- Use protocol capture to see notification data
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_ble_battery
|
||||||
|
|
||||||
|
Read battery level from a BLE device (convenience function).
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"battery_level": 75,
|
||||||
|
"unit": "percent"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_ble_battery adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Uses standard Battery Service (UUID 0x180F)
|
||||||
|
- Returns error if device doesn't support battery service
|
||||||
|
|
||||||
|
## Common UUIDs
|
||||||
|
|
||||||
|
### Services
|
||||||
|
|
||||||
|
| Service | Short UUID | Full UUID |
|
||||||
|
|---------|------------|-----------|
|
||||||
|
| Battery | 0x180F | 0000180f-0000-1000-8000-00805f9b34fb |
|
||||||
|
| Heart Rate | 0x180D | 0000180d-0000-1000-8000-00805f9b34fb |
|
||||||
|
| Device Info | 0x180A | 0000180a-0000-1000-8000-00805f9b34fb |
|
||||||
|
| Generic Access | 0x1800 | 00001800-0000-1000-8000-00805f9b34fb |
|
||||||
|
|
||||||
|
### Characteristics
|
||||||
|
|
||||||
|
| Characteristic | Short UUID | Service |
|
||||||
|
|----------------|------------|---------|
|
||||||
|
| Battery Level | 0x2A19 | Battery |
|
||||||
|
| Heart Rate Measurement | 0x2A37 | Heart Rate |
|
||||||
|
| Manufacturer Name | 0x2A29 | Device Info |
|
||||||
|
| Model Number | 0x2A24 | Device Info |
|
||||||
345
docs-site/src/content/docs/reference/device-tools.md
Normal file
345
docs-site/src/content/docs/reference/device-tools.md
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
---
|
||||||
|
title: Device Tools
|
||||||
|
description: Reference for device discovery, pairing, and connection tools
|
||||||
|
---
|
||||||
|
|
||||||
|
Tools for managing Bluetooth device lifecycle — discovery, pairing, connection, and trust.
|
||||||
|
|
||||||
|
## bt_list_devices
|
||||||
|
|
||||||
|
List known Bluetooth devices.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `filter` | string | No | "all" | Filter: "all", "paired", "connected", "trusted" |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "My Headphones",
|
||||||
|
"alias": "Work Headphones",
|
||||||
|
"paired": true,
|
||||||
|
"connected": true,
|
||||||
|
"trusted": true,
|
||||||
|
"blocked": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_list_devices adapter="hci0" filter="paired"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_device_info
|
||||||
|
|
||||||
|
Get detailed information about a specific device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"alias": "My Headphones",
|
||||||
|
"class": 2360344,
|
||||||
|
"icon": "audio-headphones",
|
||||||
|
"paired": true,
|
||||||
|
"bonded": true,
|
||||||
|
"trusted": true,
|
||||||
|
"blocked": false,
|
||||||
|
"connected": true,
|
||||||
|
"legacy_pairing": false,
|
||||||
|
"rssi": -55,
|
||||||
|
"uuids": [
|
||||||
|
"0000110b-0000-1000-8000-00805f9b34fb",
|
||||||
|
"0000110e-0000-1000-8000-00805f9b34fb"
|
||||||
|
],
|
||||||
|
"modalias": "bluetooth:v009Ep4020d0134",
|
||||||
|
"adapter": "/org/bluez/hci0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_device_info adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_device_set_alias
|
||||||
|
|
||||||
|
Set a friendly name for a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `alias` | string | Yes | New friendly name |
|
||||||
|
|
||||||
|
**Returns:** Updated device info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_device_set_alias adapter="hci0" address="AA:BB:CC:DD:EE:FF" alias="Work Headphones"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_pair
|
||||||
|
|
||||||
|
Initiate pairing with a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `pairing_mode` | string | No | "interactive" | Mode: "interactive", "auto", "elicit" |
|
||||||
|
| `timeout` | integer | No | 60 | Pairing timeout in seconds |
|
||||||
|
|
||||||
|
**Pairing Modes:**
|
||||||
|
- `interactive` — Returns status; use `bt_pair_confirm` to respond to prompts
|
||||||
|
- `auto` — Auto-accepts all requests (trusted environments only)
|
||||||
|
- `elicit` — Uses MCP elicitation for PIN prompts (if supported)
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "paired",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "My Device"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if confirmation needed:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "awaiting_confirmation",
|
||||||
|
"method": "numeric_comparison",
|
||||||
|
"passkey": 123456
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_pair adapter="hci0" address="AA:BB:CC:DD:EE:FF" pairing_mode="interactive"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_pair_confirm
|
||||||
|
|
||||||
|
Confirm or reject a pairing request.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `adapter` | string | Yes | - | Adapter name |
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `accept` | boolean | No | true | Accept or reject pairing |
|
||||||
|
| `pin` | string | No | - | PIN code if required |
|
||||||
|
| `passkey` | integer | No | - | Numeric passkey (0-999999) |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "paired",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Accept with passkey
|
||||||
|
bt_pair_confirm adapter="hci0" address="AA:BB:CC:DD:EE:FF" passkey=123456 accept=true
|
||||||
|
|
||||||
|
# Reject pairing
|
||||||
|
bt_pair_confirm adapter="hci0" address="AA:BB:CC:DD:EE:FF" accept=false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_pairing_status
|
||||||
|
|
||||||
|
Get status of pending pairing requests.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pending_requests": [
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"method": "passkey_entry",
|
||||||
|
"timestamp": "2024-01-15T10:30:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_pairing_status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_unpair
|
||||||
|
|
||||||
|
Remove pairing with a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "unpaired",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_unpair adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Removes device from known devices
|
||||||
|
- Deletes all stored pairing information
|
||||||
|
- Device must be re-paired to connect again
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_connect
|
||||||
|
|
||||||
|
Connect to a paired device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:** Updated device info with `connected: true`
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Device must be paired first
|
||||||
|
- For audio devices, also connects audio profiles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_disconnect
|
||||||
|
|
||||||
|
Disconnect from a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "disconnected",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_disconnect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Preserves pairing (device can reconnect)
|
||||||
|
- Use `bt_unpair` to fully remove device
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_trust
|
||||||
|
|
||||||
|
Set device trust status.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `trusted` | boolean | Yes | Trust state |
|
||||||
|
|
||||||
|
**Returns:** Updated device info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Trust device (auto-connect allowed)
|
||||||
|
bt_trust adapter="hci0" address="AA:BB:CC:DD:EE:FF" trusted=true
|
||||||
|
|
||||||
|
# Untrust device
|
||||||
|
bt_trust adapter="hci0" address="AA:BB:CC:DD:EE:FF" trusted=false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Trusted devices can connect automatically
|
||||||
|
- Untrusted devices require explicit connection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_block
|
||||||
|
|
||||||
|
Block or unblock a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `adapter` | string | Yes | Adapter name |
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `blocked` | boolean | Yes | Block state |
|
||||||
|
|
||||||
|
**Returns:** Updated device info
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Block device
|
||||||
|
bt_block adapter="hci0" address="AA:BB:CC:DD:EE:FF" blocked=true
|
||||||
|
|
||||||
|
# Unblock device
|
||||||
|
bt_block adapter="hci0" address="AA:BB:CC:DD:EE:FF" blocked=false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Blocked devices cannot connect
|
||||||
|
- Existing connection is terminated when blocked
|
||||||
282
docs-site/src/content/docs/reference/monitor-tools.md
Normal file
282
docs-site/src/content/docs/reference/monitor-tools.md
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
---
|
||||||
|
title: Monitor Tools
|
||||||
|
description: Reference for Bluetooth protocol capture and analysis tools
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Tools for capturing and analyzing raw Bluetooth HCI (Host Controller Interface) traffic.
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
Capture requires elevated privileges. See `bt_capture_start` for details.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## bt_capture_start
|
||||||
|
|
||||||
|
Start capturing Bluetooth HCI traffic.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `output_file` | string | Yes | - | Path for btsnoop capture file |
|
||||||
|
| `adapter` | string | No | - | Adapter index (e.g., "0" for hci0), or all if omitted |
|
||||||
|
| `include_sco` | boolean | No | false | Include SCO voice traffic |
|
||||||
|
| `include_a2dp` | boolean | No | false | Include A2DP audio streaming |
|
||||||
|
| `include_iso` | boolean | No | false | Include ISO (LE Audio) traffic |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "started",
|
||||||
|
"capture_id": "capture_abc123",
|
||||||
|
"output_file": "/tmp/bluetooth.btsnoop"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Basic capture
|
||||||
|
bt_capture_start output_file="/tmp/bluetooth.btsnoop"
|
||||||
|
|
||||||
|
# Capture from specific adapter
|
||||||
|
bt_capture_start output_file="/tmp/hci0.btsnoop" adapter="0"
|
||||||
|
|
||||||
|
# Include audio data (large files!)
|
||||||
|
bt_capture_start output_file="/tmp/audio.btsnoop" include_a2dp=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Requires root or `CAP_NET_RAW` capability on btmon
|
||||||
|
- Capture runs in background until stopped
|
||||||
|
- Audio flags generate large files quickly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_capture_stop
|
||||||
|
|
||||||
|
Stop a running Bluetooth capture.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `capture_id` | string | Yes | Capture ID from bt_capture_start |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "stopped",
|
||||||
|
"output_file": "/tmp/bluetooth.btsnoop",
|
||||||
|
"packets_captured": 1542,
|
||||||
|
"file_size": 245760
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_capture_stop capture_id="capture_abc123"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Always stop captures to ensure files are properly closed
|
||||||
|
- Capture ID is returned by bt_capture_start
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_capture_list_active
|
||||||
|
|
||||||
|
List all active Bluetooth captures.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"captures": [
|
||||||
|
{
|
||||||
|
"capture_id": "capture_abc123",
|
||||||
|
"output_file": "/tmp/bluetooth.btsnoop",
|
||||||
|
"started": "2024-01-15T10:30:00",
|
||||||
|
"adapter": "all"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_capture_list_active
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_capture_parse
|
||||||
|
|
||||||
|
Parse a btsnoop capture file and return packet summaries.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `filepath` | string | Yes | - | Path to btsnoop file |
|
||||||
|
| `max_packets` | integer | No | 100 | Maximum packets to return (0 for all) |
|
||||||
|
| `packet_type_filter` | string | No | - | Filter by type: HCI_CMD, ACL_DATA, HCI_EVENT, SCO_DATA |
|
||||||
|
| `direction_filter` | string | No | - | Filter by direction: TX or RX |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"total_packets": 1542,
|
||||||
|
"packet_types": {
|
||||||
|
"HCI_CMD": 234,
|
||||||
|
"HCI_EVENT": 456,
|
||||||
|
"ACL_DATA": 852
|
||||||
|
},
|
||||||
|
"packets": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"timestamp": "2024-01-15T10:30:00.123456",
|
||||||
|
"type": "HCI_CMD",
|
||||||
|
"direction": "TX",
|
||||||
|
"length": 7,
|
||||||
|
"summary": "Inquiry"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# Basic parse
|
||||||
|
bt_capture_parse filepath="/tmp/bluetooth.btsnoop"
|
||||||
|
|
||||||
|
# Only HCI commands
|
||||||
|
bt_capture_parse filepath="..." packet_type_filter="HCI_CMD"
|
||||||
|
|
||||||
|
# Only received packets
|
||||||
|
bt_capture_parse filepath="..." direction_filter="RX"
|
||||||
|
|
||||||
|
# First 50 packets
|
||||||
|
bt_capture_parse filepath="..." max_packets=50
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_capture_analyze
|
||||||
|
|
||||||
|
Analyze a btsnoop capture file with high-level statistics.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `filepath` | string | Yes | Path to btsnoop file |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"duration_seconds": 45.2,
|
||||||
|
"total_packets": 1542,
|
||||||
|
"protocols": {
|
||||||
|
"L2CAP": 423,
|
||||||
|
"RFCOMM": 156,
|
||||||
|
"SDP": 34,
|
||||||
|
"ATT": 289
|
||||||
|
},
|
||||||
|
"connections": [
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "My Device",
|
||||||
|
"packets": 892,
|
||||||
|
"bytes": 45678
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"errors": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_capture_analyze filepath="/tmp/bluetooth.btsnoop"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Provides higher-level view than bt_capture_parse
|
||||||
|
- Useful for understanding overall traffic patterns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## bt_capture_read_raw
|
||||||
|
|
||||||
|
Read raw packet data with btmon-style decoding.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `filepath` | string | Yes | - | Path to btsnoop file |
|
||||||
|
| `offset` | integer | No | 0 | Packets to skip from beginning |
|
||||||
|
| `count` | integer | No | 50 | Number of packets to display |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"output": "@ MGMT Command: Read Management... (0x0001) plen 0\n..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
# First 50 packets
|
||||||
|
bt_capture_read_raw filepath="/tmp/bluetooth.btsnoop"
|
||||||
|
|
||||||
|
# Skip first 100, read next 20
|
||||||
|
bt_capture_read_raw filepath="..." offset=100 count=20
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Returns btmon's human-readable packet decoding
|
||||||
|
- Useful for detailed protocol analysis
|
||||||
|
- Output can be large for many packets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Format
|
||||||
|
|
||||||
|
Captures use **btsnoop** format, compatible with:
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| Wireshark | Full GUI protocol analyzer |
|
||||||
|
| btmon | BlueZ command-line decoder |
|
||||||
|
| hcidump | Legacy packet dumper |
|
||||||
|
|
||||||
|
### Opening in Wireshark
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wireshark /tmp/bluetooth.btsnoop
|
||||||
|
```
|
||||||
|
|
||||||
|
Wireshark provides:
|
||||||
|
- Full protocol dissection
|
||||||
|
- Conversation tracking
|
||||||
|
- Expert analysis
|
||||||
|
- Multiple export formats
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
Capture requires access to the Bluetooth monitor socket:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Run as root
|
||||||
|
sudo btmon
|
||||||
|
|
||||||
|
# Option 2: Add capability (recommended)
|
||||||
|
sudo setcap cap_net_raw+ep /usr/bin/btmon
|
||||||
|
|
||||||
|
# Verify capability
|
||||||
|
getcap /usr/bin/btmon
|
||||||
|
```
|
||||||
582
docs-site/src/content/docs/reference/obex-tools.md
Normal file
582
docs-site/src/content/docs/reference/obex-tools.md
Normal file
@ -0,0 +1,582 @@
|
|||||||
|
---
|
||||||
|
title: OBEX Tools
|
||||||
|
description: Reference for OBEX file transfer, phonebook, and message tools
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Tools for OBEX profiles — file transfer (OPP/FTP), phonebook access (PBAP), and message access (MAP).
|
||||||
|
|
||||||
|
<Aside type="note">
|
||||||
|
OBEX tools require the `obexd` daemon. Use `bt_obex_status` to check availability.
|
||||||
|
</Aside>
|
||||||
|
|
||||||
|
## Setup Tools
|
||||||
|
|
||||||
|
### bt_obex_status
|
||||||
|
|
||||||
|
Check OBEX subsystem status.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "ready",
|
||||||
|
"obexd_installed": true,
|
||||||
|
"obexd_running": true,
|
||||||
|
"dbus_accessible": true,
|
||||||
|
"active_sessions": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_start_daemon
|
||||||
|
|
||||||
|
Start the obexd daemon if not running.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "started",
|
||||||
|
"pid": 12345
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_start_daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Session Management
|
||||||
|
|
||||||
|
### bt_obex_connect
|
||||||
|
|
||||||
|
Create an OBEX session to a device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `target` | string | Yes | Profile: "opp", "ftp", "pbap", "map" |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"session_id": "ftp_AABBCCDDEEFF",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"target": "ftp"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_connect address="AA:BB:CC:DD:EE:FF" target="ftp"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_disconnect
|
||||||
|
|
||||||
|
Close an OBEX session.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `session_id` | string | Yes | Session ID from bt_obex_connect |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "disconnected",
|
||||||
|
"session_id": "ftp_AABBCCDDEEFF"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_disconnect session_id="ftp_AABBCCDDEEFF"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_sessions
|
||||||
|
|
||||||
|
List active OBEX sessions.
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sessions": [
|
||||||
|
{
|
||||||
|
"session_id": "ftp_AABBCCDDEEFF",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"target": "ftp",
|
||||||
|
"created": "2024-01-15T10:30:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OPP Tools (Object Push)
|
||||||
|
|
||||||
|
### bt_obex_send_file
|
||||||
|
|
||||||
|
Send a file via Object Push Profile.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `file_path` | string | Yes | - | Local file to send |
|
||||||
|
| `wait` | boolean | No | true | Wait for transfer completion |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete",
|
||||||
|
"filename": "report.pdf",
|
||||||
|
"size": 102400,
|
||||||
|
"transferred": 102400
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if `wait=false`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "started",
|
||||||
|
"transfer_path": "/org/bluez/obex/client/session0/transfer0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="AA:BB:CC:DD:EE:FF" file_path="~/Documents/report.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_get_vcard
|
||||||
|
|
||||||
|
Pull business card (vCard) from device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `save_path` | string | Yes | Where to save the vCard |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete",
|
||||||
|
"save_path": "/home/user/contact.vcf",
|
||||||
|
"size": 512
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_get_vcard address="AA:BB:CC:DD:EE:FF" save_path="~/contact.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FTP Tools (File Transfer)
|
||||||
|
|
||||||
|
### bt_obex_browse
|
||||||
|
|
||||||
|
List files and folders at a path.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `session_id` | string | Yes | - | FTP session ID |
|
||||||
|
| `path` | string | No | "/" | Path to list ("/" for root, ".." to go up) |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"path": "/DCIM",
|
||||||
|
"entries": [
|
||||||
|
{"name": "Camera", "type": "folder"},
|
||||||
|
{"name": "photo.jpg", "type": "file", "size": 2048576}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_browse session_id="ftp_..." path="/DCIM"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_get
|
||||||
|
|
||||||
|
Download a file from the device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `session_id` | string | Yes | FTP session ID |
|
||||||
|
| `remote_path` | string | Yes | File path on device |
|
||||||
|
| `local_path` | string | Yes | Where to save locally |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete",
|
||||||
|
"remote_path": "photo.jpg",
|
||||||
|
"local_path": "/home/user/Downloads/photo.jpg",
|
||||||
|
"size": 2048576
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_get session_id="ftp_..." remote_path="photo.jpg" local_path="~/Downloads/photo.jpg"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_put
|
||||||
|
|
||||||
|
Upload a file to the device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `session_id` | string | Yes | FTP session ID |
|
||||||
|
| `local_path` | string | Yes | Local file to upload |
|
||||||
|
| `remote_path` | string | Yes | Destination path on device |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete",
|
||||||
|
"local_path": "/home/user/document.pdf",
|
||||||
|
"remote_path": "document.pdf",
|
||||||
|
"size": 102400
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_put session_id="ftp_..." local_path="~/document.pdf" remote_path="document.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_delete
|
||||||
|
|
||||||
|
Delete a file or folder on the device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `session_id` | string | Yes | FTP session ID |
|
||||||
|
| `remote_path` | string | Yes | File/folder to delete |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "deleted",
|
||||||
|
"path": "old_file.txt"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_delete session_id="ftp_..." remote_path="old_file.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_mkdir
|
||||||
|
|
||||||
|
Create a folder on the device.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `session_id` | string | Yes | FTP session ID |
|
||||||
|
| `folder_name` | string | Yes | Name of folder to create |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "created",
|
||||||
|
"folder": "Backup"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_mkdir session_id="ftp_..." folder_name="Backup"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Transfer Monitoring
|
||||||
|
|
||||||
|
### bt_obex_transfer_status
|
||||||
|
|
||||||
|
Check progress of a transfer.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `transfer_path` | string | Yes | Transfer path from send/get operations |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "active",
|
||||||
|
"filename": "large_file.mp4",
|
||||||
|
"size": 104857600,
|
||||||
|
"transferred": 52428800,
|
||||||
|
"progress_percent": 50
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
bt_obex_transfer_status transfer_path="/org/bluez/obex/client/session0/transfer0"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_obex_transfer_cancel
|
||||||
|
|
||||||
|
Cancel an in-progress transfer.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `transfer_path` | string | Yes | Transfer path to cancel |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "cancelled",
|
||||||
|
"transfer_path": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PBAP Tools (Phonebook)
|
||||||
|
|
||||||
|
### bt_phonebook_pull
|
||||||
|
|
||||||
|
Download entire phonebook as vCard file.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `save_path` | string | Yes | Where to save |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "complete",
|
||||||
|
"save_path": "/home/user/contacts.vcf",
|
||||||
|
"count": 150
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_phonebook_list
|
||||||
|
|
||||||
|
List phonebook entries with handles.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `folder` | string | No | "telecom/pb" | Phonebook folder |
|
||||||
|
|
||||||
|
**Folders:**
|
||||||
|
- `telecom/pb` — Main phonebook
|
||||||
|
- `telecom/ich` — Incoming call history
|
||||||
|
- `telecom/och` — Outgoing call history
|
||||||
|
- `telecom/mch` — Missed call history
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"entries": [
|
||||||
|
{"handle": "1.vcf", "name": "Alice Smith"},
|
||||||
|
{"handle": "2.vcf", "name": "Bob Jones"}
|
||||||
|
],
|
||||||
|
"count": 150
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_phonebook_get
|
||||||
|
|
||||||
|
Download single contact by handle.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `handle` | string | Yes | Contact handle from list |
|
||||||
|
| `save_path` | string | Yes | Where to save vCard |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_phonebook_search
|
||||||
|
|
||||||
|
Search phonebook by field.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `field` | string | Yes | Field to search: "name", "number", "email" |
|
||||||
|
| `value` | string | Yes | Search value |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_phonebook_count
|
||||||
|
|
||||||
|
Get total number of contacts.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"count": 150
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MAP Tools (Messages)
|
||||||
|
|
||||||
|
### bt_messages_folders
|
||||||
|
|
||||||
|
List message folders.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{"name": "inbox"},
|
||||||
|
{"name": "sent"},
|
||||||
|
{"name": "drafts"},
|
||||||
|
{"name": "outbox"},
|
||||||
|
{"name": "deleted"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_messages_list
|
||||||
|
|
||||||
|
List messages in a folder.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Default | Description |
|
||||||
|
|------|------|----------|---------|-------------|
|
||||||
|
| `address` | string | Yes | - | Device MAC address |
|
||||||
|
| `folder` | string | No | "inbox" | Folder to list |
|
||||||
|
| `unread_only` | boolean | No | false | Only unread messages |
|
||||||
|
| `max_count` | integer | No | 100 | Maximum messages to return |
|
||||||
|
|
||||||
|
**Returns:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"handle": "msg001",
|
||||||
|
"subject": "Meeting tomorrow",
|
||||||
|
"sender": "+15551234567",
|
||||||
|
"timestamp": "2024-01-15T10:30:00",
|
||||||
|
"read": false,
|
||||||
|
"type": "SMS"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_messages_get
|
||||||
|
|
||||||
|
Download message content.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `handle` | string | Yes | Message handle from list |
|
||||||
|
| `save_path` | string | Yes | Where to save message |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### bt_messages_send
|
||||||
|
|
||||||
|
Send a message via MAP.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
| Name | Type | Required | Description |
|
||||||
|
|------|------|----------|-------------|
|
||||||
|
| `address` | string | Yes | Device MAC address |
|
||||||
|
| `recipient` | string | Yes | Phone number to send to |
|
||||||
|
| `message` | string | Yes | Message text |
|
||||||
|
|
||||||
|
<Aside type="caution">
|
||||||
|
Message sending support varies by device. Many phones only allow read access.
|
||||||
|
</Aside>
|
||||||
197
docs-site/src/content/docs/reference/resources.md
Normal file
197
docs-site/src/content/docs/reference/resources.md
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
---
|
||||||
|
title: MCP Resources
|
||||||
|
description: Reference for mcbluetooth MCP resource URIs
|
||||||
|
---
|
||||||
|
|
||||||
|
mcbluetooth exposes live Bluetooth state through MCP resources. These provide real-time queries without tool calls.
|
||||||
|
|
||||||
|
## Resource URIs
|
||||||
|
|
||||||
|
| URI | Description |
|
||||||
|
|-----|-------------|
|
||||||
|
| `bluetooth://adapters` | All Bluetooth adapters |
|
||||||
|
| `bluetooth://paired` | Paired devices |
|
||||||
|
| `bluetooth://connected` | Connected devices |
|
||||||
|
| `bluetooth://visible` | All known/discovered devices |
|
||||||
|
| `bluetooth://trusted` | Trusted devices |
|
||||||
|
| `bluetooth://adapter/{name}` | Specific adapter details |
|
||||||
|
| `bluetooth://device/{address}` | Specific device details |
|
||||||
|
|
||||||
|
## Adapter Resources
|
||||||
|
|
||||||
|
### bluetooth://adapters
|
||||||
|
|
||||||
|
Lists all Bluetooth adapters on the system.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"alias": "My Laptop",
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"pairable": true,
|
||||||
|
"discovering": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bluetooth://adapter/{name}
|
||||||
|
|
||||||
|
Get details for a specific adapter.
|
||||||
|
|
||||||
|
**URI:** `bluetooth://adapter/hci0`
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "hci0",
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"alias": "My Laptop",
|
||||||
|
"class": 7995916,
|
||||||
|
"powered": true,
|
||||||
|
"discoverable": false,
|
||||||
|
"discoverable_timeout": 180,
|
||||||
|
"pairable": true,
|
||||||
|
"pairable_timeout": 0,
|
||||||
|
"discovering": false,
|
||||||
|
"uuids": ["0000110a-...", "0000110c-..."],
|
||||||
|
"modalias": "usb:v1D6Bp0246d0540"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Device Resources
|
||||||
|
|
||||||
|
### bluetooth://paired
|
||||||
|
|
||||||
|
Lists all paired devices across all adapters.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"alias": "My Headphones",
|
||||||
|
"paired": true,
|
||||||
|
"connected": true,
|
||||||
|
"trusted": true,
|
||||||
|
"adapter": "hci0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bluetooth://connected
|
||||||
|
|
||||||
|
Lists currently connected devices.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"connected": true,
|
||||||
|
"services": ["audio", "hfp"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bluetooth://visible
|
||||||
|
|
||||||
|
Lists all known devices (discovered or previously seen).
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "AA:BB:CC:DD:EE:FF",
|
||||||
|
"name": "Unknown Device",
|
||||||
|
"paired": false,
|
||||||
|
"connected": false,
|
||||||
|
"rssi": -75,
|
||||||
|
"last_seen": "2024-01-15T10:30:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bluetooth://trusted
|
||||||
|
|
||||||
|
Lists devices marked as trusted (auto-connect allowed).
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"trusted": true,
|
||||||
|
"paired": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### bluetooth://device/{address}
|
||||||
|
|
||||||
|
Get details for a specific device.
|
||||||
|
|
||||||
|
**URI:** `bluetooth://device/C8:7B:23:55:68:E8`
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"address": "C8:7B:23:55:68:E8",
|
||||||
|
"name": "Bose NCH700",
|
||||||
|
"alias": "My Headphones",
|
||||||
|
"class": 2360344,
|
||||||
|
"icon": "audio-headphones",
|
||||||
|
"paired": true,
|
||||||
|
"bonded": true,
|
||||||
|
"trusted": true,
|
||||||
|
"blocked": false,
|
||||||
|
"connected": true,
|
||||||
|
"legacy_pairing": false,
|
||||||
|
"rssi": -55,
|
||||||
|
"uuids": [
|
||||||
|
"0000110b-0000-1000-8000-00805f9b34fb",
|
||||||
|
"0000110e-0000-1000-8000-00805f9b34fb"
|
||||||
|
],
|
||||||
|
"modalias": "bluetooth:v009Ep4020d0134",
|
||||||
|
"adapter": "hci0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage in MCP Clients
|
||||||
|
|
||||||
|
Resources can be read using the standard MCP resource protocol:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"method": "resources/read",
|
||||||
|
"params": {
|
||||||
|
"uri": "bluetooth://paired"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison: Resources vs Tools
|
||||||
|
|
||||||
|
| Use Case | Resource | Tool |
|
||||||
|
|----------|----------|------|
|
||||||
|
| Check current state | ✓ Resources | |
|
||||||
|
| Modify state | | ✓ Tools |
|
||||||
|
| Real-time queries | ✓ Resources | |
|
||||||
|
| Complex operations | | ✓ Tools |
|
||||||
|
|
||||||
|
**Resources** are read-only and ideal for:
|
||||||
|
- Dashboard displays
|
||||||
|
- State monitoring
|
||||||
|
- Quick queries
|
||||||
|
|
||||||
|
**Tools** are for actions:
|
||||||
|
- Pairing devices
|
||||||
|
- Connecting/disconnecting
|
||||||
|
- Sending files
|
||||||
|
- Changing settings
|
||||||
147
docs-site/src/content/docs/reference/tools.md
Normal file
147
docs-site/src/content/docs/reference/tools.md
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
---
|
||||||
|
title: Tools Overview
|
||||||
|
description: Complete reference for all mcbluetooth MCP tools
|
||||||
|
---
|
||||||
|
|
||||||
|
mcbluetooth provides **61 MCP tools** organized into functional categories.
|
||||||
|
|
||||||
|
## Tool Categories
|
||||||
|
|
||||||
|
| Category | Tools | Description |
|
||||||
|
|----------|-------|-------------|
|
||||||
|
| [Adapter](/reference/adapter-tools/) | 7 | Hardware adapter management |
|
||||||
|
| [Device](/reference/device-tools/) | 12 | Device discovery, pairing, connection |
|
||||||
|
| [Audio](/reference/audio-tools/) | 7 | PipeWire/PulseAudio integration |
|
||||||
|
| [BLE](/reference/ble-tools/) | 8 | Bluetooth Low Energy & GATT |
|
||||||
|
| [OBEX](/reference/obex-tools/) | 21 | File transfer, phonebook, messages |
|
||||||
|
| [Monitor](/reference/monitor-tools/) | 6 | Protocol capture & analysis |
|
||||||
|
|
||||||
|
## Tool Naming Convention
|
||||||
|
|
||||||
|
All tools follow the pattern `bt_<category>_<action>`:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_adapter_power # Adapter category, power action
|
||||||
|
bt_ble_read # BLE category, read action
|
||||||
|
bt_obex_connect # OBEX category, connect action
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Parameters
|
||||||
|
|
||||||
|
### `adapter`
|
||||||
|
|
||||||
|
Most tools require an adapter name (e.g., `"hci0"`):
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_scan adapter="hci0" timeout=10
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `bt_list_adapters` to discover available adapters.
|
||||||
|
|
||||||
|
### `address`
|
||||||
|
|
||||||
|
Device Bluetooth MAC address in colon-separated format:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_connect adapter="hci0" address="AA:BB:CC:DD:EE:FF"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Return Values
|
||||||
|
|
||||||
|
Tools return JSON objects with:
|
||||||
|
|
||||||
|
- **Success**: Operation-specific data
|
||||||
|
- **Errors**: `{"error": "description", "code": "ERROR_CODE"}`
|
||||||
|
|
||||||
|
## Quick Reference Table
|
||||||
|
|
||||||
|
### Adapter Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_list_adapters` | List all Bluetooth adapters |
|
||||||
|
| `bt_adapter_info` | Get adapter details |
|
||||||
|
| `bt_adapter_power` | Turn adapter on/off |
|
||||||
|
| `bt_adapter_discoverable` | Set discoverable mode |
|
||||||
|
| `bt_adapter_pairable` | Set pairable mode |
|
||||||
|
| `bt_adapter_set_alias` | Set adapter name |
|
||||||
|
| `bt_scan` | Scan for devices |
|
||||||
|
|
||||||
|
### Device Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_list_devices` | List known devices |
|
||||||
|
| `bt_device_info` | Get device details |
|
||||||
|
| `bt_device_set_alias` | Set device name |
|
||||||
|
| `bt_pair` | Initiate pairing |
|
||||||
|
| `bt_pair_confirm` | Confirm/reject pairing |
|
||||||
|
| `bt_pairing_status` | Check pending pairings |
|
||||||
|
| `bt_unpair` | Remove pairing |
|
||||||
|
| `bt_connect` | Connect to device |
|
||||||
|
| `bt_disconnect` | Disconnect device |
|
||||||
|
| `bt_trust` | Set trust status |
|
||||||
|
| `bt_block` | Block/unblock device |
|
||||||
|
|
||||||
|
### Audio Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_audio_list` | List audio devices |
|
||||||
|
| `bt_audio_connect` | Connect audio profiles |
|
||||||
|
| `bt_audio_disconnect` | Disconnect audio |
|
||||||
|
| `bt_audio_set_profile` | Switch A2DP/HFP |
|
||||||
|
| `bt_audio_set_default` | Set default output |
|
||||||
|
| `bt_audio_volume` | Adjust volume |
|
||||||
|
| `bt_audio_mute` | Mute/unmute |
|
||||||
|
|
||||||
|
### BLE Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_ble_scan` | Scan for BLE devices |
|
||||||
|
| `bt_ble_services` | List GATT services |
|
||||||
|
| `bt_ble_characteristics` | List characteristics |
|
||||||
|
| `bt_ble_read` | Read characteristic |
|
||||||
|
| `bt_ble_write` | Write characteristic |
|
||||||
|
| `bt_ble_notify` | Enable/disable notifications |
|
||||||
|
| `bt_ble_battery` | Read battery level |
|
||||||
|
|
||||||
|
### OBEX Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_obex_status` | Check obexd status |
|
||||||
|
| `bt_obex_start_daemon` | Start obexd |
|
||||||
|
| `bt_obex_connect` | Create OBEX session |
|
||||||
|
| `bt_obex_disconnect` | Close session |
|
||||||
|
| `bt_obex_sessions` | List active sessions |
|
||||||
|
| `bt_obex_send_file` | Send file (OPP) |
|
||||||
|
| `bt_obex_get_vcard` | Get business card |
|
||||||
|
| `bt_obex_browse` | List files/folders |
|
||||||
|
| `bt_obex_get` | Download file |
|
||||||
|
| `bt_obex_put` | Upload file |
|
||||||
|
| `bt_obex_delete` | Delete file/folder |
|
||||||
|
| `bt_obex_mkdir` | Create folder |
|
||||||
|
| `bt_obex_transfer_status` | Check transfer progress |
|
||||||
|
| `bt_obex_transfer_cancel` | Cancel transfer |
|
||||||
|
| `bt_phonebook_pull` | Download phonebook |
|
||||||
|
| `bt_phonebook_list` | List contacts |
|
||||||
|
| `bt_phonebook_get` | Get single contact |
|
||||||
|
| `bt_phonebook_search` | Search contacts |
|
||||||
|
| `bt_phonebook_count` | Count contacts |
|
||||||
|
| `bt_messages_folders` | List message folders |
|
||||||
|
| `bt_messages_list` | List messages |
|
||||||
|
| `bt_messages_get` | Download message |
|
||||||
|
| `bt_messages_send` | Send message |
|
||||||
|
|
||||||
|
### Monitor Tools
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_capture_start` | Start HCI capture |
|
||||||
|
| `bt_capture_stop` | Stop capture |
|
||||||
|
| `bt_capture_list_active` | List active captures |
|
||||||
|
| `bt_capture_parse` | Parse capture file |
|
||||||
|
| `bt_capture_analyze` | Analyze capture |
|
||||||
|
| `bt_capture_read_raw` | Read raw packets |
|
||||||
130
docs-site/src/styles/custom.css
Normal file
130
docs-site/src/styles/custom.css
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* mcbluetooth Starlight Custom Styles */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
/* Bluetooth-inspired color palette */
|
||||||
|
--sl-color-accent-low: #1a3a5c;
|
||||||
|
--sl-color-accent: #0066cc;
|
||||||
|
--sl-color-accent-high: #3399ff;
|
||||||
|
--sl-color-white: #ffffff;
|
||||||
|
--sl-color-gray-1: #f5f6f8;
|
||||||
|
--sl-color-gray-2: #e8eaed;
|
||||||
|
--sl-color-gray-3: #c0c4cc;
|
||||||
|
--sl-color-gray-4: #888d96;
|
||||||
|
--sl-color-gray-5: #545a64;
|
||||||
|
--sl-color-gray-6: #2d3139;
|
||||||
|
--sl-color-black: #181a1f;
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--sl-font-system: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||||
|
--sl-font-system-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode accent adjustments */
|
||||||
|
:root[data-theme='dark'] {
|
||||||
|
--sl-color-accent-low: #0d2847;
|
||||||
|
--sl-color-accent: #3399ff;
|
||||||
|
--sl-color-accent-high: #66b3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
.expressive-code {
|
||||||
|
--ec-brdRad: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hero section on splash pages */
|
||||||
|
.hero {
|
||||||
|
padding-block: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card styling */
|
||||||
|
.sl-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sl-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 102, 204, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sidebar styling */
|
||||||
|
.sidebar-content {
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tool reference tables */
|
||||||
|
table {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table code {
|
||||||
|
font-size: 0.85em;
|
||||||
|
padding: 0.15em 0.35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code styling */
|
||||||
|
:not(pre) > code {
|
||||||
|
background: var(--sl-color-gray-6);
|
||||||
|
color: var(--sl-color-accent-high);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.15em 0.35em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='light'] :not(pre) > code {
|
||||||
|
background: var(--sl-color-gray-2);
|
||||||
|
color: var(--sl-color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callouts / Asides */
|
||||||
|
.starlight-aside {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
.site-footer {
|
||||||
|
border-top: 1px solid var(--sl-color-gray-5);
|
||||||
|
padding-block: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ASCII art banner (if used) */
|
||||||
|
.ascii-banner {
|
||||||
|
font-family: var(--sl-font-system-mono);
|
||||||
|
font-size: 0.65rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: pre;
|
||||||
|
overflow-x: auto;
|
||||||
|
color: var(--sl-color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tool cards grid */
|
||||||
|
.tool-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Profile badges */
|
||||||
|
.profile-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-badge.opp { background: #e3f2fd; color: #1565c0; }
|
||||||
|
.profile-badge.ftp { background: #e8f5e9; color: #2e7d32; }
|
||||||
|
.profile-badge.pbap { background: #fff3e0; color: #e65100; }
|
||||||
|
.profile-badge.map { background: #fce4ec; color: #c2185b; }
|
||||||
|
|
||||||
|
:root[data-theme='dark'] .profile-badge.opp { background: #1565c0; color: #e3f2fd; }
|
||||||
|
:root[data-theme='dark'] .profile-badge.ftp { background: #2e7d32; color: #e8f5e9; }
|
||||||
|
:root[data-theme='dark'] .profile-badge.pbap { background: #e65100; color: #fff3e0; }
|
||||||
|
:root[data-theme='dark'] .profile-badge.map { background: #c2185b; color: #fce4ec; }
|
||||||
5
docs-site/tsconfig.json
Normal file
5
docs-site/tsconfig.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"include": [".astro/types.d.ts", "**/*"],
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
||||||
368
docs/obex.md
Normal file
368
docs/obex.md
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
# OBEX Profile Support
|
||||||
|
|
||||||
|
OBEX (Object Exchange) enables file transfer and data synchronization over Bluetooth. mcbluetooth provides full support for the four major OBEX profiles through the `obexd` daemon.
|
||||||
|
|
||||||
|
## Profiles Overview
|
||||||
|
|
||||||
|
| Profile | UUID | Purpose | Typical Use |
|
||||||
|
|---------|------|---------|-------------|
|
||||||
|
| **OPP** (Object Push) | 0x1105 | Simple file sending | "Send this photo to my laptop" |
|
||||||
|
| **FTP** (File Transfer) | 0x1106 | Full file browsing | "Browse phone storage, download DCIM" |
|
||||||
|
| **PBAP** (Phonebook Access) | 0x112F | Contact/call history | "Download my contacts" |
|
||||||
|
| **MAP** (Message Access) | 0x1132 | SMS/MMS/email | "Show unread messages" |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
OBEX requires the `obexd` daemon, which is separate from the main `bluetoothd`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Arch Linux
|
||||||
|
sudo pacman -S bluez-obex
|
||||||
|
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt install bluez-obex
|
||||||
|
|
||||||
|
# Fedora
|
||||||
|
sudo dnf install bluez-obex
|
||||||
|
```
|
||||||
|
|
||||||
|
Check your setup with:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_status
|
||||||
|
```
|
||||||
|
|
||||||
|
If obexd isn't running, start it:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_start_daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: obexd runs as a user service on the session D-Bus, not the system bus. It requires a desktop session to be active.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Send a File (OPP)
|
||||||
|
|
||||||
|
The simplest OBEX operation — push a file to any device:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="C8:7B:23:55:68:E8" file_path="~/Documents/report.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
The receiving device will show an accept/reject prompt. The tool waits for completion and reports success/failure.
|
||||||
|
|
||||||
|
### Download Contacts (PBAP)
|
||||||
|
|
||||||
|
Pull all contacts from a paired phone:
|
||||||
|
|
||||||
|
```
|
||||||
|
bt_phonebook_pull address="AA:BB:CC:DD:EE:FF" save_path="~/contacts.vcf"
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a vCard file with all contacts. You can import it into any contacts app.
|
||||||
|
|
||||||
|
### Browse Phone Storage (FTP)
|
||||||
|
|
||||||
|
For full file system access, create an FTP session:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Connect
|
||||||
|
bt_obex_connect address="AA:BB:CC:DD:EE:FF" target="ftp"
|
||||||
|
# Returns: session_id="ftp_AABBCCDDEEFF"
|
||||||
|
|
||||||
|
# Browse root
|
||||||
|
bt_obex_browse session_id="ftp_AABBCCDDEEFF" path="/"
|
||||||
|
|
||||||
|
# Navigate to DCIM
|
||||||
|
bt_obex_browse session_id="ftp_AABBCCDDEEFF" path="DCIM"
|
||||||
|
|
||||||
|
# Download a photo
|
||||||
|
bt_obex_get session_id="ftp_AABBCCDDEEFF" remote_path="photo.jpg" local_path="~/Downloads/"
|
||||||
|
|
||||||
|
# Disconnect when done
|
||||||
|
bt_obex_disconnect session_id="ftp_AABBCCDDEEFF"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How-To Guides
|
||||||
|
|
||||||
|
### How to Transfer Files Between Devices
|
||||||
|
|
||||||
|
**Scenario**: You want to send multiple files to your phone.
|
||||||
|
|
||||||
|
1. **For single files**, use OPP (no session needed):
|
||||||
|
```
|
||||||
|
bt_obex_send_file address="..." file_path="file1.pdf"
|
||||||
|
bt_obex_send_file address="..." file_path="file2.jpg"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **For multiple files or browsing**, use FTP:
|
||||||
|
```
|
||||||
|
bt_obex_connect address="..." target="ftp"
|
||||||
|
bt_obex_browse session_id="..." path="/"
|
||||||
|
bt_obex_put session_id="..." local_path="file1.pdf" remote_path="file1.pdf"
|
||||||
|
bt_obex_put session_id="..." local_path="file2.jpg" remote_path="file2.jpg"
|
||||||
|
bt_obex_disconnect session_id="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to Backup Phone Contacts
|
||||||
|
|
||||||
|
**Scenario**: Create a backup of all contacts from your phone.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Pull main phonebook
|
||||||
|
bt_phonebook_pull address="..." save_path="~/backup/contacts.vcf"
|
||||||
|
|
||||||
|
# Also backup call history
|
||||||
|
bt_phonebook_pull address="..." save_path="~/backup/calls_incoming.vcf" phonebook="ich"
|
||||||
|
bt_phonebook_pull address="..." save_path="~/backup/calls_outgoing.vcf" phonebook="och"
|
||||||
|
bt_phonebook_pull address="..." save_path="~/backup/calls_missed.vcf" phonebook="mch"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Phonebook types**:
|
||||||
|
- `pb` — Main contacts (default)
|
||||||
|
- `ich` — Incoming call history
|
||||||
|
- `och` — Outgoing call history
|
||||||
|
- `mch` — Missed call history
|
||||||
|
- `cch` — Combined call history
|
||||||
|
|
||||||
|
### How to Search Contacts
|
||||||
|
|
||||||
|
**Scenario**: Find a contact by name or phone number.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Search by name
|
||||||
|
bt_phonebook_search address="..." field="name" value="John"
|
||||||
|
|
||||||
|
# Search by phone number
|
||||||
|
bt_phonebook_search address="..." field="number" value="555"
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to Read Text Messages
|
||||||
|
|
||||||
|
**Scenario**: Check unread SMS messages on your phone.
|
||||||
|
|
||||||
|
```
|
||||||
|
# List unread messages
|
||||||
|
bt_messages_list address="..." folder="inbox" unread_only=true
|
||||||
|
|
||||||
|
# Get full message content
|
||||||
|
bt_messages_get address="..." handle="msg001" save_path="~/message.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to Manage FTP Sessions
|
||||||
|
|
||||||
|
**Scenario**: You have a long-running file transfer workflow.
|
||||||
|
|
||||||
|
```
|
||||||
|
# List active sessions
|
||||||
|
bt_obex_sessions
|
||||||
|
|
||||||
|
# Check session details
|
||||||
|
bt_obex_connect address="..." target="ftp"
|
||||||
|
|
||||||
|
# Navigate folder structure
|
||||||
|
bt_obex_browse session_id="..." path="/" # Root
|
||||||
|
bt_obex_browse session_id="..." path="DCIM" # Enter folder
|
||||||
|
bt_obex_browse session_id="..." path=".." # Go up
|
||||||
|
|
||||||
|
# Create/delete
|
||||||
|
bt_obex_mkdir session_id="..." folder_name="Backup"
|
||||||
|
bt_obex_delete session_id="..." remote_path="old_file.txt"
|
||||||
|
|
||||||
|
# Always disconnect when done
|
||||||
|
bt_obex_disconnect session_id="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to Monitor Transfer Progress
|
||||||
|
|
||||||
|
**Scenario**: You're transferring a large file and want to check progress.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Start transfer without waiting
|
||||||
|
bt_obex_send_file address="..." file_path="large_video.mp4" wait=false
|
||||||
|
# Returns: transfer_path="/org/bluez/obex/client/session0/transfer0"
|
||||||
|
|
||||||
|
# Check progress
|
||||||
|
bt_obex_transfer_status transfer_path="/org/bluez/obex/client/session0/transfer0"
|
||||||
|
# Returns: status="active", transferred=52428800, size=104857600, progress_percent=50
|
||||||
|
|
||||||
|
# Cancel if needed
|
||||||
|
bt_obex_transfer_cancel transfer_path="..."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tool Reference
|
||||||
|
|
||||||
|
### Setup & Status
|
||||||
|
|
||||||
|
| Tool | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `bt_obex_status` | Check obexd installation and D-Bus connectivity |
|
||||||
|
| `bt_obex_start_daemon` | Start obexd if not running |
|
||||||
|
|
||||||
|
### Session Management
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_obex_connect` | `address`, `target` (opp/ftp/pbap/map) | Create OBEX session |
|
||||||
|
| `bt_obex_disconnect` | `session_id` | Close session |
|
||||||
|
| `bt_obex_sessions` | — | List active sessions |
|
||||||
|
|
||||||
|
### Object Push (OPP)
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_obex_send_file` | `address`, `file_path`, `wait` | Send file to device |
|
||||||
|
| `bt_obex_get_vcard` | `address`, `save_path` | Pull device's business card |
|
||||||
|
|
||||||
|
### File Transfer (FTP)
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_obex_browse` | `session_id`, `path` | List folder contents |
|
||||||
|
| `bt_obex_get` | `session_id`, `remote_path`, `local_path` | Download file |
|
||||||
|
| `bt_obex_put` | `session_id`, `local_path`, `remote_path` | Upload file |
|
||||||
|
| `bt_obex_delete` | `session_id`, `remote_path` | Delete file/folder |
|
||||||
|
| `bt_obex_mkdir` | `session_id`, `folder_name` | Create folder |
|
||||||
|
|
||||||
|
### Phonebook Access (PBAP)
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_phonebook_pull` | `address`, `save_path`, `location`, `phonebook` | Download full phonebook |
|
||||||
|
| `bt_phonebook_list` | `address`, `location`, `phonebook` | List entries with handles |
|
||||||
|
| `bt_phonebook_get` | `address`, `handle`, `save_path` | Download single entry |
|
||||||
|
| `bt_phonebook_search` | `address`, `field`, `value` | Search contacts |
|
||||||
|
| `bt_phonebook_count` | `address`, `location`, `phonebook` | Count entries |
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
- `location`: `"int"` (internal memory) or `"sim"` (SIM card)
|
||||||
|
- `phonebook`: `"pb"`, `"ich"`, `"och"`, `"mch"`, `"cch"`
|
||||||
|
- `field`: `"name"`, `"number"`, `"sound"`
|
||||||
|
|
||||||
|
### Message Access (MAP)
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_messages_folders` | `address` | List message folders |
|
||||||
|
| `bt_messages_list` | `address`, `folder`, `unread_only`, `max_count` | List messages |
|
||||||
|
| `bt_messages_get` | `address`, `handle`, `save_path` | Download message |
|
||||||
|
| `bt_messages_send` | `address`, `recipient`, `message` | Send SMS |
|
||||||
|
|
||||||
|
### Transfer Management
|
||||||
|
|
||||||
|
| Tool | Parameters | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `bt_obex_transfer_status` | `transfer_path` | Check transfer progress |
|
||||||
|
| `bt_obex_transfer_cancel` | `transfer_path` | Cancel active transfer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "obexd not found"
|
||||||
|
|
||||||
|
Install the bluez-obex package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Arch
|
||||||
|
sudo pacman -S bluez-obex
|
||||||
|
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt install bluez-obex
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Cannot connect to obexd D-Bus"
|
||||||
|
|
||||||
|
obexd runs on the **session bus**, which requires:
|
||||||
|
1. A graphical desktop session (X11 or Wayland)
|
||||||
|
2. D-Bus session daemon running
|
||||||
|
|
||||||
|
If running headless:
|
||||||
|
```bash
|
||||||
|
# Start a D-Bus session
|
||||||
|
eval $(dbus-launch --sh-syntax)
|
||||||
|
export DBUS_SESSION_BUS_ADDRESS
|
||||||
|
|
||||||
|
# Then start obexd
|
||||||
|
/usr/lib/bluetooth/obexd &
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Device rejected connection" / "NotAuthorized"
|
||||||
|
|
||||||
|
The target device must:
|
||||||
|
1. Be **paired** first (use `bt_pair`)
|
||||||
|
2. Have the profile **enabled** (check device settings)
|
||||||
|
3. Be **connected** for some profiles
|
||||||
|
|
||||||
|
Some devices require explicit authorization for OBEX access in their Bluetooth settings.
|
||||||
|
|
||||||
|
### "Profile not supported"
|
||||||
|
|
||||||
|
Not all devices support all profiles:
|
||||||
|
|
||||||
|
| Device Type | OPP | FTP | PBAP | MAP |
|
||||||
|
|-------------|-----|-----|------|-----|
|
||||||
|
| Android phones | ✓ | varies | ✓ | varies |
|
||||||
|
| iPhones | ✓ | ✗ | ✗ | ✗ |
|
||||||
|
| Feature phones | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| Bluetooth speakers | ✗ | ✗ | ✗ | ✗ |
|
||||||
|
| Cars (infotainment) | ✓ | ✗ | ✓ | ✓ |
|
||||||
|
|
||||||
|
### "Transfer stuck at 0%"
|
||||||
|
|
||||||
|
The receiving device may be showing an accept prompt. Check the device screen.
|
||||||
|
|
||||||
|
### Session disappeared
|
||||||
|
|
||||||
|
Sessions are tied to the obexd process. If obexd restarts, sessions are lost. Create a new session.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ MCP Tools (tools/obex.py) │
|
||||||
|
│ bt_obex_*, bt_phonebook_*, bt_messages_* │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ ObexClient (obex_client.py) │
|
||||||
|
│ Session management, transfer monitoring, profile methods │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ dbus-fast (async) │
|
||||||
|
│ SESSION D-Bus │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ obexd │
|
||||||
|
│ /org/bluez/obex/client/sessionN/transferM │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ BlueZ │
|
||||||
|
│ Bluetooth Stack │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### D-Bus Object Paths
|
||||||
|
|
||||||
|
- **Client**: `/org/bluez/obex`
|
||||||
|
- **Session**: `/org/bluez/obex/client/session0`
|
||||||
|
- **Transfer**: `/org/bluez/obex/client/session0/transfer0`
|
||||||
|
|
||||||
|
### Session Lifecycle
|
||||||
|
|
||||||
|
1. `CreateSession(address, {Target: "ftp"})` → session path
|
||||||
|
2. Use profile interface (FileTransfer1, PhonebookAccess1, etc.)
|
||||||
|
3. Transfers create temporary objects with Status property
|
||||||
|
4. `RemoveSession(session_path)` when done
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [BlueZ OBEX D-Bus API](https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/obex-api.txt)
|
||||||
|
- [OBEX Specification](https://www.bluetooth.com/specifications/specs/object-exchange-obex/)
|
||||||
|
- [vCard Format](https://en.wikipedia.org/wiki/VCard)
|
||||||
Loading…
x
Reference in New Issue
Block a user