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

Public API

FastestMCP keeps the public surface deliberately curated.

Current Scope

FastestMCP currently ships:

The main deferred items remain:

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:

It is not the right choice yet if you need: