@@ -138,4 +138,124 @@ public function test_connect_sends_messages(): void
138138
139139 $ this ->mcpProtocol ->connect ();
140140 }
141+
142+ /**
143+ * Test that handleMessage handles invalid JSON-RPC messages by sending an error response
144+ */
145+ public function test_handleMessage_handles_invalid_jsonrpc (): void
146+ {
147+ $ clientId = 'client_1 ' ;
148+ $ invalidMessage = ['id ' => 1 , 'method ' => 'example.method ' ];
149+
150+ $ this ->mockTransport
151+ ->expects ($ this ->once ())
152+ ->method ('pushMessage ' )
153+ ->with (
154+ $ clientId ,
155+ $ this ->callback (function (array $ response ) {
156+ $ this ->assertEquals ('2.0 ' , $ response ['jsonrpc ' ]);
157+ $ this ->assertEquals (-32600 , $ response ['error ' ]['code ' ]);
158+ $ this ->assertEquals ('Invalid Request: Not a valid JSON-RPC 2.0 message ' , $ response ['error ' ]['message ' ]);
159+ return true ;
160+ })
161+ );
162+
163+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ invalidMessage );
164+ }
165+
166+ /**
167+ * Test that handleMessage processes valid request messages and sends results using the transport
168+ */
169+ public function test_handleMessage_handles_valid_request (): void
170+ {
171+ $ clientId = 'client_1 ' ;
172+ $ validRequestMessage = ['jsonrpc ' => '2.0 ' , 'id ' => 1 , 'method ' => 'test.method ' , 'params ' => ['param1 ' => 'value1 ' ]];
173+
174+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \RequestHandler::class);
175+ $ mockHandler ->method ('isHandle ' )->with ('test.method ' )->willReturn (true );
176+ $ mockHandler ->method ('execute ' )->with ('test.method ' , ['param1 ' => 'value1 ' ])->willReturn (['response ' => 'ok ' ]);
177+ $ this ->mcpProtocol ->registerRequestHandler ($ mockHandler );
178+
179+ $ this ->mockTransport
180+ ->expects ($ this ->once ())
181+ ->method ('pushMessage ' )
182+ ->with (
183+ $ clientId ,
184+ $ this ->callback (function (array $ response ) {
185+ $ this ->assertEquals ('2.0 ' , $ response ['jsonrpc ' ]);
186+ $ this ->assertEquals (1 , $ response ['id ' ]);
187+ $ this ->assertEquals (['response ' => 'ok ' ], $ response ['result ' ]);
188+ return true ;
189+ })
190+ );
191+
192+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ validRequestMessage );
193+ }
194+
195+ /**
196+ * Test that handleMessage processes valid notification messages without sending a response
197+ */
198+ public function test_handleMessage_handles_valid_notification (): void
199+ {
200+ $ clientId = 'client_1 ' ;
201+ $ validNotificationMessage = ['jsonrpc ' => '2.0 ' , 'method ' => 'notify.method ' , 'params ' => ['param1 ' => 'value1 ' ]];
202+
203+ $ mockHandler = $ this ->createMock (\KLP \KlpMcpServer \Protocol \Handlers \NotificationHandler::class);
204+ $ mockHandler ->method ('isHandle ' )->with ('notify.method ' )->willReturn (true );
205+ $ mockHandler ->expects ($ this ->once ())->method ('execute ' )->with (['param1 ' => 'value1 ' ]);
206+ $ this ->mcpProtocol ->registerNotificationHandler ($ mockHandler );
207+
208+ $ this ->mockTransport
209+ ->expects ($ this ->never ())
210+ ->method ('pushMessage ' );
211+
212+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ validNotificationMessage );
213+ }
214+
215+ /**
216+ * Test that handleMessage responds with an error for unknown methods in requests
217+ */
218+ public function test_handleMessage_handles_unknown_method (): void
219+ {
220+ $ clientId = 'client_1 ' ;
221+ $ unknownRequestMessage = ['jsonrpc ' => '2.0 ' , 'id ' => 1 , 'method ' => 'unknown.method ' ];
222+
223+ $ this ->mockTransport
224+ ->expects ($ this ->once ())
225+ ->method ('pushMessage ' )
226+ ->with ($ this ->callback (function (...$ args ) use ($ clientId ) {
227+ $ data = $ args [1 ];
228+ $ this ->assertEquals ($ clientId , $ args [0 ]);
229+ $ this ->assertEquals ('2.0 ' , $ data ['jsonrpc ' ]);
230+ $ this ->assertEquals (1 , $ data ['id ' ]);
231+ $ this ->assertEquals (-32601 , $ data ['error ' ]['code ' ]);
232+ $ this ->assertEquals ('Method not found: unknown.method ' , $ data ['error ' ]['message ' ]);
233+ return true ;
234+ }));
235+
236+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ unknownRequestMessage );
237+ }
238+
239+ /**
240+ * Test that handleMessage responds with an error for unknown notification in requests
241+ */
242+ public function test_handleMessage_handles_unknown_notification (): void
243+ {
244+ $ clientId = 'client_1 ' ;
245+ $ unknownNotificationMessage = ['jsonrpc ' => '2.0 ' , 'method ' => 'unknown.notify ' ];
246+
247+ $ this ->mockTransport
248+ ->expects ($ this ->once ())
249+ ->method ('pushMessage ' )
250+ ->with ($ this ->callback (function (...$ args ) use ($ clientId ) {
251+ $ data = $ args [1 ];
252+ $ this ->assertEquals ($ clientId , $ args [0 ]);
253+ $ this ->assertEquals ('2.0 ' , $ data ['jsonrpc ' ]);
254+ $ this ->assertEquals (-32601 , $ data ['error ' ]['code ' ]);
255+ $ this ->assertEquals ('Method not found: unknown.notify ' , $ data ['error ' ]['message ' ]);
256+ return true ;
257+ }));
258+
259+ $ this ->mcpProtocol ->handleMessage ($ clientId , $ unknownNotificationMessage );
260+ }
141261}
0 commit comments