MCP servers crash on macOS when accessing Bluetooth — missing NSBluetoothAlwaysUsageDescription in claude-code bundle
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Summary
On macOS, any MCP server spawned by Claude Code that touches Bluetooth (CoreBluetooth) is killed by TCC, even when the MCP server's own Info.plist correctly declares NSBluetoothAlwaysUsageDescription. Root cause: macOS attributes the BLE access to the responsible app (Claude Code), and the claude-code bundle does not declare the BLE usage string.
Reproduction
macOS 26.x (also reproduces on 14/15 per design of TCC).
Configure any MCP server that uses CoreBluetooth (in my case, tokymaker-mcp for ESP32 boards over BLE) via .mcp.json stdio command.
Trigger any tool that initiates a BLE scan or connect.
The MCP child process is killed with SIGABRT. Claude sees MCP error -32000: Connection closed.
Diagnostic evidence
Crash report (~/Library/Logs/DiagnosticReports/<server>-*.ips):
termination.details: "This app has crashed because it attempted to access
privacy-sensitive data without a usage description. The app's Info.plist
must contain an NSBluetoothAlwaysUsageDescription key..."
responsibleProc: claude
parentProc: claude
The responsible process is:
~/Library/Application Support/Claude/claude-code/<version>/claude.app
Bundle ID: com.anthropic.claude-code
plutil -p on that bundle's Info.plist shows NSMicrophoneUsageDescription but no NSBluetoothAlwaysUsageDescription. The MCP server's own Info.plist does declare the key — irrelevant, because TCC checks the responsible app.
Impact
Affects every BLE-using MCP server on macOS Claude Code: hardware-control servers (ESP32, Arduino, micro:bit), smart-home (Govee, Bluetooth-only HomeKit accessories), health (heart-rate monitors), etc. There is no user-side fix — re-signing the MCP server doesn't help, and granting Bluetooth permission to other apps doesn't apply.
Workarounds today require either (a) running Claude Code from Terminal so Terminal becomes the responsible app, or (b) wrapping the MCP server in a stdio→HTTP proxy launched from Terminal. Both are inaccessible to non-developer users.
Environment
Claude Code 2.1.128 (embedded in Claude desktop)
macOS 26.3.1, Apple Silicon
MCP server: tokymaker-mcp 0.1.0 (any BLE MCP server would reproduce)
Proposed Solution
Suggested fix
Add to claude.app/Contents/Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Claude Code uses Bluetooth on behalf of MCP servers that control Bluetooth devices.</string>
One-line bundle change. Note that /Applications/Claude.app already declares this — only the embedded claude-code bundle is missing it.
Alternative Solutions
_No response_
Priority
Critical - Blocking my work
Feature Category
CLI commands and flags
Use Case Example
_No response_
Additional Context
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