Skip to main content
Glama
krantiutils

Proton Bridge MCP

by krantiutils
README.md
# Proton Bridge MCP

CLI and MCP server for sending correctly threaded replies through
Proton Mail Bridge.

The main lesson encoded here is simple:

- Use Proton Bridge **SMTP** with explicit `In-Reply-To` and `References` for
  agent-sent replies.
- Do **not** create same-thread reply drafts by IMAP `APPEND`; Proton Bridge
  may rewrite those draft headers and the sent email can leave the original
  conversation.
- Proton web/app reply composer is also safe because it creates the reply from
  the existing conversation.

## Features

- Search message headers through Proton Bridge IMAP.
- Find a thread anchor by sender and subject.
- Send a threaded reply through Proton Bridge SMTP.
- Verify sent-message headers.
- Expose the same operations as MCP tools for coding agents.
- Sending tools are dry-run by default unless `confirm_send` is set.

## Requirements

- Python 3.10+
- Proton Mail Bridge running locally
- Bridge IMAP enabled, usually `127.0.0.1:1143`
- Bridge SMTP enabled, usually `127.0.0.1:1025`

No third-party Python dependencies are required.

## Configuration

Set the Bridge account and Bridge mailbox password:

```bash
export PROTON_BRIDGE_ACCOUNT="you@example.com"
export PROTON_BRIDGE_PASSWORD="your-bridge-mailbox-password"
```

`PROTON_PW` is also accepted for the password if you already use that name.

These are Proton Bridge credentials, not necessarily your Proton web password.

## CLI Usage

From the repo root:

```bash
python3 -m krantiutils_proton.cli search \
  --from-addr collaborator@example.com \
  --subject-contains "Paper draft" \
  --limit 3
```

Dry-run a threaded reply to the latest matching incoming message:

```bash
python3 -m krantiutils_proton.cli reply-latest \
  --thread-from collaborator@example.com \
  --subject-contains "Paper draft" \
  --to collaborator@example.com \
  --body-file /tmp/reply.txt \
  --attach /tmp/paper.pdf
```

Actually send only after checking the dry-run output:

```bash
python3 -m krantiutils_proton.cli reply-latest \
  --thread-from collaborator@example.com \
  --subject-contains "Paper draft" \
  --to collaborator@example.com \
  --body-file /tmp/reply.txt \
  --attach /tmp/paper.pdf \
  --confirm-send
```

Verify sent headers:

```bash
python3 -m krantiutils_proton.cli verify-sent \
  --to-addr collaborator@example.com \
  --subject-contains "Paper draft" \
  --limit 5
```

Send a controlled threading test to yourself:

```bash
python3 -m krantiutils_proton.cli thread-test \
  --to you+thread-test@example.com \
  --count 3 \
  --confirm-send
```

## MCP Server

Run:

```bash
./proton-bridge-mcp
```

Codex-style config:

```toml
[mcp_servers.proton_bridge]
command = "/absolute/path/to/proton-bridge-mcp/proton-bridge-mcp"
env = { PROTON_BRIDGE_ACCOUNT = "you@example.com" }
```

Set `PROTON_BRIDGE_PASSWORD` in the environment available to the MCP process.

Available tools:

- `proton_search_headers`
- `proton_latest_thread_anchor`
- `proton_send_email`
- `proton_reply_to_latest`
- `proton_verify_sent`
- `proton_send_thread_test`

## Agent Workflow

For a thread-safe reply:

1. Use `proton_latest_thread_anchor` to find the latest incoming message in the
   target thread.
2. Inspect the returned `message_id`, `in_reply_to`, `references`, sender, and
   subject.
3. Dry-run `proton_reply_to_latest` without `confirm_send`.
4. Check recipient, subject, attachment paths, and the generated
   `In-Reply-To`/`References`.
5. Send only after explicit user approval with `confirm_send: true`.
6. Use `proton_verify_sent` to confirm the sent copy kept thread headers.

Never claim an IMAP-created draft is definitely on the original thread unless
the stored draft has the expected `In-Reply-To` and `References` headers.