mcp-proxy-adapter 6.3.3__py3-none-any.whl โ†’ 6.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +12 -2
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.3.dist-info โ†’ mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.3.dist-info โ†’ mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.3.dist-info โ†’ mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.3.dist-info โ†’ mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.3.dist-info โ†’ mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@ import shutil
16
16
  import sys
17
17
  import argparse
18
18
  from pathlib import Path
19
+
19
20
  # Import mcp_security_framework
20
21
  try:
21
22
  from mcp_security_framework.core.cert_manager import CertificateManager
@@ -25,6 +26,7 @@ try:
25
26
  ServerCertConfig,
26
27
  ClientCertConfig,
27
28
  )
29
+
28
30
  SECURITY_FRAMEWORK_AVAILABLE = True
29
31
  except ImportError:
30
32
  SECURITY_FRAMEWORK_AVAILABLE = False
@@ -60,7 +62,7 @@ def setup_test_environment(output_dir: Path) -> None:
60
62
  "certs",
61
63
  "keys",
62
64
  "tokens",
63
- "logs"
65
+ "logs",
64
66
  ]
65
67
  for directory in directories:
66
68
  target_dir = output_dir / directory
@@ -111,11 +113,7 @@ def setup_test_environment(output_dir: Path) -> None:
111
113
  if roles_configs_src.exists():
112
114
  shutil.copy2(roles_configs_src, output_dir / "roles.json")
113
115
  print("โœ… Updated roles.json from configs directory")
114
- print(
115
- "๐ŸŽ‰ Test environment setup completed successfully at: {}".format(
116
- output_dir
117
- )
118
- )
116
+ print("๐ŸŽ‰ Test environment setup completed successfully at: {}".format(output_dir))
119
117
 
120
118
 
121
119
  def generate_certificates_with_framework(output_dir: Path) -> bool:
@@ -123,15 +121,10 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
123
121
  Generate certificates using mcp_security_framework.
124
122
  """
125
123
  if not SECURITY_FRAMEWORK_AVAILABLE:
126
- print(
127
- "โŒ mcp_security_framework not available for certificate "
128
- "generation"
129
- )
124
+ print("โŒ mcp_security_framework not available for certificate " "generation")
130
125
  return False
131
126
  try:
132
- print(
133
- "๐Ÿ” Generating certificates using mcp_security_framework..."
134
- )
127
+ print("๐Ÿ” Generating certificates using mcp_security_framework...")
135
128
  # Configure certificate manager
136
129
  cert_config = CertificateConfig(
137
130
  cert_storage_path=str((output_dir / "certs").resolve()),
@@ -155,9 +148,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
155
148
  )
156
149
  cert_pair = cert_manager.create_root_ca(ca_config)
157
150
  if not cert_pair or not cert_pair.certificate_path:
158
- print(
159
- "โŒ Failed to create CA certificate: Invalid certificate pair"
160
- )
151
+ print("โŒ Failed to create CA certificate: Invalid certificate pair")
161
152
  return False
162
153
  print("โœ… CA certificate created successfully")
163
154
  # Find CA key file
@@ -182,10 +173,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
182
173
  )
183
174
  cert_pair = cert_manager.create_server_certificate(server_config)
184
175
  if not cert_pair or not cert_pair.certificate_path:
185
- print(
186
- "โŒ Failed to create server certificate: Invalid certificate "
187
- "pair"
188
- )
176
+ print("โŒ Failed to create server certificate: Invalid certificate " "pair")
189
177
  return False
190
178
  print("โœ… Server certificate created successfully")
191
179
  # Generate client certificates
@@ -239,7 +227,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
239
227
  roles=roles,
240
228
  permissions=permissions,
241
229
  ca_cert_path=cert_pair.certificate_path,
242
- ca_key_path=ca_key_path
230
+ ca_key_path=ca_key_path,
243
231
  )
244
232
  cert_pair = cert_manager.create_client_certificate(client_config)
245
233
  if not cert_pair or not cert_pair.certificate_path:
@@ -250,11 +238,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
250
238
  ).format(client_name)
251
239
  )
252
240
  return False
253
- print(
254
- "โœ… Client certificate {} created successfully".format(
255
- client_name
256
- )
257
- )
241
+ print("โœ… Client certificate {} created successfully".format(client_name))
258
242
  print(
259
243
  "๐ŸŽ‰ All certificates generated successfully using "
260
244
  "mcp_security_framework!"
@@ -307,19 +291,23 @@ def main() -> int:
307
291
  print("2. Verify mcp_security_framework installation")
308
292
  print("3. Check available disk space")
309
293
  return 1
310
-
294
+
311
295
  print("\n" + "=" * 60)
312
296
  print("โœ… TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
313
297
  print("=" * 60)
314
298
  print("\n๐Ÿ“‹ NEXT STEPS:")
315
299
  print("1. Generate test configurations:")
316
- print(" python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs")
300
+ print(
301
+ " python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs"
302
+ )
317
303
  print("\n2. Generate additional certificates (if needed):")
318
304
  print(" python -m mcp_proxy_adapter.examples.generate_certificates")
319
305
  print("\n3. Run security tests:")
320
306
  print(" python -m mcp_proxy_adapter.examples.run_security_tests")
321
307
  print("\n4. Start basic framework example:")
322
- print(" python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json")
308
+ print(
309
+ " python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json"
310
+ )
323
311
  print("=" * 60)
324
312
  return 0
325
313
 
@@ -14,16 +14,20 @@ import time
14
14
  import subprocess
15
15
  from pathlib import Path
16
16
  from typing import Dict, Any, Optional
17
+
17
18
  # Import mcp_security_framework
18
19
  try:
19
20
  from mcp_security_framework import SecurityManager
20
21
  from mcp_security_framework.schemas.config import SecurityConfig
22
+
21
23
  SECURITY_FRAMEWORK_AVAILABLE = True
22
24
  except ImportError:
23
25
  SECURITY_FRAMEWORK_AVAILABLE = False
24
26
  print("Warning: mcp_security_framework not available")
25
27
  # Add parent directory to path to import mcp_proxy_adapter
26
28
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
29
+
30
+
27
31
  def validate_security_config(config: Dict[str, Any]) -> bool:
28
32
  """
