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:
Ryan Malloy 2026-02-02 14:36:07 -07:00
parent e9f06173c5
commit 9d1c0f3e0f
35 changed files with 13139 additions and 0 deletions

21
docs-site/.gitignore vendored Normal file
View 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
View File

@ -0,0 +1,49 @@
# Starlight Starter Kit: Basics
[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](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 [Starlights docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat).

View 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

File diff suppressed because it is too large Load Diff

19
docs-site/package.json Normal file
View 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"
}
}

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View 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

View 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

View 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() }),
};

View 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>

View 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

View 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)

View 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

View 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/)

View 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

View 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.

View 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>

View 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

View 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.

View 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.

View 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`

View 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

View 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 |

View 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

View 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

View 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 |

View 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

View 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
```

View 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>

View 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

View 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 |

View 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
View File

@ -0,0 +1,5 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}

368
docs/obex.md Normal file
View 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)