-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Describe the bug
A clear and concise description of what the bug is.
Implement a client using the python-sdk.
Implement a FastMCP server exposing resource templates
python-sdk based client cannot display resource templates exposed by FastMCP server...
After fixing #129 this bug is exposed when using a client based on python-sdk and a server based on FastMCP.
To Reproduce
Steps to reproduce the behavior:
Implement simple MCP sever exposing a resource template:
#easy_echo.py
"""
FastMCP Echo Server
Implements resource template
"""
from mcp.server.fastmcp import FastMCP
\# Create server
mcp = FastMCP("Easy Echo Server")
@mcp.resource("template://resource/{text}/{more_text}", description="resource template")
def resource_template(text: str, more_text: str) -> str:
"""function name becomes the name"""
return f"text: {text}, more_text {more_text}"
Implement a simple MCP client to connect to the server and return the resource template
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
\# Create server parameters for stdio connection
server_params = StdioServerParameters(
command=".venv/bin/uv", # Executable
args=["run", "--with", "mcp", "mcp", "run", "examples/fastmcp/easy_echo.py"], # Properly split args
env={"PATH": ".venv/bin"} # Use dictionary for env variables
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialize the connection
await session.initialize()
\# List available resource templates
resource_templates = await session.list_resource_templates()
print(f"{resource_templates=}") # raw list_resource_templates() result
\# Extract relevant data
templates = resource_templates.resourceTemplates
print("\nAvailable Resource Templates:")
for template in templates:
print(f"🔹 Name: {template.name}")
print(f" 🔗 URI: {template.uriTemplate}")
print(f" 📜 Description: {template.description}")
print()
\# Read a resource template
resource = await session.read_resource("template://resource/hello_world/more_text")
print(f"{resource=}") # raw read_resource() results
print(f" 🔗 URI: {resource.contents[0].uri}")
print(f" 📜 Result: {resource.contents[0].text}")
print()
if __name__ == "__main__":
import asyncio
asyncio.run(run())
run the client test:
python examples/fastmcp/easy_test.py
Expected behavior
/resource/templates/list returns resource templates
(output from easy_test.py AFTER implementing simple correction in src/mcp/client/session.py)
raw output
resource=ReadResourceResult(meta=None, contents=[TextResourceContents(uri=AnyUrl('template://resource/hello_world/more_text'), mimeType='text/plain', text='text: hello_world, more_text more_text')])
structured output
1. resources/templates/list
Request:
{
"method": "resources/templates/list",
"params": {}
}
Response:
{
"resourceTemplates": [
{
"uriTemplate": "template://resource/{text}/{more_text}",
"name": "resource_template",
"description": "resource template"
}
]
}
output from easy_test.py
Processing request of type ListResourceTemplatesRequest server.py:638
resource_templates=ListResourceTemplatesResult(meta=None, nextCursor=None, resourceTemplates=[])
Available Resource Templates:
INFO Processing request of type ReadResourceRequest server.py:638
resource=ReadResourceResult(meta=None, contents=[TextResourceContents(uri=AnyUrl('template://resource/hello_world/more_text'), mimeType='text/plain', text='text: hello_world, more_text more_text')])
🔗 URI: template://resource/hello_world/more_text
📜 Result: text: hello_world, more_text more_text
Note that the inspector is implemented in typescript and will return a valid response template regardless of whether session.py is fixed.
Actual behavior
Throws error: (thrown by easy_test.py)
[01/07/25 08:35:55] INFO Processing request of type ListResourcesRequest server.py:638
resources=ListResourcesResult(meta=None, nextCursor=None, resources=[])
Available Resources:
+ Exception Group Traceback (most recent call last):
| File "src/mcp/client/stdio.py", line 153, in stdio_client
| yield read_stream, write_stream
| File "examples/fastmcp/easy_test.py", line 14, in run
| async with ClientSession(read, write) as session:
| File "src/mcp/shared/session.py", line 122, in __aexit__
| return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
| File ".venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 685, in __aexit__
| raise BaseExceptionGroup(
| exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "examples/fastmcp/easy_test.py", line 38, in run
| resource_templates = await session.list_resource_templates()
| AttributeError: 'ClientSession' object has no attribute 'list_resource_templates'
ADD TO: src/mcp/client/session.py
async def list_resource_templates(self) -> types.ListResourceTemplatesResult:
"""Send a resources/templates/list request."""
return await self.send_request(
types.ClientRequest(
types.ListResourceTemplatesRequest(
method="resources/templates/list",
)
),
types.ListResourceTemplatesResult,
)
Desktop (please complete the following information):
- OS: Mac OS Monterey
- Browser Chrome
Additional context
Although this will enable list_resource_templates, and the use of resource templates, with a custom client based on the python-sdk there does not appear to be any support for resource templates in the Claude Desktop Client - I have tested with both python-sdk and fastmcp based servers.
I understand this is not specifically a FastMCP issue, but clients may currently only be built with the python-sdk and thus clients are unable to utilize resource templates provided by FastMCP.