PrefectHQ/fastmcp · warning · UserWarning

{cls.__name__} does not define KEY_PREFIX. Component keys wi

Error message

{cls.__name__} does not define KEY_PREFIX. Component keys will not be type-prefixed, which may cause collisions.

What it means

`FastMCPComponent.__init_subclass__` requires every concrete component subclass to define a non-empty `KEY_PREFIX` so component keys are type-prefixed (e.g. `tool:`) and cannot collide across types. A subclass with an empty/missing `KEY_PREFIX` triggers this `UserWarning`.

Source

Thrown at fastmcp_slim/fastmcp/utilities/components.py:81

    if "@" in version:
        raise ValueError(
            f"Version string cannot contain '@' (used as key delimiter): {version!r}"
        )
    return version


class FastMCPComponent(FastMCPBaseModel):
    """Base class for FastMCP tools, prompts, resources, and resource templates."""

    KEY_PREFIX: ClassVar[str] = ""

    def __init_subclass__(cls, **kwargs: Any) -> None:
        super().__init_subclass__(**kwargs)
        # Warn if a subclass doesn't define KEY_PREFIX (inherited or its own)
        if not cls.KEY_PREFIX:
            import warnings

            warnings.warn(
                f"{cls.__name__} does not define KEY_PREFIX. "
                f"Component keys will not be type-prefixed, which may cause collisions.",
                UserWarning,
                stacklevel=2,
            )

    name: str = Field(
        description="The name of the component.",
    )
    version: Annotated[str | None, BeforeValidator(_coerce_version)] = Field(
        default=None,
        description="Optional version identifier for this component. "
        "Multiple versions of the same component (same name) can coexist.",
    )
    title: str | None = Field(
        default=None,
        description="The title of the component for display purposes.",
    )

View on GitHub (pinned to 1f02114297)

Solutions

  1. Set a unique class attribute: `KEY_PREFIX = "mycomponent"` on the subclass.
  2. Choose a prefix that does not collide with built-ins (tool, resource, template, prompt).
  3. For abstract intermediates that inherit a valid prefix, ensure you don't blank it out.
  4. Key the registry lookups on the prefix so collisions surface immediately in tests.

Example fix

// before
class SidebarComponent(FastMCPComponent):
    pass
// after
class SidebarComponent(FastMCPComponent):
    KEY_PREFIX = "sidebar"
Defensive patterns

Strategy: validation

Validate before calling

class Checklist:
    @staticmethod
    def validate_component_subclass(cls) -> None:
        prefix = getattr(cls, "KEY_PREFIX", None)
        assert prefix, f"{cls.__name__} must define a non-empty KEY_PREFIX"

Type guard

def has_key_prefix(cls) -> bool:
    return bool(getattr(cls, "KEY_PREFIX", None))

Try / catch

import warnings
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter("always")
    class MyComponent(FastMCPComponent):
        pass
if any("KEY_PREFIX" in str(w.message) for w in caught):
    MyComponent.KEY_PREFIX = "mycomponent"  # or fail the build

Prevention

When it happens

Trigger: Defining a subclass of a component base (e.g. a custom `Resource`/`Tool` variant) without setting `KEY_PREFIX`, or overriding it to `""`.

Common situations: Framework authors adding new component kinds; test doubles subclassing `FastMCPComponent` without keys; accidental override of an inherited prefix with an empty string.

Related errors


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