docs: add email mcp design spec
This commit is contained in:
commit
1e4e75a42f
1 changed files with 151 additions and 0 deletions
151
docs/superpowers/specs/2026-04-10-email-mcp-design.md
Normal file
151
docs/superpowers/specs/2026-04-10-email-mcp-design.md
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
# Email MCP Design
|
||||
|
||||
## Goal
|
||||
|
||||
Build a local Linux MCP server as a single Go binary with two modes:
|
||||
|
||||
- `setup`: prompt for IMAP host, username, and password, then store them in KDE Wallet if available
|
||||
- `mcp`: start an MCP server over stdio and expose read-only mail tools backed by IMAP
|
||||
|
||||
The V1 target is KDE Wallet only for secret storage, with internal interfaces designed so other secret stores can be added later without rewriting the IMAP or MCP layers.
|
||||
|
||||
## Scope
|
||||
|
||||
Included in V1:
|
||||
|
||||
- Go project from scratch
|
||||
- Single binary named `email-mcp`
|
||||
- Interactive `setup` command
|
||||
- Detection of KDE Wallet availability over D-Bus
|
||||
- Storage and retrieval of one default IMAP account in KDE Wallet
|
||||
- Read-only IMAP access
|
||||
- MCP server with a minimal tool surface
|
||||
|
||||
Out of scope for V1:
|
||||
|
||||
- OAuth2
|
||||
- Multiple mail accounts
|
||||
- Sending mail
|
||||
- Message mutation operations such as delete, move, mark read, or flag
|
||||
- Non-KDE secret stores
|
||||
- Integration tests against a real KDE Wallet instance
|
||||
|
||||
## Why Go
|
||||
|
||||
Go is the best fit for this version because the primary deliverable is a local distributable binary rather than a fast prototype. It gives a simple deployment model, good network I/O behavior for IMAP, and a clean way to define internal interfaces for future expansion. KDE Wallet integration over D-Bus is a little lower-level than Python, but still straightforward enough for the V1 scope.
|
||||
|
||||
## Architecture
|
||||
|
||||
The binary is split into two entry paths:
|
||||
|
||||
- `email-mcp setup`
|
||||
- `email-mcp mcp`
|
||||
|
||||
Internally, the code is organized behind narrow interfaces:
|
||||
|
||||
- `SecretStore`: save and load account credentials
|
||||
- `IMAPClient`: connect to IMAP and expose read-only mailbox/message operations
|
||||
- `MCPServer`: register tools and route requests to the IMAP layer
|
||||
|
||||
This keeps KDE Wallet isolated to one package and avoids coupling the MCP server to secret storage details.
|
||||
|
||||
## Data Model
|
||||
|
||||
V1 stores a single logical account under a fixed profile key, `default`.
|
||||
|
||||
Stored credential fields:
|
||||
|
||||
- `host`
|
||||
- `username`
|
||||
- `password`
|
||||
|
||||
The credential value is stored in KDE Wallet as a serialized blob owned by the application namespace `email-mcp`. The application will not hash the IMAP password because the password must be recoverable in order to authenticate to the IMAP server. Security relies on KDE Wallet protecting the secret at rest.
|
||||
|
||||
## KDE Wallet Behavior
|
||||
|
||||
The setup flow must:
|
||||
|
||||
1. Check whether the KDE Wallet D-Bus service is reachable.
|
||||
2. Open or create an application folder for `email-mcp`.
|
||||
3. Prompt the user for `host`, `username`, and `password`.
|
||||
4. Save those values under the `default` account key.
|
||||
|
||||
If KDE Wallet is not available, setup exits with a clear error and stores nothing anywhere else.
|
||||
|
||||
The MCP mode must:
|
||||
|
||||
1. Open KDE Wallet over D-Bus.
|
||||
2. Read the `default` account credential.
|
||||
3. Fail with a clear message if no credential is present.
|
||||
|
||||
## MCP Surface
|
||||
|
||||
The V1 MCP server exposes three read-only tools:
|
||||
|
||||
- `list_mailboxes`
|
||||
- `list_messages`
|
||||
- `get_message`
|
||||
|
||||
Behavior:
|
||||
|
||||
- `list_mailboxes` returns mailbox names visible to the account.
|
||||
- `list_messages` takes a mailbox and returns a small list of messages with lightweight metadata.
|
||||
- `get_message` returns one message with headers and body content suitable for MCP clients.
|
||||
|
||||
The initial protocol transport is stdio. Logging must not corrupt stdio protocol traffic, so operational logs should go to stderr or be disabled by default.
|
||||
|
||||
## IMAP Behavior
|
||||
|
||||
The IMAP layer connects to the configured host using TLS on the standard secure IMAP path. The first version is read-only by design and should avoid any mutation APIs. The connection setup should return actionable errors for authentication failure, TLS failure, or network failure without leaking secrets.
|
||||
|
||||
The message listing behavior should be intentionally conservative in V1:
|
||||
|
||||
- modest result limits
|
||||
- explicit mailbox selection
|
||||
- stable lightweight metadata for summaries
|
||||
|
||||
This keeps the first protocol surface predictable and reduces unnecessary mailbox scanning.
|
||||
|
||||
## Error Handling
|
||||
|
||||
Expected user-facing failures:
|
||||
|
||||
- KDE Wallet service unavailable
|
||||
- KDE Wallet locked or inaccessible
|
||||
- credentials not configured
|
||||
- IMAP authentication failure
|
||||
- mailbox not found
|
||||
- message not found
|
||||
|
||||
Errors should be mapped to concise messages. The process must never print stored secrets, entered passwords, or raw serialized credential payloads.
|
||||
|
||||
## File Layout
|
||||
|
||||
Planned layout:
|
||||
|
||||
- `cmd/email-mcp/main.go`
|
||||
- `internal/cli`
|
||||
- `internal/secretstore`
|
||||
- `internal/secretstore/kwallet`
|
||||
- `internal/imapclient`
|
||||
- `internal/mcpserver`
|
||||
|
||||
Tests will live next to their packages where idiomatic for Go.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
V1 tests focus on unit boundaries:
|
||||
|
||||
- credential validation and serialization
|
||||
- KDE Wallet store interface behavior with mocks or fakes
|
||||
- IMAP service behavior against mocked client boundaries
|
||||
- MCP tool handler behavior
|
||||
- error mapping and missing-credential flows
|
||||
|
||||
V1 does not require a live KDE Wallet integration test. The D-Bus integration should be kept behind a narrow adapter to make this practical.
|
||||
|
||||
## Security Notes
|
||||
|
||||
This design is acceptable for a local tool if the user already trusts KDE Wallet as the host secret manager. It is materially safer than inventing a custom local encryption scheme with a locally stored key, because the operating environment already provides secret storage controls and user-session integration.
|
||||
|
||||
The main limitation of V1 is that it stores a recoverable IMAP password. That is necessary for password-based IMAP auth. A future version should prefer OAuth2 for providers that support it.
|
||||
Loading…
Reference in a new issue