Packages
Production-grade Model Context Protocol (MCP) SDK for Elixir and Phoenix. Complete server and client support for MCP 2026-07-28 and 2025-11-25, with OAuth authentication, MCP Apps, Tasks, Streamable HTTP, stdio, strict validation, observability, and a FastMCP-inspired DSL.
Current section
Files
Jump to
Current section
Files
fastest_mcp
CHANGELOG.md
CHANGELOG.md
# Changelog
## 0.2.0 - 2026-08-12
This is a breaking protocol and lifecycle release. Applications upgrading from
0.1.x should review the migration notes below before deploying.
### MCP protocol and transport
- make MCP `2025-11-25` the sole negotiated protocol version; server metadata
can add experimental capabilities but can no longer override the protocol
version or standard capability shape
- accept MCP traffic only at the configured endpoint, `/mcp` by default, and
remove the `/health`, trailing-slash redirect, and method-specific HTTP routes
such as `/mcp/tools`, `/mcp/resources/read`, and `/mcp/tasks/*`; applications
can provide their own health or non-MCP routes in the surrounding Plug router
- require JSON-RPC 2.0 envelopes and exactly one request, notification, or
response per HTTP POST or stdio message; JSON-RPC batch arrays are no longer
accepted
- require streamable HTTP POST requests to use `Content-Type:
application/json` and advertise both `application/json` and
`text/event-stream` in `Accept`
- return `202 Accepted` with no response body for JSON-RPC notifications
- pin the official server conformance runner to
`@modelcontextprotocol/conformance@0.1.16` as a release gate without
expected-failure allowances
### Sessions and request lifecycle
- make stateful streamable HTTP sessions server-issued: `initialize` must not
send `MCP-Session-Id`; the successful response supplies it, and subsequent
requests must echo it
- enforce `initialize` followed by `notifications/initialized` before other
requests, both for stateful HTTP sessions and each stdio connection
- require `MCP-Protocol-Version: 2025-11-25` on stateful HTTP requests after
initialization, and reject unknown or terminated sessions
- remove zero-session HTTP and reject the former `stateless_http:` and
`stateless:` options; use `state_scope: :request` for request-local handler
state while retaining a normal server-issued MCP session
- add explicit context `state_scope`, negotiated protocol, client capability,
and client information fields; request-scoped HTTP contexts keep their stable
non-null session id
- remove the client's initial `session_id:` option and add `sampling_tools:`,
`sampling_context:`, and a 1 MiB default `max_sse_event_bytes:` limit
### Task compatibility
- restrict standard remote task augmentation to `tools/call`; remote
`prompts/get` and `resources/read` task extensions have been removed
- remove the non-standard wire method `tasks/sendInput` and the corresponding
<code>FastestMCP.Client.send_task_input/5</code> API
- retain local in-process prompt/resource task creation and
`FastestMCP.send_task_input/5` for Elixir-owned workflows
- normalize custom `FastestMCP.TaskBackend` callbacks: `fetch_task/3` returns
`{:ok, task}` or `{:error, reason}`, and `expire_tasks/2` returns
`{:ok, task_ids}` or `{:error, reason}`
- reconcile persisted active tasks in bounded pages when a runtime restarts and
fail orphaned work with `:runtime_restarted`
### HTTP safety and public interfaces
- default HTTP listeners to loopback and `allowed_hosts: :localhost`
- forward listener configuration through `bandit_options:` and add a supervised
streamed-request timeout through `stream_request_timeout_ms:` (60 seconds by
default)
- remove `allowed_hosts: :any` and `unsafe_allow_any_host`; use a non-empty
concrete host list for every non-loopback listener
- expose `FastestMCP.Auth.Result`, `FastestMCP.Auth.StaticToken`,
`FastestMCP.TaskBackend`, and `FastestMCP.TaskBackend.Memory` in HexDocs
- source the ExDoc module filter and module groups from one shared public-module
catalog so published docs cannot drift from the navigation groups
- authenticate every inbound HTTP message and control request, bind initialized
sessions to the authenticated identity, and apply Host/Origin validation at
the shared public Streamable HTTP entrypoint
- reject malformed, opaque, combined, and repeated Origin headers before
authentication; accepted origins are serialized HTTP(S) origins whose host
is present in `allowed_hosts`
- add optional RFC 9728 Protected Resource Metadata on the MCP resource origin,
authoritative `resource_metadata`/`scope` bearer challenges, query-token
rejection, and expected-resource/scope input for application authenticators
- add provider candidate callbacks for deterministic all-version resolution,
including lower-version fallback after visibility or policy filtering
- centralize duplicate component policy and preserve `:warn` as
warn-and-replace across server, local-provider, and component-manager
registration
- correct middleware examples to use `max_requests_per_second:`,
`max_requests:`/`window_minutes:`, and `max_size:`
### Schema, sampling, providers, and middleware
- add JSV `0.22.x` as the sole new runtime dependency and make
`FastestMCP.Schema` the compile-once validation boundary for Draft 2020-12
and Draft 7; validation is non-coercing, bounded, and redacted
- vendor the immutable MCP `2025-11-25` schema from source commit
`38c84e9f93ad191d9eb26d92b945d17bd0efcaf3` with a checked SHA-256, and cover
the FastestMCP schema boundary with focused dialect, resolver, and limit tests
- keep those vendored bytes unchanged while applying a versioned compiled-view
erratum for `NumberSchema.minimum`, `maximum`, and `default`: authoritative
`schema.ts` and the elicitation specification define numbers, while the
tagged generated JSON artifact emitted integers
- fail remote JSON Schema references closed by default; applications may opt in
to an explicit resolver or the allowlisted HTTPS resolver with verified TLS,
redirect refusal, and timeout/body limits
- canonicalize wire serialization around `_meta`, direct `resource_link`
fields, object-only structured tool content, and resource templates listed
exclusively by `resources/templates/list`; FastestMCP-only task elicitation
state now lives under `_meta.fastestmcp`
- make component authorization fail closed: only `true` and `:ok` authorize;
malformed returns, exceptions, throws, and exits deny access, while
unversioned resolution may fall back from an unauthorized higher version to
an authorized lower version
- complete sampling tool loops with `tools`, the three `toolChoice` modes,
merged result/use metadata, explicit malformed-use errors, and an eight-round
ceiling; advertise `sampling.tools` only when executable tools are configured
- bound both rate limiters with `max_clients: 10_000` by default and return
`:overloaded` when live client cardinality remains full; response limiting now
rejects limits below the smallest valid serialized tool-result envelope
- whitelist OpenAPI parameter locations without atom creation, apply override
and style/explode rules, encode paths correctly, send scalar and array JSON
bodies directly, and decode only JSON or `+json` responses
- reject fragment-bearing resource templates, external or cyclic filesystem
symlinks, and skill files outside canonical roots; reloadable skill providers
now reuse a runtime-owned metadata cache and hash only changed files
- deduplicate injected tools by component identity and use indexed exact
Registry and atomic exact-or-template component lookups
### Bidirectional sessions and optional MCP facilities
- extend the session coordinator to own lifecycle, both request-id namespaces,
active work, callback requests, output sinks, queued messages, progress
tokens, logging thresholds, roots, peer tasks, URL elicitation, and SSE replay
- run inbound HTTP and stdio work under the runtime `Task.Supervisor`; support
bidirectional cancellation and keep detached non-cancelled work supervised
after an HTTP client disconnects
- make stdio concurrently read client responses and notifications while one
serialized writer owns stdout; all diagnostics remain on stderr
- add `FastestMCP.Root`, `Context.list_roots/2`, cached roots, canonical
`file://` validation, and roots-list-change refresh
- add standard form and URL elicitation, identity-bound completion through
`FastestMCP.complete_elicitation/3`, `-32042` descriptors, HTTPS host
allowlists through `url_elicitation_allowed_hosts:`, and completion
notifications to the originating session only
- normalize the specification's backwards-compatible client capability
`elicitation: {}` to effective `elicitation.form` support; URL mode still
requires explicit `elicitation.url`
- add `FastestMCP.PeerTask` for task-augmented sampling and elicitation, with
fetch, wait, result, cancel, and status-change helpers scoped to the exact
originating server session, plus `Context.list_peer_tasks/2` for negotiated
requester task listing
- add outbound ping, full sampling result validation and tool rounds, incoming
progress callbacks, RFC 5424 logging thresholds, and bounded event rates
- add bounded logical SSE streams and same-stream `Last-Event-ID` replay; replay
state is session-local and cleared on termination or runtime restart
### New default limits
- retain a 60-second request timeout and bound each session to 100,000 used
request ids per direction, 128 pending callbacks, 128 active requests, 128
peer tasks, 128 peer-task status callbacks, 1,024 queued peer messages, and
16 MiB of queued message data
- bound each runtime to 10,000 pending callbacks, 10,000 active requests, and
64 MiB of SSE replay data
- retain at most 256 replay events and 4 MiB per logical stream for five
minutes; URL elicitation records expire after 15 minutes
- rate-limit outbound progress to 20 updates per second per token and inbound
progress/logs to 100 updates per second per session
- cap JSON Schema sources at 1 MiB and nesting at 128 levels/256 references,
with five-second compilation and one-second validation deadlines; cap opaque
cursors at 4 KiB
### 0.1.x migration checklist
- remove `stateless_http:`, `stateless:`, `strict_input_validation:`,
`dereference_schemas:`, initial client `session_id:`, `allowed_hosts: :any`,
legacy REST-shaped MCP routes, batch requests, and remote `tasks/sendInput`
- use `state_scope: :request` when handler state must reset, while preserving
the server-issued session id and initialize/initialized lifecycle
- send one JSON-RPC object per POST or stdio line; require object params and
results, use only string/integer ids, and do not reuse ids within a session
- change tool input/output schemas to object-root JSON Schema and return
schema-valid object `structuredContent`; values are no longer coerced
- move standard tool execution metadata to `execution.taskSupport`, keep only
FastestMCP extensions under `_meta.fastestmcp`, and use direct standard fields
on resource links and content blocks
- update sampling handlers to return complete `CreateMessageResult` objects
with `role`, `content`, and `model`; form elicitation accepted content must be
an object conforming to the requested schema
- continue list operations using the opaque `cursor` only; wire `pageSize` no
longer controls the server-owned page size
- update custom task backends to the fallible fetch/expiry contracts described
above and treat callback/progress/log delivery helpers as fallible operations
- configure concrete `allowed_hosts` for public mounts and, when RFC 9728
discovery is needed, an exact `protected_resource:` plus an application-owned
authenticator
## 0.1.2 - 2026-05-27
- refocus auth around application-owned authenticators, keeping the normalized
`FastestMCP.Auth` contract, `FastestMCP.Auth.Result`,
`FastestMCP.Auth.StaticToken`, and component authorization
- add function-based auth and `FastestMCP.Auth.from_assign/2` for Plug/Phoenix
integrations
- add HTTP `auth_assigns:` support so selected `conn.assigns` can feed auth
input without exposing assigns through handler request metadata
- remove bundled OAuth, JWT/JWKS, introspection, CIMD, and vendor auth provider
modules, and remove the `:assent` and `:jose` dependencies
- remove the `:jason` dependency and use Elixir's native `JSON` module
- keep default HTTP auth failures on plain bearer challenges and remove built-in
OAuth metadata/authorization/token route handling from core
- improve OpenAPI-backed tools with JSON media-type variants, form and
multipart request bodies, cookie parameters, server variable defaults, and
circular schema reference protection
- add multipart request support to `FastestMCP.HTTP.request/3`
- improve resource-template matching for hyphenated parameters, blank query
values, collision rejection, and path-capture precedence
- add server `experimental_capabilities:` metadata for initialize responses
- improve mounted runtime behavior with self-mount rejection, recursive mounted
lifespans, child-first cleanup, and stream shutdown before cleanup
- update tracing and error logging with MCP/GenAI span attributes, stable
resource span names, `error.type`, nil-attribute filtering, arity-2 loggers,
and per-error log levels
- document Phoenix-oriented auth, OpenAPI request serialization,
resource-template matching, mounted lifespans, experimental capabilities,
telemetry attributes, and error logging behavior
- add task wait behavior for input-required states, auth-scoped task ownership,
and elicitation response metadata
- improve handler result normalization for safe finite enumerable values
- add regression coverage for auth contracts, Phoenix assign auth, task
ownership, scalar elicitation, mounted wildcard resources, and tool/resource
return normalization
- document auth assign bridging, task wait behavior, elicitation response
metadata, and finite enumerable normalization
## 0.1.1 - 2026-04-17
- update broken project links in package metadata
- update the Hex package description to emphasize the BEAM-native MCP runtime,
client, auth, and transport surfaces