MCP server

Give an AI agent real mailboxes, and keep the send button yours.

A hosted Model Context Protocol server for the Gmail, Microsoft 365 and IMAP accounts you connect. Agents search and read mail, draft replies, manage events and contacts. Scopes decide which tools exist, and sends are confirmed by default.

api.workwae.com/mcp
# Sign in with OAuth: pick the workspace, scopes and accounts
claude mcp add --transport http workwae https://api.workwae.com/mcp
What it is

One endpoint, the same API underneath.

Tool calls go through the same API as /v1: scopes, plan limits, rate limits and metering apply as they do there, and every call, reads included, lands in the audit log under the surface MCP.

PropertyValue
URLhttps://api.workwae.com/mcp
TransportStreamable HTTP, stateless
Protocol versions2026-07-28, 2025-11-25, 2025-06-18
AuthenticationAn API key, an MCP key, or OAuth
Tools32, listed to a client only when its credential's scopes allow them
Prompts5, offered as slash commands
ExtensionsMCP Apps views (message review, meeting time picker); MCP Events by webhook on 2026-07-28
DiscoveryServer card at /mcp/server-card, readable without a token; listed in the MCP Registry as com.workwae/mcp
Connect

Pick the credential by who is using it.

The credential decides the scopes, and the scopes decide which tools the client sees.

API key

For your backend or a headless agent. Send it as a bearer token. Limit it to the accounts it needs; account tokens (wat_) are refused.

OAuth

For a person with a console login, in Claude, ChatGPT, Claude Code, Cursor or VS Code. The client needs only the URL. The user picks the workspace, the scopes (read, write, send, capped by their role) and the accounts.

MCP key

For your own users, who have no console login. Mint one per connected account; it works only at /mcp and answers mcp_only_key anywhere else.

API key or MCP key: send it as a header

Claude Code
claude mcp add --transport http workwae https://api.workwae.com/mcp \
  --header "Authorization: Bearer $WORKWAE_API_KEY"
Cursor
// ~/.cursor/mcp.json
{
  "mcpServers": {
    "workwae": {
      "url": "https://api.workwae.com/mcp",
      "headers": { "Authorization": "Bearer ${env:WORKWAE_API_KEY}" }
    }
  }
}
Codex CLI
# ~/.codex/config.toml
[mcp_servers.workwae]
url = "https://api.workwae.com/mcp"
bearer_token_env_var = "WORKWAE_API_KEY"
Any other client
POST https://api.workwae.com/mcp
Authorization: Bearer <API key or MCP key>
Content-Type: application/json

Use an MCP key in place of the API key in any of these. Claude.ai and ChatGPT custom connectors sign in only with OAuth, so they take the URL and no key.

OAuth

Add the URL without a header. The client sends you to the Workwae console to sign in and consent; Claude, Claude Code, ChatGPT and VS Code publish a client ID metadata document, so they connect without registering. Access tokens last 15 minutes, and every request is checked against the grant and your current role, so revoking it, lowering your role or leaving the workspace takes effect at once. Revoke a grant under Connected apps in the console.

Tools

32 tools, by the scope each needs.

Scopes do not imply each other: a credential that sends mail needs send, and also read if it should find mail first. admin is never granted to an MCP client, and no tool here needs it.

