@@ -113,39 +113,55 @@ async def handle_message(scope: Scope, receive: Receive, send: Send):
113
113
read_stream , read_stream_writer , write_stream , write_stream_reader = make_streams ()
114
114
115
115
async def handle_post_message ():
116
- request = Request (scope , receive )
117
116
try :
118
- json = await request .json ()
119
- except JSONDecodeError as err :
120
- logger .error (f"Failed to parse message: { err } " )
121
- response = Response ("Could not parse message" , status_code = 400 )
122
- await response (scope , receive , send )
123
- return
124
- try :
125
- client_message = types .JSONRPCMessage .model_validate (json )
126
- logger .debug (f"Validated client message: { client_message } " )
127
- except ValidationError as err :
128
- logger .error (f"Failed to parse message: { err } " )
129
- response = Response ("Could not parse message" , status_code = 400 )
117
+ request = Request (scope , receive )
118
+ if request .method != "POST" :
119
+ response = Response ("Method not allowed" , status_code = 405 )
120
+ await response (scope , receive , send )
121
+ return
122
+ if scope ["path" ] != "/mcp" :
123
+ response = Response ("Not found" , status_code = 404 )
124
+ await response (scope , receive , send )
125
+ return
126
+ try :
127
+ json = await request .json ()
128
+ except JSONDecodeError as err :
129
+ logger .error (f"Failed to parse message: { err } " )
130
+ response = Response ("Could not parse message" , status_code = 400 )
131
+ await response (scope , receive , send )
132
+ return
133
+
134
+ try :
135
+ client_message = types .JSONRPCMessage .model_validate (json )
136
+ logger .debug (f"Validated client message: { client_message } " )
137
+ except ValidationError as err :
138
+ logger .error (f"Failed to parse message: { err } " )
139
+ response = Response ("Could not parse message" , status_code = 400 )
140
+ await response (scope , receive , send )
141
+ return
142
+
143
+ # As part of the MCP spec we need to initialize first.
144
+ # In a stateful flow (e.g. stdio or sse transports) the client would
145
+ # send an initialize request to the server, and the server would send
146
+ # a response back to the client. In this case we're trying to be stateless,
147
+ # so we'll handle the initialization ourselves.
148
+ logger .debug ("Initializing server" )
149
+ await initialize (read_stream_writer , write_stream_reader )
150
+
151
+ # Alright, now we can send the client message.
152
+ logger .debug ("Sending client message" )
153
+ await read_stream_writer .send (client_message )
154
+
155
+ # Wait for the server's response, and forward it to the client.
156
+ server_message = await write_stream_reader .receive ()
157
+ obj = server_message .model_dump (
158
+ by_alias = True , mode = "json" , exclude_none = True
159
+ )
160
+ response = JSONResponse (obj )
130
161
await response (scope , receive , send )
131
- return
132
-
133
- # As part of the MCP spec we need to initialize first.
134
- # In a stateful flow (e.g. stdio or sse transports) the client would
135
- # send an initialize request to the server, and the server would send
136
- # a response back to the client. In this case we're trying to be stateless,
137
- # so we'll handle the initialization ourselves.
138
- logger .debug ("Initializing server" )
139
- await initialize (read_stream_writer , write_stream_reader )
140
-
141
- # Alright, now we can send the client message.
142
- logger .debug ("Sending client message" )
143
- await read_stream_writer .send (client_message )
144
- # Wait for the server's response, and forward it to the client.
145
- server_message = await write_stream_reader .receive ()
146
- obj = server_message .model_dump (by_alias = True , mode = "json" , exclude_none = True )
147
- response = JSONResponse (obj )
148
- await response (scope , receive , send )
162
+ finally :
163
+ await read_stream_writer .aclose ()
164
+ await write_stream_reader .aclose ()
149
165
150
166
async with anyio .create_task_group () as tg :
151
167
tg .start_soon (handle_post_message )
0 commit comments