Documentation

Pocketwire docs

Pair a device, connect your AI app and send your first text. Then look up the tools, the approval rules, self-hosting and fixes for common problems.

On this page Quickstart

Quickstart

You need an Android phone, or a Mac, Windows or Linux computer, and an AI app that can use remote MCP servers, such as Claude. Setup takes a few minutes.

Create an account

Sign up with your email and a password of at least 10 characters. The Free plan covers one device and 50 messages a month, and needs no card.

Pair a device

In the dashboard, open Devices and choose Add a device. You get an 8-character pairing code such as K7Q2-M9XD. It works once and expires after 10 minutes.

Android

  1. Download the signed Pocketwire APK from GitHub Releases and open it to install. Android may first ask you to allow installs from your browser. The app needs Android 8 or newer, and Obtainium can keep it up to date for you.

  2. Open Pocketwire, type the pairing code and a name for the phone, then tap Pair. Leave Server set to https://pocketwire.app unless you run your own server.

  3. Allow what Pocketwire asks for: SMS, to send the texts you approve, and notifications, to ask you about each one. A quiet notification shows that the connection is running.

The phone asks you to approve each text itself. The key it creates while pairing never leaves the phone; Pocketwire only gets the public half.

Mac, for iPhone users

  1. On your iPhone, turn on Text Message Forwarding for your Mac. You’ll find it in Settings under Messages (inside Apps on recent iOS versions). Messages on the Mac must be signed in with the same Apple Account.

  2. Download the Bridge for macOS from GitHub Releases: pocketwire-darwin-arm64 for Apple silicon or pocketwire-darwin-amd64 for Intel. Rename it to pocketwire, then pair it:

    Terminal
    chmod +x pocketwire
    ./pocketwire pair K7Q2-M9XD
    ./pocketwire run

    To keep it running after you close Terminal, and start it when you log in, run ./pocketwire service install instead of run.

  3. The first time it sends, macOS asks whether the Bridge may control Messages. Allow it. You can change this later in System Settings, under Privacy & Security, Automation.

You approve these texts in the dashboard under Approvals, because the Bridge has no screen of its own to ask on. To send iMessage instead of SMS, pair with --messages-service imessage.

Windows and Linux

  1. Install KDE Connect on the computer and on your Android phone, and pair the two. In the KDE Connect app on the phone, allow the SMS permission.

  2. Download the Bridge for your system from GitHub Releases, for example pocketwire-linux-amd64 or pocketwire-windows-amd64.exe. Rename it to pocketwire (pocketwire.exe on Windows), then pair it:

    Linux terminal
    chmod +x pocketwire
    ./pocketwire pair K7Q2-M9XD
    ./pocketwire run

    On Windows, run .\pocketwire.exe pair K7Q2-M9XD and then .\pocketwire.exe run in PowerShell. To keep the Bridge running in the background and start it when you log in, use service install instead of run.

  3. The Bridge sends through the first phone KDE Connect can reach. To pick another one, list them with kdeconnect-cli -l and pair again with --kdeconnect-device <id>.

You approve these texts in the dashboard under Approvals.

Just trying things out? Pair the Bridge with --driver dry-run. It prints each approved message in the terminal instead of sending it.

Connect your AI app

Add https://pocketwire.app/mcp to your AI app as a remote MCP server. The app opens Pocketwire’s sign-in page: sign in, check what the app asks for, and allow it. Step-by-step guides: Claude, Claude Code, Cursor and others.

Send a first text

Ask in plain words, with the number in international format:

Text +44 7700 900123 that I’m running 10 minutes late, sorry!

Your phone shows Text to +447700900123? with the whole message. Tap Send; on Android 12 and newer the phone asks you to unlock it first. With the Bridge, approve the text under Approvals in the dashboard instead. Either way, the request shows up under Activity.

Pocketwire doesn’t read your contacts. Give your AI app the number, or let it look the number up with another tool you’ve connected.

