Skip to main content
Glama
falconbradley

Apple Messages MCP

Apple Messages MCP

Читайте и ищите свои переписки iMessage, SMS и RCS из Claude на macOS.

Дополнение к claude-connector-apple-mail и claude-connector-apple-reminders.

Статус: чтение и поиск работают надёжно. Отправка работает, но не проверена на реальной отправке — вызов скрипта реализован, его синтаксис проверен, но Apple уже ломала send раньше, так что первую реальную отправку считайте тестом. См. Отправка сообщений.

Инструменты

Инструмент

Описание

get_stats

Итоги, количество непрочитанных, разбивка по службам (iMessage/SMS/RCS), диапазон дат

list_chats

Переписки, сначала самые недавние, с участниками и превью

get_chat_messages

Сообщения в одной переписке, сначала старые, с постраничной разбивкой

search_messages

Поиск подстроки по всей истории, с фильтром по переписке, отправителю и диапазону дат

get_message

Одно сообщение полностью, с вложениями и временными метками доставки

get_attachment

Вложение в байтах, в кодировке base64

refresh_search_index

Прогрев или пересоздание локального поискового индекса

compose_message

Открыть Messages с предзаполненным текстом — вы нажимаете «Отправить»

send_message

Отправить в существующую переписку; доставляется немедленно

Related MCP server: iMessage MCP Server

Требования

  • macOS 13 Ventura или новее. RCS требует macOS 26 или новее.

  • Полный доступ к диску для приложения Claude — требуется для чтения.

  • Разрешение автоматизации для Messages — требуется для отправки и для имён контактов. macOS запрашивает его автоматически.

Предоставление полного доступа к диску

  1. Системные настройки → Конфиденциальность и безопасность → Полный доступ к диску

  2. Включите Claude (добавьте /Applications/Claude.app через +, если его нет в списке)

  3. Завершите работу Claude и откройте его снова. macOS кэширует это разрешение при запуске процесса, поэтому перезапуск обязателен — без него расширение будет продолжать давать сбои.

Почему здесь нужен полный доступ к диску, а для Apple Mail — нет

Расширение Apple Mail общается с Mail.app полностью через скрипты, поэтому ему не нужны особые разрешения. Messages так работать не может.

Словарь AppleScript для Messages предоставляет ровно четыре класса — account, chat, participant, file transfer — и никакого класса сообщений. Проверено на macOS 26.5.2:

$ osascript -e 'tell application "Messages" to get every text message of first chat'
syntax error: Expected "from", etc. but found identifier. (-2741)

Переписки и участники перечисляются нормально; тексты сообщений просто не доступны. Поэтому единственный путь чтения — SQLite через ~/Library/Messages/chat.db, который защищён TCC. В отличие от автоматизации, полный доступ к диску нельзя запросить программно — пользователь должен предоставить его вручную.

Поэтому расширение использует оба разрешения для разных задач:

Задача

Механизм

Разрешение

Сообщения, переписки, поиск, вложения

SQLite на chat.db

Полный доступ к диску

Имена контактов для «сырых» идентификаторов

Скрипты Messages

Автоматизация

Отправка

Скрипты Messages (send)

Автоматизация

Окно создания, предзаполнение

Схема URL imessage: / sms:

нет

Имена контактов берутся из класса participant в Messages (свойство full name), который читает карточку контакта пользователя. Это обходит отдельно защищённую базу AddressBook — если автоматизация запрещена, идентификаторы просто отображаются как «сырые» номера.

Заметки по реализации

attributedBody. Начиная с Ventura, message.text часто равен NULL, а текст сообщения хранится в message.attributedBody в формате Apple typedstream — это устаревший формат NSArchiver, который plistlib не умеет читать. typedstream.py декодирует его на чистом Python, так что пакету не нужна зависимость PyObjC. Он опирается на имя класса NSString/NSMutableString и читает полезную нагрузку UTF-8 с префиксом длины после маркера типа +. Декодирование полное: не поддающееся декодированию тело даёт None, а не приводит к сбою запроса.

Временные метки. message.date — это эпоха Apple (2001-01-01), в секундах до macOS 13 и в наносекундах начиная с неё. Оба варианта распознаются и обрабатываются.

