Skip to main content
Glama
h-3303
by h-3303

phone-sms

Site: https://phone-sms.vercel.app · Repo: https://github.com/h-3303/phone-sms

An MCP server that lets Claude (or any MCP client) read and send SMS through your own Android phone, from your own number. It talks to the phone over KDE Connect on your local network: no cloud relay, no SMS gateway account, no app to install beyond KDE Connect itself.

agent ──MCP──▶ phone-sms ──D-Bus──▶ kdeconnectd ──LAN──▶ KDE Connect (Android) ──▶ SMS

Tools:

Tool

Does

list_threads

conversations, newest first, with the latest message; filter by contact or unread

read_thread

the last n messages of one conversation

find_contact

look up a contact by name or number fragment (from the phone's synced contacts)

send_sms

send a text, or a group text to several numbers

send_sms carries MCP's destructiveHint, and the server tells the model never to send until you have approved the exact recipient and text in the conversation. Message contents never leave your machine except as the model's context.

Requirements

  • Linux with a D-Bus session bus and KDE Connect (kdeconnectd, a current release; package kdeconnect). It does not need the Plasma desktop; it runs fine under GNOME, Hyprland, Sway…

  • An Android phone with the KDE Connect app (F-Droid / Play), paired with the computer. On the phone, enable the SMS plugin (and Contacts if you want names) and grant the SMS and contacts permissions it asks for.

  • uv and Python 3.12+.

Check the pairing: kdeconnect-cli -l should list your phone as paired and reachable.

Related MCP server: mac-messages-mcp

Install

Claude Code, as a plugin (one step):

/plugin marketplace add h-3303/phone-sms
/plugin install phone-sms@phone-sms

Claude Code, as a plain MCP server:

claude mcp add --scope user phone-sms -- uvx phone-sms

Any other MCP client (Claude Desktop config shape, Cursor, Zed, …):

{
  "mcpServers": {
    "phone-sms": {
      "command": "uvx",
      "args": ["phone-sms"]
    }
  }
}

From a checkout: uv run --directory /path/to/phone-sms -q phone-sms.

The server uses the first paired, reachable device. With several phones, pin one with PHONE_SMS_DEVICE=<id> (the id kdeconnect-cli -l prints).

CLI

The same code paths, for checking things by hand:

phone-sms threads [-n 20] [--unread]
phone-sms read <thread_id> [-n 20]
phone-sms contact <name>
phone-sms send <number>... -m "text"
phone-sms                              # MCP server on stdio

How sending works

  1. find_contact <name> gives the number; send_sms takes numbers, ideally in E.164 (+14375551234).

  2. The model shows you recipient and text and waits for your yes.

  3. send_sms answers handed to phone… once kdeconnectd has accepted the request. That is not delivery: the sent message shows up in list_threads / read_thread once the phone syncs it, usually within a minute.

Troubleshooting

  • "no paired, reachable device": open KDE Connect on the phone, same Wi-Fi, kdeconnect-cli -l.

  • Sent, but nothing arrives: on the phone, check that the SMS plugin is enabled for this computer and that Android granted KDE Connect the SMS permission. Watch the request leave the server with dbus-monitor --session "interface='org.kde.kdeconnect.device.conversations',member='sendWithoutConversation'".

  • Names missing: enable the Contacts plugin on both ends; vCards land in ~/.local/share/kpeoplevcard/kdeconnect-<device>/.

  • The kdeconnectd journal line Unimplemented conversation of type 'r' comes from the notification-forwarding plugin, not SMS.

Notes for hackers

It uses org.kde.kdeconnect.device.conversations, the interface the kdeconnect-sms app uses. The daemon object's introspection XML has duplicate methods, so device discovery is a raw D-Bus call. requestConversation first emits only cached messages, so read_thread waits for count messages or conversationLoaded, not for a quiet gap.

License

GPL-3.0-or-later, like KDE Connect.

Available Tools

4 tools
find_contactB
Read-only

Look up phone contacts by name or number fragment.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already declares this is a safe read, so the description doesn't need to reassure about mutation. It adds the useful detail that matching can be by name OR number fragment, but says nothing about auth needs, matching behavior, or result limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and this is a simple single-parameter read. The remaining gap is the lack of any guidance on matching behavior or when to prefer this over the messaging siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the schema alone gives no meaning for 'query'. The description partially compensates by explaining the query accepts a name or number fragment, but omits details like partial-match semantics or format expectations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (look up) and resource (phone contacts) plus the matching method (name or number fragment). It naturally distinguishes itself from the messaging-oriented siblings (list_threads, read_thread, send_sms), though it never explicitly names or contrasts them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance, no discussion of alternatives, and no exclusions. The purpose implies lookup usage, but an agent gets no routing help for choosing this over the sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_threadsA
Read-only

List SMS conversations, newest first, with the latest message of each.

Each line starts with the thread id, which read_thread takes.
contact: optional name or number fragment to filter on.
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
contactNo
unread_onlyNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint already declares this is a safe read. The description goes beyond that by disclosing result ordering (newest first), that each thread carries its latest message, and the per-line output shape beginning with the thread id. It does not mention pagination or result caps, but with an output schema present the return shape is already partly covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short lines, zero filler, and front-loaded with the core purpose and ordering before the read_thread linkage and the single parameter note. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the description need not explain return values, and it covers ordering, per-line format, and the read_thread connection. The main gap is the undocumented limit and unread_only parameters, which is a minor omission for an otherwise simple read-only listing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden, yet it only documents one of three parameters: 'contact: optional name or number fragment to filter on.', which usefully clarifies the fragment-matching semantics. limit and unread_only are left entirely to their self-explanatory names and defaults, so compensation is partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List SMS conversations') and adds distinguishing scope: newest-first ordering and inclusion of the latest message per thread. It also names the sibling read_thread and explains the linkage (thread id), so an agent can separate this listing tool from the read-one tool without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied through the read_thread linkage ('Each line starts with the thread id, which read_thread takes'), which does suggest a list-then-read workflow. However, there is no explicit when-to-use vs when-not, no mention of find_contact or send_sms, and no stated prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_threadB
Read-only

Read the most recent count messages of one conversation, oldest first.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
thread_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already establishes the safe-read profile, so the bar is lower. The description usefully adds ordering semantics ('oldest first') and the recency window ('most recent count messages'), which annotations do not convey, but it says nothing about how ordering interacts with a capped count or whether older messages are retrievable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, no filler, and the key scoping information (most recent, per-conversation, oldest-first order) is front-loaded. Nothing needs trimming and nothing essential is buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not required, and the tool is low complexity with only two parameters. The description covers the core behavior adequately; only edge cases (count exceeding available history, behavior when thread_id is invalid) are absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry parameter meaning. It does clarify `count` as the number of most-recent messages and the returned ordering, but leaves the schema default of 20 unmentioned and says nothing about `thread_id` beyond the name.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb ('Read') plus a precisely scoped resource ('the most recent `count` messages of one conversation'), which is clear enough to separate it from list_threads (enumerating conversations) and send_sms (writes). It does not name those siblings explicitly, but the resource framing makes the distinction inferable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance and no mention of any alternative tool, despite having three siblings. The agent must infer from the name alone that this is the tool for reading messages within an already-known thread rather than listing threads.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_smsA
Destructive

Send an SMS (several numbers = group message) from the user's phone and number.

ONLY call after the user has explicitly approved this exact recipient list and text.
`to` takes phone numbers; resolve names with find_contact first.
ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
textYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint and openWorldHint, but the description adds the crucial behavioral gate that this must not be invoked without explicit user approval of the exact recipients and text, plus the fact that multiple numbers fan out to a group message. It does not cover delivery/rate-limit behavior, but the approval requirement is the highest-value disclosure here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short lines with zero padding; the action and the approval precondition are front-loaded before the contact-resolution hint. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and annotations already cover the safety profile. The description supplies the missing operational constraints (approval gate, group semantics, name resolution) needed to invoke this destructive, open-world tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry parameter meaning; it explains that 'to' holds phone numbers (not names) and that multiple values produce a group message, which is real semantics beyond the bare array-of-strings schema. 'text' is left implicit, though its name and string type make it self-evident.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (send) and resource (SMS) plus the originating identity (user's phone and number), and clarifies the multi-recipient case as a group message. It also names find_contact, letting an agent distinguish this from the contact-resolution tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit precondition ('ONLY call after the user has explicitly approved this exact recipient list and text') and routes a prerequisite sub-task to the alternative tool ('resolve names with find_contact first'). When-to-use and which-sibling-to-use are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedfind_contact
    • First observedlist_threads
    • First observedread_thread
    • First observedsend_sms

TDQS

A3.9/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a clearly distinct action: listing threads, reading a single thread, finding contacts, and sending messages. There is no meaningful overlap between any pair.

Naming Consistency5/5

All four tools use a consistent snake_case verb_noun pattern (list_threads, read_thread, find_contact, send_sms). The convention is predictable throughout.

Tool Count4/5

Four tools is well-scoped for a focused SMS server, covering discovery, reading, contact lookup, and sending. Slightly minimal but each earns its place.

Completeness4/5

Core flows are covered: find contact, list threads, read a thread, send a message. Minor gaps exist around thread management (delete/archive, mark read) but typical agent workflows are supported.

Maintenance

ActivityNo data
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables reading, searching, and sending iMessages directly from MCP-compatible clients by accessing the local macOS iMessage database, supporting conversations, attachments, and both individual and group chats.
    381 npm
    10
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for a local-first messaging workspace that integrates Google Messages, WhatsApp, and Signal. It enables reading, sending, searching messages, and managing conversations through MCP tools.
    61
    -
  • A
    license
    B
    quality
    D
    maintenance
    MCP server for sending SMS via the SMSPM API. Send transactional SMS from Claude Desktop, Cursor, Windsurf, Cline, or any MCP client.
    1
    34 npm
    MIT