mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-26 23:44:17 +02:00
Update matching logic for resources
This commit is contained in:
parent
9ec0be8665
commit
9fdcb8ac93
3 changed files with 194 additions and 12 deletions
|
|
@ -8,7 +8,7 @@ from pydantic import AnyUrl
|
|||
|
||||
from fastmcp.exceptions import ResourceError
|
||||
from fastmcp.resources import FunctionResource, Resource
|
||||
from fastmcp.resources.template import ResourceTemplate
|
||||
from fastmcp.resources.template import ResourceTemplate, match_uri_template
|
||||
from fastmcp.settings import DuplicateBehavior
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
|
||||
|
|
@ -207,9 +207,10 @@ class ResourceManager:
|
|||
if resource := self._resources.get(uri_str):
|
||||
return resource
|
||||
|
||||
# Then check templates
|
||||
for template in self._templates.values():
|
||||
if params := template.matches(uri_str):
|
||||
# Then check templates - use the utility function to match against storage keys
|
||||
for storage_key, template in self._templates.items():
|
||||
# Try to match against the storage key (which might be a custom key)
|
||||
if params := match_uri_template(uri_str, storage_key):
|
||||
try:
|
||||
return await template.create_resource(uri_str, params)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -7,12 +7,37 @@ import re
|
|||
from collections.abc import Callable
|
||||
from typing import Annotated, Any
|
||||
|
||||
from pydantic import BaseModel, BeforeValidator, Field, TypeAdapter, validate_call
|
||||
from pydantic import (
|
||||
AnyUrl,
|
||||
BaseModel,
|
||||
BeforeValidator,
|
||||
Field,
|
||||
TypeAdapter,
|
||||
validate_call,
|
||||
)
|
||||
|
||||
from fastmcp.resources.types import FunctionResource, Resource
|
||||
from fastmcp.utilities.types import _convert_set_defaults
|
||||
|
||||
|
||||
def match_uri_template(uri: str, uri_template: str) -> dict[str, Any] | None:
|
||||
"""Match a URI against a template and extract parameters.
|
||||
|
||||
Args:
|
||||
uri: The URI to match against the template
|
||||
uri_template: The URI template to match against
|
||||
|
||||
Returns:
|
||||
A dictionary of extracted parameters if there's a match, or None if no match
|
||||
"""
|
||||
# Convert template to regex pattern
|
||||
pattern = uri_template.replace("{", "(?P<").replace("}", ">[^/]+)")
|
||||
match = re.match(f"^{pattern}$", uri)
|
||||
if match:
|
||||
return match.groupdict()
|
||||
return None
|
||||
|
||||
|
||||
class MyModel(BaseModel):
|
||||
key: str
|
||||
value: int
|
||||
|
|
@ -94,12 +119,7 @@ class ResourceTemplate(BaseModel):
|
|||
|
||||
def matches(self, uri: str) -> dict[str, Any] | None:
|
||||
"""Check if URI matches template and extract parameters."""
|
||||
# Convert template to regex pattern
|
||||
pattern = self.uri_template.replace("{", "(?P<").replace("}", ">[^/]+)")
|
||||
match = re.match(f"^{pattern}$", uri)
|
||||
if match:
|
||||
return match.groupdict()
|
||||
return None
|
||||
return match_uri_template(uri, self.uri_template)
|
||||
|
||||
async def create_resource(self, uri: str, params: dict[str, Any]) -> Resource:
|
||||
"""Create a resource from the template with the given parameters."""
|
||||
|
|
@ -110,7 +130,7 @@ class ResourceTemplate(BaseModel):
|
|||
result = await result
|
||||
|
||||
return FunctionResource(
|
||||
uri=uri, # type: ignore
|
||||
uri=AnyUrl(uri), # Explicitly convert to AnyUrl
|
||||
name=self.name,
|
||||
description=self.description,
|
||||
mime_type=self.mime_type,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue