Skip to content

Commit c4aa4e9

Browse files
akolotovclaude
andcommitted
docs: trim Credit Exhaustion section in SPEC.md to high-level description
Replace four verbose paragraphs (~350 words) with two concise sentences covering the shared-core mapping, no-retry behaviour, client surfaces, and composite-tool primary-vs-side semantics (~60 words). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 073d65a commit c4aa4e9

1 file changed

Lines changed: 2 additions & 8 deletions

File tree

SPEC.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -604,15 +604,9 @@ Credit-exhaustion responses on the PRO API *data path* are special-cased: the sh
604604

605605
**Credit Exhaustion (`402 Payment Required`)**
606606

607-
The Blockscout PRO API meters access by credits and returns `HTTP 402` with body `{"error": "Out of credits"}` when the daily allowance is exhausted, halting the request in its rate-limit gate before it reaches the upstream Blockscout instance. The shared `_make_blockscout_http_request` core maps any `402` status to a dedicated `CreditsExhaustedError` (a direct `Exception` subclass, kept separate from the generic `HTTPStatusError` enrichment path above) so credit exhaustion is surfaced as a clearly-labeled error rather than a generic transient upstream failure. Because every PRO API helper — `make_blockscout_request` (GET), `make_blockscout_post_request` (POST), and `make_metadata_request` — funnels through this single core, the mapping applies uniformly to all of them. `CreditsExhaustedError` is not part of any helper's retry set, so it propagates immediately without retries.
607+
The shared `_make_blockscout_http_request` core maps any `402` response to a dedicated `CreditsExhaustedError`, which propagates immediately without retries. REST clients receive `402 Payment Required`; native MCP clients receive an `isError: true` tool result.
608608

609-
The mapping is **plan-agnostic**. The server always authenticates with an API key, so it never reaches the keyless x402 `402` payment paths, and it does not distinguish PRO plan types: the PRO API returns `402` only for free-plan or admin-managed keys at a non-positive balance, while paid-plan keys are allowed through at a negative balance (allow-then-bill) and never receive `402` from this gate. If the deployment key is on a paid plan, `402` simply never arrives — which is acceptable.
610-
611-
The error surfaces differently per access mode:
612-
- **REST clients** receive `402 Payment Required` with the standard `{"error": ...}` body, emitted by the `handle_rest_errors` decorator.
613-
- **Native MCP clients** receive a `tools/call` result with `isError: true` whose text content carries the `CreditsExhaustedError` message; no special registration is required because FastMCP surfaces uncaught tool exceptions as error results.
614-
615-
Note on composite tools: several tools issue multiple PRO API requests concurrently via `asyncio.gather(..., return_exceptions=True)`, with exactly one hard-fail *primary* request whose exception is re-raised and surfaces directly, plus one or more optional *side* requests whose isolated failures are each downgraded to a null field plus an explanatory note. This applies to `get_address_info` (primary: address-info; side: metadata and first-transaction), `get_block_info` with `include_transactions=True` (primary: block details; side: the transactions list), and `get_transaction_info` (primary: the transaction; side: account-abstraction user operations). Because the side requests share the same `_make_blockscout_http_request` core, a `402` raised by a side request *alone* is mapped to `CreditsExhaustedError` and then absorbed into a note (partial data is still returned) rather than surfaced as a hard error. Under genuine credit exhaustion, however, every request — including the primary one — is rejected, so the `CreditsExhaustedError` still reaches the client through the primary request's re-raise.
609+
In composite tools (`get_address_info`, `get_block_info`, `get_transaction_info`), side requests absorb `CreditsExhaustedError` into a note (returning partial data) while the primary request hard-fails normally.
616610

617611
9. **Tool Title and Annotations**:
618612

0 commit comments

Comments
 (0)