Поиск. В chat.db нет текстового индекса, и большинство текстов живут только в attributedBody, где SQL их не видит. Такое сочетание сложнее, чем кажется.

Первая реализация расширяла свой предикат до m.text LIKE ? OR m.attributedBody IS NOT NULL и повторно фильтровала декодированный текст в Python. Поскольку второе условие истинно почти для каждой современной строки, LIMIT запроса усекал сканирование до нескольких сотен самых новых сообщений до того, как фильтр Python вообще запускался — поэтому любое более старое совпадение молча исчезало. Поиск реального сообщения возвращал ноль результатов, а не был медленным. На истории объёмом 916 МБ это означало, что поиск фактически покрывал только последние несколько дней.

Исправление — декодировать один раз, а не при каждом запросе. index.py зеркалирует декодированные тексты, приведённые к нижнему регистру, в ~/Library/Caches/apple-messages-mcp/search-index.db, к которому затем подключается поиск — так что совпадение, фильтры, сортировка и LIMIT применяются ко всей истории в SQL. Зеркало:

  • Инкрементальное. Новые сообщения находятся по водяному знаку message.ROWID. Правки и отмены отправки повторно используют существующий ROWID, поэтому каждое обновление также просматривает последние 2000 строк — но только те, у которых date_edited установлен или оба столбца тела теперь NULL, поскольку повторное декодирование 2000 блоков при каждом поиске — это реальная работа, которая почти всегда ничего не находит. Правка, которую Messages каким-то образом не пометил, или правка старше этого окна, требует refresh_search_index(rebuild=True). Улучшение декодера attributedBody также оправдывает пересоздание; увеличение SCHEMA_VERSION принудительно его выполняет.

  • Приведено к нижнему регистру, и только это. Отображаемый текст по-прежнему берётся из chat.db, так что зеркало — чисто оракул для сопоставления. Хранение str.casefold() уменьшает его размер вдвое и делает сопоставление без учёта регистра корректным для не-ASCII — SQLite LIKE сворачивает регистр только для ASCII.

  • Одноразовое. Оно живёт в ~/Library/Caches и пересоздаётся при удалении. Ничто здесь не пишет в chat.db.

Не FTS5, несмотря на более ранний план: FTS5 сопоставляет целые токены, поэтому MATCH 'dentist' никогда не найдёт «mydentist», что уже, чем семантика подстроки, которую документирует search_messages. Сканирование подстрок по компактному тексту в нижнем регистре уже быстрое, так что FTS5 удвоил бы индекс ради семантики, которую мы не можем использовать. Добавить его позже — изолированное изменение, если какой-то запрос вдруг станет тормозить.

Только чтение и без блокировок. Соединения открываются с mode=ro, и ни один оператор не изменяет базу данных. Если SQLite не может открыть живой WAL в режиме только для чтения, он переключается на частную копию-снимок, так что работающий Messages.app никогда не нарушается.

Tapbacks, правки, ответы. Реакции декодируются из associated_message_type (2000–2007, а диапазон 3000 — их удаления), ответы в ветках — из thread_originator_guid, а правки — из date_edited.

Отправка сообщений

В Messages нет объекта черновика, поэтому нет точного аналога подхода Mail-расширения «сначала черновик». Поэтому путь записи реализован на двух уровнях, и они намеренно не эквивалентны.

compose_message — безопасный вариант по умолчанию. Открывает Messages с получателем и текстом, предзаполненными через схему URL imessage: / sms:, и останавливается. Человек читает и нажимает «Отправить», так что ничего не покидает машину по указанию Claude. Это также единственный способ начать новую переписку. Не требует никаких разрешений.

send_message — доставляет немедленно. Использует send из интерфейса скриптов и не может быть отменено. Он принимает chat_id, а не номер телефона, что не ограничение, а суть: словарь принимает либо participant, либо chat, и адресация существующей переписки по GUID позволяет Messages выбирать транспорт (iMessage / SMS / RCS) вместо того, чтобы вызывающий угадывал и молча отправлял SMS тому, кто на iMessage. Также требуется confirm=True — чисто как защита от случайного срабатывания.

Что проверено, а что нет

Подтверждено на macOS 26.5.2 — словарь предоставляет

send : direct-parameter (file | text), to: (participant | chat)

перечисление service type — это SMS, iMessage, RCS, у chat есть свойство GUID id для адресации, и сгенерированный AppleScript компилируется.

Не подтверждено: что реальная отправка действительно доставляет. Apple уже ломала AppleScript send раньше, и его наличие в словаре никогда не было доказательством работоспособности. Ничто в тестовом наборе не доставляет сообщение, так что первая реальная отправка — это эксперимент. Если она не сработает, shortcuts run с действием «Отправить сообщение» — следующий вариант, который стоит попробовать.

Текст сообщения передаётся в AppleScript как аргумент osascript (on run argv), а не вставляется в исходный код скрипта, поэтому тело, содержащее двойную кавычку, инертно, а не вызывает синтаксическую ошибку или инъекцию.

Отправка вложений не подключена, хотя прямой параметр file означает, что она в пределах досягаемости.

Разработка

python3 tests/test_db.py       # SQL, decoder, and search-index tests
python3 tests/test_send.py     # compose URLs, send guards, argv safety
python3 tools/probe_schema.py  # verify the real chat.db (needs Full Disk Access)
./build.sh                     # test, validate manifest, pack the .mcpb

tests/test_db.py создаёт одноразовые базы данных с реальной схемой, поэтому SQL можно проверять без полного доступа к диску или реальной истории сообщений. Один из тестов прячет совпадение под 3000 более новых сообщений — это регрессионный тест для описанной выше ошибки усечённого поиска.

tests/test_send.py никогда ничего не отправляет и не открывает окно: он покрывает построитель URL, защитные условия и точный argv osascript — так что он безопасен где угодно и, соответственно, не может сказать вам, работает ли send от Apple.

Ни один из наборов не касается реального поискового индекса; оба внедряют временный.

Лицензия

MIT

Available Tools

9 tools
compose_messageA

Open Messages with a recipient and text prefilled, WITHOUT sending.

This is the safe way to write a message: it puts the text in front of the user in Messages and stops, so they read it and press send themselves. Prefer it over send_message, and use it whenever the conversation does not exist yet — send_message can only reply to an existing one.

Args: handle: Recipient phone number or email, e.g. "+15551234567". body: Text to prefill. May be empty to just open the conversation. service: "imessage" or "sms" — which transport Messages preselects.

NameRequiredDescriptionDefault
bodyNo
handleYes
serviceNoimessage

Output Schema

NameRequiredDescription
urlYes
bodyNo
noteNo
sentNo
handleYes
openedNo
serviceYes

TDQS

A5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It thoroughly covers the safety profile: the tool prefills the message, stops, and leaves sending to the user. It also states behavior for empty body and service transport selection, which goes beyond basic schema details.

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?

The description is front-loaded with the most important fact (does not send), then gives the safety rationale, routing guidance, and compact parameter docs. Every sentence adds value and none are redundant with the schema.

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?

The tool is a simple three-parameter compose action with an output schema, and the description covers all parameters, the core behavior, the user-visible side effect, and the distinction from send_message. Nothing an agent needs to invoke it correctly is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description is the only source of parameter meaning. It compensates fully: handle gets a concrete example, body explains prefill behavior and emptiness, and service gets explicit valid values and meaning ('which transport Messages preselects').

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?

The description clearly states a specific verb and resource: 'Open Messages with a recipient and text prefilled, WITHOUT sending.' It immediately distinguishes itself from send_message and names exactly what the tool does not do, so an agent can tell it apart from the sibling tool without opening the 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?

The description gives explicit routing guidance: 'Prefer it over send_message, and use it whenever the conversation does not exist yet — send_message can only reply to an existing one.' This tells the agent when to choose this tool and when to choose the alternative.

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

get_attachmentA

Retrieve an attachment's bytes, base64-encoded.

Args: attachment_id: Attachment id from get_message.

NameRequiredDescriptionDefault
attachment_idYes

Output Schema

NameRequiredDescription
sizeYes
filenameYes
mime_typeYes
data_base64Yes

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden. It discloses the retrieval behavior and the base64 encoding, but it does not mention potential side effects, error conditions, size limitations, or response structure. For a read-only retrieval tool this is adequate but not rich.

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?

