0.4.1 (2026-10-02)

Features

  • add aggregating proxy package (#243) (6a3f69c)
  • add per-component middleware (#242) (5b36942)
  • cache Snodo.Client responses from server hints (#240) (15ebbf6)
  • experiment with generated GenServer tools (#241) (2ece745)
  • expose requested URI to resource-template policies (#225) (fd71e57)
  • expose W3C trace context to handlers and instrumentation (#233) (9d52692)
  • optionally conceal authorization refusals (#231) (2991c45)
  • render MCP catalogs as Markdown (#235) (326f6e0)
  • send extension routing headers from the HTTP client (#214) (50be287)
  • support OAuth on the native HTTP listener (#222) (90fc323)

Bug Fixes

  • bound method in dispatch instrumentation (#226) (67c5876)
  • close Plug streams when their executor exits (#228) (3377fc3)
  • close subscription sources across handoff races (#232) (bc4b943)
  • count only HTTP headers against the header limit (#212) (306d719)
  • reject duplicate keys in JSON objects (#224) (0c0d1b8)
  • release request-only data from open subscriptions (#230) (2e9a08e)
  • warn on public native HTTP binds (#223) (7035549)

Performance Improvements

0.4.0 (2026-10-01)

⚠ BREAKING CHANGES

  • Snodo.Resource.Template.compile/1 returns {:error, reason} naming the unsupported shape instead of :unsupported, and the struct has new fields. Three kinds of template that compiled and matched URIs before are now refused at compile time: a variable name with a leading dot ({.ext}, {..}), which is RFC 6570 label expansion and before was read as a variable named ".ext"; templates longer than 1,024 bytes; and templates with more than 32 variables. A resource module whose :uri_template is outside the supported shapes and that does not define matches?/1 is now a compile error naming the shape; before, it compiled and matched no URI. A module that defines its own matches?/1 for such a template compiles as before, with or without @impl.

Features

Bug Fixes

0.3.2 (2026-09-30)

Features

  • add snodo_oauth resource server package (#181) (5d44db2)
  • answer input requests automatically in Snodo.Client (#179) (6d758d1)
  • drain the native HTTP listener on shutdown (#190) (e25800c)
  • ExUnit assertions for testing servers (#191) (6452f1e)
  • forward instrumentation events to :telemetry (#182) (0e783ad)
  • key identifiers for sealed MRTR request state (#192) (ecd5e14)
  • nested arguments and output schemas in the tool DSL (#193) (24f890a)
  • OAuth client support for Snodo.Client (#186) (af79ddb)
  • open subscriptions/listen streams in Snodo.Client (#184) (fa10710)
  • sampling and roots as MRTR input requests (#180) (1cf6cf1)
  • sampling and roots handler kinds in Snodo.Client (#185) (451165a)
  • Snodo.Client speaks the initialize-era protocol versions (#187) (ebc3504)

0.3.1 (2026-09-29)

Features

  • add reusable Tasks store contract tests (#172) (6b03f90)
  • add title, icons, and metadata to tool definitions (#169) (6e04d22)
  • attest release tarballs (#175) (550acf1)
  • deliver progress notifications in Snodo.Client (#177) (361595b)

Bug Fixes

  • exclude repository Mix tasks from sibling packages (#168) (d785636)

Performance Improvements

  • index Hub resource subscriptions by URI (#173) (1238f05)

0.3.0 (2026-09-27)

⚠ BREAKING CHANGES

  • snodo_plug answers 411 to a request that declares Transfer-Encoding, without reading its body. Send request bodies with Content-Length, as the native listener already requires.
  • a Tasks store started without :scope fails to start. Pass a scope function, or scope: :shared for the previous behavior.

Bug Fixes

  • apply the authorization policy to resource subscriptions and cache hints (#117) (27aaeeb)
  • authorize and validate task work before storing it (#115) (aad5c04)
  • bound HTTP connections and subscription streams (#114) (13b9352)
  • bound integer literals in Snodo.Client HTTP responses (#130) (dd0cb23)
  • bound integer literals, request ids, and progress tokens (#118) (a71e499)
  • bound memory for an unterminated stdio line (#125) (e22a878)
  • bound Snodo.Client response sizes and page counts (#119) (6e1f785), closes #88
  • bound Tasks workers, task counts, lifetimes, and inputs (#123) (098b478)
  • bound the whole request body in snodo_plug (#138) (10789ba)
  • count only digits in the JSON integer literal limit (#134) (b2f049d)
  • make subscription filter checks linear and cap resource URIs (#113) (f125936)
  • require an explicit scope in every Tasks store (#121) (bbc258f)
  • stop orphaned subscription workers and bound request bodies (#135) (0f1c8bf), closes #127

0.2.1 (2026-09-27)

Features

  • serve initialize-era clients over stdio (#75) (2a4d68c)

0.2.0 (2026-09-26)

⚠ BREAKING CHANGES

  • tool content results carry kind :content instead of :resource.
  • Snodo.Result has no error field, and Result.error/2 no longer takes an :error option.

Features

  • add Result.content/2 and deprecate Result.resource/2 (closes #59) (#72) (68c9340)

Bug Fixes

  • accept a bare authorization module in Router.dispatch/5 (closes #56) (#65) (456c816)
  • build the compliance report from the retained conformance run (closes #62) (#73) (04e4685)
  • deprecate Cancellation.cancel/2, whose reason is discarded (closes #57) (#70) (3d9e1cd)
  • explain a disabled protocol in Snodo.Test.dispatch/2 (closes #60) (#66) (3361a3d)
  • validate the Snodo.Tool description at compile time (closes #61) (#67) (45b0531)

Code Refactoring

  • remove the unread error field from Snodo.Result (closes #58) (#71) (30aad07)

0.1.0 (2026-09-26)

⚠ BREAKING CHANGES

  • rename mcp_ex to snodo (#11)

Features

  • add application authorization across discovery and dispatch (#6) (6e35765)
  • add inline components and Simple resources and prompts (#10) (927d73d)
  • add MCP.Client for in-process dispatch (#8) (466fb8c)
  • add ordinary MRTR and elicitation workflows (4914e1b)
  • add stdio and HTTP transports to MCP.Client (#9) (8d1d81e)
  • application stack, progress notifications, and conformance regression gate (#1) (d3b3041)
  • close the four target-application findings (69f44a7)
  • mirror and validate Mcp-Param headers for x-mcp-header arguments (closes #25) (#40) (ffa35c3)
  • send clientInfo in request _meta from Snodo.Client (closes #37) (#47) (3afe710)
  • support initialize-era HTTP clients alongside 2026 (closes #3) (#4) (bb43399)

Bug Fixes

  • add Host validation and tighten Origin checks on HTTP transports (closes #23) (#33) (638c26e)
  • bound stdio frame size and strip a leading BOM (closes #21) (#32) (37ae8a5)
  • do not answer JSON-RPC responses or malformed notifications (closes #18) (#28) (3f92dd1)
  • harden URI template matching boundaries (8d802fa)
  • keep initialize-era tools/list available when a tool has a non-object schema (closes #24) (#39) (d093711)
  • keep non-ASCII text intact over stdio (#26) (6f46a63)
  • restore green CI on main (#7) (892788e)
  • restore the executor's :mcp_execution message tag (#31) (aa96bed)
  • return tool input validation failures as isError results (closes #13) (#30) (c48d6ea)
  • treat client disconnect as cancellation in the Plug adapter (closes #19) (#34) (740c1cb)
  • use HTTP 200 for JSON-RPC errors on initialize-era dialects (closes #14) (#29) (dbb3b5f)
  • widen the sibling packages' dependency requirements (#50) (0413261)

Code Refactoring