@@ -188,6 +188,23 @@ async def register_gateway(self, db: Session, gateway: GatewayCreate) -> Gateway
188
188
ValueError: If required values are missing
189
189
RuntimeError: If there is an error during processing that is not covered by other exceptions
190
190
BaseException: If an unexpected error occurs
191
+
192
+ Examples:
193
+ >>> from mcpgateway.services.gateway_service import GatewayService
194
+ >>> from unittest.mock import MagicMock
195
+ >>> service = GatewayService()
196
+ >>> db = MagicMock()
197
+ >>> gateway = MagicMock()
198
+ >>> db.execute.return_value.scalar_one_or_none.return_value = None
199
+ >>> db.add = MagicMock()
200
+ >>> db.commit = MagicMock()
201
+ >>> db.refresh = MagicMock()
202
+ >>> service._notify_gateway_added = MagicMock()
203
+ >>> import asyncio
204
+ >>> try:
205
+ ... asyncio.run(service.register_gateway(db, gateway))
206
+ ... except Exception:
207
+ ... pass
191
208
"""
192
209
try :
193
210
# Check for name conflicts (both active and inactive)
@@ -279,6 +296,20 @@ async def list_gateways(self, db: Session, include_inactive: bool = False) -> Li
279
296
280
297
Returns:
281
298
List of registered gateways
299
+
300
+ Examples:
301
+ >>> from mcpgateway.services.gateway_service import GatewayService
302
+ >>> from unittest.mock import MagicMock
303
+ >>> from mcpgateway.schemas import GatewayRead
304
+ >>> service = GatewayService()
305
+ >>> db = MagicMock()
306
+ >>> gateway_obj = MagicMock()
307
+ >>> db.execute.return_value.scalars.return_value.all.return_value = [gateway_obj]
308
+ >>> GatewayRead.model_validate = MagicMock(return_value='gateway_read')
309
+ >>> import asyncio
310
+ >>> result = asyncio.run(service.list_gateways(db))
311
+ >>> result == ['gateway_read']
312
+ True
282
313
"""
283
314
query = select (DbGateway )
284
315
@@ -391,18 +422,31 @@ async def update_gateway(self, db: Session, gateway_id: str, gateway_update: Gat
391
422
raise GatewayError (f"Failed to update gateway: { str (e )} " )
392
423
393
424
async def get_gateway (self , db : Session , gateway_id : str , include_inactive : bool = True ) -> GatewayRead :
394
- """Get a specific gateway by ID.
425
+ """
426
+ Get a gateway by its ID.
395
427
396
428
Args:
397
429
db: Database session
398
430
gateway_id: Gateway ID
399
431
include_inactive: Whether to include inactive gateways
400
432
401
433
Returns:
402
- Gateway information
434
+ GatewayRead object
403
435
404
436
Raises:
405
- GatewayNotFoundError: If gateway not found
437
+ GatewayNotFoundError: If the gateway is not found
438
+
439
+ Examples:
440
+ >>> from mcpgateway.services.gateway_service import GatewayService
441
+ >>> from unittest.mock import MagicMock
442
+ >>> service = GatewayService()
443
+ >>> db = MagicMock()
444
+ >>> db.get.return_value = MagicMock()
445
+ >>> import asyncio
446
+ >>> try:
447
+ ... asyncio.run(service.get_gateway(db, 'gateway_id'))
448
+ ... except Exception:
449
+ ... pass
406
450
"""
407
451
gateway = db .get (DbGateway , gateway_id )
408
452
if not gateway :
@@ -414,21 +458,39 @@ async def get_gateway(self, db: Session, gateway_id: str, include_inactive: bool
414
458
raise GatewayNotFoundError (f"Gateway not found: { gateway_id } " )
415
459
416
460
async def toggle_gateway_status (self , db : Session , gateway_id : str , activate : bool , reachable : bool = True , only_update_reachable : bool = False ) -> GatewayRead :
417
- """Toggle gateway active status.
461
+ """
462
+ Toggle the activation status of a gateway.
418
463
419
464
Args:
420
465
db: Database session
421
- gateway_id: Gateway ID to toggle
466
+ gateway_id: Gateway ID
422
467
activate: True to activate, False to deactivate
423
- reachable: True if the gateway is reachable, False otherwise
424
- only_update_reachable: If True, only updates reachable status without changing enabled status. Applicable for changing tool status. If the tool is manually deactivated, it will not be reactivated if reachable.
468
+ reachable: Whether the gateway is reachable
469
+ only_update_reachable: Only update reachable status
425
470
426
471
Returns:
427
- Updated gateway information
472
+ The updated GatewayRead object
428
473
429
474
Raises:
430
- GatewayNotFoundError: If gateway not found
475
+ GatewayNotFoundError: If the gateway is not found
431
476
GatewayError: For other errors
477
+
478
+ Examples:
479
+ >>> from mcpgateway.services.gateway_service import GatewayService
480
+ >>> from unittest.mock import MagicMock
481
+ >>> service = GatewayService()
482
+ >>> db = MagicMock()
483
+ >>> gateway = MagicMock()
484
+ >>> db.get.return_value = gateway
485
+ >>> db.commit = MagicMock()
486
+ >>> db.refresh = MagicMock()
487
+ >>> service._notify_gateway_activated = MagicMock()
488
+ >>> service._notify_gateway_deactivated = MagicMock()
489
+ >>> import asyncio
490
+ >>> try:
491
+ ... asyncio.run(service.toggle_gateway_status(db, 'gateway_id', True))
492
+ ... except Exception:
493
+ ... pass
432
494
"""
433
495
try :
434
496
gateway = db .get (DbGateway , gateway_id )
@@ -523,15 +585,32 @@ async def _notify_gateway_updated(self, gateway: DbGateway) -> None:
523
585
await self ._publish_event (event )
524
586
525
587
async def delete_gateway (self , db : Session , gateway_id : str ) -> None :
526
- """Permanently delete a gateway.
588
+ """
589
+ Delete a gateway by its ID.
527
590
528
591
Args:
529
592
db: Database session
530
- gateway_id: Gateway ID to delete
593
+ gateway_id: Gateway ID
531
594
532
595
Raises:
533
- GatewayNotFoundError: If gateway not found
596
+ GatewayNotFoundError: If the gateway is not found
534
597
GatewayError: For other deletion errors
598
+
599
+ Examples:
600
+ >>> from mcpgateway.services.gateway_service import GatewayService
601
+ >>> from unittest.mock import MagicMock
602
+ >>> service = GatewayService()
603
+ >>> db = MagicMock()
604
+ >>> gateway = MagicMock()
605
+ >>> db.get.return_value = gateway
606
+ >>> db.delete = MagicMock()
607
+ >>> db.commit = MagicMock()
608
+ >>> service._notify_gateway_deleted = MagicMock()
609
+ >>> import asyncio
610
+ >>> try:
611
+ ... asyncio.run(service.delete_gateway(db, 'gateway_id'))
612
+ ... except Exception:
613
+ ... pass
535
614
"""
536
615
try :
537
616
# Find gateway
@@ -559,7 +638,8 @@ async def delete_gateway(self, db: Session, gateway_id: str) -> None:
559
638
raise GatewayError (f"Failed to delete gateway: { str (e )} " )
560
639
561
640
async def forward_request (self , gateway : DbGateway , method : str , params : Optional [Dict [str , Any ]] = None ) -> Any :
562
- """Forward a request to a gateway.
641
+ """
642
+ Forward a request to a gateway.
563
643
564
644
Args:
565
645
gateway: Gateway to forward to
@@ -572,6 +652,17 @@ async def forward_request(self, gateway: DbGateway, method: str, params: Optiona
572
652
Raises:
573
653
GatewayConnectionError: If forwarding fails
574
654
GatewayError: If gateway gave an error
655
+
656
+ Examples:
657
+ >>> from mcpgateway.services.gateway_service import GatewayService
658
+ >>> from unittest.mock import MagicMock
659
+ >>> service = GatewayService()
660
+ >>> gateway = MagicMock()
661
+ >>> import asyncio
662
+ >>> try:
663
+ ... asyncio.run(service.forward_request(gateway, 'method'))
664
+ ... except Exception:
665
+ ... pass
575
666
"""
576
667
if not gateway .enabled :
577
668
raise GatewayConnectionError (f"Cannot forward request to inactive gateway: { gateway .name } " )
@@ -629,15 +720,24 @@ async def _handle_gateway_failure(self, gateway: str) -> None:
629
720
self ._gateway_failure_counts [gateway .id ] = 0 # Reset after deactivation
630
721
631
722
async def check_health_of_gateways (self , gateways : List [DbGateway ]) -> bool :
632
- """Health check for a list of gateways.
633
-
634
- Deactivates gateway if gateway is not healthy.
723
+ """
724
+ Check health of gateways.
635
725
636
726
Args:
637
- gateways (List[DbGateway]) : List of gateways to check if healthy
727
+ gateways: List of DbGateway objects
638
728
639
729
Returns:
640
- bool: True if all active gateways are healthy
730
+ True if all gateways are healthy, False otherwise
731
+
732
+ Examples:
733
+ >>> from mcpgateway.services.gateway_service import GatewayService
734
+ >>> from unittest.mock import MagicMock
735
+ >>> service = GatewayService()
736
+ >>> gateways = [MagicMock()]
737
+ >>> import asyncio
738
+ >>> result = asyncio.run(service.check_health_of_gateways(gateways))
739
+ >>> isinstance(result, bool)
740
+ True
641
741
"""
642
742
# Reuse a single HTTP client for all requests
643
743
async with httpx .AsyncClient () as client :
@@ -676,13 +776,25 @@ async def check_health_of_gateways(self, gateways: List[DbGateway]) -> bool:
676
776
return True
677
777
678
778
async def aggregate_capabilities (self , db : Session ) -> Dict [str , Any ]:
679
- """Aggregate capabilities from all gateways.
779
+ """
780
+ Aggregate capabilities across all gateways.
680
781
681
782
Args:
682
783
db: Database session
683
784
684
785
Returns:
685
- Combined capabilities
786
+ Dictionary of aggregated capabilities
787
+
788
+ Examples:
789
+ >>> from mcpgateway.services.gateway_service import GatewayService
790
+ >>> from unittest.mock import MagicMock
791
+ >>> service = GatewayService()
792
+ >>> db = MagicMock()
793
+ >>> db.execute.return_value.scalars.return_value.all.return_value = [MagicMock()]
794
+ >>> import asyncio
795
+ >>> result = asyncio.run(service.aggregate_capabilities(db))
796
+ >>> isinstance(result, dict)
797
+ True
686
798
"""
687
799
capabilities = {
688
800
"prompts" : {"listChanged" : True },
0 commit comments