2.8.0 - 2026-10-19

  • Wrap every HTTP authentication in the auth/authenticate telemetry span. Its stop event carries the elapsed duration, a bounded outcome (for example :missing_credentials, :token_expired, :invalid_audience, :sender_constraint_mismatch, :dpop_replay, :dpop_nonce_required, :step_up_required, :verifier_unavailable, :verifier_failure, :principal_binding_failure), the refusal's HTTP status, and the authenticated binding. The outcome AttestoMCP records on the connection is used when present; otherwise it is classified from the captured OAuth error envelope, so the span works with every supported AttestoMCP release. auth/refusal and auth/policy_failure are unchanged.

2.7.2 - 2026-10-18

  • Fail the generated principal admission index migration before any DDL when attesto_mcp_sessions does not exist, instead of returning successfully. Ecto records a migration as applied once it returns, so the 2.7.1 skip left the index missing with no later run to add it. The version is not recorded on failure and the migration runs again once the sessions migration has been applied. A Postgres-backed regression test covers both outcomes.

2.7.1 - 2026-10-18

  • Accept --help in mix attesto_mcp_server.gen.migration; it prints the usage and the accepted options instead of failing with "invalid options".
  • Add --skip-url-elicitations to the migration generator so a host that does not use URL elicitation can rerun the task for later additions, such as the principal admission index, without the optional table coming back.
  • End generated migrations with a newline so they pass mix format --check-formatted unchanged.
  • Make the generated migrations idempotent: tables and indexes are created only when absent and dropped only when present, and the principal admission index migration skips itself with a warning when attesto_mcp_sessions does not exist yet instead of failing.

2.7.0 - 2026-10-18

  • Keep request-path rate-limit decisions constant-time by storing buckets per traffic category, pruning expired buckets during periodic cleanup, and evicting one member of the largest category without scanning or sorting the 10,000 live keys. Group authentication failures from one IPv6 /64. Once an authentication-failure bucket is exhausted, reject later attempts before token-signature verification. A separate refundable auth_checks bucket bounds concurrent verification without charging successful authentication against the failure rate; failures are recorded after verification. A full table reclaims one bucket from its most populous traffic category so one category cannot globally deny admission to new sources.
  • Bind modern subscriptions and session-bound streams to the scopes captured when they open, on every transport. Delivery now checks generic catalog scopes and resource-definition scope alternatives before any optional host reauthorization callback. Transport-neutral callers must pass granted scopes when opening a subscription or stream; compatibility arities capture none and therefore receive only notifications with no scope requirement.
  • Limit active session-bound sessions to 128 per principal and live legacy streams to eight per session and server process by default. Add max_sessions_per_principal and max_legacy_streams_per_session, exact active-session counts for the bundled stores, atomic admission across shared bundled stores, deterministic durable principal encoding across nodes, and namespace-aware optional count/admission callbacks for custom stores. Ecto updates now share the admission lock so an in-flight expiry extension cannot exceed the principal cap. Existing Ecto hosts should rerun mix attesto_mcp_server.gen.migration and apply the generated concurrent principal-admission index migration.
  • Apply configured default_scopes to completion/complete before its prompt/resource fallback scopes.
  • Replace full-catalog snapshots on selected tool, exact resource, and registered-header request paths with indexed registry lookups. Registered argument mirrors now follow a tool's wire-level name when it differs from its registry identity.
  • Split URI-template matching, multi-round retry handling, store setup, startup option validation, request-event delivery, handler invocation, protocol negotiation, and scope policy into focused internal modules. Reuse the same Ecto adapter checks, legacy-session lookup, telemetry correlation, scope-set evaluation, and bounded JSON option parsing across their callers. These internal moves preserve the public API and transport message protocol.
  • Consolidate test HTTP clients, polling, and supervised server startup in test/support so transport and concurrency regressions exercise the same helpers.
  • Retain the hidden cacheable-method and icon-limit getters as callable 2.x compatibility entry points.
  • Correct the multi-mount Phoenix example so every protected-resource metadata route names its trusted authorization-server issuer.
  • Translate the server's legacy :resource endpoint-path option to MCP 2.1's unambiguous :resource_path boundary without forwarding both keys.
  • Preserve the explicitly local allow_dynamic_origin mode by translating it to MCP 2.1's pinned callback contract, and have the installer emit allow_http: true only for an accepted HTTP loopback origin.
  • Give bounded schema compilation and instance evaluation five seconds on a loaded host. Schema and JSON node, depth, and byte limits continue to bound the work below the server's 30-second request deadline.
  • Verify the frozen 2.6 conformance fingerprint against its recorded release commit so later release work does not invalidate historical evidence.

