mcpField
C
chat-adapter-imessage

chat-adapter-imessage

github.com/photon-hqDevelopment15124 installsUpdated 12w ago
Repository

About chat-adapter-imessage

A reference skill for using chat-adapter-imessage to connect the Vercel AI SDK Chat package to iMessage. It covers local and Photon remote modes, message handling, and mode-specific operations.

Key features

  1. 01Local and remote operating modes
  2. 02Vercel AI SDK Chat adapter integration
  3. 03Send and receive iMessages
  4. 04Markdown-to-plain-text conversion
  5. 05Remote message editing, deletion, and reactions

Use cases

  1. 01Building an AI agent that chats over iMessage
  2. 02Developing locally with iMessage on a Mac
  3. 03Connecting Chat to Photon remote infrastructure

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/photon-hq/skills --skill chat-adapter-imessage

After installing, type/chat-adapter-imessagein Claude Code to confirm it loaded.

Details

From the project README

Vercel AI SDK: iMessage Adapter Skill

This skill provides a complete reference for using chat-adapter-imessage, the official Photon adapter for connecting the Vercel AI SDK (Chat SDK) to iMessage.

Overview

The adapter acts as a bridge, allowing you to build AI agents and assistants with the Vercel AI SDK that communicate with users over iMessage. It leverages @photon-ai/imessage-kit (self-hosted) and @photon-ai/advanced-imessage-kit (production infrastructure by Photon) under the hood.

Key Features
  • Two Modes: Run in local mode on any Mac for development, or remote mode connected to Photon's production iMessage infrastructure.
  • Unified Interface: Provides a consistent API for sending and receiving messages, regardless of the underlying mode.
  • Vercel AI SDK Integration: Implements the Adapter interface from the chat package, making it a drop-in solution.
  • Markdown Conversion: Automatically converts markdown from the AI SDK into iMessage-compatible plain text.

Setup and Initialization

Installation
pnpm install chat-adapter-imessage @photon-ai/imessage-kit
# For remote mode, also install the advanced kit
pnpm install @photon-ai/advanced-imessage-kit
createiMessageAdapter(config)

This is the main entry point. It creates and configures an instance of the iMessageAdapter.

import { createiMessageAdapter } from 'chat-adapter-imessage';

// Local Mode: Runs on your Mac, uses your iMessage
const localAdapter = createiMessageAdapter({ local: true });

// Remote Mode: Connects to Photon's production servers
const remoteAdapter = createiMessageAdapter({
  local: false,
  serverUrl: process.env.IMESSAGE_SERVER_URL, // Provided by Photon
  apiKey: process.env.IMESSAGE_API_KEY      // Provided by Photon
});
Configuration (iMessageAdapterConfig)
ModelocalserverUrlapiKeyDescription
LocaltrueOptionalOptionalRuns on macOS using @photon-ai/imessage-kit. serverUrl and apiKey are ignored.
RemotefalseRequiredRequiredConnects to Photon's infra using @photon-ai/advanced-imessage-kit.
Integrating with Chat

Once created, the adapter is passed to the Chat constructor from the Vercel AI SDK.

import { Chat } from 'chat';
import { createiMessageAdapter } from 'chat-adapter-imessage';

const adapter = createiMessageAdapter({ local: true });

const chat = new Chat({
  adapter,
  // ... your other Chat config
});

Core Adapter Methods

adapter.initialize(chat)

Called by the Chat instance to link the adapter. In remote mode, this method also establishes the WebSocket connection to the Photon server.

adapter.postMessage(threadId, message)

Sends a message to a specific iMessage thread.

  • threadId: The encoded thread identifier, which is the chatGuid (e.g., iMessage;-;+15551234567).
  • message: An AdapterPostableMessage object, which can be a simple string or a FormattedContent object with markdown.
const threadId = 'iMessage;-;+15551234567'; // A direct message thread

// Send a simple text message
await adapter.postMessage(threadId, 'Hello from the adapter!');

// Send a message with markdown (will be converted to plain text)
await adapter.postMessage(threadId, {
  markdown: 'Here are the results:\n\n- **Item 1**\n- *Item 2*'
});
adapter.editMessage(threadId, messageId, message)

Edits a previously sent message. Only supported in remote mode.

await adapter.editMessage(
  'iMessage;-;+15551234567',
  'p:0/GUID-OF-MESSAGE-TO-EDIT',
  'This is the corrected text.'
);
adapter.deleteMessage(threadId, messageId)

Unsends/deletes a previously sent message. Only supported in remote mode.

await adapter.deleteMessage(
  'iMessage;-;+15551234567',
  'p:0/GUID-OF-MESSAGE-TO-DELETE'
);
adapter.react(threadId, messageId, emoji)

Adds a tapback/reaction to a message. Only supported in remote mode.

  • emoji: A standard emoji character or a name like heart, like, laugh.
await adapter.react(
  'iMessage;-;+15551234567',
  'p:0/GUID-OF-MESSAGE-TO-REACT-TO',
  '❤️'
);
adapter.startGatewayListener(options)

This is the primary method for receiving messages. It starts a listener that ingests messages from both local and remote SDKs and forwards them to the Chat instance.

// In your main application file

const adapter = createiMessageAdapter({ local: true });
const chat = new Chat({ adapter });

// Start listening for incoming iMessages
adapter.startGatewayListener();

// Now, messages sent to your iMessage will be processed by the Chat SDK
chat.on('message', (message) => {
  console.log(`[${message.author.userName}]: ${message.text}`);
  // Your AI logic here...
});
adapter.handleWebhook(request)

This method is not supported. The adapter does not use traditional webhooks for message ingestion. You must use startGatewayListener() instead.


Type Reference

iMessageThreadId

The decoded threadId object.

interface iMessageThreadId {
  chatGuid: string; // e.g., "iMessage;-;+1234567890"
}
iMessageGatewayMessageData

The normalized message object that the adapter uses internally.

interface iMessageGatewayMessageData {
  guid: string;
  text: string | null;
  sender: string;
  senderName: string | null;
  chatId: string;
  isGroupChat: boolean;
  isFromMe: boolean;
  date: string; // ISO 8601
  attachments: iMessageAttachment[];
  source: 'local' | 'remote';
  raw?: unknown; // Original message object from the underlying SDK
}
NativeWebhookPayload

If using the Self-Hosted Kit's native webhook feature, this is the shape of the JSON payload that will be sent to your endpoint. The adapter can process this payload.

interface NativeWebhookPayload {
  guid: string;
  text: string | null;
  sender: string;
  chatId: string;
  // ... and other fields from the Basic Kit Message object
}

References

  1. Vercel AI SDK (Chat)
  2. chat-adapter-imessage on npm
  3. Photon

Comments

Markdown supported