Skip to content

v4.3.0

Choose a tag to compare

@github-actions github-actions released this 06 Sep 19:58
· 1 commit to main since this release
a72e3c9

Changelog - v4.3.0

All notable changes to the law-scrapper-mcp project for version v4.3.0 will be documented in this file.

The format is based on Keep a Changelog 1.1.0,
and this project adheres to Semantic Versioning 2.0.0.

[4.3.0] - 2026-09-06

Failed content loading now looks like a failure: a transient upstream problem during
get_act_details(load_content=True) used to surface as a successful response with no readable
text, and now fails the call itself. A new regression test also pins the guarantee, introduced
when this project migrated to the official MCP SDK, that any domain exception surfaces as a
protocol error (isError=true) rather than a success body with an embedded error field. Every
error message built from caller-sourced or exception text is now length-bounded.

BREAKING — content loading failures are protocol errors

get_act_details(eli=..., load_content=True) used to return a successful response with
is_loaded=false whenever loading failed — an open circuit breaker, a timeout, an HTTP 5xx
from api.sejm.gov.pl, or a conversion error. The only record of the failure was a server log
line, and the response even hinted at retrying the call that had just failed.

Such calls now fail with isError=true. Clients that treated is_loaded=false as "this act has
no text" must distinguish two cases:

  • content_status="unavailable" in a successful response — the act permanently has no
    readable text; retrying will not change that.
  • isError=true — the upstream is unreachable; retrying later may succeed.

This mirrors the change v3.1.1 made for oversized acts, which shipped as a PATCH; it is a
signalling fix, since the contract always meant "success = content loaded".

Added

  • content_status field on get_act_details output, with values not_requested, loaded and
    unavailable. The field is part of the tool's outputSchema and its structuredContent.
    loaded reflects the final in-memory state rather than this call's load_content flag, so an
    act loaded by an earlier call reports loaded even on a metadata-only call that never asked to
    load anything.
  • LAW_MCP_ERROR_MESSAGE_MAX_CHARS (default 500, range 80-10000) caps the length of error
    messages built from an exception's own text, which can quote caller input of unbounded length.
    Truncation is announced in the message rather than silent.
  • Every tool error message now ends with a fixed one-sentence remediation hint, so a caller can
    tell "retry shortly" from "this identifier does not exist" without parsing category names.
    Seven categories carry a hint: not_found, validation, precondition, content_too_large,
    unavailable, upstream, internal. content_too_large (a refusal because the act is too
    large to convert) is split out of precondition rather than sharing its "do a step first"
    wording — there is no prior step for an oversized act, and the one actionable remedy (fetch the
    source file) is already the last sentence of the body.

Changed

  • ActService._load_content no longer swallows exceptions. Transient failures propagate; only a
    permanent absence of readable text is handled internally, as ContentNotAvailableError — no
    HTML or PDF URL at all, a 404 on the text.html or text.pdf fetch, or an empty extraction
    from either format.
  • An act with neither an HTML nor a PDF text URL no longer triggers a request that its metadata
    already proves pointless.
  • A permanent absence is remembered for as long as the act's metadata stays cached
    (LAW_MCP_CACHE_DETAILS_TTL, default one hour): a repeated load_content=true call on such an
    act answers content_status="unavailable" from memory instead of re-fetching text.html /
    text.pdf. The removed placeholder document used to play that role by accident; without a
    replacement every retry would have cost api.sejm.gov.pl one or two requests for an answer that
    cannot change before the metadata it was derived from expires.
  • Hints for an act with no readable content no longer point at read_act_content, search_in_act
    or another load_content=true call; one hint names the source PDF URL when the act has one,
    alongside the unrelated analyze_act_relationships hint every get_act_details response
    already carries. An act with no PDF either gets the same explanatory hint without a URL to
    offer, rather than one pointing at a file the server itself declined to fetch.
  • A message built from an exception's own text now ends in a sentence terminator before the
    remediation sentence is appended, unless it already ends in one or ends in a URL — so the two
    sentences don't run together, and a ContentTooLargeError message can still end on a bare,
    unpunctuated PDF URL without a stray period being glued onto it.
  • The set of error categories treated as caller-sourced — and therefore subject to the length
    cap — is now validation, not_found, precondition, content_too_large and unavailable.
    unavailable is included because ApiUnavailableError's text can embed a raw httpx
    exception, which is not authored by this project even though the category itself is not new.

Removed

  • The placeholder documents *No readable content available for {eli}…* and
    *Content extraction failed…*. They were stored in the document store as if they were the act,
    made is_loaded=true untrue, and were matched by search_in_act.

Fixed

  • A failure to load content is no longer indistinguishable from an act without text: a transient
    upstream failure now propagates as isError=true instead of silently reporting
    is_loaded=false.
  • validation, not_found, precondition, content_too_large and unavailable error messages
    are now length-bounded, so text quoting unbounded caller input or upstream detail cannot fill
    the caller's whole context window.