PrefectHQ/fastmcp · error · TypeError

The @resource decorator was used incorrectly. It requires a

Error message

The @resource decorator was used incorrectly. It requires a URI as the first argument. Use @resource('uri') instead of @resource

What it means

The @resource decorator requires a URI string as its first positional argument. When applied bare as @resource (directly above a function), Python passes the function itself as `uri`; FastMCP detects this (inspect.isroutine) and raises to teach the correct usage.

Source

Thrown at fastmcp_slim/fastmcp/server/providers/local_provider/decorators/resources.py:163

        Example:
            ```python
            provider = LocalProvider()

            @provider.resource("data://config")
            def get_config() -> str:
                return '{"setting": "value"}'

            @provider.resource("data://{city}/weather")
            def get_weather(city: str) -> str:
                return f"Weather for {city}"
            ```
        """
        if isinstance(annotations, dict):
            annotations = Annotations(**annotations)

        if inspect.isroutine(uri):
            raise TypeError(
                "The @resource decorator was used incorrectly. "
                "It requires a URI as the first argument. "
                "Use @resource('uri') instead of @resource"
            )

        def decorator(fn: AnyFunction) -> Any:
            # Check for unbound method
            try:
                params = list(inspect.signature(fn).parameters.keys())
            except (ValueError, TypeError):
                params = []
            if params and params[0] in ("self", "cls"):
                fn_name = getattr(fn, "__name__", "function")
                raise TypeError(
                    f"The function '{fn_name}' has '{params[0]}' as its first parameter. "
                    f"Use the standalone @resource decorator and register the bound method:\n\n"
                    f"    from fastmcp.resources import resource\n\n"
                    f"    class MyClass:\n"

View on GitHub (pinned to 1f02114297)

Solutions

  1. Add the URI argument: use @resource('your-scheme://your-uri') instead of @resource.
  2. If configuration is needed, use @resource('uri', name=..., description=...) — parentheses are mandatory.

Example fix

// before
@resource
def get_config() -> str:
    ...

// after
@resource('config://app')
def get_config() -> str:
    ...
Defensive patterns

Strategy: validation

Validate before calling

uri = 'config://app'
if not isinstance(uri, str):
    raise TypeError('first arg to @resource must be a URI string')

@resource(uri)
def get_config() -> str:
    ...

Type guard

def has_uri_args(decorated) -> bool:
    return callable(decorated) and not inspect.isroutine(decorated)

Try / catch

try:
    mcp.add_resource(my_fn)
except TypeError as e:
    if 'requires a URI' in str(e):
        raise ValueError('forgot the URI: use @resource("uri")') from e
    raise

Prevention

When it happens

Trigger: Writing `@resource` instead of `@resource('scheme://path')` above a function, then registering it on a FastMCP instance.

Common situations: Copying the @tool pattern (which supports bare @tool) and applying it to @resource, which always requires a URI; typos when converting a plain function into a resource.

Related errors


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