Skip to content

Commit 8742101

Browse files
committed
Enhancement: compile and store the pattern once instead of recompiling it on every match, removed bare exception added value error
1 parent 8fb7988 commit 8742101

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

src/mcp/server/fastmcp/resources/templates.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class ResourceTemplate(BaseModel):
3333
fn: Callable[..., Any] = Field(exclude=True)
3434
parameters: dict[str, Any] = Field(description="JSON schema for function parameters")
3535
context_kwarg: str | None = Field(None, description="Name of the kwarg that should receive context")
36+
_compiled_pattern: re.Pattern[str] | None = None
37+
_convertors: dict[str, Convertor[Any]] | None = None
3638

3739
@classmethod
3840
def from_function(
@@ -77,12 +79,9 @@ def from_function(
7779
context_kwarg=context_kwarg,
7880
)
7981

80-
def matches(self, uri: str) -> dict[str, Any] | None:
81-
"""Check if URI matches template and extract parameters."""
82-
uriTemplate = str(self.uri_template)
83-
uri = str(uri)
84-
85-
parts = uriTemplate.strip("/").split("/")
82+
def _generate_pattern(self) -> tuple[re.Pattern[str], dict[str, Convertor[Any]]]:
83+
"""Compile the URI template into a regex pattern and associated converters."""
84+
parts = self.uri_template.strip("/").split("/")
8685
pattern_parts: list[str] = []
8786
converters: dict[str, Convertor[Any]] = {}
8887
# generate the regex pattern
@@ -106,21 +105,26 @@ def matches(self, uri: str) -> dict[str, Any] | None:
106105
else:
107106
pattern_parts.append(re.escape(part))
108107

109-
pattern = "^" + "/".join(pattern_parts) + "$"
110-
# check if the pattern matches
111-
regex = re.compile(pattern)
112-
match = regex.match(uri.strip("/"))
108+
return re.compile("^" + "/".join(pattern_parts) + "$"),converters
109+
110+
def matches(self, uri: str) -> dict[str, Any] | None:
111+
"""Check if URI matches template and extract parameters."""
112+
if not self._compiled_pattern or not self._convertors:
113+
self._compiled_pattern,self._convertors = self._generate_pattern()
114+
115+
uri = str(uri)
116+
match = self._compiled_pattern.match(uri.strip("/"))
113117
if not match:
114118
return None
115119

116120
# try to convert them into respective types
117121
result: dict[str, Any] = {}
118-
for name, conv in converters.items():
122+
for name, conv in self._convertors.items():
119123
raw_value = match.group(name)
120124
try:
121125
result[name] = conv.convert(raw_value)
122-
except Exception:
123-
return None
126+
except Exception as e:
127+
raise ValueError(f"Failed to convert '{raw_value}' for '{name}': {e}")
124128

125129
return result
126130

0 commit comments

Comments
 (0)