2.6.0 - 2026-10-17

  • Make the server-side HTTP authorization gate use the same per-method scope defaults and params-dependent completion/subscription rules as the Plug boundary. The Plug records its resolved policy so the direct server gate does not apply default_scopes twice. The local stdio adapter continues to require no fallback scopes unless scope_map or default_scopes is configured.
  • Apply one header-name policy during both tool registration and HTTP request handling, including identical token syntax and length limits for every x-mcp-header suffix and its generated Mcp-Param-* wire header.
  • Expand the supported attesto_mcp range to >= 1.3.0 and < 3.0.0, retaining the original minimum while allowing the coordinated AttestoMCP 2.0 release.
  • Exercise the retained JSV 0.24.0 floor in an explicit CI lane, and label the archived 2.3.0 dependency inventory as historical release evidence.

2.5.0 - 2026-10-15

  • Extend automatic AttestoPhoenix installation through the 4.x line while retaining the 2.14 floor and 3.x compatibility. The coordinated source and published-package lanes exercise the new major-version boundary.
  • Make multi-round input requests all-or-nothing when the client lacks any required capability. Tool and prompt retries now validate their original arguments before merging typed input responses, reject response keys that collide with declared arguments, and leave signed request state unconsumed when the client can repair the request.
  • Encode RequestState digests deterministically so clustered nodes agree on map-backed operation and caller bindings. This changes RequestState signatures: a mixed 2.4/2.5 rolling deployment can reject an in-flight multi-round request issued by the other version. RequestState lifetime is capped at 120 seconds, after which clients can begin a fresh round.
  • Re-run the configured authentication :principal callback before each matching subscription event is delivered. This refreshes revocation and principal data while preserving the stream's original actor, binding, and tenant. Hosts should keep callback lookups indexed and bounded because their cost now applies once per candidate event and subscriber; rejection or callback failure suppresses that delivery.
  • Reject javascript:, data:, and vbscript: resource identifiers and links. URI checks remain syntactic; hosts that dereference accepted resources must continue to enforce their own destination policy.
  • Bound the built-in URL elicitation store to 10,000 records and 64 MiB by default. Add url_elicitation_max_entries and url_elicitation_max_bytes for configuring those limits. Admission reclaims enough expired records to avoid a false capacity failure and never evicts a live approval. UrlElicitationStore.ETS.put/2 now returns {:error, :already_exists} for every duplicate key, including consumed records, and {:error, :capacity} when no safe space remains.
  • Treat only Plug's exact %{"_json" => list} parsed-body wrapper as a top-level JSON array. A JSON-RPC object may use _json as an extension key without being mistaken for an unsupported batch.
  • Scope one-time RequestState and cursor secret initialization locks to the local node, and treat an explicitly null token client_id like an absent client identifier during stream ownership checks.
  • Temporarily pin the repository's dev/test-only Bandit dependency to upstream commit d88b21953c65061f21136ea76a89a4f95a2ac7a1, which contains the official fix for GHSA-69m6-wcv4-rwcf. No patched Hex release exists yet; replace this pin with the first patched release when Bandit publishes one. Runtime consumers do not inherit this repository-only dependency.

2.4.0 - 2026-10-06

  • Expose an immutable, bounded snapshot of each request's _meta object to handlers and per-request callbacks as context.request_meta, for HTTP, stdio, and direct test dispatch. The snapshot is untrusted input kept apart from verified identity, scopes, tenant, and host context. Metadata above max_request_meta_bytes (65,536 bytes by default) is rejected, not truncated. AttestoMCP.Server.RequestMeta documents the contract.
  • Bind multi-round retry state to operation parameters and request metadata, except traceparent, tracestate, baggage, progressToken, and io.modelcontextprotocol/clientInfo. Tracing, progress, and display values may change on retry; application metadata and protocol settings remain bound to the original request. Denied direct tool retries do not consume their signed state. Completed tool retries discard authored cache hints.
  • Add instructions_provider for caller-specific guidance in modern discovery and session-bound initialization, and tool_presentation for caller-specific titles, descriptions, icons, and application _meta on visible tools. Failures return controlled errors, never fall back to static text, and leave a session-bound initialization retryable. Customized catalogs are part of the pagination fingerprint.
  • Add cache_policy for cache hints by operation, resource definition, and an optional resolver, with handler hints that can only shorten or restrict. Definition policies apply without a server-level policy. Personalized, filtered, paginated, and retried results stay private; resource result metadata participates in privacy selection, and continuation cursors retain their caller binding. See the migration runbook for the corrections that apply without a policy.
  • Add server_icons to the server implementation identity in discovery, modern result metadata, and 2025-11-25 initialization, with full icon validation. Preserve valid handler-authored identity, including empty optional text/icon arrays and HTTP icons, through bounded wire validation. Reject trailing control characters in configured icon MIME types and sizes.
  • Add opt-in export_schema_dialect to declare the default JSON Schema 2020-12 dialect on exported tool schema roots without changing validation.
  • Extend AttestoMCP.Server.Test with resource, prompt, completion, discovery, catalog, and generic request helpers that share one request builder and support metadata, cursors, and multi-round retry fields. Reject invalid helper options and conflicting reserved request fields consistently.
  • Initialize the fixed embedded JSON Schema meta-schemas at application startup, so the first request does not wait on their initialization lock. The three fixed roots share a ten-second startup deadline; user-supplied schema compilation and evaluation retain their one-second deadlines.

2.3.1 - 2026-10-04

  • Support JSV 0.24.x as well as 0.25.x. Both retain the existing bounded validation and format policy. The 0.24.0 floor passes the server suite and pinned JSON Schema corpus with the same explicit exclusions.

2.3.0 - 2026-10-03

  • Use JSV for bounded JSON Schema 2020-12 and draft-07 evaluation, including reference scope, numeric equality, and unevaluated annotations. Network resolution and casting remain disabled. Tool input and structured output retain format assertions by default, with schema_formats: false selecting annotation semantics.
  • Reuse successfully compiled schemas across request processes through a bounded application cache. Schema and instance limits, format policy and validation timeouts still apply; cache restarts fall back to compilation. Large or output-heavy workloads can remain slower than the previous limited validator; see the migration runbook for measured costs and cache storage limits.
  • Enforce regex limits on compiled reference targets while preserving unused annotations and literal data.
  • Gate the official required draft2020-12 corpus in CI with a frozen revision and explicit external-reference/custom-dialect exclusions.
  • Move the rate-limit application error from the reserved MCP code -32029 to -33029, retaining HTTP 429. Update clients that match the numeric code.
  • Refresh the pinned official MCP source runner to the alpha.12 source plus PR #396; distinguish this commit from the published npm alpha.12 artifact.
  • Add a coordinated-source OAuth-to-MCP integration fixture and exclude vulnerable Igniter/Mint dependency versions.
  • Recover valid multi-round retries with missing answers by requesting only the remaining inputs. Preserve validated answers and the original expiry in fresh signed state, while rejecting unbound input and replay.

2.2.0 - 2026-09-13

  • Allow a protected MCP endpoint to retain its canonical RFC 9728 resource in metadata while using Attesto core's explicit :trusted_audiences policy for access tokens issued to trusted reverse-gateway identifiers. Subscription delivery now reuses the same audience policy.

2.1.0 - 2026-09-03

  • Add staged URL elicitation support for modern interactive requests in the 2026-07-28 protocol revision (AttestoMCP.Server.UrlElicitation and AttestoMCP.Server.API helpers: stage_url_elicitation/5, resolve_url_elicitation/3, consume_url_elicitation/3).
  • Add AttestoMCP.Server.UrlElicitationStore behaviour with built-in in-process ETS adapter (AttestoMCP.Server.UrlElicitationStore.ETS) and optional PostgreSQL Ecto adapter (AttestoMCP.Server.UrlElicitationStore.Ecto).
  • Implement atomic single-use consume semantics with foreign subject precedence to prevent cross-user state disclosure.
  • Add periodic cleanup sweep of expired URL elicitations running alongside session cleanup with dedicated start, stop, and failure telemetry events.
  • Make mix attesto_mcp_server.gen.migration write a second migration, create_attesto_mcp_url_elicitations, and skip each file whose base name already exists, so an existing host that reruns the task receives only the new table.
  • Document mode: "url" elicitations in the usage guide: the link must carry the staged approval by opaque id, never as a bare route, and the staged record is subject-bound, single-use, time-limited, an explicit dead end when expired, consumed, or foreign, and swept. The section also states which operations deserve a browser gate and why the library does not refuse the mode by principal type.

2.0.1 - 2026-09-02

  • Bind automatic protected-resource callbacks to the named profile loaded from the helper's otp_app argument on attesto_phoenix 3.x, keeping multiple named profiles isolated. The helper does not select a profile from conn.private. The attesto_phoenix 2.14 compatibility path supports one globally configured profile; using it for multiple profiles can route persistent replay or revocation reads through that global profile's store.

2.0.0 - 2026-09-02

  • Make PhoenixParser treat each configured path as a decoded segment prefix: the prefix, route-equivalent trailing or repeated slashes, and every child path bypass host body parsing before authentication. This includes ordinary routes below the configured prefix, so unrelated routes must not overlap it. Malformed, oversized, multipart, and otherwise unsupported child requests reach the authenticated MCP boundary without prior body parsing.
  • Add a validated Plug client_ip callback for authenticated and failed-authentication rate-limit buckets. The default remains conn.remote_ip verbatim, including non-IP local-peer terms; explicit callback failures fail closed and emit neutral client_ip/exception telemetry.
  • Require session_clustered: true servers to configure the same explicit, shared cursor_secret on every node; an omitted or shorter-than-16-byte secret now refuses startup instead of generating incompatible per-process cursor keys. Load-balanced multi-node deployments serving stateless 2026-07-28 requests must also configure the same explicit secret, even when session_clustered is false, if cursors may cross nodes. Pagination cursors now bind to deterministic visible catalog content rather than node-local mutation history, so peers on the same OTP major with the same final catalog, secret, and pagination context can continue them across nodes even when their registration histories differ. A mixed-OTP-major rolling upgrade may invalidate in-flight cursors, so clients should restart pagination when that boundary is crossed.
  • Emit periodic session-cleanup start/stop telemetry with a bounded reaped count and neutral outcome. Custom session-store cleanup responses must be valid batches of at most 1,000 keys; oversized or malformed responses are rejected as unavailable rather than truncated. Cleanup duration covers the store cleanup call and its bounded return normalization, failure reporting, and namespace filtering, but excludes start telemetry, local stream closing, and clustered close broadcast.

1.1.0 - 2026-09-01

  • Add AttestoMCP.Server.Result.tool_from_context/2,3 so tool handlers and shared adapters inherit the supervised server's JSON budget and output canonicalization settings without repeating or overriding those options. The standalone result constructors and their secure defaults remain unchanged.

1.0.0 - 2026-09-01

  • Establish the stable 1.0 host API while preserving the strict output and string-keyed argument defaults from 0.14.
  • Add a bounded principal_binding callback so handlers can receive complete loaded principals while session ownership, subscription isolation, cursors, and accounting use a small stable identifier. Add a separate post-auth, pre-body Plug authorize gate for mount-wide policy with neutral 403 denials.
  • Let AttestoMCP.Server.Phoenix.protected_resource_options/2 compose a post-load principal callback without replacing AttestoPhoenix JTI revocation checks or principal loading.
  • Add explicit :json and :jason tool-output canonicalization modes for protocol-encoded structs and atom values, retaining bounded input, encoded, decoded, and final wire validation. Trusted exception reporters receive a value-free JSON Pointer diagnostic when canonicalization fails.
  • Add opt-in schema-limited atom keys for tool arguments. Conversion happens only after input validation, uses existing atoms, and never creates atoms from schemas or client data.
  • Add AttestoMCP.Server.Test.call_tool/4 for focused host tests that exercise scopes, definition policy, schemas, handler execution, and complete wire results through normal dispatch.
  • Support up to 32 exact MCP paths in PhoenixParser and document a complete multi-server Phoenix deployment with distinct durable-session namespaces.
  • Add bounded, cursor-based active legacy session ID pages for operator tooling. Bundled ETS and Ecto stores expose IDs without loading records or principal bindings; Ecto uses deterministic bytewise ordering.
  • Add a public migration guide for moving documented anubis_mcp component, response, context, scope, and schema APIs onto AttestoMCP registrations.

0.14.0 - 2026-09-01

  • Add an optional PostgreSQL-backed Ecto session store for the session-bound 2025-11-25 and 2025-06-18 revisions. Composite, collision-resistant server namespaces, row-locked updates, indexed expiry, and bounded cleanup let sessions survive application restarts and remain safe across nodes sharing one database.
  • Make the Phoenix installer select durable session storage automatically when it finds exactly one statically confirmed, supervised PostgreSQL host Repo. It preserves existing custom choices, leaves Repo-free hosts on ETS, and falls back to ETS with an actionable notice when a sole Repo cannot be proven supervised or its adapter cannot be proven. It also resolves literal aliases in application and config source, refuses unsupported explicit or ambiguous Repo choices, and supports explicit --session-store, --repo, and --schema-prefix choices.
  • Add mix attesto_mcp_server.gen.migration for the fixed attesto_mcp_sessions table. Generation is explicit and duplicate-safe; neither the installer nor the generator runs a database migration. Default paths follow the selected Repo's child application in umbrella projects.
  • Keep Ecto optional so non-Ecto and stdio consumers retain the existing dependency footprint and in-memory default.
  • Emit a neutral [:attesto_mcp_server, :session_store, :failure] event for each failed session-store call, keep adapter error details private, and preserve one :session_store_unavailable result through server, HTTP, and stdio boundaries.
  • Bound Ecto query, transaction, and PostgreSQL row-lock waits below the server call budget. Record-bearing listings use small batches, counts use a SQL aggregate, and cleanup loads only bounded keys. Direct loads and record-bearing listings discard detected corrupt rows under lock with bounded telemetry so one unusable row cannot wedge later work.
  • Keep session activity timestamps monotonic under concurrent refreshes and constrain session timeouts to 1..9_000_000_000_000_000_000 milliseconds. Malformed external session identifiers behave like absent sessions. Invalid stored record versions are discarded atomically, while rolling upgrades preserve higher integer record versions and bindings that a node cannot decode without creating atoms. Conditional corruption cleanup rechecks the current record under the adapter lock before deletion.
  • Reject Ecto adapter operations that require their own row-locking transaction when called inside a caller-owned Repo transaction, before changing transaction-local timeouts, returning an explicit unsupported nesting error without poisoning the host transaction.
  • In clustered mode, propagate explicit session deletion and periodic expired-row cleanup to peer processes with versioned, namespace-bound, size-limited control messages so every node closes its local streams without rebroadcast loops.
  • Make session-store outages detected before response streaming return HTTP 503 consistently across JSON-RPC POST, session-bound notification, GET, and DELETE paths. Configured HTTP method-scope checks and core method authorization precede outage disclosure. Stdio.main/1 now stops the server it owns on exit and raises when its initial durable session cannot be stored.
  • Make HexDocs open on the installer-first README so the Phoenix SaaS path is the package's default documentation entry point.

0.13.0 - 2026-08-31

  • Require attesto_mcp >= 1.3.0 and < 2.0.0, adding compatibility with the Attesto 2.x authorization contracts.
  • Accept direct public-Hex attesto_phoenix requirements from the supported 2.14.1 floor through the 3.x line, retaining fail-closed intersection and dependency-source validation.
  • Refresh path-based Mix.install/2 examples so an existing install cache cannot retain dependency versions from an earlier server release.

0.12.2 - 2026-08-30

  • Reject 2026-07-28 request metadata paired with missing, duplicate, or mismatched HTTP mirror headers before session-bound routing, preserving one neutral body_header_mismatch response across methods and stale session IDs.
  • Add a runnable Livebook walkthrough for an authenticated local server, including discovery, initialization, tool listing, and a tool call.
  • Add regression coverage proving late-bound named-server transport limits use the active server JSON budget, including absent-server startup and server restarts above the secure 2 MB default.
  • Make the real Bandit disconnect and stdio interleaving regressions independent of peer-request and EOF-drain timing on loaded test hosts.
  • Document the complete modern mirror-header contract and streamline the README around the batteries-included Phoenix path, client onboarding, and a concrete non-Phoenix dependency setup.

0.12.1 - 2026-08-30

  • Support bounded resource URI templates containing up to 16 separated simple or reserved path expressions and 32 globally unique variables. Reverse matching remains deterministic, rejects adjacent ambiguous expressions, encoded separators for simple variables, traversal, and oversized captures, and is shared by direct, batch, startup, and replacement registration paths.
  • Bound URI-template work across the complete candidate scan for one resource lookup. Budget exhaustion is distinct from a non-match, fails closed for selected resource dispatch and notification scopes, and a local resource notification reuses one scope resolution for modern and legacy delivery.
  • Limit the complete primitive catalog to 1,000 definitions across all types. Atomic batches and replacements, repeated additions, startup, and registry recovery enforce the same total without mutating the catalog or revision on rejection.
  • Add the server-wide max_json_bytes budget. The secure default remains 2,000,000 bytes; hosts may explicitly raise it to a finite maximum of 64,000,000 bytes. The selected budget now governs JSON Schema instances, handler-result normalization, final result validation, JSON-RPC encoding, Streamable HTTP, and stdio. Transport limits may not exceed their supervised server's budget. Registered definition and schema data use that same budget during startup, dynamic registration, catalog replacement, and restoration.
  • Cap omitted HTTP transport limits by the selected JSON budget, including budgets below the 2,000,000-byte nominal body default. Explicit limits above the selected budget still fail during initialization.
  • Make invalid low-level JSON-RPC max_bytes options fail closed for decoding and ID recovery instead of relying on Erlang term ordering.
  • Document the stdio adapter's 512-byte minimum frame limit alongside its server-budget ceiling.
  • Clarify that Schema.max_instance_bytes/0 denotes the secure default rather than the configurable ceiling, and that nil and true schemas remain subject to the active JSON budget.
  • Allow the public content and result constructors to opt into the same larger finite budget with max_json_bytes, while retaining the 2,000,000-byte default and all structural and canonical-Base64 checks.

0.12.0 - 2026-08-29

  • Add bounded alternative_scope_sets to primitive definitions. The primary required_scopes clause and each alternative remain all-of requirements, while any complete clause can authorize the definition consistently across catalogs, selected lookups, resource templates, subscriptions, and both protocol eras.
  • Add typed, strict AttestoMCP.Server.Content constructors and complete tool and resource constructors in AttestoMCP.Server.Result. They emit canonical string-key maps and enforce the same content, URI, JSON, and padded-Base64 rules as handler-output validation; handwritten maps remain supported.
  • Revalidate every finalized success result after adding protocol, cache, and server-identity fields. Oversized completion values and aggregate catalog or handler results now fail closed with bounded protocol errors in both eras.
  • Align handler-output validation with the MCP content contracts. Embedded resources now require one text or blob resource-content entry rather than a nested contents array. Present optional string, map, list, and size members must now have their declared types, so explicit null text/blob siblings, null MIME/description/metadata members, malformed link titles, negative link sizes, and invalid link/resource icons or annotations are rejected. Use the public content constructors when migrating affected handlers.
  • Document that JSON Schema defaults are annotations, and add the bounded, explicitly invoked AttestoMCP.Server.Schema.apply_property_defaults/2 helper for direct property defaults without changing dispatch behavior.
  • Add atomic replace_catalog/2 for bounded generated catalogs. Failed and no-op replacements leave the catalog revision unchanged; successful changes emit one list-changed notification for each affected advertised catalog category. Resources and templates share one category; completion-only changes emit none.
  • Make the 2,000,000-byte schema-instance ceiling explicit across server, Streamable HTTP, and stdio configuration. Oversized max_body_bytes or max_message_bytes settings now fail during initialization, while the message limit continues to govern JSON-RPC decoding.
  • Validate scope_map through one shared bounded policy: only supported MCP request methods are accepted, and scope lists must be unique, valid, length-bounded, and aggregate-byte-bounded in both server and Plug options.
  • Allow resolver-backed :auth to supply a strictly validated canonical resource or base origin after runtime configuration loads. The resolved URL must agree with the mounted path and any static pin, and the same identifier drives RFC 9728 metadata and audience verification.
  • Require static and resolved :base_url/:origin values to be bare HTTP origins without application paths. A static path-bearing value now fails during Plug initialization, and a resolver-returned value fails closed when the resolver is evaluated, instead of producing protected-resource metadata that disagrees with the served route.
  • Add a migration runbook for registrations, handler contracts, schema behavior, authorization ordering, Phoenix wiring, session continuity, and safe result construction.
  • Bind clustered resource-notification delivery to a versioned, bounded publisher scope snapshot and the recipient's current definition scopes. Legacy cluster resource envelopes without publisher scopes fail closed, so catalog drift during deployment cannot weaken modern or legacy delivery authorization. Per-publish authorization callbacks now suppress both modern and legacy delivery consistently.
  • Clarify the distinct modern and legacy subscription scope rules, including additive subscriptions/listen and per-notification requirements.
  • Add explicit 2025-06-18 HTTP, stdio, initialization, and revision-filtering regressions, and make live stdio tests wait for owned child processes before removing isolated build directories.

0.11.1 - 2026-08-29

  • Document the existing per-definition authorize contract, including callback forms, host context, evaluation order, neutral denial behavior, and the subscription boundary; test function and MFA callbacks on both allow and deny paths.
  • Refuse non-isolated or uninspectable Phoenix endpoint sources before editing, distinguish those failures from safe installer warnings, and make metadata route reuse diagnostics specific without relaxing preflight.
  • Clarify host-owned custom-scope configuration and pin parser bypass behavior for route-equivalent repeated trailing slashes.

0.11.0 - 2026-08-28

  • Add per-mount RFC 9728 scopes_supported configuration. Custom-scope deployments no longer have to advertise the package's generic scopes and cause clients to request grants the authorization server does not issue.
  • Add isolated host context builders, bounded server-wide telemetry dimensions, exact primitive identity on handler spans, host exception reporting, and a handler-task initialization callback with function and MFA forms.
  • Add explicit bounded client-safe handler failures with AttestoMCP.Server.Result.error/2; arbitrary failure terms and exceptions remain private.
  • Add host-wide default_scopes with explicit method-map precedence and additive subscription delivery scopes.
  • Add atomic bounded register_all/2, startup :registrations, coalesced catalog invalidations, exact registry recovery, and stable named child specs.
  • Add a durable legacy-session adapter contract, versioned bounded records, fail-closed store monitoring, and an in-memory default adapter with bounded fair cleanup, including immediate cleanup bookkeeping removal on explicit deletion. Optional clustered session mode uses one explicit shared store and namespace and fans notifications out to live peers; process-backed streams reconnect after failover, and transient store reads do not mislabel live streams as expired.
  • Add opt-in HTTP definition-scope policies for filtered tools/resource catalogs and selected tool/resource calls. Selected definitions are bound before MRTR retry-state consumption and authorized through the prepared Attesto boundary; hidden and denied definitions remain neutral, while the existing generic scope defaults and subscription generic-plus-definition reauthorization remain unchanged.
  • Make AttestoPhoenix Client ID Metadata Documents an explicit installer opt-in; existing cache, repository, prefix, allowlist, and disabled settings remain authoritative, and Req is required only for that opt-in.
  • Reuse only one statically proven published attesto_routes(protected_resource_paths: [path]) metadata route for the selected MCP path, preserving it byte-for-byte and adding only MCP wiring.
  • Preflight Phoenix endpoint parser provenance and add a literal static-route bypass, including route-equivalent trailing slashes, only for a direct standard Plug.Parsers declaration; custom or ambiguous body readers receive an actionable refusal.
  • Require header-only bearer presentation for both static and resolved auth, require successful tools with outputSchema to return conforming structured content even under permissive schemas, reject ungrantable definition scopes, redact private server options from crash status, and ignore unrelated calls, casts, and mailbox messages without terminating the server.

0.10.6 - 2026-08-28

  • Apply the automatic AttestoPhoenix access-token JTI revocation check and principal loader when authenticating each MCP request or stream, before request-body reads, returning a neutral invalid-token response when either rejects.
  • Treat configured and canonical authentication assigns as boundary-owned: clear them before verification, repopulate them only from verified results, and reject non-atom, nil, boolean, duplicate, or cross-owned assign-key configurations at Plug initialization. Verifier exceptions also retain the cleared boundary.
  • Emit a payload-free [:attesto_mcp_server, :auth, :policy_failure] telemetry event when the automatic Phoenix revocation check returns an invalid result or its revocation/principal callback or the HTTP verifier raises, throws, or exits.
  • Fix modern and legacy DPoP- and mTLS-bound subscription delivery with loaded opaque principals, including static auth configurations that use custom assign keys. Delivery re-verifies the captured token and sender binding without running host policy callbacks in shared publish processes; later revocation or principal-policy changes take effect on the next request or stream reconnect.
  • Require the oldest published compatible AttestoPhoenix release, 2.14.1, when the installer reuses its protected-resource policy.

0.10.5 - 2026-08-28

  • Carry the host's current AttestoPhoenix protected-resource adapter options into generated MCP routes, including DPoP replay/nonce, canonical-request, and mTLS certificate callbacks, instead of retaining only the core verifier.
  • Resolve automatic AttestoPhoenix authentication at request time while keeping the canonical resource and public origin statically pinned. Resolver failures fail closed; on protected MCP requests, unavailable servers, oversized headers, and unsupported methods are rejected before runtime configuration is requested.
  • Add a constrained runtime auth resolver contract for external zero-arity callbacks and portable-literal MFA values. Generated routes remain safe for Phoenix compile-time Plug initialization and cannot replace package-owned assigns or advertise unsupported bearer-token locations.
  • Migrate only exact legacy installer-owned AttestoPhoenix forwards, including interrupted mixed old/new installations, while preserving application tool registrations, refusing near matches, and leaving nested quoted examples untouched.

0.10.4 - 2026-08-28

  • Preserve Attesto's scheme-correct OAuth challenges and error details for invalid DPoP proofs, sender-bound tokens presented as Bearer, nonce requests, and insufficient scopes instead of replacing them with a generic Bearer response.
  • Keep anonymous discovery challenges error-free, pin challenge metadata to the configured canonical resource origin, and cover header and host-owned credential paths with DPoP regressions.

0.10.3 - 2026-08-28

  • Configure detected attesto_phoenix hosts for URL client metadata and native loopback clients by enabling Client ID Metadata Documents and ephemeral localhost callback ports without replacing existing host choices.
  • Add the compatible Req dependency required by the default secure CIMD fetcher only on the attesto_phoenix installer path; explicit Attesto callback installations remain dependency-neutral.
  • Harden dependency preflight to inspect only literal catalogs, intersect stable Hex requirements with the supported attesto_phoenix and Req ranges, and stop without edits on dynamic, duplicate, incompatible, restricted, custom-source, or otherwise unsafe declarations.
  • Harden route and ownership recognition across forward arities 2–4, qualified and effective scoped calls, source-ordered/chained/grouped aliases, dynamic plug refusal, Phoenix-router identity, exact generated callbacks, fully qualified generated routes, and rooted generated module references.
  • Fail closed on executable managed-module attributes, compile hooks, custom macro enablement, enclosing-file compiler directives, unsafe nested modules, and non-canonical endpoint paths; installer and runtime paths now use only slash-separated ASCII URI-unreserved segments.
  • Preserve compatibility with the exact zero-option AttestoPhoenix.Router integration emitted after a trusted primary Phoenix router use while keeping every other secondary router macro source opaque and requiring router modules to own their source file for lexical provenance.
  • Normalize atom cache-scope options, expose pagination and cache controls through the stable facade type, and keep stdio-only controls out of owned server startup.
  • Exercise the combined installers in both the reusable fixture and an actual Phoenix 1.8.13 mix phx.new application, including config construction, generated routes, warnings-as-errors compilation, starter tests, authorization-installer reruns, and a zero-diff second MCP installation.
  • Harden subscription ownership and cleanup, contain non-exception Plug failures, serialize first-use cursor secrets, and exercise prompt retrieval through both dated HTTP fixture paths.
  • Enforce prompt and resource completion scopes at the authenticated HTTP boundary, including one explicit method override for both reference types.
  • Preserve evaluated array-item annotations when JSON Schema references are reached through applicators, avoiding false rejection by unevaluatedItems.
  • Reject non-object request _meta values as correlated protocol errors while keeping both stdio and HTTP transports available for later requests.
  • Bound each legacy session and each modern resource filter to 128 unique resource URIs at 4,096 bytes per URI, detach retained URI slices from request bodies, and canonicalize duplicates without extra entries.
  • Route every supported resource-update alias through the same legacy URI filter and avoid extending idle lifetime for rejected subscription changes.
  • Reject malformed public notification fields before modern or legacy fanout, and suppress malformed direct subscription events without terminating the registry or preventing a later valid delivery.
  • Detach accepted binary JSON-RPC and modern subscription IDs from larger decoded request buffers before retaining them.
  • Refuse installer edits when existing static, parameterized, glob, resource, or forwarded routes overlap either generated mount; reject required macro calls whose router effects cannot be proven and accept callback punctuation only as a terminal Elixir identifier suffix.
  • Bind pagination cursors to their catalog method and skip explicit owner-local subscription IDs when allocating server-generated identifiers.
  • Add direct regressions for HTTP Origin enforcement and header budgets, plus a live stdio pipe recovery check spanning malformed, oversized, and valid consecutive frames.

0.10.2 - 2026-08-27

  • Document the distinct tool, prompt, resource, and completion callback inputs, including prompt and resource envelopes, their declared atom-keyed fields, and resource MRTR retry entries.
  • Add copyable prompt callback guidance after a live-client interoperability exercise exposed the ambiguity in the earlier generic callback wording.
  • Derive the default advertised server version from package application metadata so patch releases cannot retain a stale hard-coded version.

0.10.1 - 2026-08-27

  • Accept JSON request bodies already decoded by a Phoenix or Plug parser while retaining message-size, nesting, JSON-RPC validation, and recoverable-ID checks.
  • Add Phoenix-style parser-pipeline and pass-through parser regressions using a current legacy-initialize client request.

0.10.0 - 2026-08-27

  • Add an optional, idempotent Igniter installer for Phoenix hosts.
  • Scaffold a supervised MCP module, protected /mcp and RFC 9728 metadata routes, runtime configuration, and starter tests without inventing secrets or application authorization policy.
  • Detect attesto_phoenix hosts and reuse their validated Attesto configuration while keeping authorization-server concerns out of this package.
  • Use a generated application-owned metadata wrapper so Phoenix 1.7 can mount metadata and protocol routes as distinct forwarded plug modules.
  • Refuse unsafe origins, ambiguous router/module collisions, and partial edits; compare existing routes across nested scopes and aliases, refuse dynamic forwards and Phoenix 1.7 plug reuse, and preserve a zero-diff second run across the supported Igniter range.

0.9.0 - 2026-08-26

  • Accept and exactly echo MCP 2025-06-18 during legacy initialization while retaining 2025-11-25 and preferred 2026-07-28 behavior.
  • Preserve the negotiated legacy revision in HTTP session state and enforce it on later protocol-version headers.
  • Add stdio initialize/list/call coverage and authenticated HTTP lifecycle regression coverage for 2025-06-18.
  • Isolate the live stdio regression's installation cache so stale build state cannot contaminate protocol stdout startup.
  • Use the negotiated session revision when a legacy HTTP client omits the protocol-version header, while rejecting invalid or changed header values.
  • Gate catalog/content icons, explicit elicitation modes, and sampling tool selection to revisions that define those fields.
  • Reject an initialize protocol-version header when its revision was disabled by the host's protocol_versions configuration.
  • Expose the exact negotiated legacy revision as context.protocol_version to request handlers.

0.8.0

Initial Apache-2.0 release of the Attesto-native dual-era MCP server.

  • Require released attesto_mcp ~> 1.2 and use its public prepared resource protection contract without sibling-path or older-auth fallbacks.
  • Preserve unknown JSON-RPC extensions and add precise recursive message types.
  • Isolate same-session legacy streams, prefer the newest live stream for server-originated client requests, wait briefly for an owned stream during connection startup, and make stale teardown ownership-safe.
  • Make cancellation, detached-owner cleanup, nil-ID work, correlation, and request terminal telemetry exact-once under races.
  • Add frozen official conformance evidence and exact TypeScript 2.0.0 and Python 2.1.1 client smoke gates for both supported eras.