FastestMCP
FastestMCP is a BEAM-native MCP toolkit for Elixir.
It includes MCP tools, resources, prompts, middleware, auth, providers, background tasks, and streamable HTTP. FastestMCP is built as an OTP system with supervised runtime trees, explicit request, session, and task lifetimes, and module-first server startup that fits normal Elixir applications.
Installation
Add FastestMCP to your dependencies:
def deps do
[
{:fastest_mcp, "~> 0.2.0"}
]
end
Then fetch dependencies:
mix deps.get
Upgrading from 0.1.x
FastestMCP 0.2.0 has one protocol boundary: MCP 2025-11-25 over JSON-RPC
2.0. Streamable HTTP accepts one message per POST at /mcp; legacy
method-specific routes and JSON-RPC batches are gone. HTTP clients must use
the server-issued session id and complete the initialize lifecycle. Zero-session
HTTP and the stateless_http:/stateless: options are gone. Use
state_scope: :request when handler state must reset for each operation; the
MCP session, negotiated capabilities, subscriptions, and task ownership remain
available.
Remote task augmentation is standard tools/call only. Local Elixir prompt and
resource tasks remain available, as does local FastestMCP.send_task_input/5,
but the remote prompt/resource task extensions and wire tasks/sendInput method
were removed. Tool schemas are now strict JSON Schema values with object roots,
and values are never coerced. The old dereference_schemas: path is removed;
remote references require an explicit schema_options: resolver. See the
0.2.0 changelog and
transport migration notes for the full
checklist.
Quick Start
Start with a module-owned server:
defmodule MyApp.MCPServer do
use FastestMCP.ServerModule,
http: [port: 4100, allowed_hosts: :localhost]
alias FastestMCP.Context
def server(opts) do
base_server(opts)
|> FastestMCP.add_tool("sum", fn %{"a" => a, "b" => b}, _ctx -> a + b end)
|> FastestMCP.add_tool("visit", fn _arguments, ctx ->
visits = Context.get_state(ctx, :visits, 0) + 1
:ok = Context.set_state(ctx, :visits, visits)
%{visits: visits, server: ctx.server_name}
end)
end
end
children = [
MyApp.MCPServer
]
FastestMCP.call_tool(MyApp.MCPServer, "sum", %{"a" => 20, "b" => 22})
# => 42
The full onboarding path, including transport startup and the first connected client call, lives in docs/onboarding.md.
Guides
- Onboarding
- Why FastestMCP
- Components
- Tools
- Resources
- Prompts
- Context
- Dependency Injection
- Lifespan
- Transports
- Client
- Sampling and Interaction
- Pagination
- Progress
- Logging
- Telemetry
- Dynamic Component Manager
- Auth
- Middleware
- Background Tasks
- Providers and Mounting
- Transforms
- Versioning and Visibility
- Testing
- Runtime State and Storage
- Schema Validation
- Compatibility and Scope
Public API
FastestMCP keeps the public surface deliberately curated.
FastestMCP: top-level server, transport, runtime, and task helpersFastestMCP.ServerModule: preferred module-owned startup wrapperFastestMCP.Server: low-level server definition for dynamic casesFastestMCP.Context: explicit request, session, auth, and task contextFastestMCP.RequestContext: stable request snapshot derived from contextFastestMCP.Client: connected MCP client for streamable HTTP and stdioFastestMCP.Auth: auth contract and shared authenticator wrapperFastestMCP.Auth.Result: normalized authenticator resultFastestMCP.Auth.StaticToken: hermetic bearer-token authenticatorFastestMCP.Auth.ProtectedResource: RFC 9728 protected-resource metadataFastestMCP.Middleware: built-in middleware constructorsFastestMCP.Provider: provider contract for mounted and dynamic surfacesFastestMCP.ComponentManager: runtime mutation for live serversFastestMCP.Sampling: Elixir-friendly sampling helpersFastestMCP.Interact: higher-level elicitation helpersFastestMCP.Root: validated client-declaredfile://root and containment helpersFastestMCP.PeerTask: session-owned handle for sampling or elicitation work delegated to the connected clientFastestMCP.Schema,FastestMCP.Schema.Compiled, andFastestMCP.Schema.Error: strict compile-once JSON Schema boundaryFastestMCP.Schema.HTTPResolver: opt-in allowlisted HTTPS schema resolverFastestMCP.SessionStateStoreandFastestMCP.SessionStateStore.Memory: session-state backend contract and default backendFastestMCP.TaskBackendandFastestMCP.TaskBackend.Memory: background-task storage contract and default ETS-backed backendFastestMCP.Tools.Result: explicit tool result helper typeFastestMCP.Prompts.MessageandFastestMCP.Prompts.Result: explicit prompt helper typesFastestMCP.Resources.Content,FastestMCP.Resources.Result,FastestMCP.Resources.Text,FastestMCP.Resources.Binary,FastestMCP.Resources.File,FastestMCP.Resources.HTTP, andFastestMCP.Resources.Directory: explicit resource helper typesFastestMCP.Protocol: protocol version and capability helpersFastestMCP.BackgroundTask: local handle for submitted task workFastestMCP.Transport.HTTPApp: Plug-compatible MCP appFastestMCP.Transport.StreamableHTTP: streamable HTTP transportFastestMCP.Transport.Stdio: stdio transport entrypoint
Current Scope
FastestMCP currently ships:
- module-owned and dynamic server definitions
- tools, resources, resource templates, and prompts
- middleware, providers, auth, and transport-independent execution
- explicit
%FastestMCP.Context{}access to request, session, task, auth, and HTTP state FastestMCP.Context.current!/0,request_context/1, andclient_id/1for narrow convenience helpers where needed- standard prompt/resource wire completion plus Elixir-native tool and resource-template completion handlers
- explicit tool, prompt, and resource helper structs for richer payload shaping
- unified
on_duplicate:handling for local server definitions, runtime component-manager mutations, and the local provider - per-server runtime isolation, bounded concurrency, overload control, and task supervision
- streamable HTTP and stdio transports
- MCP
2025-11-25as the sole protocol version - one JSON-RPC message per request at the configured
/mcpendpoint - a Plug-first HTTP embedding surface for Bandit, Phoenix, or custom Plug apps
- a connected client for streamable HTTP and stdio
- client-side sampling, elicitation, logging, and progress callbacks
- server-originated roots, sampling, form and URL elicitation, ping, logging, progress, cancellation, and requester-side peer tasks over HTTP and stdio
- identity-bound URL elicitation completion and RFC 9728 protected-resource discovery for configured HTTP servers
- bounded SSE replay using
Last-Event-ID - Draft 2020-12 and Draft 7 JSON Schema validation through JSV, with opt-in allowlisted HTTPS reference resolution
- runtime component mutation through
FastestMCP.ComponentManager - OpenAPI-backed dynamic tool generation
The main deferred items remain:
- CLI tooling
- cluster-aware runtime behavior
- publishing automation after the first manual release path is proven
- custom app or UI layer
Standalone SSE, legacy method-specific HTTP routes, and JSON-RPC batches are
intentionally unsupported. HTTP means streamable HTTP at /mcp only.
When To Use FastestMCP
FastestMCP is a good fit when:
- you want MCP server capabilities inside an Elixir or Phoenix system
- you want module-owned startup that plugs cleanly into
application.ex - you need supervised, crash-isolated component execution
- you want a connected Elixir client for integration tests or local tooling
- you need runtime component mutation through OTP, not an external management API
- you care about explicit session and task lifetimes with bounded overload behavior
It is not the right choice yet if you need:
- standalone SSE transport compatibility
- CLI tooling
- distributed multi-node runtime behavior out of the box
- a custom app or UI layer