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.
+