Skip to main content
Resources represent data or files that an MCP client can read, and resource templates extend this concept by allowing clients to request dynamically generated resources based on parameters passed in the URI. FastMCP simplifies defining both static and dynamic resources, primarily using the @mcp.resource decorator.

What Are Resources?

Resources provide read-only access to data for the LLM or client application. When a client requests a resource URI:
  1. FastMCP finds the corresponding resource definition.
  2. If it’s dynamic (defined by a function), the function is executed.
  3. The content (text, JSON, binary data) is returned to the client.
This allows LLMs to access files, database content, configuration, or dynamically generated information relevant to the conversation.

Resources

The @resource Decorator

The most common way to define a resource is by decorating a Python function. The decorator requires the resource’s unique URI.
Key Concepts:
  • URI: The first argument to @resource is the unique URI (e.g., "resource://greeting") clients use to request this data.
  • Lazy Loading: The decorated function (get_greeting, get_config) is only executed when a client specifically requests that resource URI via resources/read.
  • Inferred Metadata: By default:
    • Resource Name: Taken from the function name (get_greeting).
    • Resource Description: Taken from the function’s docstring.

Decorator Arguments

You can customize the resource’s properties using arguments in the @mcp.resource decorator:

@resource Decorator Arguments

uri
str
required
The unique identifier for the resource
name
str | None
A human-readable name. If not provided, defaults to function name
description
str | None
Explanation of the resource. If not provided, defaults to docstring
mime_type
str | None
Specifies the content type. FastMCP often infers a default like text/plain or application/json, but explicit is better for non-text types
tags
set[str] | None
A set of strings used to categorize the resource. These can be used by the server and, in some cases, by clients to filter or group available resources.
enabled
bool
default:"True"
Deprecated in v3.0.0. Use mcp.enable() / mcp.disable() at the server level instead.
A boolean to enable or disable the resource. See Component Visibility for the recommended approach.
icons
list[Icon] | None
Optional list of icon representations for this resource or template. See Icons for detailed examples
annotations
Annotations | dict | None
An optional Annotations object or dictionary to add additional metadata about the resource.
meta
dict[str, Any] | None
Optional meta information about the resource. This data is passed through to the MCP client as the meta field of the client-side resource object and can be used for custom metadata, versioning, or other application-specific purposes.
version
str | int | None
Optional version identifier for this resource. See Versioning for details.

Using with Methods

For decorating instance or class methods, use the standalone @resource decorator and register the bound method. See Tools: Using with Methods for the pattern.

Return Values

Resource functions must return one of three types:
  • str: Sent as TextResourceContents (with mime_type="text/plain" by default).
  • bytes: Base64 encoded and sent as BlobResourceContents. You should specify an appropriate mime_type (e.g., "image/png", "application/octet-stream").
  • ResourceResult: Full control over contents, MIME types, and metadata. See ResourceResult below.
To return structured data like dicts or lists, serialize them to JSON strings using json.dumps(). This explicit approach ensures your type checker catches errors during development rather than at runtime when a client reads the resource.

ResourceResult

ResourceResult gives you explicit control over resource responses: multiple content items, per-item MIME types, and metadata at both the item and result level.
ResourceContent accepts three fields: content - The actual resource content. Can be str (text content) or bytes (binary content). This is the data that will be returned to the client. mime_type - Optional MIME type for the content. Defaults to "text/plain" for string content and "application/octet-stream" for binary content. meta - Optional metadata dictionary that will be included in the MCP response’s meta field. Use this for runtime metadata like Content Security Policy headers, caching hints, or other client-specific data. For simple cases, you can pass str or bytes directly to ResourceResult:

ResourceResult

contents
str | bytes | list[ResourceContent]
required
Content to return. Strings and bytes are wrapped in a single ResourceContent. Use a list of ResourceContent for multiple items or custom MIME types.
meta
dict[str, Any] | None
Result-level metadata, included in the MCP response’s _meta field.

ResourceContent

content
Any
required
The content data. Strings and bytes pass through directly. Other types (dict, list, BaseModel) are automatically JSON-serialized.
mime_type
str | None
MIME type. Defaults to text/plain for strings, application/octet-stream for bytes, application/json for serialized objects.
meta
dict[str, Any] | None
Item-level metadata for this specific content.

Component Visibility

You can control which resources are enabled for clients using server-level enabled control. Disabled resources don’t appear in list_resources and can’t be read.
See Visibility for the complete visibility control API including key formats, tag-based filtering, and provider-level control.

Accessing MCP Context

Resources and resource templates can access additional MCP information and features through the Context object. To access it, add a parameter to your resource function with a type annotation of Context:
For full documentation on the Context object and all its capabilities, see the Context documentation.

Async Resources

FastMCP supports both async def and regular def resource functions. Synchronous functions automatically run in a threadpool to avoid blocking the event loop. For I/O-bound operations, async functions are more efficient:

Resource Classes

While @mcp.resource is ideal for dynamic content, you can directly register pre-defined resources (like static files or simple text) using mcp.add_resource() and concrete Resource subclasses.
Common Resource Classes:
  • TextResource: For simple string content.
  • BinaryResource: For raw bytes content.
  • FileResource: Reads content from a local file path. Handles text/binary modes, encoding, and lazy reading.
  • HttpResource: Fetches content from an HTTP(S) URL (requires httpx).
  • DirectoryResource: Lists files in a local directory (returns JSON).
  • (FunctionResource: Internal class used by @mcp.resource).
Use these when the content is static or sourced directly from a file/URL, bypassing the need for a dedicated Python function.

Notifications

FastMCP automatically sends notifications/resources/list_changed notifications to connected clients when resources or templates are added, enabled, or disabled. This allows clients to stay up-to-date with the current resource set without manually polling for changes.
Notifications are only sent when these operations occur within an active MCP request context (e.g., when called from within a tool or other MCP operation). Operations performed during server initialization do not trigger notifications. Clients can handle these notifications using a message handler to automatically refresh their resource lists or update their interfaces.

Annotations

FastMCP allows you to add specialized metadata to your resources through annotations. These annotations communicate how resources behave to client applications without consuming token context in LLM prompts. Annotations serve several purposes in client applications:
  • Indicating whether resources are read-only or may have side effects
  • Describing the safety profile of resources (idempotent vs. non-idempotent)
  • Helping clients optimize caching and access patterns
You can add annotations to a resource using the annotations parameter in the @mcp.resource decorator:
FastMCP supports these standard annotations: Remember that annotations help make better user experiences but should be treated as advisory hints. They help client applications present appropriate UI elements and optimize access patterns, but won’t enforce behavior on their own. Always focus on making your annotations accurately represent what your resource actually does.

Resource Templates

Resource Templates allow clients to request resources whose content depends on parameters embedded in the URI. Define a template using the same @mcp.resource decorator, but include {parameter_name} placeholders in the URI string and add corresponding arguments to your function signature. Resource templates share most configuration options with regular resources (name, description, mime_type, tags, annotations), but add the ability to define URI parameters that map to function parameters. Resource templates generate a new resource for each unique set of parameters, which means that resources can be dynamically created on-demand. For example, if the resource template "user://profile/{name}" is registered, MCP clients could request "user://profile/ford" or "user://profile/marvin" to retrieve either of those two user profiles as resources, without having to register each resource individually.
Functions with *args are not supported as resource templates. However, unlike tools and prompts, resource templates do support **kwargs because the URI template defines specific parameter names that will be collected and passed as keyword arguments.
Here is a complete example that shows how to define two resource templates:
With these two templates defined, clients can request a variety of resources:
  • weather://london/current → Returns weather for London
  • weather://paris/current → Returns weather for Paris
  • repos://PrefectHQ/fastmcp/info → Returns info about the PrefectHQ/fastmcp repository
  • repos://prefecthq/prefect/info → Returns info about the prefecthq/prefect repository

RFC 6570 URI Templates

FastMCP implements RFC 6570 URI Templates for resource templates, providing a standardized way to define parameterized URIs. This includes support for simple expansion, wildcard path parameters, and form-style query parameters.

Wildcard Parameters

