Skip to content

v0.12.0

Choose a tag to compare

@paulbalandan paulbalandan released this 12 Aug 09:12
· 176 commits to 1.x since this release
Immutable release. Only release title and notes can be modified.
v0.12.0
e01586a

What's Changed

Lifecycle correctness on both peers: close/drain ordering, in-flight caps that hold under pressure, subscription accounting, and task expiry and stall guarantees. The schema side now honours the spec's open capability set and the empty {} sub-schemas the decoder collapses to []. Seven breaking changes are listed in BREAKING_CHANGES.md.

Added

  • ClientBuilder::setMaxInFlightDispatches() caps how many inbound messages a client processes at once.
  • RequestStateSigner::sign() and verify() take an optional binding, so a state minted for one caller does not verify for another.

Changed

  • Core\Transport\SubscriptionInterface is renamed ListenerHandleInterface (see BREAKING_CHANGES.md).
  • The in-flight dispatch cap is on by default on both peers, at DEFAULT_MAX_IN_FLIGHT (1024). See BREAKING_CHANGES.md.
  • RequestStateSigner signatures changed shape, so a state minted before this release no longer verifies.
  • VerifiedAccessToken::$subject and $clientId are non-empty-string, and an empty or non-string identity claim reads as absent rather than reaching a handler or masking a later one. See BREAKING_CHANGES.md.

Fixed

  • A close() racing an in-progress close on the stdio transports now blocks until that close settles, instead of returning early while send() was still accepted.
  • An empty {} sub-schema, which json_decode(..., true) renders as PHP [], no longer fails every tools/call with a bare internal error: the default validator restores it in every sub-schema position.
  • #[InputSchema(definition: [])] is refused at construction instead of being read differently per level.
  • A completion answering more than the spec's 100-value cap is truncated with hasMore: true and a total, instead of shipping an over-long list.
  • Icon decodes any RFC 3986 URI src instead of aborting a whole listing on an unusual scheme. The http/data restriction moved to the authoring surfaces (stores and builders). See BREAKING_CHANGES.md.
  • ServerCapabilities now keeps unknown capabilities (top level in a new extras slot, nested keys in place) and models the deprecated logging member, honouring the spec's open-set rule. See BREAKING_CHANGES.md.
  • awaitTask()'s stall ceiling now counts polls that sent no answers, so a resolver answering outside the offered set can no longer defeat it, and a key re-issued after a working round is offered again.
  • InMemoryTaskStore now fails a task that has not settled by createdAt + ttlMs and sweeps it, instead of retaining a parked task forever.
  • HeaderMismatchError now carries data like its sibling errors, instead of silently dropping it on construction and decode.
  • Building a -32021 or -32022 error without its data payload now fails with a message naming the code and the keys it requires, instead of a generic decode error.
  • A prompt or template completion registered under an all-digit name no longer fails build().
  • A discovered tool's nullable parameter now accepts the null its advertised schema permits, at the top level and inside an expanded object, instead of answering -32602.
  • A method-level #[InputSchema(...)] without definition now merges its constraints over the inferred schema instead of being silently discarded.
  • ResourceStore refuses an entry whose key differs from its resource's URI at construction, the same check its three sibling stores already run.
  • A subscriptions/listen acknowledgement no longer promises a listChanged type no registered store can produce, matching what server/discover advertises.
  • A stdio transport closed from the main context before its read loop's first turn now drains that loop before close() returns, the same as every other close path.
  • A resource reader's own ResourceNotFoundException ends the read instead of being answered by an overlapping resource template. A registry miss still falls through, signalled by the new ResourceNotRegisteredException (see BREAKING_CHANGES.md).
  • An authorization caller that stops waiting for the coordinator's lock now returns the permit it is eventually handed, so later token operations no longer depend on collection timing to proceed.
  • SubscriptionStore counts a stream whose acknowledgement is still in flight against maxSubscriptions, so the limit holds against a peer that stops reading.
  • subscriptions/listen no longer occupies an in-flight dispatch slot on a server that serves it, and listens arriving faster than the loop starts them are shed with -32000.
  • The first notifications/cancelled naming a request in flight is no longer shed by the in-flight dispatch cap, and is cancelled on admission when the cap is reached.
  • StreamableHttpServerTransport no longer leaks a request's sink when an onMessage listener throws.
  • StreamableHttpServerTransport no longer strands an in-flight request whose response or notification cannot be encoded or built, and settles those still in flight when close() runs.

Full Changelog: v0.11.0...v0.12.0