Initial Checks
Description
When implementing the roots capability in a client-server setup, the communication hangs indefinitely after the server makes a list_roots() request. The client successfully initializes with roots capability, but the server's request for roots never completes.
Observed behavior:
- Client initializes successfully with roots capability
- Server receives tool call and requests roots via
ctx.session.list_roots()
- Communication hangs at this point - no error, no timeout, just stuck
- Both client and server remain running but no further progress
Expected behavior:
- Client should receive the roots/list request
- Client should respond with the configured roots
- Server should receive the response and continue processing
Let me know if you need any additional information or would like me to try specific debugging steps.
Example Code
Example Code:
server.py
from mcp.server.fastmcp import FastMCP, Context
from mcp.types import TextContent
mcp = FastMCP(
name="mcp-roots-server",
stateless_http=True
)
@mcp.tool()
async def analyze_project(ctx: Context) -> TextContent:
print("-> Server: Requesting project roots from client...")
roots = await ctx.session.list_roots() # Hangs here
if not roots or not roots.roots:
return TextContent(text="No project roots found", type="text")
# Never reaches this point
return TextContent(text="Analysis complete", type="text")
mcp_app = mcp.streamable_http_app()
client.py
import asyncio
from pathlib import Path
from typing import Any
import mcp.types as types
from mcp.shared.context import RequestContext
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def mock_roots_list(context: RequestContext["ClientSession", Any]) -> types.ListRootsResult | types.ErrorData:
print(f"<- Client: Received roots/list request")
root_uri = f"file://{Path.cwd().absolute()}"
return types.ListRootsResult(roots=[types.Root(
uri=types.FileUrl(root_uri),
name="Current Project"
)])
async def main():
server_url = "http://localhost:8000/mcp/"
async with streamablehttp_client(server_url) as (read_stream, write_stream, get_session_id):
async with ClientSession(read_stream, write_stream, list_roots_callback=mock_roots_list) as session:
await session.initialize()
result = await session.call_tool("analyze_project")
if __name__ == "__main__":
asyncio.run(main())
Server logs:
INFO: Started server process [36096]
INFO: Application startup complete.
INFO: 127.0.0.1:51609 - "POST /mcp/ HTTP/1.1" 200 OK
INFO: 127.0.0.1:51611 - "POST /mcp/ HTTP/1.1" 202 Accepted
INFO: 127.0.0.1:51613 - "POST /mcp/ HTTP/1.1" 200 OK
Processing request of type CallToolRequest
-> Server: Requesting project roots from client...
# Hangs here
Client logs:
🚀 Connecting to MCP server at http://localhost:8000/mcp/
✅ Connected. Initializing session...
🛠️ Session initialized with roots capability.
-> Client: Calling analyze_project tool...
# Hangs here
Python & MCP Python SDK
Python & MCP Python SDK:
- Python version: 3.11.7
- MCP Python SDK version: 1.10.1
- OS: macOS 24.5.0
- Environment: Development setup using uvicorn for server
Additional Notes:
- The issue occurs consistently across multiple runs
- No error messages or exceptions are thrown
- Both client and server processes remain running
- Network requests complete successfully (200 OK responses)
- The hang occurs specifically during the roots/list request
Initial Checks
Description
When implementing the roots capability in a client-server setup, the communication hangs indefinitely after the server makes a
list_roots()request. The client successfully initializes with roots capability, but the server's request for roots never completes.Observed behavior:
ctx.session.list_roots()Expected behavior:
Let me know if you need any additional information or would like me to try specific debugging steps.
Example Code
Example Code:
server.py
client.py
Server logs:
Client logs:
Python & MCP Python SDK