Tool Area What it does
read Look, never change.
list_accounts Accounts The accounts the credential reaches: id, provider, status, time zone, capabilities and send-as addresses.
get_current_time Accounts The current date, weekday and time in a zone.
list_changes Accounts What changed across the accounts (messages, events, contacts, sends), oldest first, by cursor.
list_mailboxes Mail An account's folders or Gmail labels, with ids, roles and counts.
search_messages Mail Find or list mail by text, sender, recipient, date, flags, attachments or mailbox. With no account named, searches every account the caller reaches.
get_message Mail One message: body as text, recipients and attachment list.
list_threads Mail Conversations by latest activity, optionally in one mailbox.
get_thread Mail A whole conversation, oldest first, in one call.
get_attachment Mail Downloads an attachment, up to 10 MiB.
list_calendars Calendar An account's calendars: id, name, primary, editable and time zone.
list_events Calendar Lists or searches events overlapping a range, recurring occurrences included.
get_event Calendar One event in full: description, attendees and their answers, join link, recurrence rule.
find_availability Calendar When the given people and the account are busy, and free slots they share.
pick_meeting_time Calendar find_availability with a slot picker, where the client shows MCP Apps views.
search_contacts Contacts Finds contacts by name, email, phone or organization; returns full records.
write Change data, and save drafts. Nothing here sends mail by itself.
connect_account Accounts A link, valid an hour, where the user signs in to connect another Google, Microsoft 365 or IMAP mailbox. Refused for a key limited to accounts.
create_draft Mail Saves a draft in the account's Drafts for the user to review and send; nothing goes out.
update_draft Mail Replaces a draft's whole content; the draft gets a new id.
delete_draft Mail Deletes a draft for good; nothing is sent.
mark_messages Mail Marks up to 50 messages, or a thread, read or unread, flagged or not.
move_messages Mail Moves up to 50 messages, or a thread, to a mailbox (including trash), or changes Gmail labels.
create_event Calendar Creates an event or recurring series, optionally with an online meeting. Needs send as well when it invites people outside the account.
update_event Calendar Changes the fields given on an event or one occurrence. Needs send as well when it notifies attendees.
delete_event Calendar Deletes an event or a series. Needs send as well when it cancels for attendees.
respond_to_event Calendar Accepts, tentatively accepts or declines an invitation. Needs send as well when it tells the organizer or carries a comment.
create_contact Contacts Adds a contact to the account's address book.
update_contact Contacts Changes the fields given on a contact.
send Anything that leaves the account as email.
send_message Mail Sends an email now or at sendAt. Subject to the send policy and the user's confirmation.
send_draft Mail Sends a draft now or at sendAt. Subject to the send policy and the user's confirmation.
cancel_send Mail Cancels a queued send during the account's undo window or before its sendAt.
preview_message Mail Shows a message as it would go out, unsent; in clients with MCP Apps, as a card with Send and Edit.
commit_message Mail The review card's Send: sends what preview_message showed, once, within 10 minutes.

preview_message, commit_message and pick_meeting_time back the MCP Apps views; on 2026-07-28 they are offered only to clients that declare the extension. Calendar writes that email anyone outside the account follow the send policy like a send. Tools that act on one account take accountId (its id or email), which a credential limited to one account may leave out.

Prompts

Clients list these as slash commands. A prompt is offered only to a caller holding every scope it needs, and mentions a writing tool only when the caller has its scope.

PromptNeedsWhat it does
triage_inbox read Sorts recent inbox mail into replies needed, actions, FYI and noise.
draft_reply read, write Drafts a reply to a message for the user to review.
schedule_meeting read Finds times everyone is free and, once the user picks one, books it.
weekly_agenda read The week's events by day, with conflicts, open invitations and free blocks.
summarize_thread read Positions, decisions, open questions and next steps of a conversation.
Safety model

Agents read mail written by strangers. Sending is the risky part.

The strongest control is the credential: without send, an agent cannot be talked into sending mail or meeting invitations, whatever the model does.

Scopes decide the tool list

A client sees only the tools its scopes allow. Without send there is no send tool, and a calendar change that emails people outside the account is refused with missing_scope.

Sends are confirmed by default

The default send policy is confirm: every send needs the user's confirmation of subject, recipients and account, in a form or on the review card. A client that can do neither cannot send, and neither can a headless agent on a backend API key.

Undo and duplicate guard

cancel_send cancels a queued send during the account's undo window or before its sendAt. An identical send within 10 minutes is refused with duplicate_send, so a retried call does not send twice.

Third-party text is marked as data

Mail, event and contact text comes back in a separate block fenced by a random marker, labeled untrusted, with invisible characters stripped. It helps the model; it is not a guarantee, so keep confirmation on for agents that read mail from strangers.

Only the accounts you pick

An API key or OAuth grant can be limited to specific accounts, and an MCP key is bound to one. A grant is for one workspace.

Audited and revocable

Every tool call is recorded in the audit log, reads included. Revoke an OAuth grant, an MCP key or an API key at any time.

The send policy

Owners and admins set it under Settings, Agents (MCP), or with mcpSendPolicy in PATCH /v1/settings. It covers sends and calendar writes that email people through MCP; sends through /v1 are not affected.

FieldValuesEffect
mode confirm (default)
allow
drafts_only
confirm: every send needs the user's confirmation. allow: agents send, and clients that can ask still confirm each send. drafts_only: agents save drafts and never send.
allowedRecipientDomains Up to 100 domains, or null Recipients must be in these domains, their subdomains or the sending account's own. For a public mailbox provider such as gmail.com, only the account's own addresses.
dailySendLimit 1 to 10,000, or null Sends per credential per UTC day.
externalRecipientConfirmation true or false A send to an address the account has never sent to needs the user's confirmation.
Example: confirm, at most 50 sends a day
curl -X PATCH "https://api.workwae.com/v1/settings" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "mcpSendPolicy": { "mode": "confirm", "dailySendLimit": 50 } }'

A send the policy stops answers send_policy_refused with the rule (drafts_only, recipient_domain, daily_limit, confirm or external_recipient_confirmation) and tells the model to save a draft for the user instead. An MCP key can carry its own send policy on top of the workspace's; it can only tighten it.

What an agent cannot do

  • Change your configuration. No tool edits settings, API keys, webhooks or the send policy, and admin is never granted over OAuth or to an MCP key.
  • Send without the send scope. Nor can it email attendees, or the organizer, from a calendar change.
  • Send under confirm when it cannot ask you. A client with neither forms nor the review card cannot send.
  • Send outside the policy. Recipients outside allowedRecipientDomains and sends past dailySendLimit are refused.
  • Reach other accounts or workspaces. Accounts outside its key or grant are out of reach, and so is every other workspace.
  • Use an MCP key on the REST API. /v1 answers mcp_only_key.
Example

Draft first, send only when you confirm.

An illustration, not a recording: tool and argument names are the server's, while ids and values are made up. It assumes a one-account credential with read, write and send, the default send policy, and a client that can show a form.

  1. You

    Find Ada's unread email about the budget and draft a reply saying Thursday works.

  2. Agent calls

    search_messages{ "q": "budget", "from": "ada@example.com", "unread": true }

  3. Result, summarized

    One unread message from Ada Lovelace, subject "Q4 budget", id msg_1.

  4. Agent calls

    get_message{ "messageId": "msg_1" }

  5. Agent calls

    create_draft{ "reply": { "messageId": "msg_1", "mode": "reply" }, "body": "Thursday works for me." }

  6. Result

    Created draft drf_1 in account acc_1. To: ada@example.com From: me@example.com Subject: Re: Q4 budget

  7. You

    Looks right. Send it.

  8. Agent calls

    send_draft{ "messageId": "drf_1" }

  9. Your client asks you

    Send to ada@example.com from me@example.com, subject "Re: Q4 budget"? [ ] Send this message

  10. You

    Tick Send this message, accept.

  11. Result

    Queued send out_1 in account acc_1, status …, going out at …. It can be cancelled with cancel_send (outboxId out_1) until ….

Had the credential lacked send, the agent would have had no send_draft to call, and the draft would wait in Drafts. Under drafts_only, the call is refused with send_policy_refused and the same outcome.

Early access

Point an agent at a mailbox, with the controls on.

Workwae is in early access; tell us what you are building, and read the MCP guide in the meantime.