nLight.fit errors and limits
HTTP status codes
| Status | When | What to do |
|---|---|---|
200 |
The message was handled. A tool that itself failed still returns 200 with isError: true in the result. |
Read the result. |
202 |
The message was a notification (no id), so there is no response body. |
Nothing. |
400 |
Malformed JSON, a batch array, an unknown method, bad tool arguments, an unsupported protocol version, or routing headers that disagree with the body. | Fix the request. The JSON-RPC error code says which. |
401 |
No credential, or one that is unknown, revoked or expired. Response carries WWW-Authenticate: Bearer. |
Mint a new token. |
403 |
The token is valid but lacks the required scope, or the request carried a browser Origin header. |
Use a token with read scope; do not call this endpoint from a browser. |
405 |
The request was not a POST. Response carries Allow: POST, OPTIONS. |
MCP is POST-only. A 405 to a GET is what the Streamable HTTP transport prescribes for a server offering no server-to-client event stream; this one is stateless and has nothing to push. |
429 |
Rate limit exceeded. Response carries Retry-After in seconds. |
Back off for the stated interval. |
500 |
Server-side failure. The message is deliberately generic. | Retry; if it persists it is not something the caller can fix. |
503 |
The data store could not be reached. | Retry with backoff. |
JSON-RPC error codes
| Code | Meaning |
|---|---|
-32700 |
Parse error — the body was not valid JSON. |
-32600 |
Invalid request — not a JSON-RPC message, a batch, or an unsupported protocol version. |
-32601 |
Method not found. |
-32602 |
Invalid params — missing params.name, or a tool that is not exposed. |
-32603 |
Internal error. |
-32020 |
Header mismatch — Mcp-Method or Mcp-Name disagreed with the body, or was absent when the declared protocol version requires it. |
-32001 |
Authentication required — no credential was presented, or the one presented was rejected. Travels with HTTP 401 and a WWW-Authenticate header naming the authorization server. |
-32002 |
Forbidden — the credential is valid but lacks the scope the method needs, or the request carried a browser Origin and asked for member data. Travels with HTTP 403. |
Handle -32700 as one of two shapes. A request that declares a content type other than application/json reaches the server and is answered with the envelope above. A request that declares application/json and is not valid JSON is refused by the platform before this API sees it: HTTP 400 with an empty body and no Content-Type. Treat an empty 400 as a parse failure.
Rate limits
The MCP endpoint allows 120 requests per 60 seconds, counted per user rather than per token. Each JSON-RPC message is one HTTP request, so a multi-step agent run consumes calls quickly; the limit is set to accommodate that while still bounding a runaway loop.
The stated number is the ceiling to design against. It is not a precise meter, so do not build anything that depends on exceeding it.
Rate limit headers
You do not have to wait for a 429 to learn where you stand. Every response carries RateLimit-Policy describing the quota, and every response that spends quota also carries RateLimit describing what is left of it. Send a credential and every request is counted, so every response reports both. Send none and tools/list is still counted, while the negotiation methods (initialize, server/discover, ping) are answered without touching the limiter and carry the policy alone.
| Header | Example | Meaning |
|---|---|---|
RateLimit-Policy |
"mcp";q=120;w=60 |
The fixed shape of the quota: q requests per w seconds. Stable across responses. |
RateLimit |
"mcp";r=118;t=47 |
Live state: r requests remaining, t seconds until the window refreshes. |
RateLimit-Limit |
120 |
The same quota in the superseded three-header form, sent for client compatibility. |
RateLimit-Remaining |
118 |
Requests left in this window. |
RateLimit-Reset |
47 |
Seconds until the window refreshes. |
Retry-After |
47 |
Sent only on a 429. Seconds to wait before retrying. |
RateLimit and RateLimit-Policy follow draft-ietf-httpapi-ratelimit-headers. The three-header form is the earlier draft, kept because most existing clients read it. All of them are listed in Access-Control-Expose-Headers, so a browser-based client can read them cross-origin.
Version and lifecycle headers
| Header | Meaning |
|---|---|
Api-Version |
The API version that served the response. |
Link |
service-desc points to the OpenAPI document, service-doc to the developer documentation, version-history to the versioning policy. |
Deprecation |
Present only on a deprecated resource. An RFC 9745 structured field date. |
Sunset |
Present only when a retirement date is fixed. An RFC 8594 HTTP-date. |
Nothing is deprecated today. See versioning and deprecation for the notice periods these headers promise.
Result size
A single tool result is capped at 100,000 characters, roughly 25k tokens. Beyond that the payload is truncated and an explicit [TRUNCATED: ...] marker is appended, so a clipped series can never read as a complete one. If you hit it, narrow the date window or name fewer metrics.
Protocol versions
Send your revision in the MCP-Protocol-Version header. Supported, newest first:
2026-07-282025-11-252025-06-182025-03-26
An unrecognised version is refused with a 400 that carries the full supported list in error.data.supported, so a client can pick one instead of guessing. Omitting the header entirely is read as 2025-03-26, the last revision that predates the header.
From 2026-07-28 onward, every request must also carry Mcp-Method, and Mcp-Name when the message addresses something (tools/call). The server checks them against the body and rejects disagreement, so an intermediary cannot route on one operation while the server performs another.
Scopes
Tokens carry explicit scopes: read, write. They are not cumulative — a write token does not imply read. Every MCP method today requires read, including initialize and ping.