Repository navigation
v0.8.0 — Dataverse service protection limits and request timeouts
Added
-
DATAVERSE_REQUEST_TIMEOUT_MS(default 30000, maximum 120000, matching Dataverse's own 2-minute limit on a message operation): every Dataverse request and the token request to Microsoft Entra ID now time out instead of hanging a tool call indefinitely. The error says which request timed out. A value that is not a whole number from 1 to 120000 is reported throughdataverse_setuplike a missing variable, rather than silently replaced by the default (#73). -
Handling of Dataverse service protection limits (closes #74). A
429 Too Many Requestsused to fail the tool call with the raw Dataverse error. Now:- A throttled request is resent after the wait its
Retry-Afterheader asks for, up toDATAVERSE_MAX_ATTEMPTSsends in total (default 3). Without a usable header the server backs off 2 s, then 4 s, and so on. While it waits, no other request is sent, because Dataverse extends the wait for a client that keeps sending. - If the waits of one request would add up to more than
DATAVERSE_MAX_RETRY_WAIT_MS(default 15000), or the attempts run out, the tool call fails with "Dataverse is busy: a service protection limit was reached. Retry in N s." The raw Dataverse 429 text is no longer shown. - At most
DATAVERSE_MAX_CONCURRENCYrequests are in flight (default 8). Up toDATAVERSE_MAX_QUEUE_LENGTHmore (default 100) wait their turn in arrival order for at mostDATAVERSE_MAX_QUEUE_WAIT_MS(default 10000); beyond either bound the call fails with a "Dataverse is busy … Retry later" error instead of queuing indefinitely. - All five variables are optional. An out-of-range value is reported through
dataverse_setuprather than replaced by the default.
Behaviour to know about: writes are retried after a 429 like reads, as Microsoft's own clients do. A 429 holds other requests back for the wait Dataverse asked for, but no longer than
DATAVERSE_MAX_RETRY_WAIT_MS(closes #88): in a live test Dataverse answered light requests straight after a 429 withRetry-After: 300, so a longer pause would only have been downtime of our own making. With the defaults the limits add at most 25 s of waiting to a request, chosen so that one request at the default timeout still fits the 60 s a client built on the MCP TypeScript SDK waits by default; the README gives the full arithmetic. - A throttled request is resent after the wait its
Changed
- Tools are registered by purpose instead of by topic (closes #72):
metadata-read,data-read,data-write,actions,functionsanddevelopment, as named in ADR-0001 §4. Nothing a client sees changes except order: tool names, descriptions, input schemas andDATAVERSE_ALLOW_DELETEbehaviour are identical, pinned by atools/listsnapshot taken before the change.tools/listnow returns tools grouped this way rather than in the old per-file order. - Tool input schemas are built once at module load instead of on every registration, ahead of SDK v2 building a server instance per HTTP request.
- When the cached token has expired, concurrent tool calls share one token request instead of each sending their own (#73).
- The client reports failures as typed errors (
DataverseApiErrorwithstatusand the Dataverse errorcode,DataverseTimeoutError,DataverseNetworkError,DataverseAuthError), and tools map "not found" by status rather than by matching message text. API error messages read as before. A network failure now says which request failed and why, instead of a barefetch failed(#73). - HTTP execution sits behind a
RequestExecutorinterface, the seam for throttling handling (#74), acting on behalf of a user (#77) and audit logging (#78) (#73).
Fixed
- The server no longer writes a non-protocol line to stdout at startup. When a
.envfile was loaded, dotenv 17 printed a banner (◇ injected env (7) from .env // tip: …) withconsole.log, and on stdio stdout is the MCP protocol stream. Clients built on the MCP TypeScript SDK reported a parse error for that line and carried on; a stricter client could refuse the connection. Present in every release since 0.1.0. get_picklist_options,add_attributeandcreate_entityno longer report "Global OptionSet not found" for a server error whose body happens to contain "404". They matched404anywhere in the message; they now check the status (#73).