diff --git a/src/fastmcp/utilities/components.py b/src/fastmcp/utilities/components.py index 168599807..dc787e3c9 100644 --- a/src/fastmcp/utilities/components.py +++ b/src/fastmcp/utilities/components.py @@ -31,7 +31,13 @@ def get_fastmcp_metadata(meta: dict[str, Any] | None) -> FastMCPMeta: """ if not meta: return {} - return cast(FastMCPMeta, meta.get("fastmcp") or meta.get("_fastmcp") or {}) + + for key in ("fastmcp", "_fastmcp"): + metadata = meta.get(key) + if isinstance(metadata, dict): + return cast(FastMCPMeta, metadata) + + return {} def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]: diff --git a/tests/utilities/test_components.py b/tests/utilities/test_components.py index d359ca467..d8b852986 100644 --- a/tests/utilities/test_components.py +++ b/tests/utilities/test_components.py @@ -13,6 +13,7 @@ FastMCPComponent, FastMCPMeta, _convert_set_default_none, + get_fastmcp_metadata, ) @@ -251,6 +252,25 @@ class WithPrefix(FastMCPComponent): assert WithPrefix.make_key("test") == "custom:test" +class TestGetFastMCPMetadata: + """Tests for get_fastmcp_metadata helper.""" + + def test_returns_fastmcp_namespace_when_dict(self): + meta = {"fastmcp": {"tags": ["a"]}, "_fastmcp": {"tags": ["b"]}} + + assert get_fastmcp_metadata(meta) == {"tags": ["a"]} + + def test_falls_back_to_legacy_namespace_when_dict(self): + meta = {"fastmcp": "invalid", "_fastmcp": {"tags": ["legacy"]}} + + assert get_fastmcp_metadata(meta) == {"tags": ["legacy"]} + + def test_ignores_non_dict_metadata(self): + assert get_fastmcp_metadata({"fastmcp": "invalid"}) == {} + assert get_fastmcp_metadata({"fastmcp": ["invalid"]}) == {} + assert get_fastmcp_metadata({"_fastmcp": "invalid"}) == {} + + class TestComponentEnableDisable: """Tests for the enable/disable methods raising NotImplementedError."""