Providers let FastestMCP expose components that do not live directly on the base server struct.
This is the composition layer of the runtime. It is how one server can present components from:
- mounted FastestMCP servers
- standalone local providers
- OpenAPI-generated tool catalogs
- skill directories
- custom dynamic sources
Why Providers Exist
Without providers, every component would need to be copied onto the base server definition before startup. That works for small static servers, but it is not a good fit for mounted runtimes, generated tool catalogs, or dynamic external component sources.
Providers let FastestMCP keep one runtime and one execution pipeline while sourcing components from multiple places.
Mounted Servers
The simplest composition pattern is mounting one FastestMCP server into another:
child =
FastestMCP.server("child")
|> FastestMCP.add_tool("echo", fn arguments, _ctx -> arguments end)
parent =
FastestMCP.server("parent")
|> FastestMCP.mount(child, namespace: "child")Mounted components participate in normal:
- list operations
- tool calls
- resource reads
- prompt rendering
Use namespace: whenever the child may overlap with parent component names.
Mounting a server into itself is rejected.
Mounted servers enter their own lifespans when the parent runtime starts. Child
handlers receive the mounted server's ctx.lifespan_context, and shutdown runs
mounted cleanup before parent cleanup.
Mount Filtering
Mounted servers can be filtered by tags:
parent =
FastestMCP.server("parent")
|> FastestMCP.mount(child, include_tags: ["allowed"])Or:
parent =
FastestMCP.server("parent")
|> FastestMCP.mount(child, exclude_tags: ["blocked"])This is useful when a child server is large but the parent should only surface part of it.
Standalone Local Providers
FastestMCP also ships an explicit local provider module for dynamic composition without creating a separate server:
provider =
FastestMCP.Providers.Local.new(name: "dynamic")
|> FastestMCP.Providers.Local.add_tool("dynamic.echo", fn arguments, _ctx -> arguments end)
server =
FastestMCP.server("providers")
|> FastestMCP.add_provider(provider)Use this when you want provider behavior, but your source is still local Elixir code.
OpenAPI-backed Providers
OpenAPI support is the fastest way to turn an existing HTTP API into a tool catalog:
server =
FastestMCP.from_openapi(openapi_spec,
name: "petstore",
base_url: "https://api.example.com"
)
{:ok, _pid} = FastestMCP.start_server(server)
FastestMCP.list_tools("petstore")Under the hood, FastestMCP maps OpenAPI operations to tools, builds schemas from parameters and request bodies, and routes calls through its shared HTTP helper.
OpenAPI-backed tools serialize common HTTP request shapes:
- JSON and vendor JSON media types such as
application/problem+json application/x-www-form-urlencodedmultipart/form-data- cookie parameters through the
Cookieheader
Parameter locations are limited to the standard path/query/header/cookie
strings without creating atoms. Operation parameters override path-level
parameters by {location, name}; style/explode defaults are applied before
encoding arrays and objects, and path spaces use %20. Scalar and array JSON
request bodies are sent directly rather than wrapped. Responses are decoded
only when their media type is JSON or ends in +json.
Server URL variables are expanded from their declared defaults when a provider
base URL is derived from the document. Component $ref resolution tracks
visited references, so circular schemas are left as references instead of
recursing indefinitely.
Skills Providers
FastestMCP can expose skill directories as MCP resources:
provider =
FastestMCP.Providers.SkillsDirectory.new(
roots: ["~/.claude/skills", "~/.codex/skills"],
reload: false
)
server =
FastestMCP.server("skills")
|> FastestMCP.add_provider(provider)This is useful when you want local skills to become discoverable through MCP resource reads without hand-registering each file.
Skill roots are canonicalized before discovery. A main or supporting file is
rejected if its resolved path leaves the owning root. With reload: true, the
runtime activates a metadata-keyed cache and re-reads/re-hashes only files whose
size or modification data changed; unchanged skills reuse their compiled
component representation.
Custom Providers
When components come from somewhere else entirely, write a custom provider.
At minimum, a provider can implement one or more of:
list_components/3get_component_candidates/4get_component/4get_resource_target_candidates/3get_resource_target/3http_routes/1
Candidate callbacks are the preferred exact-lookup interface for versioned
providers. Return every matching version; FastestMCP applies provider transforms
once, then chooses the highest candidate that remains visible and authorized.
Legacy single-result callbacks remain supported and are authoritative, so an
exact lookup does not also enumerate the provider. A provider that implements
only list_components/3 uses the generic all-version fallback. Implement a
candidate callback whenever an exact lookup must expose multiple versions.
Example:
defmodule MyApp.CountingProvider do
defstruct [:tool]
def list_components(%__MODULE__{tool: tool}, :tool, _operation), do: [tool]
def list_components(%__MODULE__{}, _component_type, _operation), do: []
def get_component(%__MODULE__{tool: tool}, :tool, "dynamic_echo", _operation), do: tool
def get_component(%__MODULE__{}, _component_type, _identifier, _operation), do: nil
endThen:
server =
FastestMCP.server("providers")
|> FastestMCP.add_provider(%MyApp.CountingProvider{tool: my_tool})Use a custom provider when your components come from a database, config store, external service, or plugin system.
Provider Transforms
Provider-backed components can be reshaped without changing the source:
- namespacing
- tool renaming
- stacked provider transforms
See Transforms for the detailed patterns.
What FastestMCP Does Not Ship Yet
FastestMCP v0.2 does not yet expose filesystem or proxy providers as public built-ins. The current provider surface focuses on:
- mounted FastestMCP servers
- explicit local providers
- OpenAPI-backed providers
- skills providers
- custom provider implementations
That keeps the public surface focused on provider shapes already exercised by the runtime and test suite.
Why This Shape
Providers let FastestMCP keep one runtime while sourcing components from many places.
Mounted servers, OpenAPI catalogs, skill directories, and dynamic custom sources all still feed the same operation pipeline. That is the key property: composition without inventing a second execution model.