Desktop Bridge

The Bridge is one small program for macOS, Windows and Linux. It opens a secure connection out to Pocketwire, so it needs no open ports, and sends each approved text through a driver. GitHub Releases has builds for x86-64 and ARM64 on all three systems, with a SHA256SUMS file to check them against. The examples below assume the program is on your PATH as pocketwire.

Commands

CommandWhat it does
pocketwire pair <CODE>Links this computer to your account, with the options below.
pocketwire runStays connected in the foreground and sends approved texts. Stop it with Ctrl+C.
pocketwire service installKeeps the Bridge running in the background and starts it when you log in: a launchd agent on macOS, a systemd user service on Linux, a scheduled task on Windows. service uninstall removes it.
pocketwire doctorShows the pairing and which drivers work on this computer.
pocketwire test-send <number> <text>Sends one text straight through the driver after you type yes. It doesn’t go through Pocketwire, so it isn’t logged. Good for checking a driver.
pocketwire unpairForgets the pairing on this computer. Remove the device in the dashboard too.
pocketwire versionPrints the version.

Options for pair

OptionDefaultMeaning
--nameThe computer’s nameHow the device is named in the dashboard.
--drivermacos-messages on a Mac, kdeconnect elsewhereHow texts are sent. See drivers below.
--serverhttps://pocketwire.appYour own server, if you self-host. The POCKETWIRE_SERVER variable works too.
--kdeconnect-deviceFirst reachable phoneWhich KDE Connect device to send through.
--messages-servicesmsUse imessage to have Messages send iMessage instead.

Drivers

DriverRuns onNeeds
macos-messagesmacOSMessages signed in. For SMS, an iPhone with Text Message Forwarding turned on for this Mac. Automation permission for Messages, asked for once.
kdeconnectWindows, LinuxKDE Connect paired with an Android phone, and the SMS permission allowed in the KDE Connect app on the phone.
dry-runAllNothing. Prints messages instead of sending them.

Where the pairing is kept

Pairing creates a key pair on your computer, and only the public key is sent to Pocketwire. The private key and settings live in config.json, readable only by you: in ~/Library/Application Support/pocketwire/ on macOS, %AppData%\pocketwire\ on Windows and ~/.config/pocketwire/ on Linux. Set POCKETWIRE_CONFIG to use another path.

Connect to Claude

Pocketwire works in Claude as a custom connector. Custom connectors are available on Claude’s paid plans; on Team and Enterprise, an owner may need to add Pocketwire for the organization first.

  1. In Claude, open Settings, then Connectors, and choose Add custom connector.

  2. Name it Pocketwire and paste this server URL:

    https://pocketwire.app/mcp
  3. Add the connector and choose Connect. Claude opens Pocketwire: sign in, check what Claude asks for, and choose Allow.

  4. In a chat, make sure Pocketwire is switched on in the tools menu, then ask for a text. Claude usually checks with you before it calls send_sms, and then your phone asks too.

What an app can do

The consent screen names the app, where it will send you back to, and each kind of access it asks for:

AccessOn the consent screenUsed by
devices:readSee your paired devices and whether they are onlinelist_devices
sms:sendSend text messages from your phone (subject to your approval settings)send_sms, get_message_status
messages:readSee the status and history of messages it sentget_message_status, list_recent_messages

Note that list_recent_messages reads your whole activity log, so it also shows texts that other connected apps sent.

Connecting an app never changes your approval settings: with the defaults, every text still waits for your tap on Send. Disconnect an app under Connected apps in the dashboard, and its access ends at once.

Other AI apps

Any app that supports remote MCP servers with OAuth sign-in can use Pocketwire, with the same URL everywhere: https://pocketwire.app/mcp.

Claude Code

Terminal
claude mcp add --transport http pocketwire https://pocketwire.app/mcp

Then run /mcp in Claude Code and choose Pocketwire to sign in.