29
33
  Validate security configuration using mcp_security_framework.
@@ -46,7 +50,7 @@ def validate_security_config(config: Dict[str, Any]) -> bool:
46
50
  auth=security_section.get("auth", {}),
47
51
  ssl=security_section.get("ssl", {}),
48
52
  permissions=security_section.get("permissions", {}),
49
- rate_limit=security_section.get("rate_limit", {})
53
+ rate_limit=security_section.get("rate_limit", {}),
50
54
  )
51
55
  # Create SecurityManager for validation
52
56
  security_manager = SecurityManager(security_config)
@@ -63,6 +67,8 @@ def validate_security_config(config: Dict[str, Any]) -> bool:
63
67
  except Exception as e:
64
68
  print(f"โŒ Error validating security configuration: {e}")
65
69
  return False
70
+
71
+
66
72
  def test_configuration(config_path: str, timeout: int = 30) -> bool:
67
73
  """
68
74
  Test a configuration by creating an application and validating it.
@@ -76,11 +82,12 @@ def test_configuration(config_path: str, timeout: int = 30) -> bool:
76
82
  print("=" * 60)
77
83
  try:
78
84
  # Load configuration
79
- with open(config_path, 'r') as f:
85
+ with open(config_path, "r") as f:
80
86
  config = json.load(f)
81
87
  # Import required modules
82
88
  from mcp_proxy_adapter.core.app_factory import create_application
83
89
  from mcp_proxy_adapter.core.app_runner import ApplicationRunner
90
+
84
91
  # Create application
85
92
  print("๐Ÿ”ง Creating application...")
86
93
  app = create_application(config)
@@ -133,16 +140,24 @@ def test_configuration(config_path: str, timeout: int = 30) -> bool:
133
140
  except Exception as e:
134
141
  print(f"โŒ Configuration test failed: {e}")
135
142
  return False
143
+
144
+
136
145
  def main():
137
146
  """Main function for command line execution."""
138
147
  parser = argparse.ArgumentParser(description="Test MCP Proxy Adapter configuration")
139
- parser.add_argument("--config", "-c", required=True, help="Path to configuration file")
140
- parser.add_argument("--timeout", "-t", type=int, default=30, help="Timeout in seconds")
148
+ parser.add_argument(
149
+ "--config", "-c", required=True, help="Path to configuration file"
150
+ )
151
+ parser.add_argument(
152
+ "--timeout", "-t", type=int, default=30, help="Timeout in seconds"
153
+ )
141
154
  args = parser.parse_args()
142
155
  if not os.path.exists(args.config):
143
156
  print(f"โŒ Configuration file not found: {args.config}")
144
157
  return 1
145
158
  success = test_configuration(args.config, args.timeout)
146
159
  return 0 if success else 1
160
+
161
+
147
162
  if __name__ == "__main__":
148
163
  exit(main())
@@ -7,10 +7,13 @@ configurations with the new protocols section and fixes for ProtocolMiddleware i
7
7
  import sys
8
8
  import json
9
9
  from pathlib import Path
10
+
10
11
  # Add the project root to the path
11
12
  project_root = Path(__file__).parent.parent.parent
12
13
  sys.path.insert(0, str(project_root))
13
14
  from mcp_proxy_adapter.utils.config_generator import ConfigGenerator
15
+
16
+
14
17
  def test_config_generator():
15
18
  """Test the configuration generator with different types."""
16
19
  generator = ConfigGenerator()
@@ -22,7 +25,7 @@ def test_config_generator():
22
25
  "https_token",
23
26
  "https_no_protocol_middleware",
24
27
  "mtls",
25
- "mtls_no_protocol_middleware"
28
+ "mtls_no_protocol_middleware",
26
29
  ]
27
30
  print("Testing Configuration Generator")
28
31
  print("=" * 50)
@@ -37,17 +40,26 @@ def test_config_generator():
37
40
  protocols = config["protocols"]
38
41
  print(f"โœ… Protocols section found:")
39
42
  print(f" - enabled: {protocols.get('enabled', 'NOT SET')}")
40
- print(f" - allowed_protocols: {protocols.get('allowed_protocols', 'NOT SET')}")
41
- print(f" - default_protocol: {protocols.get('default_protocol', 'NOT SET')}")
43
+ print(
44
+ f" - allowed_protocols: {protocols.get('allowed_protocols', 'NOT SET')}"
45
+ )
46
+ print(
47
+ f" - default_protocol: {protocols.get('default_protocol', 'NOT SET')}"
48
+ )
42
49
  else:
43
50
  print("โŒ Protocols section missing!")
44
51
  # Check SSL configuration
45
52
  ssl_enabled = config.get("ssl", {}).get("enabled", False)
46
- security_ssl_enabled = config.get("security", {}).get("ssl", {}).get("enabled", False)
53
+ security_ssl_enabled = (
54
+ config.get("security", {}).get("ssl", {}).get("enabled", False)
55
+ )
47
56
  print(f" - legacy ssl.enabled: {ssl_enabled}")
48
57
  print(f" - security.ssl.enabled: {security_ssl_enabled}")
49
58
  # Check if configuration is valid for its type
50
- if config_type == "https_no_protocol_middleware" or config_type == "mtls_no_protocol_middleware":
59
+ if (
60
+ config_type == "https_no_protocol_middleware"
61
+ or config_type == "mtls_no_protocol_middleware"
62
+ ):
51
63
  if protocols.get("enabled") == False:
52
64
  print("โœ… ProtocolMiddleware correctly disabled")
53
65
  else:
@@ -59,13 +71,15 @@ def test_config_generator():
59
71
  print("โŒ ProtocolMiddleware should be enabled but is disabled")
60
72
  # Save configuration to file for inspection
61
73
  output_file = f"test_config_{config_type}.json"
62
- with open(output_file, 'w') as f:
74
+ with open(output_file, "w") as f:
63
75
  json.dump(config, f, indent=2)
64
76
  print(f" - Configuration saved to {output_file}")
65
77
  except Exception as e:
66
78
  print(f"โŒ Error generating {config_type} configuration: {e}")
67
79
  print("\n" + "=" * 50)
68
80
  print("Configuration generator test completed!")
81
+
82
+
69
83
  def test_config_with_comments():
70
84
  """Test configuration generation with comments."""
71
85
  generator = ConfigGenerator()
@@ -76,11 +90,13 @@ def test_config_with_comments():
76
90
  commented_config = generator.generate_config_with_comments("https")
77
91
  print("โœ… HTTPS configuration with comments generated successfully")
78
92
  # Save to file
79
- with open("test_https_with_comments.json", 'w') as f:
93
+ with open("test_https_with_comments.json", "w") as f:
80
94
  f.write(commented_config)
81
95
  print(" - Configuration saved to test_https_with_comments.json")
82
96
  except Exception as e:
83
97
  print(f"โŒ Error generating configuration with comments: {e}")
98
+
99
+
84
100
  if __name__ == "__main__":
85
101
  test_config_generator()
86
102
  test_config_with_comments()
@@ -12,6 +12,7 @@ import time
12
12
  import requests
13
13
  from pathlib import Path
14
14
  from typing import Dict, Any, List
15
+
15
16
  # Configuration for testing
16
17
  CONFIGS = {
17
18
  "basic_framework": {
@@ -20,7 +21,7 @@ CONFIGS = {
20
21
  "http_auth": {"port": 8001, "ssl": False, "auth": True},
21
22
  "https_auth": {"port": 8444, "ssl": True, "auth": True},
22
23
  "mtls_no_roles": {"port": 9443, "ssl": True, "auth": True, "mtls": True},
23
- "mtls_with_roles": {"port": 9444, "ssl": True, "auth": True, "mtls": True}
24
+ "mtls_with_roles": {"port": 9444, "ssl": True, "auth": True, "mtls": True},
24
25
  },
25
26
  "full_application": {
26
27
  "http_simple": {"port": 9000, "ssl": False, "auth": False},
@@ -28,26 +29,28 @@ CONFIGS = {
28
29
  "http_auth": {"port": 9001, "ssl": False, "auth": True},
29
30
  "https_auth": {"port": 9446, "ssl": True, "auth": True},
30
31
  "mtls_no_roles": {"port": 9447, "ssl": True, "auth": True, "mtls": True},
31
- "mtls_with_roles": {"port": 9448, "ssl": True, "auth": True, "mtls": True}
32
- }
33
- }
34
- API_KEYS = {
35
- "admin": "admin-secret-key-123",
36
- "user": "user-secret-key-456"
32
+ "mtls_with_roles": {"port": 9448, "ssl": True, "auth": True, "mtls": True},
33
+ },
37
34
  }
35
+ API_KEYS = {"admin": "admin-secret-key-123", "user": "user-secret-key-456"}
36
+
37
+
38
38
  class ExampleTester:
39
39
  """Test examples with different configurations."""
40
+
40
41
  def __init__(self):
41
42
  self.examples_dir = Path(__file__).parent
42
43
  self.results = {}
43
44
  self.processes = []
45
+
44
46
  def generate_certificates(self):
45
47
  """Generate certificates for testing."""
46
48
  print("๐Ÿ” Generating certificates...")
47
49
  cert_script = self.examples_dir.parent / "generate_certificates.py"
48
50
  if cert_script.exists():
49
- result = subprocess.run([sys.executable, str(cert_script)],
50
- capture_output=True, text=True)
51
+ result = subprocess.run(
52
+ [sys.executable, str(cert_script)], capture_output=True, text=True
53
+ )
51
54
  if result.returncode == 0:
52
55
  print("โœ… Certificates generated successfully")
53
56
  return True
@@ -55,27 +58,31 @@ class ExampleTester:
55
58
  print(f"โŒ Certificate generation failed: {result.stderr}")
56
59
  return False
57
60
  else:
58
- print("โš ๏ธ Certificate generation script not found, using existing certificates")
61
+ print(
62
+ "โš ๏ธ Certificate generation script not found, using existing certificates"
63
+ )
59
64
  return True
65
+
60
66
  def start_server(self, example_type: str, config_name: str) -> subprocess.Popen:
61
67
  """Start a server with specific configuration."""
62
- config_path = self.examples_dir / example_type / "configs" / f"{config_name}.json"
68
+ config_path = (
69
+ self.examples_dir / example_type / "configs" / f"{config_name}.json"
70
+ )
63
71
  main_script = self.examples_dir / example_type / "main.py"
64
72
  if not config_path.exists():
65
73
  raise FileNotFoundError(f"Configuration file not found: {config_path}")
66
74
  if not main_script.exists():
67
75
  raise FileNotFoundError(f"Main script not found: {main_script}")
68
- cmd = [
69
- sys.executable, str(main_script),
70
- "--config", str(config_path)
71
- ]
76
+ cmd = [sys.executable, str(main_script), "--config", str(config_path)]
72
77
  print(f"๐Ÿš€ Starting {example_type} server with {config_name} config...")
73
78
  process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
74
79
  # Wait for server to start
75
80
  time.sleep(5)
76
81
  return process
77
- def test_health_endpoint(self, port: int, ssl: bool = False, auth: bool = False,
78
- api_key: str = None) -> Dict[str, Any]:
82
+
83
+ def test_health_endpoint(
84
+ self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
85
+ ) -> Dict[str, Any]:
79
86
  """Test health endpoint."""
80
87
  protocol = "https" if ssl else "http"
81
88
  url = f"{protocol}://localhost:{port}/health"
@@ -87,15 +94,20 @@ class ExampleTester:
87
94
  return {
88
95
  "success": True,
89
96
  "status_code": response.status_code,
90
- "response": response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text
97
+ "response": (
98
+ response.json()
99
+ if response.headers.get("content-type", "").startswith(
100
+ "application/json"
101
+ )
102
+ else response.text
103
+ ),
91
104
  }
92
105
  except Exception as e:
93
- return {
94
- "success": False,
95
- "error": str(e)
96
- }
97
- def test_echo_command(self, port: int, ssl: bool = False, auth: bool = False,
98
- api_key: str = None) -> Dict[str, Any]:
106
+ return {"success": False, "error": str(e)}
107
+
108
+ def test_echo_command(
109
+ self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
110
+ ) -> Dict[str, Any]:
99
111
  """Test echo command."""
100
112
  protocol = "https" if ssl else "http"
101
113
  url = f"{protocol}://localhost:{port}/cmd"
@@ -106,22 +118,23 @@ class ExampleTester:
106
118
  "jsonrpc": "2.0",
107
119
  "method": "echo",
108
120
  "params": {"message": "Hello from test!"},
109
- "id": 1
121
+ "id": 1,
110
122
  }
111
123
  try:
112
- response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
124
+ response = requests.post(
125
+ url, json=data, headers=headers, verify=False, timeout=10
126
+ )
113
127
  return {
114
128
  "success": True,
115
129
  "status_code": response.status_code,
116
- "response": response.json()
130
+ "response": response.json(),
117
131
  }
118
132
  except Exception as e:
119
- return {
120
- "success": False,
121
- "error": str(e)
122
- }
123
- def test_full_application_commands(self, port: int, ssl: bool = False, auth: bool = False,
124
- api_key: str = None) -> Dict[str, Any]:
133
+ return {"success": False, "error": str(e)}
134
+
135
+ def test_full_application_commands(
136
+ self, port: int, ssl: bool = False, auth: bool = False, api_key: str = None
137
+ ) -> Dict[str, Any]:
125
138
  """Test full application specific commands."""
126
139
  protocol = "https" if ssl else "http"
127
140
  url = f"{protocol}://localhost:{port}/cmd"
@@ -134,40 +147,39 @@ class ExampleTester:
134
147
  "jsonrpc": "2.0",
135
148
  "method": "custom_echo",
136
149
  "params": {"message": "Custom echo test", "repeat": 3},
137
- "id": 1
150
+ "id": 1,
138
151
  }
139
152
  try:
140
- response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
153
+ response = requests.post(
154
+ url, json=data, headers=headers, verify=False, timeout=10
155
+ )
141
156
  results["custom_echo"] = {
142
157
  "success": True,
143
158
  "status_code": response.status_code,
144
- "response": response.json()
159
+ "response": response.json(),
145
160
  }
146
161
  except Exception as e:
147
- results["custom_echo"] = {
148
- "success": False,
149
- "error": str(e)
150
- }
162
+ results["custom_echo"] = {"success": False, "error": str(e)}
151
163
  # Test dynamic calculator command
152
164
  data = {
153
165
  "jsonrpc": "2.0",
154
166
  "method": "dynamic_calculator",
155
167
  "params": {"operation": "add", "a": 10, "b": 5},
156
- "id": 2
168
+ "id": 2,
157
169
  }
158
170
  try:
159
- response = requests.post(url, json=data, headers=headers, verify=False, timeout=10)
171
+ response = requests.post(
172
+ url, json=data, headers=headers, verify=False, timeout=10
173
+ )
160
174
  results["dynamic_calculator"] = {
161
175
  "success": True,
162
176
  "status_code": response.status_code,
163
- "response": response.json()
177
+ "response": response.json(),
164
178
  }
165
179
  except Exception as e:
166
- results["dynamic_calculator"] = {
167
- "success": False,
168
- "error": str(e)
169
- }
180
+ results["dynamic_calculator"] = {"success": False, "error": str(e)}
170
181
  return results
182
+
171
183
  def run_tests(self):
172
184
  """Run all tests."""
173
185
  print("๐Ÿงช Starting Example Tests")
@@ -196,30 +208,37 @@ class ExampleTester:
196
208
  print(f" ๐Ÿ“ Testing echo command...")
197
209
  if auth:
198
210
  # Test with admin key
199
- echo_result = self.test_echo_command(port, ssl, auth, API_KEYS["admin"])
211
+ echo_result = self.test_echo_command(
212
+ port, ssl, auth, API_KEYS["admin"]
213
+ )
200
214
  else:
201
215
  echo_result = self.test_echo_command(port, ssl, auth)
202
216
  print(f" Echo: {'โœ…' if echo_result['success'] else 'โŒ'}")
203
217
  # Test full application specific commands
204
218
  if example_type == "full_application":
205
219
  print(f" ๐Ÿ”ง Testing full application commands...")
206
- app_results = self.test_full_application_commands(port, ssl, auth,
207
- API_KEYS["admin"] if auth else None)
220
+ app_results = self.test_full_application_commands(
221
+ port, ssl, auth, API_KEYS["admin"] if auth else None
222
+ )
208
223
  for cmd_name, result in app_results.items():
209
- print(f" {cmd_name}: {'โœ…' if result['success'] else 'โŒ'}")
224
+ print(
225
+ f" {cmd_name}: {'โœ…' if result['success'] else 'โŒ'}"
226
+ )
210
227
  # Store results
211
228
  self.results[f"{example_type}_{config_name}"] = {
212
229
  "health": health_result,
213
230
  "echo": echo_result,
214
- "config_info": config_info
231
+ "config_info": config_info,
215
232
  }
216
233
  if example_type == "full_application":
217
- self.results[f"{example_type}_{config_name}"]["app_commands"] = app_results
234
+ self.results[f"{example_type}_{config_name}"][
235
+ "app_commands"
236
+ ] = app_results
218
237
  except Exception as e:
219
238
  print(f" โŒ Error testing {config_name}: {e}")
220
239
  self.results[f"{example_type}_{config_name}"] = {
221
240
  "error": str(e),
222
- "config_info": config_info
241
+ "config_info": config_info,
223
242
  }
224
243
  finally:
225
244
  # Stop server
@@ -228,6 +247,7 @@ class ExampleTester:
228
247
  process.wait()
229
248
  time.sleep(2)
230
249
  self.print_results()
250
+
231
251
  def print_results(self):
232
252
  """Print test results."""
233
253
  print("\n๐Ÿ“Š Test Results Summary")
@@ -247,8 +267,10 @@ class ExampleTester:
247
267
  print(f" Echo: {'โœ…' if echo_success else 'โŒ'}")
248
268
  # Check app commands for full application
249
269
  if "app_commands" in result:
250
- app_success = all(cmd_result.get("success", False)
251
- for cmd_result in result["app_commands"].values())
270
+ app_success = all(
271
+ cmd_result.get("success", False)
272
+ for cmd_result in result["app_commands"].values()
273
+ )
252
274
  print(f" App Commands: {'โœ…' if app_success else 'โŒ'}")
253
275
  # Overall test success
254
276
  test_success = health_success and echo_success
@@ -259,15 +281,19 @@ class ExampleTester:
259
281
  print("๐ŸŽ‰ All tests passed!")
260
282
  else:
261
283
  print("โš ๏ธ Some tests failed. Check the details above.")
284
+
262
285
  def cleanup(self):
263
286
  """Cleanup processes."""
264
287
  for process in self.processes:
265
288
  if process.poll() is None:
266
289
  process.terminate()
267
290
  process.wait()
291
+
292
+
268
293
  def main():
269
294
  """Main function."""
270
295
  import sys
296
+
271
297
  tester = ExampleTester()
272
298
  try:
273
299
  tester.run_tests()
@@ -277,5 +303,7 @@ def main():
277
303
  print(f"\nโŒ Test execution failed: {e}")
278
304
  finally:
279
305
  tester.cleanup()
306
+
307
+
280
308
  if __name__ == "__main__":
281
309
  main()