A Deno monorepo containing packages for iMessage access on macOS:
- @wyattjoh/imessage - Core library for read-only iMessage database access
- @wyattjoh/imessage-mcp - Model Context Protocol (MCP) server for LLM integration
- Search messages by text content, contact, or date range
- Get recent messages
- List all chats/conversations
- Get all contacts/handles
- Retrieve messages from specific chats
- Search macOS Contacts by name with iMessage handle ID correlation
- macOS (iMessage is only available on macOS)
- Deno 2.x or later
- Read access to
~/Library/Messages/chat.db
- Read access to
~/Library/Application Support/AddressBook/
(for contacts search)
Core library for accessing iMessage data:
deno add @wyattjoh/imessage
import { openMessagesDatabase, searchMessages } from "@wyattjoh/imessage";
const db = await openMessagesDatabase();
const results = await searchMessages(db, { query: "hello" });
db.close();
MCP server for LLM integration:
# Run directly from JSR
deno run --allow-read --allow-env --allow-sys --allow-ffi jsr:@wyattjoh/imessage-mcp
# Or install globally
deno install --global --allow-read --allow-env --allow-sys --allow-ffi -n imessage-mcp jsr:@wyattjoh/imessage-mcp
For Claude Desktop app integration, add this to your claude_desktop_config.json
:
{
"mcpServers": {
"imessage": {
"command": "deno",
"args": [
"run",
"--allow-read",
"--allow-env",
"--allow-sys",
"--allow-ffi",
"jsr:@wyattjoh/imessage-mcp"
]
}
}
}
- Clone this repository
- Install dependencies:
deno cache src/index.ts
- Run the server:
deno run --allow-read --allow-env --allow-sys --allow-ffi src/index.ts # Or use the task: deno task start
-
search_messages - Search messages with filters
query
(optional): Text to search forhandle
(optional): Phone number or email to filter bystartDate
(optional): ISO datetime string for start dateendDate
(optional): ISO datetime string for end datelimit
(optional): Maximum results (1-200, default: 100)offset
(optional): Pagination offset (default: 0)
-
get_recent_messages - Get the most recent messages
limit
(optional): Number of messages (1-100, default: 20)offset
(optional): Pagination offset (default: 0)
-
get_chats - List all conversations
limit
(optional): Number of chats (1-200, default: 50)offset
(optional): Pagination offset (default: 0)
-
get_handles - Get all contacts/handles
limit
(optional): Number of handles (1-200, default: 100)offset
(optional): Pagination offset (default: 0)
-
get_messages_from_chat - Get messages from a specific chat
chatGuid
(required): The chat GUIDlimit
(optional): Number of messages (1-200, default: 50)offset
(optional): Pagination offset (default: 0)
-
search_contacts - Search macOS Contacts by name and get phone numbers
firstName
(required): First name to search for (e.g., 'John')lastName
(optional): Last name to search for (e.g., 'Smith'). If omitted, searches across all name fieldslimit
(optional): Maximum results (1-200, default: 50)offset
(optional): Pagination offset (default: 0)- Returns contact info with phone numbers and email addresses that can be used as handle parameters
- Searches directly in the macOS AddressBook database for better performance and reliability
All tools now support pagination using limit
and offset
parameters and return pagination metadata:
// Get first 20 recent messages
get_recent_messages({ limit: 20, offset: 0 });
// Get next 20 recent messages (page 2)
get_recent_messages({ limit: 20, offset: 20 });
// Get first 10 chats
get_chats({ limit: 10, offset: 0 });
// Get messages 51-100 from a specific chat
get_messages_from_chat({
chatGuid: "iMessage;-;+15551234",
limit: 50,
offset: 50,
});
// Search with pagination
search_messages({
query: "meeting",
limit: 100,
offset: 200,
});
// Search contacts with pagination
search_contacts({
firstName: "John",
lastName: "Smith",
limit: 50,
offset: 0,
});
All paginated tools now return responses in this format:
{
"data": [
// Array of results (messages, chats, handles, etc.)
],
"pagination": {
"total": 1250, // Total number of results available
"limit": 100, // Current page size
"offset": 200, // Current offset
"hasMore": true, // Whether there are more results to fetch
"page": 3, // Current page number (1-indexed)
"totalPages": 13 // Total number of pages
}
}
This metadata helps you:
- Know the total number of results without fetching all of them
- Determine if there are more pages to fetch (
hasMore
) - Calculate which page you're on and how many pages exist
- Build proper pagination UI components
- This server runs with read-only access to the iMessage database
- No messages can be sent or modified
- The server only accesses local data
This is a Deno workspace monorepo. All commands run from the root affect all packages.
# Clone the repository
git clone https://github.com/wyattjoh/imessage-mcp.git
cd imessage-mcp
# Cache dependencies
deno cache packages/*/mod.ts
# Format all code
deno task fmt
# Lint all packages
deno task lint
# Type check all packages
deno task check
# Run tests
deno task test
# Run MCP server locally
cd packages/imessage-mcp
deno run --allow-read --allow-env --allow-sys --allow-ffi mod.ts
# Publish packages (CI/CD)
deno publish
# Work on @wyattjoh/imessage
cd packages/imessage
deno test --allow-read --allow-env --allow-ffi
# Work on @wyattjoh/imessage-mcp
cd packages/imessage-mcp
deno run --allow-read --allow-env --allow-sys --allow-ffi mod.ts
MIT