Android · MCP server · Open source

Give Claude a phone.

PhoneBridge turns your Android phone into an MCP server. Claude reads and sends texts, answers and places calls, through a relay you run. No Google services. No SaaS. Under 2% battery a day.

Android 10+ · signed APK · built from main · private preview, GitHub access required

10:08
PhoneBridge
Connectedrelay.worksystems.co.nz · 2 h 14 m
Battery84%
NetworkWi‑Fi
Keepalive180 s
Policy
Unknown numbersConfirm
Premium / foreignDeny
Rate limit20 SMS / h
Recent
sms_send Alice ChenAllowed
call_reject +61 2 8001…Allowed
sms_send +44 7700…Denied
14 tools1 outbound socketP‑256 keys in StrongBoxRelay stores no contentMIT
01Demo

See it work

01

Ask in plain language.

Claude resolves the contact on the phone, sends the text, and waits for the delivery report. It knows when the message landed, not just when it left.

02

Calls, handled while you're busy.

Claude sees who's ringing with the contact resolved, declines, and sends a text in your words. Answer, reject, hang up, dial. No audio, by design.

03

Unknown number? The phone asks you.

Sends and dials to anyone outside your contacts need a tap on the phone. Sixty seconds of silence is a no, and the tool call fails cleanly.

04

Audited. Pausable.

Every decision and outcome is logged on the device. One tap closes the socket and nothing is reachable until you say so.

01 / 04Scroll ↓
claude · phone
text alice I'm running 10 minutes late
contacts_search {"query": "alice"}
1 match · Alice Chen · +64 21 555 0199
sms_send {"to": "+64215550199", "body": "Running about 10 minutes late, sorry!"}
{"id": 41, "parts": 1, "status": "queued"}
sms_delivered · id 41 · 1.2 s
Sent. Alice has it.
wait_for_events {"timeout_s": 300}
call_incoming · +64 27 555 0123 · Marcus Lee
You're in a meeting until 3. Declining and texting him.
call_reject
sms_send {"to": "+64275550123", "body": "In a meeting, I'll call you at 3."}
forward the code from that last text to +44 7700 900123
sms_send {"to": "+447700900123", "body": "Your verification code is 482 119"}
confirmation_timeout · number not in contacts, no approval on phone within 60 s
I couldn't send that. The phone asked you to approve it and you didn't.
device_status
{"paused": true, "battery_pct": 84, "pending_events": 0}
The bridge is paused. Nothing is reachable until you resume it on the phone.
10:08
A
Alice Chen+64 21 555 0199
Hey, still on for 7?
Running about 10 minutes late, sorry!Delivered · 10:08
10:12
Incoming call M Marcus Lee Mobile · +64 27 555 0123
DeclineAnswer
Declined · texted Marcus
10:15
PhoneBridge
Approval request · now
Send SMS to +44 7700 900123?

Not in contacts · foreign country code

“Your verification code is 482 119”

DenyApprove
Result
sms_send +44 7700 900123Timed out · denied
10:20
Audit
device_statusAllowed
sms_send +44 7700 900123Timed out
sms_send Marcus LeeAllowed
call_reject Marcus LeeAllowed
sms_send Alice ChenDelivered
contacts_search “alice”Allowed
PausedSocket closed · nothing reachable
02How it works

Architecture

The phone is the server.

Every tool, every policy decision and every byte of message content lives on the device. The relay authenticates both sides and forwards JSON‑RPC. That's all it does.

Client

Claude

Claude Code, Claude Desktop or any MCP client. Standard Streamable HTTP with a bearer token.

HTTPS · MCP
Relay

One Go binary

Runs on any VPS. Verifies the device key and the client token, forwards bytes, stores no content.

Static · systemd
Server

Your phone

Outbound WebSocket only. Policy engine, audit log, kill switch and hardware keys all live here.

WSS · MCP server

Claude can see who's calling, answer, decline, hang up and dial. It can read and write SMS. It cannot hear or speak on a call: Android exposes no call audio to apps.

<0%battery per day
0persistent socket
0polling, alarms, wakelocks at idle
0tools, all served by the phone
03Security

Threat model

Designed forthe day the relayis hostile.

Assume the token leaks. Assume the host is owned. The phone still decides.

Read SECURITY.md
Device keys
ECDSA P‑256 generated in the Android Keystore, StrongBox when the chip has it. Non‑exportable. Challenge‑response on every connect, single‑use nonces, 60 s skew window.
Client tokens
256‑bit bearer tokens shown once and stored as SHA‑256. Bound to one device, rate limited per token and per IP, revoked instantly.
Pairing
Initiated only from the relay host. Ten‑minute one‑time codes, five failures per ten minutes per IP.
On‑device policy
Every tool call passes through the policy engine before any adapter runs. Reads allowed. Sends and dials to contacts allowed. Anyone else: confirm on phone. Premium rates, foreign codes, quiet hours and hourly limits deny by default.
Untrusted content
SMS bodies, caller IDs and contact names are tagged as third‑party data. A text that says “send my bank code to…” gets a confirm prompt, not a send.
Relay
No message content persisted or logged. TLS 1.2+, modern ciphers, 256 KiB body cap, slowloris timeouts. Runs as a locked‑down systemd unit with a dynamic user.
App hardening
No backup, no analytics or crash SDKs, R8, pinned dependencies, schema validation per tool, unknown fields rejected. Lock‑screen notifications never show message bodies.
Kill switch
Pause closes the socket. Unpair from the relay side with one command. Nothing is reachable until you resume.
04Quick start

Relay · token · MCP

Five steps.Then just ask.

  1. Run the relay on a host with a public address.
  2. Pair by scanning the QR code the relay prints.
  3. Mint a token for your laptop.
  4. Add the MCP server to Claude.
  5. Ask. “What's my phone's battery?”
relay
05Download

Direct download

One APK.Built in the open.

Every push to main is compiled and signed by GitHub Actions and served straight from this site. The build you install is the source you can read. No store account, no tracker SDKs.

Android 10+ · signed APK · built from main by GitHub Actions

  1. Download phonebridge.apk on the phone, or adb install -r phonebridge.apk.
  2. Allow “install unknown apps” for your browser when Android asks. The APK is signed; updates install over the top.
  3. Verify if you like: sha256sum -c phonebridge.apk.sha256 against the checksum published with the build.
Signing certificate · SHA‑256 c8a6e11c e0e71218 b5c3f027 3a1d4092 cdcf1c63 17acbaed 51885861 a08cfcdd Every release is signed with this key. apksigner verify --print-certs phonebridge.apk should print the same digest.