Skip to content

Commit 2011579

Browse files
committed
add happy path test
1 parent bce74b3 commit 2011579

File tree

1 file changed

+46
-18
lines changed

1 file changed

+46
-18
lines changed

tests/server/test_streamableHttp.py

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
This file contains tests for request validation in the StreamableHTTP transport.
55
"""
66

7+
import contextlib
78
import multiprocessing
89
import socket
910
import time
10-
from collections.abc import AsyncGenerator, Generator
11+
from collections.abc import Generator
1112
from http import HTTPStatus
1213
from uuid import uuid4
13-
import contextlib
14+
1415
import anyio
1516
import pytest
1617
import requests
@@ -19,7 +20,7 @@
1920
from starlette.applications import Starlette
2021
from starlette.requests import Request
2122
from starlette.responses import Response
22-
from starlette.routing import Mount, Route
23+
from starlette.routing import Mount
2324

2425
from mcp.server import Server
2526
from mcp.server.streamableHttp import (
@@ -29,11 +30,8 @@
2930
)
3031
from mcp.shared.exceptions import McpError
3132
from mcp.types import (
32-
EmptyResult,
3333
ErrorData,
34-
JSONRPCMessage,
3534
TextContent,
36-
TextResourceContents,
3735
Tool,
3836
)
3937

@@ -106,11 +104,9 @@ def create_app(session_id=None) -> Starlette:
106104
# Create server instance
107105
server = ServerTest()
108106

109-
# Store the server instances between requests for session management
110107
server_instances = {}
111108
# Lock to prevent race conditions when creating new sessions
112109
session_creation_lock = anyio.Lock()
113-
# Task group for running server instances
114110
task_group = None
115111

116112
@contextlib.asynccontextmanager
@@ -130,7 +126,6 @@ async def lifespan(app):
130126
task_group = None
131127
print("Resources cleaned up successfully.")
132128

133-
# ASGI handler for streamable HTTP connections
134129
async def handle_streamable_http(scope, receive, send):
135130
request = Request(scope, receive)
136131
request_mcp_session_id = request.headers.get(MCP_SESSION_ID_HEADER)
@@ -141,12 +136,11 @@ async def handle_streamable_http(scope, receive, send):
141136
and request_mcp_session_id in server_instances
142137
):
143138
transport = server_instances[request_mcp_session_id]
144-
print("Session already exists, handling request directly")
139+
145140
await transport.handle_request(scope, receive, send)
146-
elif session_id is None or request_mcp_session_id is None:
141+
elif request_mcp_session_id is None:
147142
async with session_creation_lock:
148-
# For tests with fixed session ID
149-
new_session_id = session_id if session_id else uuid4().hex
143+
new_session_id = uuid4().hex
150144

151145
http_transport = StreamableHTTPServerTransport(
152146
mcp_session_id=new_session_id,
@@ -156,11 +150,14 @@ async def handle_streamable_http(scope, receive, send):
156150
read_stream, write_stream = streams
157151

158152
async def run_server():
159-
await server.run(
160-
read_stream,
161-
write_stream,
162-
server.create_initialization_options(),
163-
)
153+
try:
154+
await server.run(
155+
read_stream,
156+
write_stream,
157+
server.create_initialization_options(),
158+
)
159+
except Exception as e:
160+
print(f"Server exception: {e}")
164161

165162
if task_group is None:
166163
response = Response(
@@ -533,3 +530,34 @@ def test_session_termination(session_server, server_url):
533530
)
534531
assert response.status_code == 404
535532
assert "Session has been terminated" in response.text
533+
534+
535+
def test_response(basic_server, server_url):
536+
"""Test response handling for a valid request."""
537+
mcp_url = f"{server_url}/mcp"
538+
response = requests.post(
539+
mcp_url,
540+
headers={
541+
"Accept": "application/json, text/event-stream",
542+
"Content-Type": "application/json",
543+
},
544+
json=INIT_REQUEST,
545+
)
546+
assert response.status_code == 200
547+
548+
# Now terminate the session
549+
session_id = response.headers.get(MCP_SESSION_ID_HEADER)
550+
551+
# Try to use the terminated session
552+
tools_response = requests.post(
553+
mcp_url,
554+
headers={
555+
"Accept": "application/json, text/event-stream",
556+
"Content-Type": "application/json",
557+
MCP_SESSION_ID_HEADER: session_id, # Use the session ID we got earlier
558+
},
559+
json={"jsonrpc": "2.0", "method": "tools/list", "id": "tools-1"},
560+
stream=True, # Important for SSE
561+
)
562+
assert tools_response.status_code == 200
563+
assert tools_response.headers.get("Content-Type") == "text/event-stream"

0 commit comments

Comments
 (0)