# Limits and troubleshooting

> Quotas shared with the REST API, hourly safety budgets, response sizes, known limits of the MCP server, and what each error means.

Source: https://docs.maylee.app/mcp/limits

## Quotas

Every tool call counts against the workspace's API quota, **shared with the REST API** (see [Rate limits and quotas](/rate-limits)):

| Plan | Requests per minute | Requests per month | Ids per bulk call |
| --- | --- | --- | --- |
| Free | 60 | 10,000 | 60 |
| Premium | 300 | 200,000 | 100 |
| Expert | 1,000 | 1,000,000 | 100 |

Every tool call costs 1 request, bulk tools cost the number of ids, get_reference costs nothing. The quota is shared with the Maylee REST API.

## Hourly safety budgets and sizes

- 500 emails moved to Trash or Spam per hour per connection.
- 50 outbound sends per hour per connection (send, schedule, unsubscribe).
- 200 recipients per hour per connection (to, cc and bcc together), and at most 50 in one email.
- 30 Magic Reply generations per hour per workspace.
- Pages of 1 to 50 emails (25 by default).
- get_thread returns the 10 newest messages and 4,000 characters per body by default, and at most 60,000 characters of bodies per response.
- get_attachment reads files up to 5 MB and returns text 40,000 characters at a time by default (100,000 at most).
- Attachments added through the MCP server: 5 MB per file, 25 MB in total per draft.

A tool call times out after 55 seconds (`QUERY_TIMEOUT`). The work it started may still finish: check its effect before retrying, with the same `idempotencyKey` if the tool has one.

## Known limits

**Email and drafting**

* A draft is always sent from the main address of its mailbox, never from a send-as alias (the app has the same limit). `send_email` supports verified aliases.
* `Reply-To` headers are not stored, so `draft_reply` addresses the sender. When an email asks to be answered elsewhere, the assistant adds the right address with `extraTo`.
* Sending or deleting a draft only affects Maylee's copy: a draft started in Gmail, Outlook or on the mail server stays in the provider's Drafts folder.
* Search covers subjects, senders, To recipients and the first lines of emails, not full bodies or Cc recipients.
* The assistant can read text files, PNG, JPEG, GIF and WebP images and PDF documents up to 5 MB. Office documents and archives return their metadata and a link to open the email in Maylee.
* AI classification (new emails and `classify_existing_emails`), Magic Reply and Auto-Draft share the workspace's monthly AI allowance. When it runs out, AI features pause until the 1st of the month.

**Connections**

* Changing your password (as opposed to resetting it) does not disconnect assistants. Revoke them one by one in **Settings**, **API keys**, &#x2A;*AI assistants (MCP)**.
* The authorization request of the consent flow expires after 10 minutes: start the connection again from the assistant.
* Creating an account or resetting a password from the consent flow loses the authorization request: finish that step, then start the connection again from the assistant.
* A client that switches return address (for example VS Code between vscode.dev and its desktop app) may get one `invalid_grant` error: the next attempt shows the consent screen for the new address.

**Protocol**

* The full list is large (69 tools), and every tool description takes room in the model's context. A client that caps the number of tools, or a coding assistant that only needs email, can load a subset with `?toolsets=reference,emails,compose`.
* The transport is stateless: no server-sent events, no list-changed notifications, no sampling or elicitation.
* Every result carries its data twice, as a JSON text block and as `structuredContent`, as the MCP specification recommends for clients that only read text.

## Troubleshooting

HTTP-level errors (authentication, method, toolsets) use the Maylee format `{ "code", "error", "details" }`. Tool errors come back as tool results with `isError: true` and the same JSON as text.

| Situation                                               | What it means                                                                                                                             |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `401` with a `WWW-Authenticate` challenge               | No token: the client should start the OAuth flow by itself.                                                                               |
| `401` with `error="invalid_token"`                      | The token is invalid, expired or revoked: connect again.                                                                                  |
| `403 WORKSPACE_SUSPENDED`                               | The workspace is suspended: reactivate the subscription.                                                                                  |
| `403 INSUFFICIENT_SCOPE`                                | The API key lacks the `read` scope, or the connection lacks the permission a tool needs. Connect again and tick it on the consent screen. |
| `404` on `/mcp`                                         | The workspace is provided through Emelia (white-label), where the MCP server is not available.                                            |
| `405 METHOD_NOT_ALLOWED`                                | A `GET` or `DELETE` on `/mcp`: the transport only accepts `POST`.                                                                         |
| `400 VALIDATION_FAILED` on connect                      | An unknown name in `?toolsets=`.                                                                                                          |
| `CONFIRMATION_REQUIRED` (tool result)                   | The tool needs `confirm: true`. The assistant should show you the summary and ask.                                                        |
| `VALIDATION_FAILED` (tool result)                       | Wrong or unknown arguments. `details` lists the faulty fields, and the valid parameter names for an unknown one.                          |
| `QUERY_TIMEOUT` (tool result)                           | The call took more than 55 seconds. Check its effect before retrying.                                                                     |
| `SERVICE_UNAVAILABLE` (tool result)                     | The safety budgets cannot be checked right now: sending, trashing and moving to Spam are refused. Retry later.                            |
| `RATE_LIMIT_EXCEEDED` or `QUOTA_EXCEEDED` (tool result) | The workspace quota, shared with the REST API, is used up for this minute or this month.                                                  |
