Pairing 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?
Section titled “What is a Pairing Agent?”In BlueZ, a pairing agent is a program that:
- Registers with BlueZ’s AgentManager
- Receives callbacks during pairing
- Responds to PIN/passkey requests
- Confirms or rejects pairings
Without an agent, pairing requests fail because there’s no program to handle the negotiation.
Secure Simple Pairing (SSP)
Section titled “Secure Simple Pairing (SSP)”Modern Bluetooth uses SSP with four association models:
Just Works
Section titled “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
Section titled “Numeric Comparison”Both devices show 6-digit code; user confirms they match.
Your device: 123456Their device: 123456Do 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
Section titled “Passkey Entry”One device displays code; user enters it on the other.
Their device shows: 123456Enter on your device: [______]- One device has display, other has keyboard
- Code entry proves physical access
Example devices: Phone pairing with keyboard
Legacy PIN
Section titled “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
Section titled “mcbluetooth Pairing Modes”The bt_pair tool supports three modes:
Interactive Mode (Default)
Section titled “Interactive Mode (Default)”bt_pair adapter="hci0" address="..." pairing_mode="interactive"- mcbluetooth initiates pairing
- Returns immediately with status
- If confirmation needed, returns passkey/info
- Use
bt_pair_confirmto 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
Section titled “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
Best for: Automated testing, trusted lab environments.
Elicit Mode
Section titled “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
Section titled “Agent Implementation”Registration
Section titled “Registration”mcbluetooth registers its agent at startup:
# Register with BlueZagent_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
Section titled “Capability Declaration”The agent declares “KeyboardDisplay” capability:
- Can display codes (for numeric comparison)
- Can accept input (for passkey entry)
- Maximizes pairing compatibility
Callback Methods
Section titled “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
Section titled “Handling Pending Requests”When pairing requires confirmation:
# Store pending request_pending_pairings[address] = { "method": "numeric_comparison", "passkey": 123456, "timestamp": datetime.now()}
# Return to bt_pair callerreturn { "status": "awaiting_confirmation", "method": "numeric_comparison", "passkey": 123456}Later, bt_pair_confirm resolves it:
@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
Section titled “Troubleshooting Pairing””No agent registered”
Section titled “”No agent registered””mcbluetooth’s agent didn’t register properly:
- Check mcbluetooth is running
- Verify D-Bus connectivity
- Check for existing agents (some DEs register their own)
“Authentication rejected”
Section titled ““Authentication rejected””The other device rejected pairing:
- Device may have reached pairing limit
- Try removing existing pairing on both sides
- Restart Bluetooth on the other device
Pairing timeout
Section titled “Pairing timeout”No response within timeout period:
- Extend timeout:
bt_pair ... timeout=120 - Check
bt_pairing_statusfor pending requests - Other device may need user interaction
Wrong passkey
Section titled “Wrong passkey”For Passkey Entry mode:
- Ensure you’re entering the exact code shown
- Some devices show passkey only briefly
- Use
bt_pairing_statusto see expected passkey
Security Considerations
Section titled “Security Considerations”MITM Protection
Section titled “MITM Protection”| Mode | MITM Protected |
|---|---|
| Just Works | ✗ No |
| Numeric Comparison | ✓ Yes |
| Passkey Entry | ✓ Yes |
| Legacy PIN | Partial |
Best Practices
Section titled “Best Practices”- Prefer Numeric Comparison - Verify codes match on both devices
- Avoid auto mode in production - Human verification is important
- Check device identity - Verify name/address before confirming
- Remove unused pairings - Reduce attack surface
Agent Conflicts
Section titled “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:
- Temporarily stop the DE’s Bluetooth applet
- Or use mcbluetooth’s agent alongside (may cause double prompts)