diff --git a/README.md b/README.md index f9609f6..c627fdf 100644 --- a/README.md +++ b/README.md @@ -146,12 +146,17 @@ Search is limited to locally cached history. Bodies are bounded and report trunc attachment bytes are available through the evidence tools below. Arbitrary local filesystem access is not exposed. Treat mail content as untrusted data and review a draft before authorizing your client to send it. -## MCP draft attachments and Drive +## MCP content operations + +MCP covers content actions across mail, calendar, contacts, tasks, notes and Drive. Use `get_action_guide` to discover workflows and current tool descriptions. See [MCP content operations](docs/mcp-content-actions.md) for the action matrix, reply-with-attachment steps, account permissions and provider limits. Workspace accounts must be explicitly enabled in MCP settings. + +### Draft attachments and Drive Enable draft edits and separately select **Allowed Drive accounts** in MCP Settings. Mailbox access never grants Drive access automatically. Sending remains a separate permission. -- `get_capabilities` reports permissions and limits. `update_draft`, `remove_draft_attachment`, and +- `get_capabilities` reports permissions, limits, the server’s registered tool names, and an embedded usage guide for draft attachments and Drive uploads. It explains why attachments use separate tools after `create_draft`, how to pass IDs/version tokens and byte chunks, when sharing occurs, and how to recover from missing client tools or interrupted uploads. If the returned tool list differs from your client’s list, refresh discovery/reconnect and verify the endpoint and running app version. +- `update_draft`, `remove_draft_attachment`, and `read_draft_attachment` use the `updatedAt` from `read_draft` to reject stale edits or reads. - Upload bytes using `begin_attachment_upload`, sequential `upload_attachment_chunk` calls, then `complete_attachment_upload`. Supply the byte count and SHA-256; each base64 chunk is at most diff --git a/docs/mcp-content-actions.md b/docs/mcp-content-actions.md new file mode 100644 index 0000000..64dbbe6 --- /dev/null +++ b/docs/mcp-content-actions.md @@ -0,0 +1,47 @@ +# MCP content operations + +Start with `get_capabilities`. It reports permissions, allowed mailbox/Drive/workspace accounts, limits, registered tools, and workflow guidance. Use `get_action_guide(topic)` with `mail`, `calendar`, `people`, `tasks`, `notes`, `drive`, or `all` for tool descriptions. This information comes from the running server, not a fixed tool-count assumption. + +If a listed tool is missing in a client, refresh discovery/reconnect, check the endpoint and running app version, and if necessary start a fresh client session. Do not claim an operation is unsupported solely because one client has an older list. The caller must use tools actually exposed to it. + +| Workspace | Content operations | +| --- | --- | +| Mail | Read/search messages and threads; read headers; create/edit/delete drafts; provider-backed reply/reply-all/forward drafts; importance, flags and receipt requests where supported; attachment upload/read/remove; send through Busy; move/archive/delete/junk/not-junk; read/flag/pin state; inspect/cancel pending actions and request sync | +| Calendar | List calendars/events; create/edit/delete events with descriptions, attendees, reminders and recurrence; create an event from the full cached email body | +| People | Search saved contacts, including allowed shared address books; create/edit/delete contacts with full contact details; search discovered correspondents and save them as contacts | +| To Do | List/create/rename/delete task lists; list/create/edit/delete tasks; complete/reopen tasks; descriptions, due dates, reminders, recurrence, categories and importance | +| Notes | Navigate notebooks, sections and pages; read page content; create/update/delete pages | +| Drive | List/read/search via existing tools; create folders; upload/replace/download/rename/move/delete files; create read-only sharing links | + +Workspace account access is explicitly enabled in Settings → MCP and independent of mailboxes and Drive accounts. Edit permission applies to writes. Sending permission additionally gates mail sending and calendar operations that can issue invitations/updates/cancellations. These settings never replace user authorization for a particular send or public share. Settings/navigation/account sign-in and granting MCP access remain human actions in the app. + +## Reply with an attachment + +1. Read the source using `read_mail` and `read_mail_headers`; honor Reply-To and the user's recipient restrictions. +2. Call `create_response_draft` with explicit `kind` (`Reply`, `ReplyAll`, or `Forward`) and the complete To, Cc and Bcc. Empty CC/BCC means none. It creates a real provider response draft; `create_draft` creates a new message. +3. Read the returned draft, then use `begin_attachment_upload`, sequential `upload_attachment_chunk` calls, and `complete_attachment_upload`. Pass the exact current `updatedAt`, real byte size and SHA-256. Repeat serially with a fresh draft version for additional files. +4. Read the complete draft and only call `send_draft` when explicitly authorized. Inspect Busy state for the remote outcome. + +The client must be able to read the actual file bytes. BetterMail does not read client paths or fetch arbitrary attachment URLs. A Windows path in a transcript is not an upload, nor evidence that another client can access the file. Obtain the file through the client's supported file mechanism when necessary. + +Oversized attachments can create a public OneDrive link during upload completion, before mail is sent; obtain sharing authorization first. Forwarding preserves source attachments. Response creation may have an uncertain outcome if interrupted after the provider creates the draft; inspect drafts before retrying. + +Microsoft 365 uses [provider response drafts](https://learn.microsoft.com/en-us/graph/api/message-createreply?view=graph-rest-1.0). Gmail uses the source thread ID plus [reply headers](https://developers.google.com/workspace/gmail/api/guides/threads); draft updates preserve those headers when attachments/body change. + +## Provider limits and state + +Cross-account mail moves, Google Drive, and creating/deleting OneNote notebooks or sections are not supported by the current app/provider. OneNote's document-library limits still apply. A registered tool is not a guarantee that every account supports that action. + +Provider-backed workspace calls need connectivity. Mutations request normal background sync so the UI cache catches up; a stale cache is not proof a remote write failed. Read state before destructive or replacement updates. Notes have a best-effort modified-time guard; workspace provider writes generally do not offer atomic version checks. Paging uses offset/limit and should restart after collection changes. Do not blindly retry an uncertain remote mutation. + +### Stuck Busy actions + +`list_busy` and `get_action` expose the provider error, failure count, last attempt/failure timestamps, +retry pause state and recovery guidance. Three failures pause automatic attempts; existing high-count +items pause too. `check_mail_action` performs read-only server checks, including a bounded search +that requires the exact Internet Message-ID within the same mailbox. A missing or ambiguous result +is not evidence of deletion or delivery. `retry_mail_action` explicitly authorizes another attempt +without erasing history; a subsequent failure pauses again. Fix the reported cause first. Unconfirmed +sends cannot be retried through this tool. Earlier pending actions for the same message must be resolved +first. A changed server ID is reported, not automatically rebound; verify and perform the intended +operation in the provider before cancelling the obsolete local action. diff --git a/docs/ui/screenshots/busy-dark.png b/docs/ui/screenshots/busy-dark.png new file mode 100644 index 0000000..ccc4857 Binary files /dev/null and b/docs/ui/screenshots/busy-dark.png differ diff --git a/docs/ui/screenshots/busy-light.png b/docs/ui/screenshots/busy-light.png new file mode 100644 index 0000000..517c7df Binary files /dev/null and b/docs/ui/screenshots/busy-light.png differ diff --git a/src/BetterMail.App/MainWindow.axaml b/src/BetterMail.App/MainWindow.axaml index f3b3848..928c1a4 100644 --- a/src/BetterMail.App/MainWindow.axaml +++ b/src/BetterMail.App/MainWindow.axaml @@ -829,18 +829,28 @@ - + -