@@ -63,7 +63,7 @@ def test_roundtrip(self):
6363
6464class TestEventTopicDescriptor :
6565 def test_basic (self ):
66- d = EventTopicDescriptor (pattern = "foo/bar" , description = "A topic" , retained = True )
66+ d = EventTopicDescriptor (pattern = "foo/bar" , description = "A topic" , retained = True , schema = None )
6767 assert d .pattern == "foo/bar"
6868 assert d .description == "A topic"
6969 assert d .retained is True
@@ -84,7 +84,7 @@ def test_defaults(self):
8484 def test_with_topics (self ):
8585 c = EventsCapability (
8686 topics = [
87- EventTopicDescriptor (pattern = "a/b" , description = "Alpha-bravo" , retained = True ),
87+ EventTopicDescriptor (pattern = "a/b" , description = "Alpha-bravo" , retained = True , schema = None ),
8888 ],
8989 instructions = "Subscribe to a/b for updates" ,
9090 )
@@ -117,11 +117,13 @@ def test_inherits_meta(self):
117117 )
118118 assert p .meta is None
119119 # _meta field should be serializable
120- p2 = EventParams (
121- topic = "test/topic" ,
122- eventId = "abc123" ,
123- payload = "hello" ,
124- _meta = {"related_request_id" : "req-1" },
120+ p2 = EventParams .model_validate (
121+ {
122+ "topic" : "test/topic" ,
123+ "eventId" : "abc123" ,
124+ "payload" : "hello" ,
125+ "_meta" : {"related_request_id" : "req-1" },
126+ }
125127 )
126128 data = p2 .model_dump (by_alias = True )
127129 assert data ["_meta" ] == {"related_request_id" : "req-1" }
@@ -240,7 +242,7 @@ def test_unsubscribe_result(self):
240242 def test_list_result (self ):
241243 r = EventListResult (
242244 topics = [
243- EventTopicDescriptor (pattern = "x/y" , description = "desc" ),
245+ EventTopicDescriptor (pattern = "x/y" , description = "desc" , schema = None ),
244246 ]
245247 )
246248 data = r .model_dump (by_alias = True , mode = "json" )
@@ -256,29 +258,29 @@ class TestInvalidEventEffect:
256258 def test_invalid_type_rejected (self ):
257259 """EventEffect with an invalid type literal should be rejected by Pydantic."""
258260 with pytest .raises (ValidationError ):
259- EventEffect ( type = " bogus_effect" )
261+ EventEffect . model_validate ({ " type" : " bogus_effect"} )
260262
261263 def test_invalid_priority_rejected (self ):
262264 """EventEffect with an invalid priority literal should be rejected."""
263265 with pytest .raises (ValidationError ):
264- EventEffect ( type = " inject_context" , priority = " super_duper" )
266+ EventEffect . model_validate ({ " type" : " inject_context" , " priority" : " super_duper"} )
265267
266268
267269class TestInvalidEventParams :
268270 def test_missing_topic_rejected (self ):
269271 """EventParams missing required 'topic' field should fail validation."""
270272 with pytest .raises (ValidationError ):
271- EventParams ( eventId = " e1" , payload = "x" )
273+ EventParams . model_validate ({ " eventId" : " e1" , " payload" : "x" } )
272274
273275 def test_missing_event_id_rejected (self ):
274276 """EventParams missing required 'event_id' field should fail validation."""
275277 with pytest .raises (ValidationError ):
276- EventParams ( topic = " a/b" , payload = "x" )
278+ EventParams . model_validate ({ " topic" : " a/b" , " payload" : "x" } )
277279
278280 def test_missing_payload_rejected (self ):
279281 """EventParams missing required 'payload' field should fail validation."""
280282 with pytest .raises (ValidationError ):
281- EventParams ( topic = " a/b" , eventId = " e1" )
283+ EventParams . model_validate ({ " topic" : " a/b" , " eventId" : " e1"} )
282284
283285
284286# ---------------------------------------------------------------------------
@@ -293,58 +295,43 @@ async def _on_subscribe_events(
293295 ctx : RequestContext [ServerSession , Any ],
294296 params : EventSubscribeParams ,
295297) -> EventSubscribeResult :
296- subscribed = []
298+ subscribed : list [ SubscribedTopic ] = []
297299 for pattern in params .topics :
298300 await _registry .add ("test-session" , pattern )
299301 subscribed .append (SubscribedTopic (pattern = pattern ))
300302 return EventSubscribeResult (subscribed = subscribed )
301303
302304
303- async def _on_unsubscribe_events (
304- ctx : RequestContext [ServerSession , Any ],
305- params : EventUnsubscribeParams ,
306- ) -> EventUnsubscribeResult :
307- for pattern in params .topics :
308- await _registry .remove ("test-session" , pattern )
309- return EventUnsubscribeResult (unsubscribed = params .topics )
310-
311-
312305def _create_test_server () -> Server :
313306 server = Server ("test-events-server" )
314307
315308 # Register event handlers via request_handlers dict (keyed by type)
316309 async def subscribe_handler (req : EventSubscribeRequest ):
317310 ctx = server .request_context
318- result = await _on_subscribe_events (ctx , req .root .params if hasattr (req , "root" ) else req .params )
319- return types .ServerResult (result )
320-
321- async def unsubscribe_handler (req : EventUnsubscribeRequest ):
322- ctx = server .request_context
323- result = await _on_unsubscribe_events (ctx , req .root .params if hasattr (req , "root" ) else req .params )
311+ result = await _on_subscribe_events (ctx , req .params )
324312 return types .ServerResult (result )
325313
326314 server .request_handlers [EventSubscribeRequest ] = subscribe_handler
327- server .request_handlers [EventUnsubscribeRequest ] = unsubscribe_handler
328315 return server
329316
330317
331318async def _message_handler (
332319 message : RequestResponder [types .ServerRequest , types .ClientResult ] | types .ServerNotification | Exception ,
333320) -> None :
334321 if isinstance (message , Exception ):
335- raise message
322+ raise message # pragma: no cover
336323
337324
338325async def _run_server (server_session : ServerSession , server : Server ) -> None :
339326 async for message in server_session .incoming_messages :
340327 if isinstance (message , Exception ):
341- raise message
328+ raise message # pragma: no cover
342329 if isinstance (message , RequestResponder ):
343330 with message :
344331 req = message .request
345332 # v1.27.0: request_handlers keyed by type
346333 handler = server .request_handlers .get (type (req .root ))
347- if handler :
334+ if handler : # pragma: no branch
348335 from mcp .server .lowlevel .server import request_ctx
349336
350337 token = request_ctx .set (
@@ -423,7 +410,7 @@ async def event_handler(params: EventParams):
423410 assert len (received_events [0 ].event_id ) > 0
424411
425412 tg .cancel_scope .cancel ()
426- except (anyio .ClosedResourceError , anyio .EndOfStream ):
413+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
427414 pass
428415
429416
@@ -479,7 +466,7 @@ async def handle_event(params: EventParams):
479466 assert received_events [0 ].payload == "via-decorator"
480467
481468 tg .cancel_scope .cancel ()
482- except (anyio .ClosedResourceError , anyio .EndOfStream ):
469+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
483470 pass
484471
485472
@@ -534,7 +521,7 @@ async def event_handler(params: EventParams):
534521 assert received_events [0 ].topic == "anything/goes"
535522
536523 tg .cancel_scope .cancel ()
537- except (anyio .ClosedResourceError , anyio .EndOfStream ):
524+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
538525 pass
539526
540527
@@ -598,7 +585,7 @@ async def event_handler(params: EventParams):
598585 assert received_events [0 ].payload == "match"
599586
600587 tg .cancel_scope .cancel ()
601- except (anyio .ClosedResourceError , anyio .EndOfStream ):
588+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
602589 pass
603590
604591
@@ -647,7 +634,7 @@ async def test_handle_event_with_no_handler():
647634 # If we get here without exception, the test passes
648635
649636 tg .cancel_scope .cancel ()
650- except (anyio .ClosedResourceError , anyio .EndOfStream ):
637+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
651638 pass
652639
653640
@@ -757,7 +744,7 @@ async def event_handler(params: EventParams):
757744 assert evt .expires_at == future
758745
759746 tg .cancel_scope .cancel ()
760- except (anyio .ClosedResourceError , anyio .EndOfStream ):
747+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
761748 pass
762749
763750
@@ -816,5 +803,5 @@ async def event_handler(params: EventParams):
816803 assert ts <= datetime .now (timezone .utc )
817804
818805 tg .cancel_scope .cancel ()
819- except (anyio .ClosedResourceError , anyio .EndOfStream ):
806+ except (anyio .ClosedResourceError , anyio .EndOfStream ): # pragma: no cover
820807 pass
0 commit comments