Resource templates support wildcard parameters that can match multiple path segments. Standard parameters ({param}) match a single URI segment before decoding and do not cross literal ”/” boundaries in the request URI. Wildcard parameters ({param*}) can capture multiple segments including slashes. Wildcards capture all subsequent path segments up until the defined part of the URI template (whether literal or another parameter). This allows you to have multiple wildcard parameters in a single URI template.
Wildcard parameters are useful when:
  • Working with file paths or hierarchical data
  • Creating APIs that need to capture variable-length path segments
  • Building URL-like patterns similar to REST APIs
Note that like regular parameters, each wildcard parameter must still be a named parameter in your function signature, and all required function parameters must appear in the URI template.

Filesystem Path Safety

Template parameters are decoded before your function receives them. A standard {filename} parameter matches one URI segment before decoding, so a request like files://a%2Fb passes filename="a/b" to the handler. Treat template values as untrusted decoded URI data whenever they determine filesystem paths. Validate the final resolved path against an allowed root before reading:
Use wildcard parameters ({path*}) for resources whose URI shape intentionally includes slashes, and apply the same containment check before accessing the filesystem.

Query Parameters

FastMCP supports RFC 6570 form-style query parameters using the {?param1,param2} syntax. Query parameters provide a clean way to pass optional configuration to resources without cluttering the path. Query parameters must be optional function parameters (have default values), while path parameters map to required function parameters. This enforces a clear separation: required data goes in the path, optional configuration in query params.
Example requests:
  • data://123 → Uses default format "json"
  • data://123?format=xml → Uses format "xml"
  • api://users?version=2&limit=50version=2, limit=50, offset=0
  • files://src/main.py?encoding=ascii&lines=50 → Custom encoding and line limit
FastMCP automatically coerces query parameter string values to the correct types based on your function’s type hints (int, float, bool, str). Query parameters vs. hidden defaults: Query parameters expose optional configuration to clients. To hide optional parameters from clients entirely (always use defaults), simply omit them from the URI template:

Template Parameter Rules

FastMCP enforces these validation rules when creating resource templates:
  1. Required function parameters (no default values) must appear in the URI path template
  2. Query parameters (specified with {?param} syntax) must be optional function parameters with default values
  3. All URI template parameters (path and query) must exist as function parameters
Optional function parameters (those with default values) can be:
  • Included as query parameters ({?param}) - clients can override via query string
  • Omitted from URI template - always uses default value, not exposed to clients
  • Used in alternative path templates - enables multiple ways to access the same resource
Multiple templates for one function: Create multiple resource templates that expose the same function through different URI patterns by manually applying decorators:
Now an LLM or client can retrieve user information in two different ways:
  • users://email/alice@example.com → Looks up user by email (with name=None)
  • users://name/Bob → Looks up user by name (with email=None)
This approach allows a single function to be registered with multiple URI patterns while keeping the implementation clean and straightforward. Templates provide a powerful way to expose parameterized data access points following REST-like principles.

Error Handling

If your resource function encounters an error, you can raise a standard Python exception (ValueError, TypeError, FileNotFoundError, custom exceptions, etc.) or a FastMCP ResourceError. By default, all exceptions (including their details) are logged and converted into an MCP error response to be sent back to the client LLM. This helps the LLM understand failures and react appropriately. If you want to mask internal error details for security reasons, you can:
  1. Use the mask_error_details=True parameter when creating your FastMCP instance:
  1. Or use ResourceError to explicitly control what error information is sent to clients:
When mask_error_details=True, only error messages from ResourceError will include details, other exceptions will be converted to a generic message.

Server Behavior

Duplicate Resources

You can configure how the FastMCP server handles attempts to register multiple resources or templates with the same URI. Use the on_duplicate_resources setting during FastMCP initialization.
The duplicate behavior options are:
  • "warn" (default): Logs a warning, and the new resource/template replaces the old one.
  • "error": Raises a ValueError, preventing the duplicate registration.
  • "replace": Silently replaces the existing resource/template with the new one.
  • "ignore": Keeps the original resource/template and ignores the new registration attempt.

Versioning

Resources and resource templates support versioning, allowing you to maintain multiple implementations under the same URI while clients automatically receive the highest version. See Versioning for complete documentation on version comparison, retrieval, and migration patterns.