Skip to content

Commit 645f23e

Browse files
committed
flake8 fix
Signed-off-by: Mihai Criveti <[email protected]>
1 parent ac605f6 commit 645f23e

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

mcpgateway/transports/streamablehttp_transport.py

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
server_id_var: contextvars.ContextVar[str] = contextvars.ContextVar("server_id", default=None)
5858

59-
## ------------------------------ Event store ------------------------------
59+
# ------------------------------ Event store ------------------------------
6060

6161

6262
@dataclass
@@ -92,7 +92,16 @@ def __init__(self, max_events_per_stream: int = 100):
9292
self.event_index: dict[EventId, EventEntry] = {}
9393

9494
async def store_event(self, stream_id: StreamId, message: JSONRPCMessage) -> EventId:
95-
"""Stores an event with a generated event ID."""
95+
"""
96+
Stores an event with a generated event ID.
97+
98+
Args:
99+
stream_id (StreamId): The ID of the stream.
100+
message (JSONRPCMessage): The message to store.
101+
102+
Returns:
103+
EventId: The ID of the stored event.
104+
"""
96105
event_id = str(uuid4())
97106
event_entry = EventEntry(event_id=event_id, stream_id=stream_id, message=message)
98107

@@ -117,7 +126,16 @@ async def replay_events_after(
117126
last_event_id: EventId,
118127
send_callback: EventCallback,
119128
) -> StreamId | None:
120-
"""Replays events that occurred after the specified event ID."""
129+
"""
130+
Replays events that occurred after the specified event ID.
131+
132+
Args:
133+
last_event_id (EventId): The ID of the last received event. Replay starts after this event.
134+
send_callback (EventCallback): Async callback to send each replayed event.
135+
136+
Returns:
137+
StreamId | None: The stream ID if the event is found and replayed, otherwise None.
138+
"""
121139
if last_event_id not in self.event_index:
122140
logger.warning(f"Event ID {last_event_id} not found in store")
123141
return None
@@ -138,7 +156,7 @@ async def replay_events_after(
138156
return stream_id
139157

140158

141-
## ------------------------------ Streamable HTTP Transport ------------------------------
159+
# ------------------------------ Streamable HTTP Transport ------------------------------
142160

143161

144162
@asynccontextmanager
@@ -148,7 +166,7 @@ async def get_db():
148166
149167
Yields:
150168
A database session instance from SessionLocal.
151-
Ensures the session is closed after use.
169+
Ensures the session is closed after use.
152170
"""
153171
db = SessionLocal()
154172
try:
@@ -168,7 +186,7 @@ async def call_tool(name: str, arguments: dict) -> List[Union[types.TextContent,
168186
169187
Returns:
170188
List of content (TextContent, ImageContent, or EmbeddedResource) from the tool response.
171-
Logs and returns an empty list on failure.
189+
Logs and returns an empty list on failure.
172190
"""
173191
try:
174192
async with get_db() as db:
@@ -190,7 +208,7 @@ async def list_tools() -> List[types.Tool]:
190208
191209
Returns:
192210
A list of Tool objects containing metadata such as name, description, and input schema.
193-
Logs and returns an empty list on failure.
211+
Logs and returns an empty list on failure.
194212
"""
195213
server_id = server_id_var.get()
196214

@@ -260,6 +278,10 @@ async def handle_streamable_http(self, scope: Scope, receive: Receive, send: Sen
260278
scope (Scope): ASGI scope object containing connection information.
261279
receive (Receive): ASGI receive callable.
262280
send (Send): ASGI send callable.
281+
282+
Raises:
283+
Exception: Any exception raised during request handling is logged.
284+
263285
Logs any exceptions that occur during request handling.
264286
"""
265287

@@ -277,20 +299,30 @@ async def handle_streamable_http(self, scope: Scope, receive: Receive, send: Sen
277299
raise
278300

279301

280-
## ------------------------- Authentication for /mcp routes ------------------------------
302+
# ------------------------- Authentication for /mcp routes ------------------------------
281303

282304

283305
async def streamable_http_auth(scope, receive, send):
284306
"""
285307
Perform authentication check in middleware context (ASGI scope).
286308
287-
If path does not end with "/mcp", just continue (return True).
309+
This function is intended to be used in middleware wrapping ASGI apps.
310+
It authenticates only requests targeting paths ending in "/mcp" or "/mcp/".
288311
289-
Only check Authorization header for Bearer token.
290-
If no Bearer token provided, allow (return True).
312+
Behavior:
313+
- If the path does not end with "/mcp", authentication is skipped.
314+
- If there is no Authorization header, the request is allowed.
315+
- If a Bearer token is present, it is verified using `verify_credentials`.
316+
- If verification fails, a 401 Unauthorized JSON response is sent.
291317
292-
If auth_required is True and Bearer token provided, verify it.
293-
If verification fails, send 401 JSONResponse and return False.
318+
Args:
319+
scope: The ASGI scope dictionary, which includes request metadata.
320+
receive: ASGI receive callable used to receive events.
321+
send: ASGI send callable used to send events (e.g. a 401 response).
322+
323+
Returns:
324+
bool: True if authentication passes or is skipped.
325+
False if authentication fails and a 401 response is sent.
294326
"""
295327

296328
path = scope.get("path", "")

0 commit comments

Comments
 (0)