Skip to content

Commit 9268cab

Browse files
committed
use request.scope
1 parent 5413bca commit 9268cab

File tree

4 files changed

+25
-23
lines changed

4 files changed

+25
-23
lines changed

src/mcp/server/sse.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,8 @@ async def handle_post_message(
203203
await writer.send(err)
204204
return
205205

206-
# Pass the raw request object for maximum flexibility
207-
# Consumers can use isinstance to check the request type
208-
metadata = ServerMessageMetadata(request_context=request)
206+
# Pass the ASGI scope for framework-agnostic access to request data
207+
metadata = ServerMessageMetadata(request_context=dict(request.scope))
209208
session_message = SessionMessage(message, metadata=metadata)
210209
logger.debug(f"Sending session message to writer: {session_message}")
211210
response = Response("Accepted", status_code=202)

src/mcp/types.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@
3636
Role = Literal["user", "assistant"]
3737
RequestId = str | int
3838
AnyFunction: TypeAlias = Callable[..., Any]
39-
# HTTP request object from web framework (e.g., starlette.requests.Request)
40-
RequestData: TypeAlias = object
39+
# Dictionary containing request metadata (headers, path, method, etc.
40+
# based on ASGI scope for most of the trasport implementations)
41+
RequestData: TypeAlias = dict[str, Any]
4142

4243

4344
class RequestParams(BaseModel):

tests/server/fastmcp/test_integration.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -441,10 +441,12 @@ def make_fastmcp_with_context_app():
441441
def echo_headers(ctx: Context) -> str:
442442
"""Returns the request headers as JSON."""
443443
headers_info = {}
444-
if ctx.request_context.request and isinstance(
445-
ctx.request_context.request, Request
446-
):
447-
headers_info = dict(ctx.request_context.request.headers)
444+
if ctx.request_context.request:
445+
# Extract headers from ASGI scope
446+
headers_list = ctx.request_context.request.get("headers", [])
447+
headers_info = {
448+
k.decode("latin-1"): v.decode("latin-1") for k, v in headers_list
449+
}
448450
return json.dumps(headers_info)
449451

450452
# Tool that returns full request context
@@ -455,13 +457,15 @@ def echo_context(custom_request_id: str, ctx: Context) -> str:
455457
"custom_request_id": custom_request_id,
456458
"headers": {},
457459
"method": None,
458-
"url": None,
460+
"path": None,
459461
}
460462
if ctx.request_context.request:
461-
if isinstance(ctx.request_context.request, Request):
462-
context_data["headers"] = dict(ctx.request_context.request.headers)
463-
context_data["method"] = ctx.request_context.request.method
464-
context_data["url"] = str(ctx.request_context.request.url)
463+
# Extract data from ASGI scope
464+
headers_list = ctx.request_context.request.get("headers", [])
465+
context_data["headers"] = {
466+
k.decode("latin-1"): v.decode("latin-1") for k, v in headers_list
467+
}
468+
context_data["method"] = ctx.request_context.request.get("method")
465469
return json.dumps(context_data)
466470

467471
# Create the SSE app
@@ -558,10 +562,7 @@ async def test_fast_mcp_with_request_context(
558562
context_data["headers"].get("authorization")
559563
== "Bearer fastmcp-test-token"
560564
)
561-
assert context_data["method"] == "POST" # SSE messages are POSTed
562-
assert (
563-
"/messages/" in context_data["url"]
564-
) # Should contain the messages endpoint
565+
assert context_data["method"] == "POST" #
565566

566567

567568
@pytest.mark.anyio

tests/shared/test_sse.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,12 @@ async def handle_call_tool(name: str, args: dict) -> list[TextContent]:
333333
try:
334334
context = self.request_context
335335
if context.request:
336-
# Check if it's a Starlette Request object
337-
from starlette.requests import Request
338-
339-
if isinstance(context.request, Request):
340-
headers_info = dict(context.request.headers)
336+
# Extract headers from ASGI scope
337+
headers_list = context.request.get("headers", [])
338+
headers_info = {
339+
k.decode("latin-1"): v.decode("latin-1")
340+
for k, v in headers_list
341+
}
341342
except LookupError:
342343
pass # No request context available
343344

0 commit comments

Comments
 (0)