AtlatestRepositorybureau
1
# Bureau3
Bureau is an MCP server for Fastmail email and calendar, built with Sigil.5
## Project Structure7
```8
bureau/9
├── package.sgl # Package definition10
├── dev-redirects.sgl # Points deps at local sigil checkout11
├── .env # Credentials (gitignored)12
├── src/bureau/13
│ ├── main.sgl # Entry point: MCP server setup and run14
│ ├── config.sgl # Env var credential reading15
│ ├── connection.sgl # Lazy JMAP/CalDAV client caching16
│ ├── email.sgl # Email tool handlers17
│ ├── calendar.sgl # Calendar tool handlers18
│ └── format.sgl # Output formatting + ISO 8601 parsing19
└── test/test-bureau.sgl # Unit tests20
```22
## Dependencies24
Bureau depends on these Sigil packages:25
- **sigil-mcp** — MCP server framework26
- **sigil-jmap** — JMAP email client (Fastmail, etc.)27
- **sigil-caldav** — CalDAV calendar client28
- **sigil-run**, **sigil-stdlib**, **sigil-tls**, **sigil-http** — transitive deps declared explicitly30
## Building32
Always build with `--redirects` to use the local Sigil checkout:34
```bash35
/path/to/sigil/build/dev/bin/sigil build --redirects dev-redirects.sgl36
```38
The dev config produces a bundled binary at `build/dev/bin/bureau`.40
If you get stale cache errors (empty `.a` files, corrupt `.sgb`), clear the cache:41
```bash42
rm -rf ~/.cache/sigil/store43
```45
## Credentials47
Bureau needs a `.env` file (gitignored) with three variables:49
```51
BUREAU_FASTMAIL_API_TOKEN=fmu1-...52
BUREAU_FASTMAIL_APP_PASSWORD=fmu1-...53
```55
- **BUREAU_FASTMAIL_USERNAME** — Fastmail email address (used as CalDAV username)56
- **BUREAU_FASTMAIL_API_TOKEN** — Fastmail API token for JMAP email access (`Authorization: Bearer <token>`)57
- **BUREAU_FASTMAIL_APP_PASSWORD** — Fastmail app password for CalDAV calendar access (HTTP Basic auth)59
These must be separate credentials — an API token (Settings → API tokens) for60
JMAP and an app password (Settings → App passwords) for CalDAV.62
## Testing MCP Tools64
Test tools by piping JSON-RPC messages to the bureau binary:66
```bash67
source .env && echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}68
{"jsonrpc":"2.0","method":"notifications/initialized"}69
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"bureau/mailboxes","arguments":{}}}' | timeout 30 ./build/dev/bin/bureau serve 2>&170
```72
To extract just the tool response text:73
```bash74
... | grep -o '"text":"[^"]*"'75
```77
## Fastmail-Specific Notes79
- **JMAP session URL**: Use `https://api.fastmail.com/jmap/session` directly. The `.well-known/jmap` URL returns a redirect that sigil-http doesn't follow.80
- **CalDAV namespace**: Must use `urn:ietf:params:xml:ns:caldav` (the short form `urn:ietf:params:caldav` causes 403 on REPORT requests).81
- **CalDAV discovery**: Fastmail doesn't support `calendar-home-set` on the principal URL. The client falls back to replacing `/principals/` with `/calendars/` in the principal path.82
- **JMAP onSuccessUpdateEmail**: Fastmail rejects `#draft` back-reference keys in `onSuccessUpdateEmail`. The send flow uses a separate `Email/set` call to move to Sent after submission.83
- **JSON null values**: JSON null is truthy in Sigil. Always guard with `(string? x)` before calling string operations on values that might be null.85
## MCP Tools87
### Email88
- `bureau/mailboxes` — List mailboxes with counts89
- `bureau/email-search` — Search emails with filters90
- `bureau/email-read` — Read full email by ID91
- `bureau/email-send` — Send email (use `identity` param for sender address)92
- `bureau/email-reply` — Reply with threading93
- `bureau/email-move` — Move to mailbox94
- `bureau/email-archive` — Archive email95
- `bureau/email-trash` — Trash single email96
- `bureau/email-trash-batch` — Trash multiple emails (comma-separated IDs)97
- `bureau/email-flag` — Flag/unflag98
- `bureau/email-mark-read` — Mark read/unread100
### Calendar101
- `bureau/calendars` — List calendars102
- `bureau/events` — Query events in date range103
- `bureau/event-details` — Full event details104
- `bureau/event-create` — Create event105
- `bureau/event-update` — Update event106
- `bureau/event-delete` — Delete event107
- `bureau/free-slots` — Find free time slots109
### Utility110
- `bureau/identities` — Sending identities111
- `bureau/status` — Connection health check