The description is minimal and focused: one clear sentence defining the operation, followed by a short, relevant parameter note. Every word contributes to understanding the tool's purpose and usage.

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?

For a tool with a single parameter and an output schema, the description covers the key operational detail (base64 encoding) and parameter origin. It does not explain what the returned object looks like, but the presence of an output schema reduces the need for that in the description.

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 description coverage is 0%, but the description adds valuable meaning by explaining where attachment_id originates (`from get_message`). This goes beyond the schema's bare integer type and helps the agent source the correct identifier.

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?

The description states a specific verb and resource: 'Retrieve an attachment's bytes' with the encoding detail (base64). This clearly distinguishes it from sibling tools like get_message, which retrieves message metadata rather than binary content.

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

Usage Guidelines4/5

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

It specifies that the attachment_id comes from `get_message`, which gives clear contextual guidance on how this tool fits into a workflow. It does not explicitly discuss alternatives or when-not-to-use, but the associated source of the ID is a strong usage signal.

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

get_chat_messagesA

Read messages from one conversation, returned oldest-first.

In Claude the result renders as an inline card, so don't repeat its contents in your reply — a one-line summary or the answer to the user's question is enough.

Args: chat_id: Conversation id from list_chats. limit: Maximum messages to return (default 50). before_id: Return messages older than this message id, to page back through history.

NameRequiredDescriptionDefault
limitNo
chat_idYes
before_idNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

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

No annotations are supplied, so the description carries the burden and does disclose meaningful behavior: oldest-first ordering, paging semantics via before_id, and Claude-side rendering as an inline card. It stops short of stating read-only safety, rate limits, or default truncation consequences.

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

Conciseness4/5

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

Front-loaded with the core action, then the rendering caveat, then args. Every sentence is useful, though the Claude-specific rendering note is slightly verbose for an agent-facing definition.

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 needn't explain return values, and params are all covered. For a scoped, read-only read tool this is close to complete; the only gaps are the missing explicit read-only/rate-limit framing.

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 description coverage is 0%, so the description must compensate, and it does: chat_id is tied to list_chats, limit is defined as max messages with default 50, and before_id is explained as "older than this message id, to page back through history." It could go further on boundary behavior, but all three params are meaningfully covered.

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+resource ("Read messages") scoped to "one conversation," and adds the ordering guarantee (oldest-first). It implicitly separates itself from conversation-wide search, though it does not name search_messages or get_message explicitly.

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 rather than stated: it tells the agent to page back with before_id and points at list_chats for the chat_id source, plus a rendering hint. There is no explicit when-to-use-this-vs-search_messages/get_message guidance or when-not condition.

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

get_messageA

Read one message in full, including attachments and delivery times.

In Claude the result renders as an inline card, so don't repeat its contents in your reply — a one-line summary or the answer to the user's question is enough.

Args: message_id: Message id from search_messages or get_chat_messages.

NameRequiredDescriptionDefault
message_idYes

Output Schema

NameRequiredDescription
idYes
dateNo
guidYes
textNo
senderNo
chat_idNo
is_readNo
serviceNo
tapbackNo
chat_nameNo
date_readNo
is_editedNo
is_unsentNo
is_from_meNo
attachmentsNo
sender_nameNo
reply_to_guidNo
date_deliveredNo
has_attachmentsNo

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description must carry the behavioral burden. It discloses the return content (attachments, delivery times) and that it renders as an inline card, which is useful for response formatting. However, it does not state whether it requires authentication, whether it is read-only (implied by 'Read'), or any rate limits or side effects.

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

Conciseness4/5

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

Front-loaded with the core action and result content, then a separate practical instruction about rendering, then the argument. It is appropriately sized for a simple getter. The 'Args:' section is slightly redundant given the schema, but not wasteful.

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?

Given the tool's simplicity (one required param, output schema exists), the description provides enough to invoke correctly and sets expectations about the return format. Missing explicit usage boundaries against sibling list/search tools, but overall complete for this scope.

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

Parameters2/5

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

