From 61d98b41d1b50dc03fd167a6f8d41ee4b87c586b Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Sat, 17 Jan 2026 14:40:16 -0500 Subject: [PATCH] refactor: reverse visibility for get_resource/_get_resource methods --- src/fastmcp/server/middleware/authorization.py | 2 +- src/fastmcp/server/providers/aggregate.py | 4 ++-- src/fastmcp/server/providers/base.py | 10 +++++----- src/fastmcp/server/providers/fastmcp_provider.py | 6 +++--- src/fastmcp/server/providers/filesystem.py | 4 ++-- src/fastmcp/server/providers/local_provider.py | 2 +- src/fastmcp/server/providers/openapi/provider.py | 2 +- src/fastmcp/server/server.py | 8 ++++---- tests/server/providers/test_transforming_provider.py | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/fastmcp/server/middleware/authorization.py b/src/fastmcp/server/middleware/authorization.py index 1b696fe20..8fb149f78 100644 --- a/src/fastmcp/server/middleware/authorization.py +++ b/src/fastmcp/server/middleware/authorization.py @@ -202,7 +202,7 @@ class AuthMiddleware(Middleware): ) # Get resource/template (component auth is checked in get_*, raises if unauthorized) - component = await fastmcp.fastmcp._get_resource(str(uri)) + component = await fastmcp.fastmcp.get_resource(str(uri)) if component is None: component = await fastmcp.fastmcp._get_resource_template(str(uri)) if component is None: diff --git a/src/fastmcp/server/providers/aggregate.py b/src/fastmcp/server/providers/aggregate.py index bc8ad906c..e2b53ffa6 100644 --- a/src/fastmcp/server/providers/aggregate.py +++ b/src/fastmcp/server/providers/aggregate.py @@ -159,7 +159,7 @@ class AggregateProvider(Provider): ) return self._collect_list_results(results, "list_resources") - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get resource by URI. @@ -170,7 +170,7 @@ class AggregateProvider(Provider): If specified, returns highest version matching the spec from any provider. """ results = await gather( - *[p._get_resource(uri, version) for p in self._providers], + *[p.get_resource(uri, version) for p in self._providers], return_exceptions=True, ) return self._get_highest_version_result(results, f"get_resource({uri!r})") # type: ignore[return-value] diff --git a/src/fastmcp/server/providers/base.py b/src/fastmcp/server/providers/base.py index 8595c9371..2ebe7941e 100644 --- a/src/fastmcp/server/providers/base.py +++ b/src/fastmcp/server/providers/base.py @@ -153,7 +153,7 @@ class Provider: return await chain() - async def _get_resource( + async def get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get resource by transformed URI with all transforms applied. @@ -164,7 +164,7 @@ class Provider: """ async def base(u: str, version: VersionSpec | None = None) -> Resource | None: - return await self.get_resource(u, version) + return await self._get_resource(u, version) chain = base for transform in self.transforms: @@ -280,12 +280,12 @@ class Provider: """ return [] - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a specific resource by URI. - Default implementation filters list_resources() and returns highest + Default implementation filters _list_resources() and returns highest version matching the spec. Args: @@ -295,7 +295,7 @@ class Provider: Returns: The Resource if found, or None to continue searching other providers. """ - resources = await self.list_resources() + resources = await self._list_resources() matching = [r for r in resources if str(r.uri) == uri] if version: matching = [r for r in matching if version.matches(r.version)] diff --git a/src/fastmcp/server/providers/fastmcp_provider.py b/src/fastmcp/server/providers/fastmcp_provider.py index b18caeb6b..0054e4638 100644 --- a/src/fastmcp/server/providers/fastmcp_provider.py +++ b/src/fastmcp/server/providers/fastmcp_provider.py @@ -520,16 +520,16 @@ class FastMCPProvider(Provider): raw_resources = await self.server.get_resources(run_middleware=True) return [FastMCPProviderResource.wrap(self.server, r) for r in raw_resources] - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a concrete resource by URI as a FastMCPProviderResource. Passes the full VersionSpec to the nested server, which handles both - exact version matching and range filtering. Uses _get_resource to ensure + exact version matching and range filtering. Uses get_resource to ensure the nested server's transforms are applied. """ - raw_resource = await self.server._get_resource(uri, version) + raw_resource = await self.server.get_resource(uri, version) if raw_resource is None: return None return FastMCPProviderResource.wrap(self.server, raw_resource) diff --git a/src/fastmcp/server/providers/filesystem.py b/src/fastmcp/server/providers/filesystem.py index 56c1fe534..9092d37ab 100644 --- a/src/fastmcp/server/providers/filesystem.py +++ b/src/fastmcp/server/providers/filesystem.py @@ -191,12 +191,12 @@ class FileSystemProvider(LocalProvider): await self._ensure_loaded() return await super()._list_resources() - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a resource by URI, reloading if in reload mode.""" await self._ensure_loaded() - return await super().get_resource(uri, version) + return await super()._get_resource(uri, version) async def list_resource_templates(self) -> Sequence[ResourceTemplate]: """Return all resource templates, reloading if in reload mode.""" diff --git a/src/fastmcp/server/providers/local_provider.py b/src/fastmcp/server/providers/local_provider.py index 788768b23..3a8bb1289 100644 --- a/src/fastmcp/server/providers/local_provider.py +++ b/src/fastmcp/server/providers/local_provider.py @@ -528,7 +528,7 @@ class LocalProvider(Provider): if isinstance(v, Resource) and self._is_component_enabled(v) ] - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a resource by URI. diff --git a/src/fastmcp/server/providers/openapi/provider.py b/src/fastmcp/server/providers/openapi/provider.py index 839ca004d..263948b27 100644 --- a/src/fastmcp/server/providers/openapi/provider.py +++ b/src/fastmcp/server/providers/openapi/provider.py @@ -368,7 +368,7 @@ class OpenAPIProvider(Provider): """Return all resources created from the OpenAPI spec.""" return list(self._resources.values()) - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a resource by URI.""" diff --git a/src/fastmcp/server/server.py b/src/fastmcp/server/server.py index f2e2c3555..77521ecfc 100644 --- a/src/fastmcp/server/server.py +++ b/src/fastmcp/server/server.py @@ -1223,12 +1223,12 @@ class FastMCP(Provider, Generic[LifespanResultT]): return _dedupe_with_versions(authorized, lambda r: str(r.uri)) - async def get_resource( + async def _get_resource( self, uri: str, version: VersionSpec | None = None ) -> Resource | None: """Get a resource by URI via aggregation from providers. - This is the raw lookup that Provider._get_resource() wraps with transforms. + This is the raw lookup that Provider.get_resource() wraps with transforms. Aggregates from all sub-providers and applies component-level auth. Args: @@ -1240,7 +1240,7 @@ class FastMCP(Provider, Generic[LifespanResultT]): """ # Aggregate from all sub-providers (each applies their own transforms) results = await gather( - *[p._get_resource(uri, version) for p in self._providers], + *[p.get_resource(uri, version) for p in self._providers], return_exceptions=True, ) @@ -1666,7 +1666,7 @@ class FastMCP(Provider, Generic[LifespanResultT]): resource_uri=uri, ) as span: # Try concrete resources first (transforms + auth via _get_resource) - resource = await self._get_resource(uri, version=version) + resource = await self.get_resource(uri, version=version) if resource is not None: span.set_attributes(resource.get_span_attributes()) if task_meta is not None and task_meta.fn_key is None: diff --git a/tests/server/providers/test_transforming_provider.py b/tests/server/providers/test_transforming_provider.py index 28f89293b..b2021abd6 100644 --- a/tests/server/providers/test_transforming_provider.py +++ b/tests/server/providers/test_transforming_provider.py @@ -197,7 +197,7 @@ class TestTransformReverseLookup: layer = Namespace("ns") async def get_resource(uri: str, version=None): - return await provider.get_resource(uri, version) + return await provider._get_resource(uri, version) resource = await layer.get_resource("resource://ns/data", get_resource)