diff --git a/docs/python-sdk-pages.json b/docs/python-sdk-pages.json index 32abc995c..b840660b3 100644 --- a/docs/python-sdk-pages.json +++ b/docs/python-sdk-pages.json @@ -31,6 +31,16 @@ } ] }, + { + "group": "fastmcp.resources", + "pages": [ + "python-sdk/fastmcp-resources-base", + "python-sdk/fastmcp-resources-function_resource", + "python-sdk/fastmcp-resources-security", + "python-sdk/fastmcp-resources-template", + "python-sdk/fastmcp-resources-types" + ] + }, { "group": "fastmcp.server", "pages": [ diff --git a/docs/python-sdk/fastmcp-resources-base.mdx b/docs/python-sdk/fastmcp-resources-base.mdx new file mode 100644 index 000000000..6df16ea9e --- /dev/null +++ b/docs/python-sdk/fastmcp-resources-base.mdx @@ -0,0 +1,196 @@ +--- +title: base +sidebarTitle: base +--- + +# `fastmcp.resources.base` + + +Base classes and interfaces for FastMCP resources. + +## Functions + +### `convert_raw_to_resource_result` + +```python +convert_raw_to_resource_result(raw_value: Any) -> ResourceResult +``` + + +Wrap a user function's return value in a ResourceResult. + +Shared by `Resource` and `ResourceTemplate` so both honor the MIME type +the component declares in listings. A component that advertises +`text/csv` must not serve `text/plain` on read. + +**Args:** +- `raw_value`: The value returned by the user's function. +- `mime_type`: The component's declared MIME type, forwarded to content items. +- `meta`: Component-level meta (e.g. `ui` metadata for MCP Apps CSP/permissions) +propagated to each content item. + + +## Classes + +### `ResourceContent` + + +Wrapper for resource content with optional MIME type and metadata. + +Accepts any value for content - strings and bytes pass through directly, +other types (dict, list, BaseModel, etc.) are automatically JSON-serialized. + + +**Methods:** + +#### `to_mcp_resource_contents` + +```python +to_mcp_resource_contents(self, uri: AnyUrl | str) -> mcp_types.TextResourceContents | mcp_types.BlobResourceContents +``` + +Convert to MCP resource contents type. + +**Args:** +- `uri`: The URI of the resource (required by MCP types) + +**Returns:** +- TextResourceContents for str content, BlobResourceContents for bytes + + +### `ResourceResult` + + +Canonical result type for resource reads. + +Provides explicit control over resource responses: multiple content items, +per-item MIME types, and metadata at both the item and result level. + + +**Methods:** + +#### `to_mcp_result` + +```python +to_mcp_result(self, uri: AnyUrl | str) -> mcp_types.ReadResourceResult +``` + +Convert to MCP ReadResourceResult. + +**Args:** +- `uri`: The URI of the resource (required by MCP types) + +**Returns:** +- MCP ReadResourceResult with converted contents + + +### `InputRequiredResourceResult` + + +The full result of a single multi-round-trip resource read (SEP-2322). + +`InputRequiredResult` is a result type, not a `tools/call` feature: any +request may resolve to one. When a resource or resource template returns an +`InputRequiredResult` from its body to ask the client for input, that ask is +the legitimate result of this `resources/read` — so FastMCP wraps it in this +`ResourceResult` subclass, mirroring `InputRequiredToolResult` and +`InputRequiredPromptResult`, and it flows through the middleware chain as an +ordinary return value. + +Invariant: the wrapped `InputRequiredResult` is never serialized as resource +contents. `contents` is always empty; the wire handler (`_on_read_resource`) +reads `.input_required` and returns it to the runner. + + +### `Resource` + + +Base class for all resources. + + +**Methods:** + +#### `from_function` + +```python +from_function(cls, fn: Callable[..., Any], uri: str | AnyUrl) -> FunctionResource +``` + +#### `set_default_mime_type` + +```python +set_default_mime_type(cls, mime_type: str | None) -> str +``` + +Set default MIME type if not provided. + + +#### `set_default_name` + +```python +set_default_name(self) -> Self +``` + +Set default name from URI if not provided. + + +#### `read` + +```python +read(self) -> str | bytes | ResourceResult +``` + +Read the resource content. + +Subclasses implement this to return resource data. Supported return types: + - str: Text content + - bytes: Binary content + - ResourceResult: Full control over contents and result-level meta + + +#### `convert_result` + +```python +convert_result(self, raw_value: Any) -> ResourceResult +``` + +Convert a raw result to ResourceResult. + +This is used in two contexts: +1. In _read() to convert user function return values to ResourceResult +2. In tasks_result_handler() to convert Docket task results to ResourceResult + +Handles ResourceResult passthrough and converts raw values using +ResourceResult's normalization. When the raw value is a plain +string or bytes, the resource's own ``mime_type`` is forwarded so +that ``ui://`` resources (and others with non-default MIME types) +don't fall back to ``text/plain``. + +The resource's component-level ``meta`` (e.g. ``ui`` metadata for +MCP Apps CSP/permissions) is propagated to each content item so +that hosts can read it from the ``resources/read`` response. + + +#### `to_mcp_resource` + +```python +to_mcp_resource(self, **overrides: Any) -> SDKResource +``` + +Convert the resource to an SDKResource. + + +#### `key` + +```python +key(self) -> str +``` + +The globally unique lookup key for this resource. + + +#### `get_span_attributes` + +```python +get_span_attributes(self) -> dict[str, Any] +``` diff --git a/docs/python-sdk/fastmcp-resources-function_resource.mdx b/docs/python-sdk/fastmcp-resources-function_resource.mdx new file mode 100644 index 000000000..1e34ae1a1 --- /dev/null +++ b/docs/python-sdk/fastmcp-resources-function_resource.mdx @@ -0,0 +1,81 @@ +--- +title: function_resource +sidebarTitle: function_resource +--- + +# `fastmcp.resources.function_resource` + + +Standalone @resource decorator for FastMCP. + +## Functions + +### `resource` + +```python +resource(uri: str) -> Callable[[F], F] +``` + + +Standalone decorator to mark a function as an MCP resource. + +Returns the original function with metadata attached. Register with a server +using mcp.add_resource(). + + +## Classes + +### `DecoratedResource` + + +Protocol for functions decorated with @resource. + + +### `ResourceMeta` + + +Metadata attached to functions by the @resource decorator. + + +### `FunctionResource` + + +A resource that defers data loading by wrapping a function. + +The function is only called when the resource is read, allowing for lazy loading +of potentially expensive data. This is particularly useful when listing resources, +as the function won't be called until the resource is actually accessed. + +The function can return: +- str for text content (default) +- bytes for binary content +- other types will be converted to JSON + + +**Methods:** + +#### `from_function` + +```python +from_function(cls, fn: Callable[..., Any], uri: str | AnyUrl | None = None) -> FunctionResource +``` + +Create a FunctionResource from a function. + +**Args:** +- `fn`: The function to wrap +- `uri`: The URI for the resource (required if metadata not provided) +- `metadata`: ResourceMeta object with all configuration. If provided, +individual parameters must not be passed. +- `name, title, etc.`: Individual parameters for backwards compatibility. +Cannot be used together with metadata parameter. + + +#### `read` + +```python +read(self) -> str | bytes | ResourceResult +``` + +Read the resource by calling the wrapped function. + diff --git a/docs/python-sdk/fastmcp-resources-security.mdx b/docs/python-sdk/fastmcp-resources-security.mdx new file mode 100644 index 000000000..453553de2 --- /dev/null +++ b/docs/python-sdk/fastmcp-resources-security.mdx @@ -0,0 +1,74 @@ +--- +title: security +sidebarTitle: security +--- + +# `fastmcp.resources.security` + + +Path-safety policy for templated resource parameters. + +Templated resources (`@mcp.resource("file:///{path}")`-style) extract +parameter values straight out of the request URI and hand them to the +resource function. When those values flow into filesystem or URI +construction, a malicious client can smuggle path-traversal payloads +(`../`, absolute paths, null bytes) through the template. + +`ResourceSecurity` screens extracted parameter values *before* the +resource handler runs. It is applied by default to every templated +read, mirroring the posture of the underlying MCP SDK's +`ResourceSecurity` (traversal, absolute paths, and null bytes rejected). + +The screening reuses the SDK's component-based traversal check, so a +value that merely *contains* dots (e.g. `HEAD~3..HEAD`, `v1..v2`, +`file.tar.gz`) is not rejected — only an actual `..` path segment is. + + +## Classes + +### `InheritSecurity` + + +Sentinel type: inherit the server-wide resource-security default. + +Distinguishes "no per-component policy was set" (inherit whatever the +server configured) from an explicit ``None`` (screening disabled for +this component). + + +### `ResourceSecurity` + + +Security policy applied to extracted resource template parameters. + +These checks run after a URI has matched a template and its +parameter values have been extracted and percent-decoded. They catch +path-traversal and absolute-path injection regardless of how the +value was encoded in the URI (literal, `%2F`, `%5C`, `%2E%2E`). + +All checks default on. Screen a value like `HEAD~3..HEAD` (dots +inside a single segment) passes — only a standalone `..` segment is +treated as traversal. + + +**Methods:** + +#### `validate` + +```python +validate(self, params: Mapping[str, object]) -> str | None +``` + +Check all parameter values against the configured policy. + +String values (and lists of strings, from wildcard `{path*}` +parameters that span multiple segments) are screened; non-string +values are ignored, since traversal is a string-path concern. + +**Args:** +- `params`: Extracted template parameters. + +**Returns:** +- The name of the first parameter that fails, or `None` if all +- values pass. + diff --git a/docs/python-sdk/fastmcp-resources-template.mdx b/docs/python-sdk/fastmcp-resources-template.mdx new file mode 100644 index 000000000..8968fc441 --- /dev/null +++ b/docs/python-sdk/fastmcp-resources-template.mdx @@ -0,0 +1,224 @@ +--- +title: template +sidebarTitle: template +--- + +# `fastmcp.resources.template` + + +Resource template functionality. + +## Functions + +### `extract_query_params` + +```python +extract_query_params(uri_template: str) -> set[str] +``` + + +Extract query parameter names from RFC 6570 `{?param1,param2}` syntax. + + +### `build_regex` + +```python +build_regex(template: str) -> re.Pattern[str] | None +``` + + +Build regex pattern for URI template, handling RFC 6570 syntax. + +Supports: +- `{var}` - simple path parameter +- `{var*}` - wildcard path parameter (captures multiple segments) +- `{?var1,var2}` - query parameters (ignored in path matching) + +Hyphens in parameter names are normalized to underscores in regex group +names so that matched groups are valid Python identifiers. + +Returns None if the template produces an invalid regex (e.g. parameter +names with leading digits or duplicates from a remote server). + + +### `match_uri_template` + +```python +match_uri_template(uri: str, uri_template: str) -> dict[str, str] | None +``` + + +Match URI against template and extract both path and query parameters. + +Supports RFC 6570 URI templates: +- Path params: `{var}`, `{var*}` +- Query params: `{?var1,var2}` + + +### `expand_uri_template` + +```python +expand_uri_template(uri_template: str, params: dict[str, Any]) -> str +``` + + +Expand a URI template with parameters — inverse of `match_uri_template`. + +Supports the same RFC 6570 subset: +- Path params: `{var}`, `{var*}` +- Query params: `{?var1,var2}` + + +## Classes + +### `ResourceTemplate` + + +A template for dynamically creating resources. + + +**Methods:** + +#### `resolve_security` + +```python +resolve_security(self, server_default: ResourceSecurity | None) -> ResourceSecurity | None +``` + +Resolve the effective security policy for this template. + +A per-component ``security`` overrides the server default. +``INHERIT_SECURITY`` (the field default) inherits ``server_default``; +an explicit ``None`` disables screening for this template. + + +#### `from_function` + +```python +from_function(fn: Callable[..., Any], uri_template: str, name: str | None = None, version: str | int | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, auth: AuthCheck | list[AuthCheck] | None = None, security: ResourceSecurity | None | InheritSecurity = INHERIT_SECURITY) -> FunctionResourceTemplate +``` + +#### `set_default_mime_type` + +```python +set_default_mime_type(cls, mime_type: str | None) -> str +``` + +Set default MIME type if not provided. + + +#### `matches` + +```python +matches(self, uri: str) -> dict[str, Any] | None +``` + +Check if URI matches template and extract parameters. + + +#### `read` + +```python +read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult +``` + +Read the resource content. + + +#### `convert_result` + +```python +convert_result(self, raw_value: Any) -> ResourceResult +``` + +Convert a raw result to ResourceResult. + +This is used in two contexts: +1. In _read() to convert user function return values to ResourceResult +2. In tasks_result_handler() to convert Docket task results to ResourceResult + +Handles ResourceResult passthrough and converts raw values using +ResourceResult's normalization. The template's own ``mime_type`` is +forwarded so that reads match the MIME type the template advertises +in ``resources/templates/list``. + + +#### `create_resource` + +```python +create_resource(self, uri: str, params: dict[str, Any]) -> Resource +``` + +Create a resource from the template with the given parameters. + +The base implementation does not support background tasks. +Use FunctionResourceTemplate for task support. + + +#### `to_mcp_template` + +```python +to_mcp_template(self, **overrides: Any) -> SDKResourceTemplate +``` + +Convert the resource template to an SDKResourceTemplate. + + +#### `from_mcp_template` + +```python +from_mcp_template(cls, mcp_template: SDKResourceTemplate) -> ResourceTemplate +``` + +Creates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object. + + +#### `key` + +```python +key(self) -> str +``` + +The globally unique lookup key for this template. + + +#### `get_span_attributes` + +```python +get_span_attributes(self) -> dict[str, Any] +``` + +### `FunctionResourceTemplate` + + +A template for dynamically creating resources. + + +**Methods:** + +#### `create_resource` + +```python +create_resource(self, uri: str, params: dict[str, Any]) -> Resource +``` + +Create a resource from the template with the given parameters. + + +#### `read` + +```python +read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult +``` + +Read the resource content. + + +#### `from_function` + +```python +from_function(cls, fn: Callable[..., Any], uri_template: str, name: str | None = None, version: str | int | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, auth: AuthCheck | list[AuthCheck] | None = None, security: ResourceSecurity | None | InheritSecurity = INHERIT_SECURITY) -> FunctionResourceTemplate +``` + +Create a template from a function. + diff --git a/docs/python-sdk/fastmcp-resources-types.mdx b/docs/python-sdk/fastmcp-resources-types.mdx new file mode 100644 index 000000000..c47ce0d5a --- /dev/null +++ b/docs/python-sdk/fastmcp-resources-types.mdx @@ -0,0 +1,134 @@ +--- +title: types +sidebarTitle: types +--- + +# `fastmcp.resources.types` + + +Concrete resource implementations. + +## Classes + +### `TextResource` + + +A resource that reads from a string. + + +**Methods:** + +#### `read` + +```python +read(self) -> ResourceResult +``` + +Read the text content. + + +### `BinaryResource` + + +A resource that reads from bytes. + + +**Methods:** + +#### `read` + +```python +read(self) -> ResourceResult +``` + +Read the binary content. + + +### `FileResource` + + +A resource that reads from a file. + +Set is_binary=True to read file as binary data instead of text. + + +**Methods:** + +#### `validate_absolute_path` + +```python +validate_absolute_path(cls, path: Path) -> Path +``` + +Ensure path is absolute. + + +#### `set_binary_from_mime_type` + +```python +set_binary_from_mime_type(cls, is_binary: bool, info: ValidationInfo) -> bool +``` + +Set is_binary based on mime_type if not explicitly set. + + +#### `read` + +```python +read(self) -> ResourceResult +``` + +Read the file content. + + +### `HttpResource` + + +A resource that reads from an HTTP endpoint. + + +**Methods:** + +#### `read` + +```python +read(self) -> ResourceResult +``` + +Read the HTTP content. + + +### `DirectoryResource` + + +A resource that lists files in a directory. + + +**Methods:** + +#### `validate_absolute_path` + +```python +validate_absolute_path(cls, path: Path) -> Path +``` + +Ensure path is absolute. + + +#### `list_files` + +```python +list_files(self) -> list[Path] +``` + +List files in the directory. + + +#### `read` + +```python +read(self) -> ResourceResult +``` + +Read the directory listing. +