2.8.0 - 2026-10-19
- Wrap every HTTP authentication in the
auth/authenticatetelemetry span. Itsstopevent carries the elapsedduration, a boundedoutcome(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 HTTPstatus, and the authenticatedbinding. 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/refusalandauth/policy_failureare unchanged.
2.7.2 - 2026-10-18
- Fail the generated principal admission index migration before any DDL when
attesto_mcp_sessionsdoes 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
--helpinmix attesto_mcp_server.gen.migration; it prints the usage and the accepted options instead of failing with "invalid options". - Add
--skip-url-elicitationsto 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-formattedunchanged. - 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_sessionsdoes 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 refundableauth_checksbucket 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_principalandmax_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 rerunmix attesto_mcp_server.gen.migrationand apply the generated concurrent principal-admission index migration. - Apply configured
default_scopestocompletion/completebefore 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/supportso 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
:resourceendpoint-path option to MCP 2.1's unambiguous:resource_pathboundary without forwarding both keys. - Preserve the explicitly local
allow_dynamic_originmode by translating it to MCP 2.1's pinned callback contract, and have the installer emitallow_http: trueonly 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_scopestwice. The local stdio adapter continues to require no fallback scopes unlessscope_mapordefault_scopesis 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-headersuffix and its generatedMcp-Param-*wire header. - Expand the supported
attesto_mcprange 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
:principalcallback 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:, andvbscript: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_entriesandurl_elicitation_max_bytesfor configuring those limits. Admission reclaims enough expired records to avoid a false capacity failure and never evicts a live approval.UrlElicitationStore.ETS.put/2now 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_jsonas 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_idlike 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
_metaobject to handlers and per-request callbacks ascontext.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 abovemax_request_meta_bytes(65,536 bytes by default) is rejected, not truncated.AttestoMCP.Server.RequestMetadocuments the contract. - Bind multi-round retry state to operation parameters and request metadata,
except
traceparent,tracestate,baggage,progressToken, andio.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_providerfor caller-specific guidance in modern discovery and session-bound initialization, andtool_presentationfor caller-specific titles, descriptions, icons, and application_metaon 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_policyfor 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_iconsto the server implementation identity in discovery, modern result metadata, and2025-11-25initialization, 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_dialectto declare the default JSON Schema 2020-12 dialect on exported tool schema roots without changing validation. - Extend
AttestoMCP.Server.Testwith 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: falseselecting 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
-32029to-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_audiencespolicy 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-28protocol revision (AttestoMCP.Server.UrlElicitationandAttestoMCP.Server.APIhelpers:stage_url_elicitation/5,resolve_url_elicitation/3,consume_url_elicitation/3). - Add
AttestoMCP.Server.UrlElicitationStorebehaviour 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.migrationwrite 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_appargument onattesto_phoenix3.x, keeping multiple named profiles isolated. The helper does not select a profile fromconn.private. Theattesto_phoenix2.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
PhoenixParsertreat 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_ipcallback for authenticated and failed-authentication rate-limit buckets. The default remainsconn.remote_ipverbatim, including non-IP local-peer terms; explicit callback failures fail closed and emit neutralclient_ip/exceptiontelemetry. - Require
session_clustered: trueservers to configure the same explicit, sharedcursor_secreton 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 stateless2026-07-28requests must also configure the same explicit secret, even whensession_clusteredis 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,3so 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_bindingcallback 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 Plugauthorizegate for mount-wide policy with neutral 403 denials. - Let
AttestoMCP.Server.Phoenix.protected_resource_options/2compose a post-load principal callback without replacing AttestoPhoenix JTI revocation checks or principal loading. - Add explicit
:jsonand:jasontool-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/4for 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
PhoenixParserand 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_mcpcomponent, 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-25and2025-06-18revisions. 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-prefixchoices. - Add
mix attesto_mcp_server.gen.migrationfor the fixedattesto_mcp_sessionstable. 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_unavailableresult 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_000milliseconds. 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/1now 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_phoenixrequirements 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/2examples so an existing install cache cannot retain dependency versions from an earlier server release.
0.12.2 - 2026-08-30
- Reject
2026-07-28request metadata paired with missing, duplicate, or mismatched HTTP mirror headers before session-bound routing, preserving one neutralbody_header_mismatchresponse 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_bytesbudget. 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_bytesoptions 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/0denotes the secure default rather than the configurable ceiling, and thatnilandtrueschemas 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_setsto primitive definitions. The primaryrequired_scopesclause 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.Contentconstructors and complete tool and resource constructors inAttestoMCP.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
contentsarray. 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/2helper for direct property defaults without changing dispatch behavior. - Add atomic
replace_catalog/2for 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_bytesormax_message_bytessettings now fail during initialization, while the message limit continues to govern JSON-RPC decoding. - Validate
scope_mapthrough 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
:authto 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/:originvalues 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/listenand per-notification requirements. - Add explicit
2025-06-18HTTP, 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
authorizecontract, 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_supportedconfiguration. 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_scopeswith 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.Parsersdeclaration; custom or ambiguous body readers receive an actionable refusal. - Require header-only bearer presentation for both static and resolved auth,
require successful tools with
outputSchemato 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_phoenixhosts for URL client metadata and native loopback clients by enabling Client ID Metadata Documents and ephemerallocalhostcallback ports without replacing existing host choices. - Add the compatible Req dependency required by the default secure CIMD
fetcher only on the
attesto_phoenixinstaller path; explicit Attesto callback installations remain dependency-neutral. - Harden dependency preflight to inspect only literal catalogs, intersect
stable Hex requirements with the supported
attesto_phoenixand 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.Routerintegration 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.newapplication, 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
_metavalues 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
/mcpand RFC 9728 metadata routes, runtime configuration, and starter tests without inventing secrets or application authorization policy. - Detect
attesto_phoenixhosts 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-18during legacy initialization while retaining2025-11-25and preferred2026-07-28behavior. - 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_versionsconfiguration. - Expose the exact negotiated legacy revision as
context.protocol_versionto request handlers.
0.8.0
Initial Apache-2.0 release of the Attesto-native dual-era MCP server.
- Require released
attesto_mcp ~> 1.2and 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.