> ## Documentation Index
> Fetch the complete documentation index at: https://docs.impellabs.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits

> Rate limits, and the transport constraints that look like faults and are not.

**Preview.** Two kinds of limit apply: how often you may call, and what the
transport will accept at all.

## Rate limits

Requests are counted against several dimensions at once, and the first one to
run out refuses the call. The defaults, per 60-second window:

| Dimension           | Requests / minute | Counts                                                              |
| ------------------- | ----------------- | ------------------------------------------------------------------- |
| `credential`        | 900               | Everything sent with one key — the dimension an MCP client lands on |
| `tenant`            | 300               | The whole workspace, across every surface                           |
| `tenant` + endpoint | 300               | Per endpoint, so saturating one does not starve the others          |
| `agent`             | 300               | Per agent                                                           |
| `principal`         | 60                | Per end user                                                        |

<Note>
  The ordering is the policy: a single end user may burst, a workspace may burst
  harder, and a credential that fans a whole customer base into one key hardest.
  These are the same limits `/api/v2/` runs on — an MCP client is not throttled
  separately, it is throttled by the same counter.
</Note>

A refusal comes back as a tool error carrying `rate_limited` and a retry hint.
Unlike an empty wallet, **retrying does help here** — wait out the window.

The windows are fixed rather than sliding, so a caller can send up to two
windows' worth across a boundary. That is a known and deliberate trade: a
sliding window needs a read-modify-write the cache API cannot make atomic, and
the cost of the fixed one is something you notice in a graph rather than an
outage.

## Transport constraints

These are the ones that look like faults in a test client and are not. Every one
of them is what the Streamable HTTP transport permits or requires — the
[`2025-06-18`
spec](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)
for a handshake-era client, and `2026-07-28` for a modern one, which turned
three of these from a server's choice into the rule.

| You send                                    | You get                                                                        | Why                                                                                                                                                        |
| ------------------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /mcp`                                  | **405**                                                                        | No SSE stream to open. A server that does not offer one answers 405, and the current revision deleted the GET endpoint outright.                           |
| `DELETE /mcp`                               | **405**                                                                        | No sessions, so nothing to tear down.                                                                                                                      |
| `Mcp-Session-Id`, from an older client      | Ignored, never echoed                                                          | The current revision's own instruction for session traffic. This endpoint has never minted one.                                                            |
| A notification or a response (no `id`)      | **202**, empty body                                                            | A MUST. There is no result to return, so there is no body.                                                                                                 |
| A JSON-RPC batch (an array)                 | **400**                                                                        | Batching was removed in `2025-06-18` and did not come back. One message per POST.                                                                          |
| An unsupported `MCP-Protocol-Version`       | **400**, `-32022`                                                              | The body carries `data.supported` — the list to retry from — and `data.requested` echoed back, in case an intermediary rewrote the header.                 |
| No `MCP-Protocol-Version` at all            | Treated as `2025-03-26`                                                        | The spec's compatibility rule for clients that predate the header. The current revision lets a server refuse instead; this one does not.                   |
| A mirrored header disagreeing with the body | **400**, `-32020`                                                              | Modern era only. `Mcp-Method` and `Mcp-Name` let a gateway route without parsing; the two must not disagree.                                               |
| A method this server does not implement     | **404** for a modern client, **200** for a handshake one — `-32601` either way | The 404 distinguishes "no such MCP method" from "not an MCP endpoint". A handshake-era client would read a 404 as a missing endpoint, so it keeps the 200. |
| A request from an unexpected `Origin`       | Refused                                                                        | DNS-rebinding defence, and a MUST.                                                                                                                         |

### Which revisions are accepted

Four, in two eras: the current **`2026-07-28`**, which has no handshake, and the
handshake revisions **`2025-06-18`**, **`2025-03-26`** and **`2024-11-05`**. The
list the server actually answers on is `mcpserver/protocol.py:
SUPPORTED_PROTOCOL_VERSIONS`, and `server/discover` reads it out over the wire
so a client never has to trust this page for it.

**Which era a request is served in is decided by the `MCP-Protocol-Version`
header alone**, so a client working today keeps working untouched — an absent
header still means `2025-03-26`. [Protocol revisions](/connect/protocol) is the
whole story: what a modern client must send, what `server/discover` answers, and
the three error codes this revision added.

A client built for a revision we do *not* speak is still not locked out. The
`initialize` handshake answers in the newest **handshake** revision we speak
rather than refusing over a string, so such a client negotiates down and carries
on — because a handshake that failed on an unrecognised version string would
make the client list a whitelist by accident. The **400** is reserved for a
client that keeps asserting an unsupported revision in the header *after* that,
and it names what we do speak.

<Note>
  **No `Mcp-Session-Id` is ever issued, in either era.** Sessions were a MAY in
  the handshake era and `2026-07-28` removed them from the protocol altogether,
  so there was nothing to unwind here: a stateless server removes an entire
  class of expiry bugs — there is no session to go stale between a tool listing
  and a tool call. If your client is waiting for one, it will not arrive, and it
  does not need it.
</Note>

## Response bodies

Requests get `Content-Type: application/json` and a single JSON object. There is
no SSE on this endpoint in Preview: streaming a tool result buys nothing when
the result is a JSON object, and it costs every client an extra parsing path.

## What is deliberately not here yet

<AccordionGroup>
  <Accordion title="MCP resources and prompts">
    Tools first. The server advertises tools capability and nothing else.
  </Accordion>

  <Accordion title="Server-sent events on /mcp">
    Conformant to omit, and it earns nothing while every result is a JSON
    object.
  </Accordion>

  <Accordion title="Sessions">
    See above. Not planned, and `2026-07-28` removed them from the spec.
  </Accordion>

  <Accordion title="Revision 2025-11-25">
    Deliberately absent from `SUPPORTED_PROTOCOL_VERSIONS`, and the omission is
    the decision rather than a gap. Nothing in the installed base speaks it, and
    it added surface — tasks, URL-mode elicitation — that this server does not
    implement. Claiming it would be advertising a revision we would then have to
    refuse features from. A client that asks for it is answered `-32022` with
    the four we do speak, which is one retry rather than a guess. See [Protocol
    revisions](/connect/protocol).
  </Accordion>

  <Accordion title="Sampling, elicitation and roots">
    This server asks nothing of a client. `clientCapabilities` is required on
    every modern request and is read only to enforce its presence — which is why
    `-32021` (`MissingRequiredClientCapability`) is a code this server names and
    never emits.
  </Accordion>
</AccordionGroup>

<Warning>
  **Preview means the tool set may change.** Names and schemas can move between
  releases. Call `tools/list` at connection time rather than hard-coding a tool
  name in an unattended integration, and expect this page's guarantees about the
  *transport* to be steadier than the ones about the *tools*.
</Warning>
