mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-28 02:10:38 +02:00
chore: Update SDK documentation (#4679)
This commit is contained in:
parent
9feb1f378b
commit
803da5319c
30 changed files with 4066 additions and 90 deletions
194
docs/python-sdk/fastmcp-server-extensions.mdx
Normal file
194
docs/python-sdk/fastmcp-server-extensions.mdx
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
---
|
||||
title: extensions
|
||||
sidebarTitle: extensions
|
||||
---
|
||||
|
||||
# `fastmcp.server.extensions`
|
||||
|
||||
|
||||
FastMCP-native server extension API (SEP-2133).
|
||||
|
||||
An MCP extension is an opt-in, capability-negotiated bundle of protocol
|
||||
behaviour identified by a reverse-DNS string (e.g. `io.modelcontextprotocol/tasks`).
|
||||
Unlike the SDK's `mcp.server.extension.Extension`, a FastMCP `ServerExtension`
|
||||
is bound to its `FastMCP` instance at registration, so its request handlers and
|
||||
its `tools/call` interceptor can reach the component registry, `Context`, and
|
||||
auth scope that the SDK's model withholds.
|
||||
|
||||
An extension contributes any subset of four things:
|
||||
|
||||
- **A negotiated capability.** `settings()` is spliced into
|
||||
`ServerCapabilities.extensions[identifier]` (see `LowLevelServer.get_capabilities`).
|
||||
- **New request methods.** `methods()` returns `MethodBinding`s, each wired onto
|
||||
the low-level server via `add_request_handler` when the extension is registered.
|
||||
- **A `tools/call` interceptor.** `intercept_tool_call()` is the last gate before
|
||||
a tool body runs — it composes *after* the FastMCP middleware chain and *before*
|
||||
component execution, so it can observe, short-circuit, or pass a call through.
|
||||
- **A lifespan.** `lifespan()` is entered with the server's lifespan and exited on
|
||||
shutdown — the hook the SDK's `Extension` lacks, needed to start backends/workers.
|
||||
|
||||
The base class follows the SDK's httpx-style shape: every contribution method has
|
||||
a default, so a subclass overrides only what it needs.
|
||||
|
||||
|
||||
## Functions
|
||||
|
||||
### `read_client_extension_settings` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L235" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
read_client_extension_settings(ctx: ServerRequestContext[Any, Any], identifier: str) -> dict[str, Any] | None
|
||||
```
|
||||
|
||||
|
||||
Read a client's per-request extension opt-in from the request `_meta`.
|
||||
|
||||
SEP-2133 extensions negotiate per request: the client repeats its extension
|
||||
capabilities in each request's `_meta` under
|
||||
`io.modelcontextprotocol/clientCapabilities` → `extensions` → `identifier`.
|
||||
Returns the declared settings dict (possibly empty) when the extension was
|
||||
opted in for this request, or `None` when it was not.
|
||||
|
||||
|
||||
### `build_method_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L249" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
build_method_handler(binding: MethodBinding) -> ExtensionRequestHandler
|
||||
```
|
||||
|
||||
|
||||
Wrap a `MethodBinding` into a low-level request handler.
|
||||
|
||||
The adapter enforces `protocol_versions` gating (rejecting other versions as
|
||||
`METHOD_NOT_FOUND`, since `add_request_handler` registers unconditionally)
|
||||
and binds the FastMCP request context so the handler can use `get_context()`,
|
||||
auth, and other request-scoped dependencies.
|
||||
|
||||
|
||||
### `wrap_tool_call_interceptor` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L278" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
wrap_tool_call_interceptor(extension: ServerExtension, call_next: Callable[[Any], Awaitable[Any]]) -> Callable[[Any], Awaitable[Any]]
|
||||
```
|
||||
|
||||
|
||||
Fold one extension's `intercept_tool_call` around a middleware `call_next`.
|
||||
|
||||
The returned wrapper is a FastMCP `CallNext`: it hands the extension the
|
||||
validated `tools/call` params, the FastMCP `Context`, and a zero-arg
|
||||
continuation that runs the rest of the chain and, finally, the tool body.
|
||||
|
||||
|
||||
## Classes
|
||||
|
||||
### `MethodBinding` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L77" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
A new request method an extension serves, e.g. `tasks/get`.
|
||||
|
||||
`params_type` validates incoming params before `handler` runs; it should
|
||||
subclass `RequestParams` so `_meta` parses uniformly. `protocol_versions`,
|
||||
when set, restricts the method to those wire versions — a request at any
|
||||
other version is rejected as `METHOD_NOT_FOUND`, mirroring the spec's
|
||||
`(method, version)` boundary. `None` (the default) admits every version.
|
||||
|
||||
Extension methods are additive: `method` must not name a spec-defined
|
||||
request method (`tools/call`, `completion/complete`, ...). Binding one would
|
||||
silently shadow the server's own handler. Both constraints are enforced at
|
||||
construction.
|
||||
|
||||
|
||||
### `ServerExtension` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L111" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
Base class for an opt-in FastMCP server extension (SEP-2133).
|
||||
|
||||
Subclass, set `identifier`, and override the contribution methods that
|
||||
apply. Every method has a default, so a minimal extension overrides only
|
||||
`identifier` and one contribution. `identifier` is validated at
|
||||
subclass-definition time when set as a class attribute, and again at
|
||||
registration (which covers per-instance identifiers assigned in `__init__`).
|
||||
|
||||
Register an instance with `FastMCP.add_extension(...)`, which binds the
|
||||
extension to the server so `self.server`, `intercept_tool_call`, and method
|
||||
handlers can reach FastMCP-level constructs.
|
||||
|
||||
|
||||
**Methods:**
|
||||
|
||||
#### `server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L149" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
server(self) -> FastMCP
|
||||
```
|
||||
|
||||
The FastMCP server this extension is registered on.
|
||||
|
||||
Handlers, interceptors, and lifespan code reach the component registry,
|
||||
`Context`, and auth scope through here. Raises if the extension has not
|
||||
been registered with `FastMCP.add_extension()`.
|
||||
|
||||
|
||||
#### `settings` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L165" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
settings(self) -> dict[str, Any]
|
||||
```
|
||||
|
||||
Per-extension settings advertised at `capabilities.extensions[identifier]`.
|
||||
|
||||
An empty dict (the default) advertises the extension with no settings.
|
||||
|
||||
|
||||
#### `methods` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L172" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
methods(self) -> Sequence[MethodBinding]
|
||||
```
|
||||
|
||||
New request methods this extension serves (additive).
|
||||
|
||||
|
||||
#### `lifespan` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L176" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
lifespan(self) -> AbstractAsyncContextManager[None]
|
||||
```
|
||||
|
||||
A context manager entered with the server's lifespan, exited on shutdown.
|
||||
|
||||
Default: a no-op. Override to start and stop resources an extension owns
|
||||
(a task-queue backend and worker, say). Entered once per runtime tree, at
|
||||
the root — a mounted child defers to the root, as the shared Docket does.
|
||||
|
||||
|
||||
#### `intercept_tool_call` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L185" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
intercept_tool_call(self, params: CallToolRequestParams, context: Context, call_next: ToolCallContinuation) -> ToolCallOutcome
|
||||
```
|
||||
|
||||
Wrap `tools/call`. Default: pass through unchanged.
|
||||
|
||||
Runs after the FastMCP middleware chain and before the tool body, so it
|
||||
is the last gate before execution. Override to observe the call, to
|
||||
short-circuit (return a result without awaiting `call_next`), or to pass
|
||||
it through (`return await call_next()`). `params` is the validated
|
||||
`tools/call` params; `context` is the FastMCP `Context`, from which the
|
||||
tool being called (`context.fastmcp.get_tool(params.name)`), auth scope,
|
||||
and the server are reachable. Multiple extensions nest with the
|
||||
first-registered outermost.
|
||||
|
||||
|
||||
#### `client_settings` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/fastmcp_slim/fastmcp/server/extensions.py#L204" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
client_settings(self, ctx: ServerRequestContext[Any, Any]) -> dict[str, Any] | None
|
||||
```
|
||||
|
||||
This extension's per-request opt-in settings declared by the client.
|
||||
|
||||
Reads the request's `_meta` client-capabilities block. Returns the
|
||||
declared settings dict (possibly empty) when the client opted this
|
||||
extension in for the request, or `None` when it did not. Convenience for
|
||||
`read_client_extension_settings(ctx, self.identifier)`.
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue