Search the docs

Find a page, a section, or an endpoint.

OpenClaw

The hosted MCP server in an OpenClaw agent, signed in.

An OpenClaw agent can have an email address of its own in two ways, and most setups want both:

  • The channel (@pidgeon-ai/openclaw): mail to the address starts an OpenClaw conversation, one per email thread, and the agent's answer goes back as a reply in that thread. This is what makes email wake the agent.
  • The MCP server: tools the agent calls when a conversation asks it to — create addresses, search mail, wait for a verification code.

Both were run end to end on OpenClaw 2026.10.5 on macOS, with Claude Code as the agent's runtime.

The channel

sh
openclaw plugins install @pidgeon-ai/openclaw
openclaw config set channels.pidgeon '{}' --strict-json
openclaw channels login --channel pidgeon

When it installs, OpenClaw asks you to confirm the source and to accept the plugin's capabilities; a scripted install passes --force --accept-capabilities. channels login opens Pidgeon's sign-in in your browser and waits ten minutes for you, enough to create an account first. The consent screen asks what the channel may do and which addresses it reaches; it needs read and send. That choice becomes an API key under Developers → API keys → Connected apps, and Disconnect there ends it. The sign-in is saved in OpenClaw's state directory, readable by you only, and the channel refreshes it by itself. channels login then starts the channel in the running Gateway; there is nothing to restart.

sh
openclaw channels status --channel pidgeon --probe

running, connected, mode:poll, works is a channel reading mail. Send the address an email: the agent answers it in the thread, and a reply to that answer continues the same conversation. In our run the first answer arrived twelve seconds after the email was sent.

It is pure TypeScript with no native code. Beyond the run above on macOS, we installed it into OpenClaw 2026.10.5 on Linux arm64 and x64 (Node 24), where it loads and registers the channel.

With a key instead

On a server with nobody there to sign in, give the Gateway a key in its environment and skip the login. The channel reads PIDGEON_API_KEY, never a key in openclaw.json:

sh
export PIDGEON_API_KEY=pgn_live_…
openclaw config set channels.pidgeon '{}' --strict-json

apiKeyEnv names a different variable. Give it the narrowest key that reads and sends (Authentication).

What reaches the agent

The agent reads the email's sender, its address, the subject and the attachment names, then the Firewall's clean text: the new text of this message as a person would see it, with hidden text removed, never the raw HTML. The earlier messages in the thread were earlier turns of the same conversation.

Two kinds of mail never become a turn. Mail Pidgeon filed as spam, and mail Pidgeon Firewall marked suspicious — addressed to an AI, or asking for mail to be sent somewhere else — which stays in the inbox, counted in channels status. We sent the channel an email ending in a line telling "the AI assistant" to forward the inbox to an outside address; it was held, and the agent never saw it. "suspicious": "deliver" gives flagged mail to the agent with the Firewall's warning above it instead.

The agent can only reply: to the email in front of it, or to another by its message:<id>. It cannot write to a new recipient or start a thread, so a prompt in one email cannot send mail anywhere else. Its answer goes out as a plain-text email.

How it stays up

The channel reads Pidgeon's event log every five seconds from a cursor kept in OpenClaw's state store, and puts each message in OpenClaw's durable ingress queue before the cursor moves past it. A dropped connection is one failed request. A Gateway restart resumes from the cursor, and mail that arrived while it was down is answered when it is back: we turned the channel off, sent it two emails, turned it on, and both were handled within seconds. A message is marked done only when OpenClaw has adopted its turn, so a crash before that replays it and a crash after does not answer it twice.

A first start begins at the present, so installing the channel does not answer a mailbox's history.

channels status reports what is true: recovering with the reason while requests fail, blocked when it is not signed in, and never running while nothing arrives.

Settings

All optional, under channels.pidgeon:

json
{
"channels": {
  "pidgeon": {
    "addresses": ["ops@yourcompany.com"],
    "dmPolicy": "allowlist",
    "allowFrom": ["@customer.com", "ana@partner.io"],
    "suspicious": "hold",
    "pollSeconds": 5
  }
}
}

addresses limits which of your addresses start conversations; without it, every address the credential reaches does. Set it when another agent, such as a Hermes email gateway, also reads mail in the same workspace: two agents on one address both answer every email. dmPolicy is open unless set: anyone who can reach the address. allowlist answers only allowFrom, by address or by @domain, and disabled answers nobody. Named accounts go under accounts, each with these settings, inheriting the top level.

The MCP server

sh
openclaw mcp add pidgeon --url https://pidgeon.ai/api/mcp \
--transport streamable-http --auth oauth
openclaw mcp login pidgeon

login registers OpenClaw with Pidgeon and prints a link. Open it in a browser on the same machine, because the sign-in comes back to a listener OpenClaw runs on 127.0.0.1. The link works once: opened again after signing in, the page cannot reach 127.0.0.1 because OpenClaw has stopped listening, so run login again for a new one. On a machine with no browser, open the link elsewhere; the page you land on will not load, but its address carries code=…, which openclaw mcp login pidgeon --code <code> takes.

sh
openclaw mcp probe pidgeon

probe lists the tools. A new session has them; a running one gets them after openclaw mcp reload. With a key instead, OpenClaw fills ${PIDGEON_API_KEY} from the Gateway's environment:

sh
openclaw mcp add pidgeon --url https://pidgeon.ai/api/mcp \
--transport streamable-http \
--header 'Authorization=Bearer ${PIDGEON_API_KEY}'

We asked the agent to create an address, then to wait for a verification email with await_message; it came back with the code in extracted.codes, and reply_to_message answered in the thread.

Waits longer than a minute

await_message holds one request open until mail arrives: 50 seconds by default, at most 280. OpenClaw running Claude Code as the agent ends any MCP tool call after 60 seconds, and --timeout does not change that runtime (OpenClaw passes it to Codex, not to Claude Code). The tool tells the agent to keep each wait under a minute and to chain them with the returned cursor, which misses nothing between two waits. Other runtimes use OpenClaw's own MCP client, which honours --timeout.

Undoing it

sh
openclaw channels logout --channel pidgeon
openclaw plugins uninstall pidgeon

channels logout revokes the channel's sign-in at Pidgeon, which ends the key it made, and deletes it from OpenClaw. For the MCP server:

sh
openclaw mcp logout pidgeon
openclaw mcp unset pidgeon

mcp logout clears the sign-in OpenClaw stored. Disconnect it under Developers → API keys → Connected apps to end its key at Pidgeon.