PrefectHQ/fastmcp · error · TypeError

The @resource decorator requires a URI. Use @resource('uri')

Error message

The @resource decorator requires a URI. Use @resource('uri') instead of @resource

What it means

The @resource decorator must be applied with a URI string: @resource('data://x'). Using bare @resource (decorating the function directly, so uri is the function object) is a usage error; inspect.isroutine detects it and raises this TypeError with the corrective hint.

Source

Thrown at fastmcp_slim/fastmcp/resources/function_resource.py:247

    description: str | None = None,
    icons: list[Icon] | None = None,
    mime_type: str | None = None,
    tags: set[str] | None = None,
    annotations: Annotations | dict[str, Any] | None = None,
    meta: dict[str, Any] | None = None,
    auth: AuthCheck | list[AuthCheck] | None = None,
    security: ResourceSecurity | None | InheritSecurity = INHERIT_SECURITY,
) -> 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().
    """
    if isinstance(annotations, dict):
        annotations = Annotations(**annotations)

    if inspect.isroutine(uri):
        raise TypeError(
            "The @resource decorator requires a URI. "
            "Use @resource('uri') instead of @resource"
        )

    def attach_metadata(fn: F) -> F:
        metadata = ResourceMeta(
            uri=uri,
            name=name,
            version=version,
            title=title,
            description=description,
            icons=icons,
            tags=tags,
            mime_type=mime_type,
            annotations=annotations,
            meta=meta,
            auth=auth,
            security=security,

View on GitHub (pinned to 1f02114297)

Solutions

  1. Add the URI argument: @mcp.resource('data://my-data') above the function
  2. If parameters vary per-call, you may need @mcp.resource('data://{id}') template syntax with the URI including placeholders
  3. Keep parentheses: @resource(...) is a factory, not a direct decorator

Example fix

// before
@mcp.resource
def get_data(): ...
// after
@mcp.resource("data://my-data")
def get_data(): ...
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect
def valid_decorator_use(uri):
    return not inspect.isroutine(uri)  # must be a URI string, not a function

Type guard

def is_bare_decorator(resource_arg) -> bool:
    return inspect.isroutine(resource_arg)

Try / catch

try:
    @mcp.resource
    def fn(): ...
except TypeError as e:
    raise SyntaxHintError("add a URI: @mcp.resource('scheme://path')") from e

Prevention

When it happens

Trigger: @mcp.resource\ndef get_data(): ... — i.e. the decorator used without parentheses/arguments, so the 'uri' parameter receives the function itself.

Common situations: Copy-paste from plain-Python decorator examples; forgetting the URI argument during refactoring from function registrations to decorators.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/1a9b0e15dba7ead0. Report an issue: GitHub.