Schema description coverage is 0%, meaning the message_id parameter has no schema-level description; the description alone documents it as 'Message id from search_messages or get_chat_messages'. For a single required parameter with zero coverage, this is the minimum viable but still does not explain format or constraints beyond the example source.

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 (Read) and resource (one message) with explicit scope ('in full, including attachments and delivery times'). It is clear this retrieves a single message, distinguishing it from list_chats, get_chat_messages, and search_messages.

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

Usage Guidelines4/5

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

Implicitly guides the agent by naming the source of message_id ('from search_messages or get_chat_messages'), establishing the prerequisite discovery step. It does not explicitly state when-not to use it (e.g., versus get_chat_messages for bulk retrieval), leaving a small gap.

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

get_statsA

Overview of the Messages database: message and chat totals, unread count, attachment count, a per-service breakdown (iMessage / SMS / RCS), and the date range covered.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
by_serviceNo
attachmentsYes
group_chatsYes
total_chatsYes
database_bytesNo
newest_messageNo
oldest_messageNo
total_messagesYes
unread_messagesYes

TDQS

A4.1/5.0
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes the content returned, which implies a read-only aggregate query, but it does not explicitly state that it does not modify data or that it reflects the current database state. The disclosure is adequate but not thorough.

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?

The description is a single, well-structured sentence that front-loads the resource ('Messages database') and then lists the key statistics returned. There is no fluff or redundancy; every phrase adds informational value.

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?

For a zero-parameter, read-only statistics tool with an output schema, the description provides sufficient context on what to expect: totals, counts, breakdown, and date range. No critical missing information is apparent; an agent can correctly decide when and how to invoke this tool based on the description alone.

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?

The tool has zero parameters, so the schema is trivially complete. The description goes beyond the schema by explaining the kind of information returned, which is useful for an agent deciding whether to call it. Baseline for zero-parameter tools is 4, and the description earns it.

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?

The description clearly states the tool provides an overview of the Messages database with specific aggregate statistics (message/chat totals, unread count, attachment count, per-service breakdown, date range). This distinguishes it from sibling tools like list_chats or get_chat_messages, which fetch individual records rather than summary data.

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?

The description implies use when a high-level overview of the entire database is needed, but it does not explicitly state when to choose this over alternatives, nor does it mention exclusions or alternatives. The usage context is clear but left to inference.

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

list_chatsA

List conversations, most recently active first.

In Claude the result renders as an inline card, so don't repeat its contents in your reply — a one-line summary or the answer to the user's question is enough.

Args: limit: Maximum conversations to return (default 30). offset: Conversations to skip, for paging through the list.

NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses the ordering guarantee and the host-side rendering behavior (inline card, don't repeat contents), which is genuinely useful context, but it never states read-only semantics, page-size limits, or what happens when limit exceeds the total conversation count.

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

Conciseness4/5

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

Purpose and ordering are front-loaded in the first sentence, followed by the host-rendering note and compact parameter list. The Claude-specific rendering paragraph is somewhat verbose but earns its place by preventing duplicated output.

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. For a zero-annotation list tool the description covers purpose, ordering, paging, and host display adequately; the only real gap is not routing the agent away from sibling retrieval/search tools.

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 description coverage is 0%, so the description must document the parameters and it does: limit as maximum conversations to return with default 30, and offset as conversations to skip for paging. It adds meaning for offset beyond the bare schema, though it adds little beyond the schema's own default for limit.

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 and resource ('List conversations') plus the sort order ('most recently active first'), which the agent cannot infer elsewhere. It does not, however, name or distinguish itself from the closest siblings (get_chat_messages, search_messages), so differentiation is left to inference.

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 by 'List conversations' — browsing rather than reading or searching a specific conversation. There is no explicit statement of when to prefer this over search_messages or get_chat_messages, and no prerequisites or exclusions are given.

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

refresh_search_indexA

Update the local search index, and report on it.

search_messages keeps this current on its own, so calling this is optional. It is useful for warming the index deliberately — the first build on a large history decodes every message and takes a while — and for forcing a full rebuild.

Args: rebuild: Discard the index and decode every message again. Needed only to pick up edits to messages older than the recent-edit window.

NameRequiredDescriptionDefault
rebuildNo

Output Schema

NameRequiredDescription
pathNo
addedNo
builtNo
rebuiltNo
removedNo
scannedNo
secondsNo
updatedNo
built_atNo
watermarkNo
index_bytesNo
indexed_messagesNo

TDQS

A4.8/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral disclosure burden. It openly states that the first build decodes every message and takes a while, and that rebuild discards the index and decodes everything again, which communicates the costly and somewhat destructive nature of a rebuild. It could go further on side effects or performance expectations, but the key behavioral traits are disclosed.

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?

The description is compact and well-structured: a one-line summary, a clearly labeled usage rationale, and an Args section that explains the only parameter. Every sentence contributes useful information, and the key facts are front-loaded.

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?

Given the tool has only one parameter, an output schema, and no annotations, the description provides all essential context: what the tool does, when it is needed, and what the rebuild flag means. The wording about the optional nature and the purpose of rebuilding makes this fully actionable for an agent.

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

Parameters5/5

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

Schema description coverage is 0%, but the description fully compensates by explaining the single parameter 'rebuild' in meaningful terms: it discards the index, decodes every message again, and is needed only to pick up edits older than the recent-edit window. This adds substantial decision-making value beyond the bare boolean schema definition.

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?

The description clearly states a specific action ('Update the local search index') and a reporting behavior, so an agent knows exactly what the tool does. It also distinguishes itself from search_messages, which maintains the index automatically, preventing confusion among sibling tools.

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?

The description explicitly says calling this tool is optional because search_messages keeps the index current, then gives concrete use cases: warming the index deliberately and forcing a full rebuild. This gives an agent clear conditions for when to invoke this tool versus relying on search_messages.

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

search_messagesA

Search message bodies across every conversation, over all history.

Backed by a local index of decoded message bodies, which is brought up to date automatically. The first search on a large history has to build that index and may take a while; later searches are fast.

In Claude the result renders as an inline card, so don't repeat its contents in your reply — a one-line summary or the answer to the user's question is enough.

Args: query: Text to look for (case-insensitive substring match). Leave it out to search on the filters alone — chat_id plus a date range with no search term reads one conversation newest-first. limit: Maximum messages to return (default 30). chat_id: Restrict to one conversation from list_chats. from_me: True for only messages you sent, False for only received. after: Only messages at or after this time. before: Only messages at or before this time.

NameRequiredDescriptionDefault
afterNo
limitNo
queryNo
beforeNo
chat_idNo
from_meNo

Output Schema

NameRequiredDescription
queryYes
totalYes
messagesNo
truncatedNo

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does so well: it discloses that results come from a local decoded-body index kept up to date automatically, that the first search on a large history is slow while later ones are fast, and that results render as an inline card that shouldn't be repeated. It does not state the ordering of global (non-chat-scoped) results or any permission/auth constraints.

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

Conciseness4/5

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

Front-loads the purpose, then index/latency behavior, then rendering guidance, then the arg list — a sensible order with no filler. The rendering note is arguably tangential to tool selection but is genuinely useful invocation context, so the extra length is defensible.

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?

For a six-parameter search tool with no annotations and 0% schema coverage, the description covers purpose, latency behavior, output rendering, and every parameter. The output schema handles return values, so the only mild gap is the unspecified ordering of results when no chat_id is given.

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

Parameters5/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 supply all parameter meaning, and it documents every one of the six: query as case-insensitive substring, limit as max results with default 30, chat_id scoped to list_chats, from_me sent/received polarity, and after/before as inclusive 'at or after'/'at or before' bounds. The inclusive boundary semantics are extra information the schema's date-time types do not convey.

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 and resource with explicit scope: 'Search message bodies across every conversation, over all history.' It distinguishes itself from the narrower retrieval siblings by emphasizing 'every conversation' and full history, though it never names an alternative like get_chat_messages. Adding the case-insensitive substring detail further pins down what 'search' means here.

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

Usage Guidelines4/5

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

Gives concrete conditions: leave query out to search filters alone, and 'chat_id plus a date range with no search term reads one conversation newest-first.' It also points to list_chats as the source of chat_id. It stops short of explicitly saying when to prefer this over get_chat_messages or refresh_search_index.

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

send_messageA

Send a message to an existing conversation. This delivers immediately.

IRREVERSIBLE — the message goes out as soon as this runs, and scripting cannot unsend it. Confirm the exact recipient and wording with the user before calling, and pass confirm=True to acknowledge that. If they have not clearly asked for it to be sent, use compose_message instead and let them press send.

Messages picks the transport (iMessage, SMS, or RCS) for the conversation itself, which is why this addresses a chat rather than a raw handle. To start a new conversation, use compose_message.

Args: chat_id: Conversation id from list_chats. body: Text to send. confirm: Must be True. A guard against sending by accident.

NameRequiredDescriptionDefault
bodyYes
chat_idYes
confirmNo

Output Schema

NameRequiredDescription
bodyYes
sentNo
chat_idYes
chat_guidYes
chat_nameNo
charactersNo

TDQS

A4.9/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden — and it delivers. It discloses immediacy ('delivers immediately'), irreversibility ('scripting cannot unsend it'), automatic transport selection (iMessage/SMS/RCS), and why the tool addresses a chat rather than a raw handle. This is precisely the behavioral context an agent needs before invoking an irreversible action.

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

Conciseness4/5

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

Well-structured with the critical IRREVERSIBLE warning front-loaded immediately after the one-line purpose. The compose_message alternative is mentioned twice, but each mention serves a distinct routing case. Slightly longer than strictly necessary, yet every sentence carries safety-relevant content, so the length is earned.

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?

For a safety-critical, irreversible tool with zero annotations and zero schema descriptions, this is remarkably complete: it covers safety guardrails, when-to-use routing, transport behavior, parameter sourcing, and the confirm requirement. An output schema exists, so return values need not be documented. Nothing essential for correct invocation is missing.

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

Parameters5/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 compensate — it does fully. chat_id is sourced from list_chats, body is defined as text, and confirm is documented as 'Must be True' with its safety purpose explained. Notably, the schema marks confirm as optional with default false, and the description corrects this dangerous ambiguity by stating the requirement explicitly.

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 action ('Send a message to an existing conversation') with an unambiguous verb+resource pair. It distinguishes itself from sibling compose_message by explicitly scoping to existing conversations, and from the read-only siblings by naming the mutation it performs.

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?

Explicitly names compose_message as the alternative in two distinct routing conditions: when the user has not clearly asked for sending, and when starting a new conversation. Also instructs the agent to confirm recipient and wording with the user before calling, leaving no ambiguity about when this tool is appropriate.

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. 9 tool updatesv0.2.2
    • First observedcompose_message
    • First observedget_attachment
    • First observedget_chat_messages
    • First observedget_message
    • First observedget_stats
    • First observedlist_chats
    • First observedrefresh_search_index
    • First observedsearch_messages
    • First observedsend_message

TDQS

A4.1/5.0

Scored across 9 tools

Disambiguation4/5

Each tool has a clear primary purpose: listing chats, reading messages, single-message lookup, attachments, stats, compose, send, and index refresh are all distinct. The only mild overlap is between get_chat_messages and search_messages when search is given a chat_id with no query term, but the descriptions explicitly clarify this boundary.

Naming Consistency5/5

All tools use snake_case with a verb_noun shape (list_chats, get_message, send_message, compose_message, search_messages, refresh_search_index). No mixed conventions or vague standalone verbs.

Tool Count5/5

Nine tools is well-scoped for a Messages client: a compact read/search surface plus the two write paths (compose/send) and one maintenance operation. Nothing feels redundant or missing by count.

Completeness4/5

Core lifecycle is covered: discover chats, read messages, search, fetch attachments, send and draft messages, plus stats and index maintenance. Minor gaps remain (e.g. group-chat creation or participant management, reactions, marking read), but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to send and read iMessages on macOS, with smart contact lookup, message history retrieval, and cross-conversation search using natural language commands.
    6
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to read and search through iMessage, SMS, and RCS conversations, including mixed-protocol group chats with Android users. It decodes binary message data from the macOS Messages database to provide a comprehensive view of message history.
    335 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to send and read iMessages on macOS, with human approval required for sending and no auto-replies.
    9 npm
    2
    Apache 2.0
  • A
    license
    A
    quality
    D
    maintenance
    Connects Claude Desktop to iMessage on macOS, enabling reading conversations, searching messages, sending texts, and managing attachments.
    7
    8 npm
    MIT