You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Question: How to get a resource argument containing "/" ? #436
Seems this could still be relevant, maybe we could consider looking into doing something similar to FastAPI/Starlette with {file_path:path} where path specifies this can have slashes in it.
@Kludex do you think this makes sense? Did it work well for Starlette?
"""Test resource templates with path parameters containing forward slashes."""importjsonfromtypingimportAnyimportpytestfrommcp.server.fastmcp.resourcesimportFunctionResource, ResourceTemplatedeftest_template_with_path_parameter_single_level():
"""Test matching URIs with single-level path parameters."""deffolder_contents(path: str) ->list[str]:
return ["file1.txt", "file2.txt"]
template=ResourceTemplate.from_function(
fn=folder_contents,
uri_template="folder://{path}",
name="folder",
)
# Single level path should workparams=template.matches("folder://root")
assertparams== {"path": "root"}
deftest_template_with_path_parameter_nested_path():
"""Test matching URIs with nested path parameters containing forward slashes. This is the issue reported in #436. A user wants to define a resource like: @mcp.resource("folder://{path}") def folder_contents(path: str) -> list[str]: And then be able to match URIs like "folder://xxx/abc/zzz/" where the path parameter contains forward slashes. Currently, this fails because the regex pattern uses [^/]+ which excludes forward slashes. """deffolder_contents(path: str) ->list[str]:
# This would return the contents of the nested directoryreturn ["file1.txt", "file2.txt"]
template=ResourceTemplate.from_function(
fn=folder_contents,
uri_template="folder://{path}",
name="folder",
)
# Nested paths with slashes should work but currently failparams=template.matches("folder://xxx/abc/zzz/")
# This should match and extract the full pathassertparamsisnotNone, "Failed to match nested path with slashes"assertparams== {"path": "xxx/abc/zzz/"}
deftest_template_with_path_parameter_various_paths():
"""Test matching various nested paths."""defget_file(path: str) ->str:
returnf"Content of {path}"template=ResourceTemplate.from_function(
fn=get_file,
uri_template="file://{path}",
name="file",
)
# Test various nested pathstest_cases= [
("file://simple", {"path": "simple"}),
("file://one/two", {"path": "one/two"}),
("file://one/two/three", {"path": "one/two/three"}),
("file://very/deep/nested/path/to/file.txt",
{"path": "very/deep/nested/path/to/file.txt"}),
("file://path/with/trailing/slash/",
{"path": "path/with/trailing/slash/"}),
("file://path.with.dots/file.txt",
{"path": "path.with.dots/file.txt"}),
]
foruri, expected_paramsintest_cases:
params=template.matches(uri)
assertparamsisnotNone, f"Failed to match URI: {uri}"assertparams==expected_params, (
f"For URI {uri}, expected {expected_params} but got {params}"
)
deftest_template_with_multiple_params_and_path():
"""Test template with multiple parameters where one is a path."""defget_resource(bucket: str, path: str) ->dict[str, Any]:
return {"bucket": bucket, "path": path}
template=ResourceTemplate.from_function(
fn=get_resource,
uri_template="s3://{bucket}/{path}",
name="s3",
)
# This should extract bucket and path separately,# with path potentially containing slashesparams=template.matches("s3://mybucket/folder/subfolder/file.txt")
assertparamsisnotNone# If the regex allowed slashes in the last parameter,# this would work correctlyassertparams["bucket"] =="mybucket"# The path might contain slashesassert"file.txt"inparams["path"]
@pytest.mark.anyioasyncdeftest_create_resource_with_nested_path():
"""Test creating a resource from template with nested path parameter."""defread_folder(path: str) ->list[str]:
# Simulate reading a folder at the given pathifpath=="project/src/components":
return ["Button.tsx", "Card.tsx", "Header.tsx"]
return []
template=ResourceTemplate.from_function(
fn=read_folder,
uri_template="folder://{path}",
name="folder",
)
# Try to match and create a resource with a nested pathuri="folder://project/src/components"params=template.matches(uri)
assertparamsisnotNoneresource=awaittemplate.create_resource(uri, params)
assertisinstance(resource, FunctionResource)
content=awaitresource.read()
assertisinstance(content, str)
data=json.loads(content)
assert"Button.tsx"indataassert"Card.tsx"indataassert"Header.tsx"indata
Seems this could still be relevant, maybe we could consider looking into doing something similar to FastAPI/Starlette with {file_path:path} where path specifies this can have slashes in it.
@Kludex do you think this makes sense? Did it work well for Starlette?
It does work well, there's no way to do that without the converters.
Seems this could still be relevant, maybe we could consider looking into doing something similar to FastAPI/Starlette with {file_path:path} where path specifies this can have slashes in it. @Kludex do you think this makes sense? Did it work well for Starlette?
It does work well, there's no way to do that without the converters.
Can we just import from starlette or do we need to implement something custom
Seems this could still be relevant, maybe we could consider looking into doing something similar to FastAPI/Starlette with {file_path:path} where path specifies this can have slashes in it. @Kludex do you think this makes sense? Did it work well for Starlette?
It does work well, there's no way to do that without the converters.
Can we just import from starlette or do we need to implement something custom
Activity
felixweinberger commentedon Oct 7, 2025
Hi is this still a problem? If yes could you provide a code snippet that demonstrates the issue, your expectations and where it fails?
maxisbey commentedon Oct 8, 2025
Seems this could still be relevant, maybe we could consider looking into doing something similar to FastAPI/Starlette with
{file_path:path}wherepathspecifies this can have slashes in it.@Kludex do you think this makes sense? Did it work well for Starlette?
maxisbey commentedon Oct 8, 2025
Claude's repro:
Kludex commentedon Oct 8, 2025
It does work well, there's no way to do that without the converters.
maxisbey commentedon Oct 8, 2025
Can we just import from starlette or do we need to implement something custom
Kludex commentedon Dec 4, 2025
I think we can copy that logic in here.
maxisbey commentedon Dec 8, 2025
related: #220