By SolAstrius
Letterdog — the user's personal self-hosted mail, calendar, and contacts (JMAP). Curated MCP tools plus the full-coverage letterdog CLI and workflow skills.
Build concise one-day briefs from Letterdog — the user's personal self-hosted mail/calendar/contacts (JMAP), not Google Calendar. Use when the user asks for today's, tomorrow's, or a dated agenda, remaining meetings, conflicts, free windows, a day shape, or a daily calendar brief.
Find practical ways to open time in Letterdog — the user's personal self-hosted mail/calendar/contacts (JMAP), not Google Calendar. Use when the user wants to clear a day, make a focus block, identify movable meetings, create holds, or draft safe reschedules.
Schedule groups with Letterdog availability data — the user's personal self-hosted mail/calendar/contacts (JMAP), not Google Calendar. Use when the user wants candidate meeting times, attendee or room availability checks, conflict ranking, temporary holds, or multi-participant event creation.
Prepare for meetings from Letterdog calendar events — the user's personal self-hosted mail/calendar/contacts (JMAP), not Google Calendar. Use when the user asks what a meeting is about, what to read, who is attending, what links or attachments matter, or for a concise prep brief.
Letterdog — the user's personal self-hosted mail/calendar/contacts (JMAP/JSCalendar), not Google Calendar. Use when inspecting calendars/events, checking availability, creating or updating events, editing recurring series or single occurrences, RSVP-ing, or making safe calendar changes on the user's own server.
External network access
Connects to servers outside your machine
Own this plugin?
Verify ownership to unlock analytics, metadata editing, and a verified badge. GitHub access is read-only (username + org membership).
Sign in to claimOwn this plugin?
Verify ownership to unlock analytics, metadata editing, and a verified badge. GitHub access is read-only (username + org membership).
Sign in to claimBased on adoption, maintenance, documentation, and repository signals. Not a security audit or endorsement.
Letterdog is a personal PIM connector: one Deno domain core over JMAP (mail, calendars, contacts, principals, blobs) with two surfaces built from a single operation registry —
letterdog) exposing every op at full spec fidelity for local agents (Bash), bulk
pipelines, and humans.The backend it fronts is a self-hosted Stalwart server (JMAP primary, CalDAV as the raw-iCalendar escape hatch), but the core targets JMAP-the-standard through a provider adapter. Design: docs/v2-design.md; normative contracts and op inventory: docs/v2-contracts.md; generated surface map: docs/tool-mapping.md. Live Stalwart deviations the connector works around: docs/stalwart-conformance.md (per-RFC detail in docs/rfc-notes/).
The v1 server (main.ts, src/*.ts, src/tools/) remains deployed and untouched; v2 lives in
src/core/, src/mcp/, src/cli/, entrypoint v2.ts.
v2.ts MCP entrypoint (HTTP default; MCP_TRANSPORT=stdio for local)
src/core/ops/ THE op registry — every capability defined once, surfaced twice
src/core/jmap/ typed JMAP client, session cache (per actor fingerprint), envelopes
src/core/schemas/ Zod: RFC 8621 mail filters, RFC 8984 JSCalendar, JSContact
src/core/projections.ts brief/full/raw output shaping (brief default everywhere)
src/core/safety.ts confirmation policy matrix + self-contained signed confirm tokens
src/core/compose.ts RFC-correct reply threading, forwards, attachment planning
src/core/query.ts Gmail-syntax → Email/query filter translation
src/core/provider/ Stalwart adapter (v0.16 hybrid shapes) + generic JMAP fallback
src/mcp/server.ts MCP frontend (ops tagged "mcp" → tools)
src/cli/ CLI frontend (ALL ops → subcommands, registry-driven --help)
tests/v2/ unit tests (no network)
skills/ letterdog-* skills for Claude Code / Cowork
deno task check:v2 # fmt + lint + typecheck + unit tests (v2)
deno task dev:v2:http # MCP server on http://127.0.0.1:8787/mcp
deno task dev:v2:stdio # MCP server on stdio (env bearer fallback allowed)
deno task cli -- mail search "in:inbox is:unread" --limit 10 --json
deno task gen:tool-mapping # regenerate docs/tool-mapping.md from the registry
deno task check # v1 suite (unchanged)
Local auth: put STALWART_BEARER=... in .env (or the environment). The HTTP server forwards each
request's Authorization header verbatim to Stalwart — the env bearer is a local-dev / stdio
fallback only (STALWART_ALLOW_ENV_BEARER_FALLBACK).
The HTTP transport doubles as a minimal MCP OAuth resource server backed by Stalwart's own OAuth2/OIDC server (Stalwart is the authorization server — no separate IdP). Two things make an OAuth-capable client log in automatically instead of needing a pasted token:
GET /.well-known/oauth-protected-resource → RFC 9728 metadata listing Stalwart as the
authorization_servers entry.401 with
WWW-Authenticate: Bearer ... resource_metadata="<this-host>/.well-known/oauth-protected-resource".The client then discovers Stalwart, dynamically registers, runs auth-code + PKCE against Stalwart's
/login, and calls back with a Stalwart access token — which the connector forwards to Stalwart
exactly like a pasted bearer. The connector never issues tokens, holds no client secret, and is
never in the redirect path. Direct bearer pass-through still works unchanged: a client that
already sends Authorization: Bearer … never sees the challenge.
Set PUBLIC_BASE_URL to the connector's public origin (e.g. https://mcp.mail.astrius.ink) so the
advertised resource id and metadata URL are correct; when unset it is derived per-request from
X-Forwarded-Proto + Host. Set OAUTH_PROTECTED_RESOURCE=false to disable this and restore the
legacy bare Bearer/Basic challenge.
The CLI is a Deno program; compile it to a binary on PATH:
deno compile --allow-net --allow-env --allow-read --allow-write \
-o ~/.local/bin/letterdog src/cli/main.ts
letterdog --help
letterdog mail search 'from:klarna after:2026-06-01' --json
Auth: STALWART_BEARER in the environment (on this machine: launchctl env), --bearer-env NAME to
read a different variable, --url / --account to override the target. Output: human tables on a
TTY; NDJSON with --json (or when piped); --json=full|raw for deeper projections.
npx claudepluginhub solastrius/letterdog --plugin letterdogPython tooling via Astral's ty (type checking) and Ruff (linting/formatting)
Example plugin with a simple greeting skill
Patched Telegram channel with markdown formatting, sticker support, and pack management
Matrix channel — receive and reply to Matrix messages from Claude Code
Nix language support via nixd (type checking, options completion, go-to-definition) with nixfmt formatting
Harness-native ECC operator layer - 67 agents, 278 skills, 94 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses
Reliable automation, in-depth debugging, and performance analysis in Chrome using Chrome DevTools and Puppeteer
Evidence-gated AI coding workflow: scan → analyze → plan → TDD → execute → fix → verify → review, powered by Codebase Memory MCP >= 0.9.0 with optional Serena LSP intelligence. Includes blast-radius planning, test/cycle gates, independent review, and Windows Git Bash hook auto-resolution.
Enterprise AI agent orchestration plugin with 150+ commands, 74+ specialized agents, SPARC methodology, swarm coordination, GitHub integration, and neural training capabilities