Skip to content

Commit d7c21c1

Browse files
committed
bug fix
1 parent bc7df53 commit d7c21c1

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def from_function(
8989
required_params, optional_params = cls._analyze_function_params(original_fn)
9090

9191
# Extract path parameters from URI template
92-
path_params: set[str] = set(re.findall(r"{(\w+)}", re.sub(r"{(\?.+?)}", "", uri_template)))
92+
path_params: set[str] = set(re.findall(r"{\s*(\w+)(?::[^}]+)?\s*}", re.sub(r"{\?.+?}", "", uri_template)))
9393

9494
# Extract query parameters from the URI template if present
9595
query_param_match = re.search(r"{(\?(?:\w+,)*\w+)}", uri_template)
@@ -100,12 +100,12 @@ def from_function(
100100
query_params = set(query_str[1:].split(",")) # Remove the leading '?' and split
101101

102102
if context_kwarg:
103-
required_params = required_params.remove(context_kwarg)
103+
required_params.remove(context_kwarg)
104104

105105
# Validate path parameters match required function parameters
106106
if path_params != required_params:
107107
raise ValueError(
108-
f"Mismatch between URI path parameters {path_params} and required function parameters {required_params}"
108+
f"Mismatch between URI path parameters {path_params} and required function parameters {required_params} with context parameters {context_kwarg}"
109109
)
110110

111111
# Validate query parameters are a subset of optional function parameters
@@ -133,7 +133,8 @@ def from_function(
133133

134134
def _generate_pattern(self) -> tuple[re.Pattern[str], dict[str, Convertor[Any]]]:
135135
"""Compile the URI template into a regex pattern and associated converters."""
136-
parts = self.uri_template.strip("/").split("/")
136+
path_template = re.sub(r"\{\?.*?\}", "", self.uri_template)
137+
parts = path_template.strip("/").split("/")
137138
pattern_parts: list[str] = []
138139
converters: dict[str, Convertor[Any]] = {}
139140
# generate the regex pattern
@@ -223,26 +224,23 @@ async def create_resource(
223224
) -> Resource:
224225
"""Create a resource from the template with the given parameters."""
225226
try:
226-
# Add context to params if needed
227-
params = inject_context(self.fn, params, context, self.context_kwarg) #type: ignore
228-
229227
# Prepare parameters for function call
230228
# For optional parameters not in URL, use their default values
231-
232229
# First add extracted parameters
233230
fn_params = {
234231
name: value
235232
for name, value in params.items()
236233
if name in self.required_params or name in self.optional_params
237234
}
238-
235+
# Add context to params
236+
fn_params = inject_context(self.fn, fn_params, context, self.context_kwarg) #type: ignore
239237
# self.fn is now multiply-decorated:
240238
# 1. validate_call for coercion/validation
241239
# 2. our new decorator for default fallback on optional param validation err
242240
result = self.fn(**fn_params)
243241
if inspect.iscoroutine(result):
244242
result = await result
245-
243+
246244
return FunctionResource(
247245
uri=uri, # type: ignore
248246
name=self.name,

0 commit comments

Comments
 (0)