I just published two packages that let you give Claude, GPT-4, or any MCP-compatible LLM read-only access to your iMessage database on macOS. Here's how to actually use them.
What These Packages Do
The @wyattjoh/imessage-mcp
package is a Model Context Protocol server that exposes your iMessage database to LLMs. The @wyattjoh/imessage
package is the core library if you want to build your own tools.
Both are now available on JSR:
Getting Started with Claude Desktop
Let me walk you through the setup. First, you'll need Claude Desktop (version 0.7.0 or later).
Edit your Claude Desktop configuration:
1# On macOS
2code ~/Library/Application\ Support/Claude/claude_desktop_config.json
3
Add the iMessage server to your MCP servers:
1{
2 "mcpServers": {
3 "imessage": {
4 "command": "deno",
5 "args": [
6 "run",
7 "--allow-read",
8 "--allow-env",
9 "--allow-sys",
10 "--allow-ffi",
11 "jsr:@wyattjoh/imessage-mcp"
12 ]
13 }
14 }
15}
Restart Claude Desktop. You'll see a small plug icon showing the MCP connection is active.
What You Can Actually Do
Once it's connected, you can ask Claude things like:
"Show me all messages from John Smith in the last week"
Claude will:
- Search your contacts for John Smith
- Find his phone number
- Search messages from that number
- Paginate through all results (not just the first batch)
Here's what's happening behind the scenes:
1// Claude first searches contacts
2await searchContacts({
3 firstName: "John",
4 lastName: "Smith"
5});
6// Returns: ["+15551234567"]
7
8// Then searches messages with that handle
9await searchMessages({
10 handle: "+15551234567",
11 startDate: "2025-01-28T00:00:00Z"
12});
The Six Tools Available
The MCP server exposes six tools that cover most use cases:
1. Search Messages
1searchMessages({
2 query?: string, // Full-text search
3 handle?: string, // Phone or email
4 startDate?: string, // ISO date
5 endDate?: string, // ISO date
6 limit?: number, // Max 200
7 offset?: number // For pagination
8})
2. Get Recent Messages
1getRecentMessages({
2 limit?: number, // Max 100
3 offset?: number // For pagination
4})
3. Get Chats
1getChats({
2 limit?: number, // Max 200
3 offset?: number // For pagination
4})
4. Get Messages from Chat
1getMessagesFromChat({
2 chatGuid: string, // From getChats()
3 limit?: number,
4 offset?: number
5})
5. Get All Handles
1getHandles({
2 limit?: number,
3 offset?: number
4})
6. Search Contacts
1searchContacts({
2 firstName: string,
3 lastName?: string,
4 limit?: number,
5 offset?: number
6})
Using the Core Library Directly
If you want to build your own tools instead of using the MCP server, install the core library:
1deno add @wyattjoh/imessage
Then use it directly:
1import {
2 openDatabase,
3 searchMessages,
4 searchContacts
5} from "@wyattjoh/imessage";
6
7// Open the iMessage database
8const db = openDatabase();
9
10// Search for messages
11const messages = await searchMessages(db, {
12 query: "meeting tomorrow",
13 limit: 50
14});
15
16// Search contacts
17const contacts = await searchContacts(db, {
18 firstName: "Alice"
19});
20
21db.close();
Every function returns paginated results:
1interface PaginatedResult<T> {
2 data: T[];
3 pagination: {
4 limit: number;
5 offset: number;
6 total: number;
7 hasMore: boolean; // Check this!
8 };
9}
Important: Always Paginate
Here's the thing that will trip you up: all results are paginated. If you're asking for a conversation summary or analysis, you need ALL the messages, not just the first page.
1let offset = 0;
2let hasMore = true;
3const allMessages = [];
4
5while (hasMore) {
6 const result = await searchMessages(db, {
7 handle: "+15551234567",
8 limit: 100,
9 offset
10 });
11
12 allMessages.push(...result.data);
13 hasMore = result.pagination.hasMore;
14 offset += result.pagination.limit;
15}
The MCP server handles this automatically when Claude requests data, but if you're using the core library, you need to handle it yourself.
Setting Up Development
If you want to contribute or modify the packages, clone the repo:
1git clone <https://github.com/wyattjoh/imessage-mcp>
2cd imessage-mcp
3
4# Install Deno if needed
5curl -fsSL <https://deno.land/install.sh> | sh
6
7# Run tests
8deno task test
9
10# Run the MCP server locally
11cd packages/imessage-mcp
12deno run --allow-read --allow-env --allow-sys --allow-ffi mod.ts
The monorepo structure keeps the core library and MCP server separate:
1packages/
2├── imessage/ # Core library
3└── imessage-mcp/ # MCP server
Privacy and Security Notes
A few important things:
- Read-only access - The packages can only read your messages, not send them
- Local only - Everything runs on your machine, no data leaves your computer
- macOS only - Requires access to
~/Library/Messages/chat.db
- Permission required - Deno will ask for file system access
Common Use Cases
Here are some things people are using this for:
Message Analysis
- "How many times did I mention 'project deadline' last month?"
- "What restaurants did Sarah recommend in our chats?"
Conversation Summaries
- "Summarize my conversation with Mom from last week"
- "What did the team discuss about the new feature?"
Contact Search
- "Find all messages from people named David"
- "Show me texts from unknown numbers"
Time-based Queries
- "What did I text about yesterday?"
- "Show me all weekend messages from December"
What's Next
The packages are open source and accepting contributions. Some ideas for the future:
- Export tools for backing up conversations
- Rich media support (images, attachments)
- Conversation analytics
- Windows/Linux support for other messaging databases
Try It Now
- Install Claude Desktop
- Add the configuration above
- Ask Claude about your messages
Or grab the core library and build your own tools:
1deno add @wyattjoh/imessage
The full source is at github.com/wyattjoh/imessage-mcp.
Have questions or run into issues? Open an issue on GitHub or reach out on BlueSky @wyattjoh.