Cursor

Add Pocketwire to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project. Cursor asks you to sign in the first time it connects.

mcp.json
{
  "mcpServers": {
    "pocketwire": {
      "url": "https://pocketwire.app/mcp"
    }
  }
}

ChatGPT, Claude Duet and others

Where your app lets you add a custom connector or a remote MCP server, add the URL above and choose OAuth if it asks how to sign in. In ChatGPT, whether custom connectors are available depends on your plan and workspace settings.

Building your own client

  • Transport: Streamable HTTP at /mcp, stateless, with JSON responses.
  • Discovery: unauthenticated requests get 401 with a WWW-Authenticate header that points to /.well-known/oauth-protected-resource/mcp. Authorization server metadata is at /.well-known/oauth-authorization-server.
  • Clients: client ID metadata documents or dynamic client registration. Redirect URIs must be HTTPS, a loopback address on any port, or a private-use scheme.
  • Flow: authorization code with PKCE; S256 is required. The resource parameter is checked as the token’s audience.
  • Tokens: access tokens last an hour. Refresh tokens last 30 days and change on every use; reusing an old one revokes the whole grant.
  • Scopes: devices:read, sms:send and messages:read, plus offline_access.

MCP tools

Pocketwire gives your agent four tools and nothing else. Each has a title and MCP annotations; send_sms is marked as destructive, so clients know to check with you before calling it. There’s no tool for texting a list of people, reading your inbox or reading replies.

list_devices

read-onlydevices:read

Lists your paired phones and Bridges, whether each one is online, and whether it can send SMS.

No parameters. Returns devices, each with device_id, name, kind, platform, online, can_send_sms and last_seen_at.

send_sms

sends a textsms:send

Sends a text from your own number through a paired device. Depending on your settings, it first waits for your approval on the phone or in the dashboard.

  • tostring · required

    Recipient in E.164 format, such as +48501234567. Spaces, dots, dashes and brackets are removed, and a leading 00 becomes +.

  • bodystring · required

    The exact text, 1 to 1,600 characters. Longer texts go out as several SMS parts.

  • device_idstring · optional

    Which device to send from, from list_devices. By default, the first online device.

The call waits up to 25 seconds for the message to be sent, rejected or expired, then returns the message as it stands, with its message_id. If you haven’t tapped Send by then, the status is awaiting_approval or queued, and the agent can check again with get_message_status.

get_message_status

read-onlymessages:read or sms:send

Returns the current state of a message that send_sms created.

  • message_idstring · required

    The message_id that send_sms returned, such as msg_Qm3v7KxR2pTnF8wd.

list_recent_messages

read-onlymessages:read

Lists recent messages from your activity log, newest first, with recipient, status and time, including texts other connected apps sent. The text itself is included only if you turned on message history.

  • limitinteger · optional

    How many messages, from 1 to 50. Default 10.

What a message looks like

send_sms result
{
  "message_id": "msg_Qm3v7KxR2pTnF8wd",
  "device_id": "dev_8bQe1sKfP0xYtL2m",
  "to": "+48501234567",
  "status": "sent",
  "error": null,
  "approval": "device",
  "client_name": "Claude",
  "body_length": 59,
  "segments": 1,
  "created_at": "2026-10-29T13:01:48.000Z",
  "updated_at": "2026-10-29T13:02:03.000Z"
}

approval says where the message was approved: device (on the phone), dashboard or none (trusted contact, or a setting that didn’t ask). Times are in UTC.

Statuses

StatusMeaning
queuedAccepted, waiting for your device to pick it up.
awaiting_approvalWaiting for your tap on Send, on the phone or in the dashboard.
sendingApproved. The device is sending it.
sentThe device handed it to the mobile network, or to Messages on a Mac.
deliveredThe network confirmed delivery. Android only, where your carrier sends delivery reports.
failedIt couldn’t be sent. error says why, for example no_service or radio_off on Android.
rejectedYou tapped Reject. Nothing was sent.
expiredNobody approved it within 10 minutes (approval_timeout), or the device stayed unreachable (device_unreachable).

Errors

When a request can’t go ahead, the tool returns an error with a plain message the agent can pass on. Numbers in the messages depend on your plan.

WhenThe agent is told
No device is pairedNo device is paired yet. Pair a phone or the desktop Bridge at /app/devices.
device_id isn’t yoursNo such device on this account.
The number isn’t validPhone number must be in international E.164 format, e.g. +48501234567.
The text is empty or too longMessage must be 1–1600 characters.
Too many at onceToo many messages this minute (limit 5). Try again shortly. Or: Daily limit of 20 messages reached.
The month’s quota is used upMonthly quota of 50 messages reached on the Free plan.
Too many new numbers todayYou can text at most 5 new numbers per day on the Free plan.
Sending is pausedSending is paused for this account. Resume it in the Pocketwire dashboard.
The app wasn’t given that accessThis connection was not granted “sms:send”. Reconnect Pocketwire and allow it.
Unknown message_idNo such message on this account.

Approvals and limits

Pocketwire assumes your agent can get things wrong, or be tricked by something it read. Approvals keep you in the loop, and limits cap the damage if something slips through.

When Pocketwire asks

Choose this under Settings in the dashboard.

SettingPlansWhat happens
Every messageAll plans; the only one on FreeEvery text waits for your tap on Send. This is the default and what we recommend.
Only the first message to a new numberPro, TeamPocketwire asks the first time your agent texts a number. Once a text to it has gone out, later ones go without asking.

Android phones ask with a notification that shows the number and the whole text, with Reject and Send. On Android 12 and newer, Send asks you to unlock the phone first. Tap the notification to see the request in full before you decide. Bridge devices are approved in the dashboard under Approvals, which refreshes itself every 10 seconds. A request nobody answers expires after 10 minutes, and nothing is sent.

Trusted contacts

On Pro and Team, add numbers under Settings, Trusted contacts, with a name if you like. Texts to those numbers go out without asking. Every other number still follows your approval setting.

Limits

Limits apply to every request, whoever approves it. Requests you rejected and requests that expired don’t count.

FreeProTeam
Devices1310
Messages a month502,00010,000
Messages a day203002,000
Messages a minute52060
New numbers a day550200
Activity log kept for7 days1 year1 year
Trusted contactsNoYesYes

A day is any 24 hours, and a month is the calendar month in UTC. A new number is one your account has never texted before. Numbers shorter than 7 digits, such as short codes, are refused.

Kill switch

Pause all sending in the dashboard’s Settings stops everything at once: while it’s on, every request is refused and the agent is told that sending is paused. The Android app has its own Pause sending switch, which refuses every request on that phone, whatever the dashboard says.

Security and privacy

  • Outbound only. Phones and Bridges connect out to Pocketwire over TLS. Nothing listens for connections on your devices.
  • Keys stay on the device. Pairing creates a key pair on the phone or computer. Only the public key is sent, and the device proves itself with the private one.
  • Message text isn’t kept. The text is stored encrypted only until the message is sent, rejected, failed or expired, then deleted, unless you turn on message history. The log keeps the recipient, the length, a SHA-256 fingerprint of the text, the status and the times.
  • Encrypted at rest. Recipients, and the text while it waits, are encrypted with AES-256-GCM. The key lives in the server’s environment, never in the database.
  • Hashed secrets. Access tokens, refresh tokens and pairing codes are stored only as SHA-256 hashes, and passwords with scrypt.
  • Checked twice. The phone and the Bridge check every request again before sending: a valid number, 1 to 1,600 characters, not expired, not a repeat.
  • Hosted in the EU. Our servers and backups are with Hetzner, in the European Union.

Not end-to-end encrypted. Your AI app sends each message to Pocketwire in an ordinary MCP tool call, so our server sees the text while it passes it on to your phone. If no third party may see your messages, host Pocketwire yourself.

Reporting a vulnerability

Email security@pocketwire.app, in English or Polish. Please give us a reasonable time to fix a problem before you make it public. Details of how we handle personal data are in the privacy policy.

Self-hosting

Run Pocketwire Cloud on your own server and no message passes through us. The repository’s infra folder has a production setup for one Linux server with Docker: Pocketwire itself, Caddy for automatic HTTPS, and Litestream for continuous backups of the SQLite database.

  1. Point your domain at the server with A and AAAA records, for the domain and for www.

  2. In a copy of the repository on the server, create the settings file and two secrets:

    Server
    cd pocketwire/infra
    cp .env.example .env
    openssl rand -base64 32   # paste as ENCRYPTION_KEY
    openssl rand -base64 32   # paste as HMAC_SECRET

    Set DOMAIN, ENCRYPTION_KEY and HMAC_SECRET in .env. The LITESTREAM_* values send backups to any S3-compatible bucket. If you don’t want off-site backups, remove the litestream service from docker-compose.yml.

  3. Start it:

    Server
    docker compose up -d --build

    Caddy gets a certificate on the first request. https://your-domain/healthz should answer {"ok":true}.

  4. Use your server everywhere: on Android, type your address in the Server field when pairing; pair the Bridge with --server https://your-domain; connect AI apps to https://your-domain/mcp.

Keep .env somewhere safe, such as a password manager. If ENCRYPTION_KEY is lost, stored recipients can’t be read any more.

To update, pull the newer code and run docker compose up -d --build again. For help with a larger setup, talk to us.

Try it on your computer

Terminal
cd server && npm install && npm run dev   # http://localhost:8080

Sign up at http://localhost:8080/app/signup, pair the Bridge with --server http://localhost:8080 --driver dry-run, and point an MCP client at http://localhost:8080/mcp. Claude on the web needs a public HTTPS address, for example through a tunnel.

Troubleshooting

My agent says no device is paired, or the device is offline

Check Devices in the dashboard. If the device shows as offline, open the Android app, or start the Bridge with pocketwire run (or pocketwire service install to keep it running), and check that it has a connection.

The approval notification doesn’t show up

Make sure Pocketwire may show notifications and that its Approvals channel isn’t turned off in Android’s settings. If Android paused the background connection, Pocketwire shows a notification asking you to reconnect: tap it. On some phones it helps to exclude Pocketwire from battery optimization.

The message expired

Requests expire after 10 minutes if nobody approves them, or if the device stays unreachable. Ask your agent to send it again.

“Phone number must be in international E.164 format”

Use a plus sign and the country code, such as +48501234567 or +44 7700 900123. Numbers shorter than 7 digits, like short codes, aren’t accepted.

A limit was reached

You hit a per-minute, daily, monthly or new-number limit. The limits table shows them for each plan; the per-minute and daily ones free up on their own.

Messages on the Mac doesn’t send

Run pocketwire doctor. Check that Messages is signed in, that Text Message Forwarding is on for this Mac on your iPhone, and that the Bridge may control Messages in System Settings, under Privacy & Security, Automation. When the Bridge runs as a service, its log is in ~/Library/Logs/pocketwire-bridge.log.

KDE Connect doesn’t send

Run kdeconnect-cli -l to check that the phone is paired and reachable, and that the KDE Connect app on the phone has the SMS permission. Then send yourself a test with pocketwire test-send and your own number.

Claude can’t connect, or a tool says access wasn’t granted

Check that the URL is exactly https://pocketwire.app/mcp. If you chose Deny by mistake, or a tool says the connection wasn’t granted some access, remove the connector, add it again and allow it.

Still stuck?

Write to support@pocketwire.app with the time and, if you have it, the message ID (msg_…). Never send us your password.