mcp-proxy-adapter 6.9.27__py3-none-any.whl โ†’ 6.9.29__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (212) hide show
  1. mcp_proxy_adapter/__init__.py +10 -0
  2. mcp_proxy_adapter/__main__.py +8 -21
  3. mcp_proxy_adapter/api/app.py +10 -913
  4. mcp_proxy_adapter/api/core/__init__.py +18 -0
  5. mcp_proxy_adapter/api/core/app_factory.py +243 -0
  6. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  7. mcp_proxy_adapter/api/core/registration_manager.py +166 -0
  8. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  9. mcp_proxy_adapter/api/handlers.py +78 -199
  10. mcp_proxy_adapter/api/middleware/__init__.py +1 -44
  11. mcp_proxy_adapter/api/middleware/base.py +0 -42
  12. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
  13. mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
  14. mcp_proxy_adapter/api/middleware/factory.py +0 -94
  15. mcp_proxy_adapter/api/middleware/logging.py +0 -112
  16. mcp_proxy_adapter/api/middleware/performance.py +0 -35
  17. mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
  18. mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
  19. mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
  20. mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
  21. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  22. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  23. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  24. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  25. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  26. mcp_proxy_adapter/api/schemas.py +0 -61
  27. mcp_proxy_adapter/api/tool_integration.py +0 -117
  28. mcp_proxy_adapter/api/tools.py +0 -46
  29. mcp_proxy_adapter/cli/__init__.py +12 -0
  30. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  31. mcp_proxy_adapter/cli/commands/client.py +100 -0
  32. mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
  33. mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
  34. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  35. mcp_proxy_adapter/cli/commands/server.py +174 -0
  36. mcp_proxy_adapter/cli/commands/sets.py +128 -0
  37. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  38. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  39. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  40. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  41. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  42. mcp_proxy_adapter/cli/main.py +63 -0
  43. mcp_proxy_adapter/cli/parser.py +324 -0
  44. mcp_proxy_adapter/cli/validators.py +231 -0
  45. mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
  46. mcp_proxy_adapter/client/proxy.py +45 -0
  47. mcp_proxy_adapter/commands/__init__.py +44 -28
  48. mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
  49. mcp_proxy_adapter/commands/base.py +19 -43
  50. mcp_proxy_adapter/commands/builtin_commands.py +0 -75
  51. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  52. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  53. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  54. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  55. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  56. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  57. mcp_proxy_adapter/commands/catalog_manager.py +58 -928
  58. mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
  59. mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
  60. mcp_proxy_adapter/commands/command_registry.py +172 -904
  61. mcp_proxy_adapter/commands/config_command.py +0 -28
  62. mcp_proxy_adapter/commands/dependency_container.py +1 -70
  63. mcp_proxy_adapter/commands/dependency_manager.py +0 -128
  64. mcp_proxy_adapter/commands/echo_command.py +0 -34
  65. mcp_proxy_adapter/commands/health_command.py +0 -3
  66. mcp_proxy_adapter/commands/help_command.py +0 -159
  67. mcp_proxy_adapter/commands/hooks.py +0 -137
  68. mcp_proxy_adapter/commands/key_management_command.py +0 -25
  69. mcp_proxy_adapter/commands/load_command.py +7 -78
  70. mcp_proxy_adapter/commands/plugins_command.py +0 -16
  71. mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
  72. mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
  73. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  74. mcp_proxy_adapter/commands/registration_status_command.py +0 -43
  75. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  76. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  77. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  78. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  79. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  80. mcp_proxy_adapter/commands/reload_command.py +0 -80
  81. mcp_proxy_adapter/commands/result.py +25 -77
  82. mcp_proxy_adapter/commands/role_test_command.py +0 -44
  83. mcp_proxy_adapter/commands/roles_management_command.py +0 -199
  84. mcp_proxy_adapter/commands/security_command.py +0 -30
  85. mcp_proxy_adapter/commands/settings_command.py +0 -68
  86. mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
  87. mcp_proxy_adapter/commands/token_management_command.py +0 -1
  88. mcp_proxy_adapter/commands/transport_management_command.py +0 -20
  89. mcp_proxy_adapter/commands/unload_command.py +0 -71
  90. mcp_proxy_adapter/config.py +15 -626
  91. mcp_proxy_adapter/core/__init__.py +5 -39
  92. mcp_proxy_adapter/core/app_factory.py +14 -36
  93. mcp_proxy_adapter/core/app_runner.py +0 -27
  94. mcp_proxy_adapter/core/auth_validator.py +1 -93
  95. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  96. mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
  97. mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
  98. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  99. mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
  100. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
  101. mcp_proxy_adapter/core/certificate_utils.py +64 -903
  102. mcp_proxy_adapter/core/client.py +0 -6
  103. mcp_proxy_adapter/core/client_manager.py +0 -19
  104. mcp_proxy_adapter/core/client_security.py +0 -2
  105. mcp_proxy_adapter/core/config/__init__.py +18 -0
  106. mcp_proxy_adapter/core/config/config.py +195 -0
  107. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  108. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  109. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  110. mcp_proxy_adapter/core/config/simple_config.py +112 -0
  111. mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
  112. mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
  113. mcp_proxy_adapter/core/config_converter.py +0 -186
  114. mcp_proxy_adapter/core/config_validator.py +96 -1238
  115. mcp_proxy_adapter/core/errors.py +7 -42
  116. mcp_proxy_adapter/core/job_manager.py +54 -0
  117. mcp_proxy_adapter/core/logging.py +2 -22
  118. mcp_proxy_adapter/core/mtls_asgi.py +0 -20
  119. mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
  120. mcp_proxy_adapter/core/mtls_proxy.py +0 -80
  121. mcp_proxy_adapter/core/mtls_server.py +3 -173
  122. mcp_proxy_adapter/core/protocol_manager.py +1 -191
  123. mcp_proxy_adapter/core/proxy/__init__.py +22 -0
  124. mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
  125. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
  126. mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
  127. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  128. mcp_proxy_adapter/core/proxy_client.py +0 -1
  129. mcp_proxy_adapter/core/proxy_registration.py +36 -912
  130. mcp_proxy_adapter/core/role_utils.py +0 -308
  131. mcp_proxy_adapter/core/security_adapter.py +1 -36
  132. mcp_proxy_adapter/core/security_factory.py +1 -150
  133. mcp_proxy_adapter/core/security_integration.py +0 -33
  134. mcp_proxy_adapter/core/server_adapter.py +1 -40
  135. mcp_proxy_adapter/core/server_engine.py +2 -173
  136. mcp_proxy_adapter/core/settings.py +0 -127
  137. mcp_proxy_adapter/core/signal_handler.py +0 -65
  138. mcp_proxy_adapter/core/ssl_utils.py +19 -137
  139. mcp_proxy_adapter/core/transport_manager.py +0 -151
  140. mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
  141. mcp_proxy_adapter/core/utils.py +1 -182
  142. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  143. mcp_proxy_adapter/core/validation/config_validator.py +211 -0
  144. mcp_proxy_adapter/core/validation/file_validator.py +73 -0
  145. mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
  146. mcp_proxy_adapter/core/validation/security_validator.py +58 -0
  147. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  148. mcp_proxy_adapter/custom_openapi.py +33 -652
  149. mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
  150. mcp_proxy_adapter/examples/check_config.py +0 -2
  151. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  152. mcp_proxy_adapter/examples/config_builder.py +13 -2
  153. mcp_proxy_adapter/examples/config_cli.py +0 -1
  154. mcp_proxy_adapter/examples/create_test_configs.py +0 -46
  155. mcp_proxy_adapter/examples/debug_request_state.py +0 -1
  156. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
  157. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
  158. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
  159. mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
  160. mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
  161. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
  162. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
  163. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
  164. mcp_proxy_adapter/examples/full_application/main.py +186 -150
  165. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
  166. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
  167. mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
  168. mcp_proxy_adapter/examples/generate_config.py +65 -11
  169. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  170. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  171. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  172. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  173. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  174. mcp_proxy_adapter/examples/required_certificates.py +0 -2
  175. mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
  176. mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
  177. mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
  178. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  179. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  180. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  181. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  182. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  183. mcp_proxy_adapter/examples/security_test_client.py +24 -1075
  184. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  185. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  186. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  187. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  188. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  189. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  190. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  191. mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
  192. mcp_proxy_adapter/examples/test_config.py +0 -3
  193. mcp_proxy_adapter/examples/test_config_builder.py +25 -405
  194. mcp_proxy_adapter/examples/test_examples.py +0 -1
  195. mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
  196. mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
  197. mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
  198. mcp_proxy_adapter/examples/universal_client.py +0 -6
  199. mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
  200. mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
  201. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
  202. mcp_proxy_adapter/integrations/__init__.py +25 -0
  203. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  204. mcp_proxy_adapter/main.py +70 -62
  205. mcp_proxy_adapter/openapi.py +0 -22
  206. mcp_proxy_adapter/version.py +1 -1
  207. {mcp_proxy_adapter-6.9.27.dist-info โ†’ mcp_proxy_adapter-6.9.29.dist-info}/METADATA +2 -1
  208. mcp_proxy_adapter-6.9.29.dist-info/RECORD +235 -0
  209. {mcp_proxy_adapter-6.9.27.dist-info โ†’ mcp_proxy_adapter-6.9.29.dist-info}/entry_points.txt +1 -1
  210. mcp_proxy_adapter-6.9.27.dist-info/RECORD +0 -149
  211. {mcp_proxy_adapter-6.9.27.dist-info โ†’ mcp_proxy_adapter-6.9.29.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.9.27.dist-info โ†’ mcp_proxy_adapter-6.9.29.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
  """
3
3
  Author: Vasiliy Zdanovskiy
4
4
  email: vasilyvz@gmail.com
5
+
5
6
  Enhanced script for setting up test environment for MCP Proxy Adapter.
6
7
  Prepares the test environment with all necessary files, directories, and configurations.
7
8
  Includes comprehensive documentation and validation for configuration settings.
@@ -19,18 +20,12 @@ Features:
19
20
  - Enhanced error handling and troubleshooting
20
21
  """
21
22
  import os
22
- import shutil
23
- import subprocess
24
23
  import sys
25
24
  import argparse
26
- import json
27
25
  from pathlib import Path
28
- from typing import Dict, List, Any, Tuple
29
26
 
30
27
  # Import mcp_security_framework
31
28
  try:
32
- from mcp_security_framework.core.cert_manager import CertificateManager
33
- from mcp_security_framework.schemas.config import (
34
29
  CertificateConfig,
35
30
  CAConfig,
36
31
  ServerCertConfig,
@@ -42,1486 +37,199 @@ except ImportError:
42
37
  SECURITY_FRAMEWORK_AVAILABLE = False
43
38
  print("Warning: mcp_security_framework not available")
44
39
 
45
-
46
- class ConfigurationValidator:
47
- """
48
- Validates MCP Proxy Adapter configurations for mutually exclusive settings
49
- and protocol compatibility.
50
- """
51
-
52
- def __init__(self):
53
- self.errors: List[str] = []
54
- self.warnings: List[str] = []
55
-
56
- def validate_config(
57
- self, config: Dict[str, Any], config_name: str
58
- ) -> Tuple[bool, List[str], List[str]]:
59
- """
60
- Validate a configuration for mutually exclusive settings and protocol compatibility.
61
-
62
- Args:
63
- config: Configuration dictionary to validate
64
- config_name: Name of the configuration for error reporting
65
-
66
- Returns:
67
- Tuple of (is_valid, errors, warnings)
68
- """
69
- self.errors = []
70
- self.warnings = []
71
-
72
- # Validate protocol settings
73
- self._validate_protocol_settings(config, config_name)
74
-
75
- # Validate SSL/TLS settings
76
- self._validate_ssl_settings(config, config_name)
77
-
78
- # Validate mTLS settings
79
- self._validate_mtls_settings(config, config_name)
80
-
81
- # Validate authentication settings
82
- self._validate_auth_settings(config, config_name)
83
-
84
- return len(self.errors) == 0, self.errors, self.warnings
85
-
86
- def _validate_protocol_settings(
87
- self, config: Dict[str, Any], config_name: str
88
- ) -> None:
89
- """Validate protocol configuration settings."""
90
- protocols = config.get("protocols", {})
91
-
92
- if not protocols.get("enabled", False):
93
- self.warnings.append(
94
- f"โš ๏ธ {config_name}: Protocol middleware is disabled - all protocols will be allowed"
95
- )
96
- return
97
-
98
- allowed_protocols = protocols.get("allowed_protocols", [])
99
- if not allowed_protocols:
100
- self.errors.append(
101
- f"โŒ {config_name}: No allowed protocols specified when protocol middleware is enabled"
102
- )
103
- return
104
-
105
- # Check for invalid protocol combinations
106
- if "http" in allowed_protocols and "https" in allowed_protocols:
107
- self.warnings.append(
108
- f"โš ๏ธ {config_name}: Both HTTP and HTTPS protocols are allowed - consider security implications"
109
- )
110
-
111
- if "mtls" in allowed_protocols and "http" in allowed_protocols:
112
- self.errors.append(
113
- f"โŒ {config_name}: mTLS and HTTP protocols are mutually exclusive - mTLS requires HTTPS"
114
- )
115
-
116
- def _validate_ssl_settings(self, config: Dict[str, Any], config_name: str) -> None:
117
- """Validate SSL/TLS configuration settings."""
118
- security = config.get("security", {})
119
- ssl = security.get("ssl", {})
120
-
121
- if not ssl.get("enabled", False):
122
- return
123
-
124
- # Check certificate file requirements
125
- cert_file = ssl.get("server_cert_file")
126
- key_file = ssl.get("server_key_file")
127
-
128
- if not cert_file or not key_file:
129
- self.errors.append(
130
- f"โŒ {config_name}: SSL enabled but server certificate or key file not specified"
131
- )
132
-
133
- # Check CA certificate requirements
134
- ca_cert_file = ssl.get("ca_cert_file")
135
- verify_server = ssl.get("verify_server", True)
136
-
137
- if verify_server and not ca_cert_file:
138
- self.warnings.append(
139
- f"โš ๏ธ {config_name}: Server verification enabled but no CA certificate specified"
140
- )
141
-
142
- def _validate_mtls_settings(self, config: Dict[str, Any], config_name: str) -> None:
143
- """Validate mTLS configuration settings."""
144
- security = config.get("security", {})
145
- ssl = security.get("ssl", {})
146
-
147
- if not ssl.get("enabled", False):
148
- return
149
-
150
- # Check if mTLS is configured
151
- client_cert_file = ssl.get("client_cert_file")
152
- client_key_file = ssl.get("client_key_file")
153
- verify_client = ssl.get("verify_client", False)
154
-
155
- if verify_client and (not client_cert_file or not client_key_file):
156
- self.errors.append(
157
- f"โŒ {config_name}: Client verification enabled but client certificate or key file not specified"
158
- )
159
-
160
- # Check protocol compatibility
161
- protocols = config.get("protocols", {})
162
- if protocols.get("enabled", False):
163
- allowed_protocols = protocols.get("allowed_protocols", [])
164
- if verify_client and "mtls" not in allowed_protocols:
165
- self.warnings.append(
166
- f"โš ๏ธ {config_name}: Client verification enabled but 'mtls' not in allowed protocols"
167
- )
168
-
169
- def _validate_auth_settings(self, config: Dict[str, Any], config_name: str) -> None:
170
- """Validate authentication configuration settings."""
171
- security = config.get("security", {})
172
- auth = security.get("auth", {})
173
-
174
- if not auth.get("enabled", False):
175
- return
176
-
177
- # Check token requirements
178
- token_required = auth.get("token_required", False)
179
- if token_required and not auth.get("token_secret"):
180
- self.errors.append(
181
- f"โŒ {config_name}: Token authentication enabled but no token secret specified"
182
- )
40
+ # Import setup modules
41
+ ConfigurationValidator,
42
+ create_test_files,
43
+ create_configuration_documentation,
44
+ generate_enhanced_configurations,
45
+ generate_certificates_with_framework,
46
+ test_proxy_registration,
47
+ run_full_test_suite,
48
+ setup_test_environment,
49
+ )
183
50
 
184
51
 
185
52
  def _get_package_paths() -> tuple[Path, Path]:
186
53
  """
187
- Resolve source paths for examples and utils relative to this file
188
- to avoid importing the package during setup.
189
- """
190
- # When running from installed package, __file__ points to .venv/lib/python3.x/site-packages/mcp_proxy_adapter/examples/setup_test_environment.py
191
- # We need to go up to the package root: .venv/lib/python3.x/site-packages/mcp_proxy_adapter/
192
- pkg_root = Path(__file__).resolve().parents[1]
193
- examples_path = pkg_root / "examples"
194
- utils_path = (
195
- pkg_root / "examples" / "scripts"
196
- ) # utils scripts are in examples/scripts in the package
197
-
198
- return examples_path, utils_path
199
-
200
-
201
- def create_configuration_documentation(output_dir: Path) -> None:
202
- """
203
- Create comprehensive documentation for MCP Proxy Adapter configurations.
204
- """
205
- docs_dir = output_dir / "docs"
206
- docs_dir.mkdir(parents=True, exist_ok=True)
207
-
208
- # Create main configuration guide
209
- config_guide = docs_dir / "CONFIGURATION_GUIDE.md"
210
- with open(config_guide, "w", encoding="utf-8") as f:
211
- f.write(
212
- """# MCP Proxy Adapter Configuration Guide
213
-
214
- ## Overview
215
-
216
- This guide explains how to configure MCP Proxy Adapter for different deployment scenarios,
217
- including HTTP, HTTPS, and mTLS configurations.
218
-
219
- ## Configuration Structure
220
-
221
- ```json
222
- {
223
- "server": {
224
- "host": "0.0.0.0",
225
- "port": 8000
226
- },
227
- "protocols": {
228
- "enabled": true,
229
- "allowed_protocols": ["https", "mtls"]
230
- },
231
- "security": {
232
- "ssl": {
233
- "enabled": true,
234
- "server_cert_file": "path/to/server.crt",
235
- "server_key_file": "path/to/server.key",
236
- "ca_cert_file": "path/to/ca.crt",
237
- "client_cert_file": "path/to/client.crt",
238
- "client_key_file": "path/to/client.key",
239
- "verify_server": true,
240
- "verify_client": false,
241
- "min_tls_version": "TLSv1.2"
242
- },
243
- "auth": {
244
- "enabled": false,
245
- "token_required": false,
246
- "token_secret": "your-secret-key"
247
- }
248
- }
249
- }
250
- ```
251
-
252
- ## Protocol Configuration
253
-
254
- ### Protocol Middleware
255
-
256
- The `protocols` section controls which protocols are allowed:
257
-
258
- - `enabled: true` - Protocol validation is active
259
- - `enabled: false` - All protocols are allowed (bypasses validation)
260
-
261
- ### Allowed Protocols
262
-
263
- - `"http"` - Plain HTTP (insecure)
264
- - `"https"` - HTTPS with server certificate
265
- - `"mtls"` - Mutual TLS (client and server certificates)
266
-
267
- ### Protocol Combinations
268
-
269
- **Valid combinations:**
270
- - `["https"]` - HTTPS only
271
- - `["https", "mtls"]` - HTTPS and mTLS
272
- - `["http"]` - HTTP only (not recommended for production)
273
-
274
- **Invalid combinations:**
275
- - `["http", "mtls"]` - HTTP and mTLS are mutually exclusive
276
- - `["http", "https"]` - Mixed HTTP/HTTPS (security risk)
277
-
278
- ## SSL/TLS Configuration
279
-
280
- ### Server Certificates
281
-
282
- Required for HTTPS and mTLS:
283
- - `server_cert_file` - Server certificate file
284
- - `server_key_file` - Server private key file
285
-
286
- ### CA Certificates
287
-
288
- - `ca_cert_file` - CA certificate for server verification
289
- - `verify_server: true` - Verify server certificate against CA
290
- - `verify_server: false` - Disable server certificate verification
291
-
292
- ### Client Certificates (mTLS)
293
-
294
- - `client_cert_file` - Client certificate file
295
- - `client_key_file` - Client private key file
296
- - `verify_client: true` - Require client certificates
297
- - `verify_client: false` - No client certificate required
298
-
299
- ## Authentication
300
-
301
- ### Token Authentication
302
-
303
- - `auth.enabled: true` - Enable authentication
304
- - `token_required: true` - Require authentication tokens
305
- - `token_secret` - Secret key for token validation
306
-
307
- ## Common Configuration Patterns
308
-
309
- ### 1. Development (HTTP)
310
- ```json
311
- {
312
- "protocols": {"enabled": false},
313
- "security": {"ssl": {"enabled": false}}
314
- }
315
- ```
316
-
317
- ### 2. Production HTTPS
318
- ```json
319
- {
320
- "protocols": {
321
- "enabled": true,
322
- "allowed_protocols": ["https"]
323
- },
324
- "security": {
325
- "ssl": {
326
- "enabled": true,
327
- "server_cert_file": "certs/server.crt",
328
- "server_key_file": "keys/server.key",
329
- "verify_server": true,
330
- "ca_cert_file": "certs/ca.crt"
331
- }
332
- }
333
- }
334
- ```
335
-
336
- ### 3. mTLS with Client Verification
337
- ```json
338
- {
339
- "protocols": {
340
- "enabled": true,
341
- "allowed_protocols": ["https", "mtls"]
342
- },
343
- "security": {
344
- "ssl": {
345
- "enabled": true,
346
- "server_cert_file": "certs/server.crt",
347
- "server_key_file": "keys/server.key",
348
- "ca_cert_file": "certs/ca.crt",
349
- "client_cert_file": "certs/client.crt",
350
- "client_key_file": "keys/client.key",
351
- "verify_server": true,
352
- "verify_client": true
353
- }
354
- }
355
- }
356
- ```
357
-
358
- ## Validation Rules
359
-
360
- The configuration validator checks for:
361
-
362
- 1. **Mutually Exclusive Settings:**
363
- - HTTP and mTLS protocols
364
- - Client verification without client certificates
365
- - Server verification without CA certificates
366
-
367
- 2. **Required Dependencies:**
368
- - SSL enabled requires server certificates
369
- - mTLS requires both server and client certificates
370
- - Protocol middleware enabled requires allowed protocols
371
-
372
- 3. **Security Warnings:**
373
- - HTTP and HTTPS in same configuration
374
- - Server verification without CA certificate
375
- - Client verification without mTLS protocol
54
+ Get paths to the package and examples directory.
376
55
 
377
- ## Troubleshooting
378
-
379
- ### Common Issues
380
-
381
- 1. **"Protocol not allowed" errors:**
382
- - Check `protocols.allowed_protocols` includes required protocol
383
- - Ensure `protocols.enabled: true` for validation
384
-
385
- 2. **SSL certificate errors:**
386
- - Verify certificate file paths are correct
387
- - Check certificate validity and format
388
- - Ensure CA certificate matches server certificate
389
-
390
- 3. **mTLS connection failures:**
391
- - Verify client certificates are valid
392
- - Check `verify_client: true` is set
393
- - Ensure "mtls" is in allowed protocols
394
-
395
- ### Debug Mode
396
-
397
- Enable debug logging to troubleshoot issues:
398
-
399
- ```json
400
- {
401
- "logging": {
402
- "level": "DEBUG",
403
- "handlers": ["console", "file"]
404
- }
405
- }
406
- ```
407
- """
408
- )
409
-
410
- print(f"โœ… Created configuration documentation: {config_guide}")
411
-
412
-
413
- def create_test_files(output_dir: Path) -> None:
414
- """
415
- Create additional test files for proxy registration testing.
56
+ Returns:
57
+ Tuple of (package_path, examples_path)
416
58
  """
417
- # Create test proxy server script
418
- test_proxy_server = output_dir / "test_proxy_server.py"
419
- with open(test_proxy_server, "w", encoding="utf-8") as f:
420
- f.write(
421
- '''#!/usr/bin/env python3
422
- """
423
- Author: Vasiliy Zdanovskiy
424
- email: vasilyvz@gmail.com
425
-
426
- Simple mTLS proxy server for testing proxy registration SSL fix.
427
- """
428
- import asyncio
429
- import os
430
- import ssl
431
- from fastapi import FastAPI, Request
432
- from fastapi.responses import JSONResponse
433
- import hypercorn.asyncio
434
- import hypercorn.config
435
-
436
-
437
- app = FastAPI(title="Test mTLS Proxy Server", version="1.0.0")
438
-
439
-
440
- @app.post("/register")
441
- async def register_server(request: Request):
442
- """Register server endpoint."""
443
- try:
444
- data = await request.json()
445
- print(f"โœ… Received registration request: {data}")
446
-
447
- # Check if client certificate is present
448
- client_cert = request.client
449
- if client_cert:
450
- print(f"โœ… Client certificate verified: {client_cert}")
451
-
452
- return JSONResponse(
453
- status_code=200,
454
- content={
455
- "success": True,
456
- "server_key": f"{data.get('server_id', 'unknown')}_1",
457
- "message": "Server registered successfully"
458
- }
459
- )
460
- except Exception as e:
461
- print(f"โŒ Registration error: {e}")
462
- return JSONResponse(
463
- status_code=500,
464
- content={
465
- "success": False,
466
- "error": {
467
- "message": str(e),
468
- "code": "REGISTRATION_ERROR"
469
- }
470
- }
471
- )
472
-
473
-
474
- @app.post("/unregister")
475
- async def unregister_server(request: Request):
476
- """Unregister server endpoint."""
477
- try:
478
- data = await request.json()
479
- print(f"โœ… Received unregistration request: {data}")
480
-
481
- # Check if client certificate is present
482
- client_cert = request.client
483
- if client_cert:
484
- print(f"โœ… Client certificate verified for unregistration: {client_cert}")
485
-
486
- return JSONResponse(
487
- status_code=200,
488
- content={
489
- "success": True,
490
- "message": "Server unregistered successfully"
491
- }
492
- )
493
- except Exception as e:
494
- print(f"โŒ Unregistration error: {e}")
495
- return JSONResponse(
496
- status_code=500,
497
- content={
498
- "success": False,
499
- "error": {
500
- "message": str(e),
501
- "code": "UNREGISTRATION_ERROR"
502
- }
503
- }
504
- )
505
-
506
-
507
- @app.get("/health")
508
- async def health_check():
509
- """Health check endpoint."""
510
- return JSONResponse(
511
- status_code=200,
512
- content={
513
- "status": "healthy",
514
- "message": "mTLS Proxy Server is running"
515
- }
516
- )
517
-
518
-
519
- async def main():
520
- """Run the mTLS proxy server."""
521
- print("๐Ÿš€ Starting Test mTLS Proxy Server...")
522
- print("๐Ÿ“ก Server URL: https://127.0.0.1:20005")
523
- print("๐Ÿ” mTLS enabled with client certificate verification")
524
- print("๐Ÿ“‹ Available endpoints:")
525
- print(" POST /register - Register server")
526
- print(" POST /unregister - Unregister server")
527
- print(" GET /health - Health check")
528
- print("โšก Press Ctrl+C to stop\\n")
529
-
530
- # Configure Hypercorn
531
- config = hypercorn.config.Config()
532
- config.bind = ["127.0.0.1:20005"]
533
- config.loglevel = "info"
59
+ # Get the directory containing this script
60
+ script_dir = Path(__file__).parent.absolute()
534
61
 
535
- # Check if certificates exist, if not run without SSL
536
- cert_file = "certs/localhost_server.crt"
537
- key_file = "keys/server_key.pem"
62
+ # Package path is the parent of examples
63
+ package_path = script_dir.parent
538
64
 
539
- if os.path.exists(cert_file) and os.path.exists(key_file):
540
- print("๐Ÿ” Using SSL certificates for mTLS")
541
- config.certfile = cert_file
542
- config.keyfile = key_file
543
- else:
544
- print("โš ๏ธ SSL certificates not found, running without SSL")
545
- # Run on HTTP instead of HTTPS
546
- config.bind = ["127.0.0.1:20005"]
547
-
548
- # Run server with Hypercorn
549
- await hypercorn.asyncio.serve(app, config)
550
-
551
-
552
- if __name__ == "__main__":
553
- asyncio.run(main())
554
- '''
555
- )
556
-
557
- # Make it executable
558
- test_proxy_server.chmod(0o755)
559
- print(f"โœ… Created test proxy server: {test_proxy_server}")
560
-
561
- # Create test script for proxy registration
562
- test_script = output_dir / "test_proxy_registration.py"
563
- with open(test_script, "w", encoding="utf-8") as f:
564
- f.write(
565
- '''#!/usr/bin/env python3
566
- """
567
- Author: Vasiliy Zdanovskiy
568
- email: vasilyvz@gmail.com
569
-
570
- Test script to verify proxy registration SSL configuration fix.
571
- """
572
- import sys
573
- import subprocess
574
- import time
575
- import requests
576
- from pathlib import Path
577
-
578
-
579
- def test_proxy_registration():
580
- """Test proxy registration with SSL configuration."""
581
- print("๐Ÿงช Testing Proxy Registration SSL Configuration Fix")
582
- print("=" * 60)
65
+ # Examples path
66
+ examples_path = script_dir
583
67
 
584
- # Error tracking
585
- error_count = 0
586
- errors = []
587
-
588
- # Kill any existing process on port 20005
589
- print("๐Ÿงน Killing any existing process on port 20005...")
590
- try:
591
- subprocess.run(["fuser", "-k", "20005/tcp"], check=False, capture_output=True)
592
- except FileNotFoundError:
593
- # fuser not available, try with lsof
594
- try:
595
- # Get PIDs using lsof
596
- result = subprocess.run(["lsof", "-ti:20005"], capture_output=True, text=True, check=False)
597
- if result.returncode == 0 and result.stdout.strip():
598
- pids = result.stdout.strip().split('\\n')
599
- for pid in pids:
600
- if pid.strip():
601
- subprocess.run(["kill", "-9", pid.strip()], check=False, capture_output=True)
602
- except:
603
- pass
604
-
605
- # Start proxy server
606
- print("๐Ÿš€ Starting test proxy server...")
607
- proxy_process = subprocess.Popen([
608
- sys.executable, "test_proxy_server.py"
609
- ], cwd=Path(__file__).parent)
610
-
611
- try:
612
- # Wait for server to start
613
- print("โณ Waiting for proxy server to start...")
614
- time.sleep(5)
615
-
616
- # Test proxy server health - try both HTTP and HTTPS
617
- print("๐Ÿ” Testing proxy server health...")
618
- proxy_working = False
619
-
620
- # Try HTTP first
621
- try:
622
- print("๐Ÿ” Trying HTTP connection...")
623
- response = requests.get(
624
- "http://127.0.0.1:20005/health",
625
- timeout=10
626
- )
627
- if response.status_code == 200:
628
- print("โœ… Proxy server is running on HTTP")
629
- proxy_working = True
630
- else:
631
- print(f"โš ๏ธ HTTP health check failed: {response.status_code}")
632
- except Exception as e:
633
- print(f"โš ๏ธ HTTP connection failed: {e}")
634
-
635
- # Try HTTPS if HTTP failed
636
- if not proxy_working:
637
- try:
638
- print("๐Ÿ” Trying HTTPS connection...")
639
- response = requests.get(
640
- "https://127.0.0.1:20005/health",
641
- verify=False,
642
- timeout=10
643
- )
644
- if response.status_code == 200:
645
- print("โœ… Proxy server is running on HTTPS")
646
- proxy_working = True
647
- else:
648
- print(f"โš ๏ธ HTTPS health check failed: {response.status_code}")
649
- except Exception as e:
650
- print(f"โš ๏ธ HTTPS connection failed: {e}")
651
-
652
- if not proxy_working:
653
- error_count += 1
654
- errors.append("Failed to connect to proxy server on both HTTP and HTTPS")
655
- print("โŒ Failed to connect to proxy server on both HTTP and HTTPS")
656
- return False
657
-
658
- # Test mTLS server with registration
659
- print("๐Ÿš€ Starting mTLS server with proxy registration...")
660
- server_process = subprocess.Popen([
661
- sys.executable, "-m", "mcp_proxy_adapter",
662
- "--config", "configs/test_proxy_registration.json"
663
- ], cwd=Path(__file__).parent)
664
-
665
- try:
666
- # Wait for server to start and attempt registration
667
- print("โณ Waiting for server to start and register...")
668
- time.sleep(10)
669
-
670
- # Check if server is running
671
- if server_process.poll() is None:
672
- print("โœ… mTLS server started successfully")
673
-
674
- # Check if registration was successful by querying the proxy server
675
- print("โณ Checking registration status...")
676
- time.sleep(5) # Give more time for registration attempt
677
-
678
- if server_process.poll() is None:
679
- print("โœ… Server is running - checking registration status...")
680
-
681
- # Try to check if server is registered by querying proxy server
682
- try:
683
- # Check if we can get server list from proxy (if it has such endpoint)
684
- # For now, we'll assume registration is successful if server is still running
685
- # and no error messages were shown in the logs
686
- print("โœ… Server is running and appears to be registered successfully")
687
- print("โœ… Proxy registration test PASSED")
688
- return True
689
- except Exception as e:
690
- error_count += 1
691
- errors.append(f"Failed to verify registration: {e}")
692
- print(f"โŒ Failed to verify registration: {e}")
693
- print(f"๐Ÿ“Š Error count: {error_count}")
694
- print(f"๐Ÿ“‹ Errors: {errors}")
695
- return False
696
- else:
697
- error_count += 1
698
- errors.append("Server stopped unexpectedly")
699
- print("โŒ Server stopped unexpectedly")
700
- print(f"๐Ÿ“Š Error count: {error_count}")
701
- print(f"๐Ÿ“‹ Errors: {errors}")
702
- return False
703
- else:
704
- error_count += 1
705
- errors.append("mTLS server failed to start")
706
- print("โŒ mTLS server failed to start")
707
- print(f"๐Ÿ“Š Error count: {error_count}")
708
- print(f"๐Ÿ“‹ Errors: {errors}")
709
- return False
710
-
711
- finally:
712
- # Clean up server process
713
- if server_process.poll() is None:
714
- server_process.terminate()
715
- server_process.wait()
716
-
717
- finally:
718
- # Clean up proxy process
719
- if proxy_process.poll() is None:
720
- proxy_process.terminate()
721
- proxy_process.wait()
722
-
723
-
724
- def main():
725
- """Run the test."""
726
- success = test_proxy_registration()
727
-
728
- if success:
729
- print("\\n๐ŸŽ‰ All tests passed! Proxy registration SSL fix is working correctly.")
730
- return 0
731
- else:
732
- print("\\nโŒ Tests failed. Check the logs above for details.")
733
- return 1
734
-
735
-
736
- if __name__ == "__main__":
737
- sys.exit(main())
738
- '''
739
- )
740
-
741
- # Make it executable
742
- test_script.chmod(0o755)
743
- print(f"โœ… Created test script: {test_script}")
744
-
745
-
746
- def generate_enhanced_configurations(output_dir: Path) -> None:
747
- """
748
- Generate enhanced configurations with proper protocol settings and validation.
749
- """
750
- configs_dir = output_dir / "configs"
751
- configs_dir.mkdir(parents=True, exist_ok=True)
752
-
753
- validator = ConfigurationValidator()
754
-
755
- # Single comprehensive HTTP configuration with all features
756
- configs = {
757
- "comprehensive_http.json": {
758
- "uuid": "550e8400-e29b-41d4-a716-446655440000",
759
- "server": {
760
- "host": "127.0.0.1",
761
- "port": 20001,
762
- "debug": False,
763
- "log_level": "INFO",
764
- "workers": 1,
765
- "reload": False,
766
- },
767
- "ssl": {"enabled": False},
768
- "security": {
769
- "enabled": True,
770
- "auth": {
771
- "enabled": True,
772
- "methods": ["api_key"],
773
- "api_keys": {
774
- "admin-token-123": "admin",
775
- "user-token-456": "user",
776
- "readonly-token-789": "readonly",
777
- "guest-token-abc": "guest",
778
- "proxy-token-def": "proxy",
779
- },
780
- },
781
- "permissions": {"enabled": True, "roles_file": "configs/roles.json"},
782
- },
783
- "registration": {
784
- "enabled": True,
785
- "url": "http://127.0.0.1:3004/proxy",
786
- "name": "comprehensive_http_adapter",
787
- "capabilities": [
788
- "http",
789
- "token_auth",
790
- "roles",
791
- "registration",
792
- "heartbeat",
793
- ],
794
- "retry_count": 3,
795
- "retry_delay": 5,
796
- "heartbeat": {"enabled": True, "interval": 30},
797
- },
798
- "protocols": {"enabled": True, "allowed_protocols": ["http"]},
799
- }
800
- }
801
-
802
- # Generate and validate configurations
803
- for config_name, config_data in configs.items():
804
- config_path = configs_dir / config_name
805
-
806
- # Validate configuration
807
- is_valid, errors, warnings = validator.validate_config(config_data, config_name)
808
-
809
- if not is_valid:
810
- print(f"โŒ Configuration {config_name} has errors:")
811
- for error in errors:
812
- print(f" {error}")
813
- continue
814
-
815
- if warnings:
816
- print(f"โš ๏ธ Configuration {config_name} has warnings:")
817
- for warning in warnings:
818
- print(f" {warning}")
819
-
820
- # Write configuration file
821
- with open(config_path, "w", encoding="utf-8") as f:
822
- json.dump(config_data, f, indent=2)
823
-
824
- print(f"โœ… Generated configuration: {config_path}")
825
-
826
- # Create configuration index
827
- index_path = configs_dir / "README.md"
828
- with open(index_path, "w", encoding="utf-8") as f:
829
- f.write(
830
- """# Comprehensive HTTP Configuration
831
-
832
- This directory contains a single comprehensive HTTP configuration with all features enabled.
833
-
834
- ## Available Configuration
835
-
836
- ### Comprehensive HTTP
837
- - `comprehensive_http.json` - Complete HTTP server with all features
838
-
839
- ## Features
840
-
841
- ### Security
842
- - **Token Authentication**: API key-based access control with 5 predefined tokens
843
- - **Role-based Permissions**: Granular access control with 5 roles
844
- - **Roles**: admin, user, readonly, guest, proxy
845
-
846
- ### Authentication Tokens
847
- - `admin-token-123` โ†’ admin role (full access)
848
- - `user-token-456` โ†’ user role (read, write, execute)
849
- - `readonly-token-789` โ†’ readonly role (read only)
850
- - `guest-token-abc` โ†’ guest role (limited access)
851
- - `proxy-token-def` โ†’ proxy role (registration, heartbeat)
852
-
853
- ### Registration & Monitoring
854
- - **Proxy Registration**: Automatic service discovery
855
- - **Heartbeat**: 30-second health monitoring
856
- - **Retry Logic**: 3 attempts with 5-second delay
857
-
858
- ### Protocols
859
- - **HTTP**: Standard web protocol (port 20001)
860
-
861
- ## Usage
862
-
863
- ### Starting the Server
864
- ```bash
865
- # Start comprehensive HTTP server
866
- python -m mcp_proxy_adapter --config configs/comprehensive_http.json
867
- ```
868
-
869
- ### Testing Authentication
870
- ```bash
871
- # Test with admin token
872
- curl -H "Authorization: Bearer admin-token-123" http://localhost:20001/health
873
-
874
- # Test with user token
875
- curl -H "Authorization: Bearer user-token-456" http://localhost:20001/health
876
-
877
- # Test with readonly token
878
- curl -H "Authorization: Bearer readonly-token-789" http://localhost:20001/health
879
- ```
880
-
881
- ## Configuration Details
882
-
883
- - **Server**: 127.0.0.1:20001
884
- - **SSL**: Disabled (HTTP only)
885
- - **Authentication**: Token-based with roles
886
- - **Registration**: Enabled with proxy server
887
- - **Heartbeat**: 30-second interval
888
- - **Protocols**: HTTP only
889
-
890
- ## Customization
891
-
892
- Edit `comprehensive_http.json` to:
893
- - Change server host/port
894
- - Add/modify authentication tokens
895
- - Update role permissions
896
- - Modify registration settings
897
- - Adjust heartbeat interval
898
-
899
- ## Troubleshooting
900
-
901
- 1. **Port Conflicts**: Ensure port 20001 is not in use
902
- 2. **Token Issues**: Verify token format and role mapping
903
- 3. **Registration Issues**: Check proxy server availability
904
- 4. **Permission Errors**: Verify roles.json file exists
905
- """
906
- )
907
-
908
- print(f"โœ… Created configuration index: {index_path}")
909
-
910
-
911
- def setup_test_environment(output_dir: Path) -> None:
912
- """
913
- Setup test environment under output_dir with required files
914
- and directories.
915
-
916
- All created directories and copied files are rooted at output_dir
917
- so users can run scripts relative to that directory.
918
- """
919
- print("๐Ÿ”ง Setting up enhanced test environment...")
920
- output_dir = output_dir.resolve()
921
- output_dir.mkdir(parents=True, exist_ok=True)
922
-
923
- # Create test environment directory structure
924
- directories = [
925
- "examples/basic_framework",
926
- "examples/full_application",
927
- "scripts",
928
- "configs",
929
- "certs",
930
- "keys",
931
- "tokens",
932
- "logs",
933
- "docs",
934
- ]
935
- for directory in directories:
936
- target_dir = output_dir / directory
937
- target_dir.mkdir(parents=True, exist_ok=True)
938
- print(f"โœ… Created directory: {target_dir}")
939
-
940
- # Resolve package paths
941
- examples_src_root, utils_src_root = _get_package_paths()
942
-
943
- # Copy example files
944
- basic_framework_src = examples_src_root / "basic_framework"
945
- if basic_framework_src.exists():
946
- shutil.copytree(
947
- basic_framework_src,
948
- output_dir / "examples/basic_framework",
949
- dirs_exist_ok=True,
950
- )
951
- print("โœ… Copied basic_framework examples")
952
-
953
- full_application_src = examples_src_root / "full_application"
954
- if full_application_src.exists():
955
- shutil.copytree(
956
- full_application_src,
957
- output_dir / "examples/full_application",
958
- dirs_exist_ok=True,
959
- )
960
- print("โœ… Copied full_application examples")
961
-
962
- # Copy utility scripts from examples/scripts
963
- config_generator_src = utils_src_root / "config_generator.py"
964
- if config_generator_src.exists():
965
- shutil.copy2(config_generator_src, output_dir / "scripts/")
966
- print("โœ… Copied config_generator.py")
967
-
968
- # Copy certificate generation scripts from examples/scripts
969
- create_certs_src = utils_src_root / "create_certificates_simple.py"
970
- if create_certs_src.exists():
971
- shutil.copy2(create_certs_src, output_dir / "scripts/")
972
- print("โœ… Copied create_certificates_simple.py")
973
-
974
- cert_tokens_src = utils_src_root / "generate_certificates_and_tokens.py"
975
- if cert_tokens_src.exists():
976
- shutil.copy2(cert_tokens_src, output_dir / "scripts/")
977
- print("โœ… Copied generate_certificates_and_tokens.py")
978
-
979
- # Copy test suite runner from examples
980
- test_suite_src = examples_src_root / "run_full_test_suite.py"
981
- if test_suite_src.exists():
982
- shutil.copy2(test_suite_src, output_dir)
983
- print("โœ… Copied run_full_test_suite.py")
984
-
985
- # Copy other required test files from examples
986
- test_files = [
987
- "create_test_configs.py",
988
- "run_security_tests.py",
989
- "run_proxy_server.py",
990
- ]
991
- for test_file in test_files:
992
- test_file_src = examples_src_root / test_file
993
- if test_file_src.exists():
994
- shutil.copy2(test_file_src, output_dir)
995
- print(f"โœ… Copied {test_file}")
996
-
997
- # Create comprehensive_config.json if it doesn't exist
998
- comprehensive_config_dst = output_dir / "comprehensive_config.json"
999
- if not comprehensive_config_dst.exists():
1000
- # Create a basic comprehensive config
1001
- comprehensive_config = {
1002
- "uuid": "79db1fa0-ff4e-4695-8c94-1d5ac470b613",
1003
- "server": {"host": "127.0.0.1", "port": 20001},
1004
- "ssl": {
1005
- "enabled": False,
1006
- "cert_file": "certs/localhost_server.crt",
1007
- "key_file": "keys/server_key.pem",
1008
- "ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
1009
- "verify_client": False,
1010
- },
1011
- "security": {
1012
- "enabled": True,
1013
- "auth": {
1014
- "enabled": True,
1015
- "methods": ["token"],
1016
- "api_keys": {
1017
- "admin-token-123": "admin",
1018
- "user-token-456": "user",
1019
- "readonly-token-789": "readonly",
1020
- },
1021
- },
1022
- "permissions": {"enabled": True, "roles_file": "roles.json"},
1023
- },
1024
- "protocols": {
1025
- "enabled": True,
1026
- "default_protocol": "http",
1027
- "allowed_protocols": ["http"],
1028
- },
1029
- }
1030
-
1031
- with open(comprehensive_config_dst, "w", encoding="utf-8") as f:
1032
- json.dump(comprehensive_config, f, indent=2)
1033
- print("โœ… Created comprehensive_config.json")
1034
- else:
1035
- print("โœ… comprehensive_config.json already exists")
1036
-
1037
- # Copy roles.json to the root directory for compatibility
1038
- roles_src = examples_src_root / "roles.json"
1039
- if roles_src.exists():
1040
- shutil.copy2(roles_src, output_dir)
1041
- print("โœ… Copied roles.json to root directory")
1042
- else:
1043
- # Create a basic roles.json if it doesn't exist
1044
- roles_config = {
1045
- "roles": {
1046
- "admin": {
1047
- "permissions": ["*"],
1048
- "description": "Full access to all commands",
1049
- },
1050
- "user": {
1051
- "permissions": ["echo", "health", "help"],
1052
- "description": "Basic user permissions",
1053
- },
1054
- "readonly": {
1055
- "permissions": ["health", "help"],
1056
- "description": "Read-only access",
1057
- },
1058
- }
1059
- }
1060
-
1061
- roles_dst = output_dir / "roles.json"
1062
- with open(roles_dst, "w", encoding="utf-8") as f:
1063
- json.dump(roles_config, f, indent=2)
1064
- print("โœ… Created roles.json in root directory")
1065
-
1066
- # Also copy from configs directory if it exists
1067
- roles_configs_src = output_dir / "configs" / "roles.json"
1068
- if roles_configs_src.exists():
1069
- shutil.copy2(roles_configs_src, output_dir / "roles.json")
1070
- print("โœ… Updated roles.json from configs directory")
1071
-
1072
- # Create configuration documentation
1073
- create_configuration_documentation(output_dir)
1074
-
1075
- # Generate enhanced configurations
1076
- generate_enhanced_configurations(output_dir)
1077
-
1078
- # Create test files
1079
- create_test_files(output_dir)
1080
-
1081
- print(
1082
- "๐ŸŽ‰ Enhanced test environment setup completed successfully at: {}".format(
1083
- output_dir
1084
- )
1085
- )
1086
-
1087
-
1088
- def generate_certificates_with_framework(output_dir: Path) -> bool:
1089
- """
1090
- Generate certificates using mcp_security_framework.
1091
- """
1092
- if not SECURITY_FRAMEWORK_AVAILABLE:
1093
- print("โŒ mcp_security_framework not available for certificate " "generation")
1094
- return False
1095
- try:
1096
- print("๐Ÿ” Generating certificates using mcp_security_framework...")
1097
- # Configure certificate manager
1098
- cert_config = CertificateConfig(
1099
- cert_storage_path=str((output_dir / "certs").resolve()),
1100
- key_storage_path=str((output_dir / "keys").resolve()),
1101
- default_validity_days=365,
1102
- key_size=2048,
1103
- hash_algorithm="sha256",
1104
- )
1105
- cert_manager = CertificateManager(cert_config)
1106
- # Generate CA certificate
1107
- ca_config = CAConfig(
1108
- common_name="MCP Proxy Adapter Test CA",
1109
- organization="Test Organization",
1110
- organizational_unit="Certificate Authority",
1111
- country="US",
1112
- state="Test State",
1113
- locality="Test City",
1114
- validity_years=10, # Use validity_years instead of validity_days
1115
- key_size=2048,
1116
- hash_algorithm="sha256",
1117
- )
1118
- cert_pair = cert_manager.create_root_ca(ca_config)
1119
- if not cert_pair or not cert_pair.certificate_path:
1120
- print("โŒ Failed to create CA certificate: Invalid certificate pair")
1121
- return False
1122
- print("โœ… CA certificate created successfully")
1123
- # Find CA key file
1124
- ca_key_path = cert_pair.private_key_path
1125
- # Generate server certificate (localhost_server.crt)
1126
- server_config = ServerCertConfig(
1127
- common_name="localhost",
1128
- organization="Test Organization",
1129
- organizational_unit="Server",
1130
- country="US",
1131
- state="Test State",
1132
- locality="Test City",
1133
- validity_days=365,
1134
- key_size=2048,
1135
- hash_algorithm="sha256",
1136
- subject_alt_names=[
1137
- "localhost",
1138
- "127.0.0.1",
1139
- ],
1140
- ca_cert_path=cert_pair.certificate_path,
1141
- ca_key_path=ca_key_path,
1142
- )
1143
- cert_pair = cert_manager.create_server_certificate(server_config)
1144
- if not cert_pair or not cert_pair.certificate_path:
1145
- print("โŒ Failed to create server certificate: Invalid certificate " "pair")
1146
- return False
1147
- print("โœ… Server certificate created successfully")
1148
-
1149
- # Generate additional server certificate (mcp_proxy_adapter_server.crt) for HTTPS configs
1150
- server_config2 = ServerCertConfig(
1151
- common_name="mcp_proxy_adapter_server",
1152
- organization="Test Organization",
1153
- organizational_unit="Server",
1154
- country="US",
1155
- state="Test State",
1156
- locality="Test City",
1157
- validity_days=365,
1158
- key_size=2048,
1159
- hash_algorithm="sha256",
1160
- subject_alt_names=[
1161
- "localhost",
1162
- "127.0.0.1",
1163
- "mcp_proxy_adapter_server",
1164
- ],
1165
- ca_cert_path=cert_pair.certificate_path,
1166
- ca_key_path=cert_pair.private_key_path,
1167
- )
1168
- cert_pair2 = cert_manager.create_server_certificate(server_config2)
1169
- if not cert_pair2 or not cert_pair2.certificate_path:
1170
- print("โŒ Failed to create mcp_proxy_adapter_server certificate: Invalid certificate " "pair")
1171
- return False
1172
- print("โœ… mcp_proxy_adapter_server certificate created successfully")
1173
-
1174
- # Create symlinks with the expected names for HTTPS configs
1175
- import shutil
1176
- certs_dir = output_dir / "certs"
1177
- keys_dir = output_dir / "keys"
1178
-
1179
- # Create symlink for mcp_proxy_adapter_server.crt
1180
- expected_cert_path = certs_dir / "mcp_proxy_adapter_server.crt"
1181
- if not expected_cert_path.exists():
1182
- shutil.copy2(cert_pair2.certificate_path, expected_cert_path)
1183
- print(f"โœ… Created mcp_proxy_adapter_server.crt: {expected_cert_path}")
1184
-
1185
- # Create symlink for mcp_proxy_adapter_server.key
1186
- expected_key_path = certs_dir / "mcp_proxy_adapter_server.key"
1187
- if not expected_key_path.exists():
1188
- shutil.copy2(cert_pair2.private_key_path, expected_key_path)
1189
- print(f"โœ… Created mcp_proxy_adapter_server.key: {expected_key_path}")
1190
- # Generate client certificates
1191
- client_configs = [
1192
- (
1193
- "admin",
1194
- ["admin"],
1195
- [
1196
- "read",
1197
- "write",
1198
- "execute",
1199
- "delete",
1200
- "admin",
1201
- "register",
1202
- "unregister",
1203
- "heartbeat",
1204
- "discover",
1205
- ],
1206
- ),
1207
- (
1208
- "user",
1209
- ["user"],
1210
- [
1211
- "read",
1212
- "execute",
1213
- "register",
1214
- "unregister",
1215
- "heartbeat",
1216
- "discover",
1217
- ],
1218
- ),
1219
- ("readonly", ["readonly"], ["read", "discover"]),
1220
- ("guest", ["guest"], ["read", "discover"]),
1221
- (
1222
- "proxy",
1223
- ["proxy"],
1224
- ["register", "unregister", "heartbeat", "discover"],
1225
- ),
1226
- ]
1227
- for client_name, roles, permissions in client_configs:
1228
- client_config = ClientCertConfig(
1229
- common_name=f"{client_name}-client",
1230
- organization="Test Organization",
1231
- organizational_unit="Client",
1232
- country="US",
1233
- state="Test State",
1234
- locality="Test City",
1235
- validity_days=730,
1236
- key_size=2048,
1237
- hash_algorithm="sha256",
1238
- roles=roles,
1239
- permissions=permissions,
1240
- ca_cert_path=cert_pair.certificate_path,
1241
- ca_key_path=cert_pair.private_key_path,
1242
- )
1243
- client_cert_pair = cert_manager.create_client_certificate(client_config)
1244
- if not client_cert_pair or not client_cert_pair.certificate_path:
1245
- print(
1246
- (
1247
- "โŒ Failed to create client certificate {}: "
1248
- "Invalid certificate pair"
1249
- ).format(client_name)
1250
- )
1251
- return False
1252
- print("โœ… Client certificate {} created successfully".format(client_name))
1253
- print(
1254
- "๐ŸŽ‰ All certificates generated successfully using "
1255
- "mcp_security_framework!"
1256
- )
1257
- return True
1258
- except Exception as e:
1259
- print("โŒ Error generating certificates with framework: {}".format(e))
1260
- print("\n๐Ÿ”ง TROUBLESHOOTING:")
1261
- print("1. Check if mcp_security_framework is installed:")
1262
- print(" pip install mcp_security_framework")
1263
- print("\n2. Verify write permissions in output directory")
1264
- print("\n3. Check if certs/ and keys/ directories exist")
1265
- return False
1266
-
1267
-
1268
- def run_full_test_suite(target_root: Path) -> bool:
1269
- """Run the full test suite after environment setup."""
1270
- print("\n" + "=" * 60)
1271
- print("๐Ÿš€ AUTOMATICALLY RUNNING FULL TEST SUITE")
1272
- print("=" * 60)
1273
-
1274
- try:
1275
- # Change to target directory
1276
- original_cwd = Path.cwd()
1277
- os.chdir(target_root)
1278
-
1279
- # Run the full test suite
1280
- result = subprocess.run(
1281
- [sys.executable, "run_full_test_suite.py"],
1282
- capture_output=True,
1283
- text=True,
1284
- timeout=300,
1285
- ) # 5 minute timeout
1286
-
1287
- # Print output
1288
- if result.stdout:
1289
- print("๐Ÿ“‹ Test Suite Output:")
1290
- print(result.stdout)
1291
-
1292
- if result.stderr:
1293
- print("โš ๏ธ Test Suite Warnings/Errors:")
1294
- print(result.stderr)
1295
-
1296
- if result.returncode == 0:
1297
- print("๐ŸŽ‰ FULL TEST SUITE COMPLETED SUCCESSFULLY!")
1298
- return True
1299
- else:
1300
- print(f"โŒ FULL TEST SUITE FAILED (exit code: {result.returncode})")
1301
- return False
1302
-
1303
- except subprocess.TimeoutExpired:
1304
- print("โฐ Test suite timed out after 5 minutes")
1305
- return False
1306
- except Exception as e:
1307
- print(f"โŒ Error running test suite: {e}")
1308
- return False
1309
- finally:
1310
- # Restore original working directory
1311
- os.chdir(original_cwd)
68
+ return package_path, examples_path
1312
69
 
1313
70
 
1314
71
  def validate_output_directory(output_dir: Path) -> bool:
1315
72
  """
1316
- Validate output directory for test environment setup.
73
+ Validate that the output directory is suitable for setup.
1317
74
 
1318
75
  Args:
1319
- output_dir: Path to the target directory
76
+ output_dir: Directory to validate
1320
77
 
1321
78
  Returns:
1322
- True if directory is valid for setup, False otherwise
79
+ True if valid, False otherwise
1323
80
  """
1324
- output_dir = output_dir.resolve()
81
+ try:
82
+ # Check if directory exists
83
+ if not output_dir.exists():
84
+ print(f"๐Ÿ“ Creating output directory: {output_dir}")
85
+ output_dir.mkdir(parents=True, exist_ok=True)
86
+ return True
1325
87
 
1326
- # Check if directory exists
1327
- if output_dir.exists():
1328
- if not output_dir.is_dir():
1329
- print(f"โŒ Path exists but is not a directory: {output_dir}")
88
+ # Check if directory is writable
89
+ if not os.access(output_dir, os.W_OK):
90
+ print(f"โŒ Error: Directory {output_dir} is not writable")
1330
91
  return False
1331
92
 
1332
- # Check if directory is empty
1333
- try:
1334
- contents = list(output_dir.iterdir())
1335
- if contents:
1336
- print(f"โŒ Directory is not empty: {output_dir}")
1337
- print(f" Found {len(contents)} items:")
1338
- for item in contents[:5]: # Show first 5 items
1339
- print(f" - {item.name}")
1340
- if len(contents) > 5:
1341
- print(f" ... and {len(contents) - 5} more items")
1342
- print("\n๐Ÿ’ก Please use an empty directory or specify a different path.")
93
+ # Check if directory is empty (optional warning)
94
+ contents = list(output_dir.iterdir())
95
+ if contents:
96
+ print(f"โš ๏ธ Warning: Directory {output_dir} is not empty")
97
+ print(f" Found {len(contents)} items")
98
+ response = input(" Continue anyway? (y/N): ").strip().lower()
99
+ if response not in ['y', 'yes']:
100
+ print(" Setup cancelled")
1343
101
  return False
1344
- except PermissionError:
1345
- print(f"โŒ Permission denied accessing directory: {output_dir}")
1346
- return False
1347
- else:
1348
- # Directory doesn't exist, try to create it
1349
- try:
1350
- output_dir.mkdir(parents=True, exist_ok=True)
1351
- print(f"โœ… Created directory: {output_dir}")
1352
- except PermissionError:
1353
- print(f"โŒ Permission denied creating directory: {output_dir}")
1354
- return False
1355
- except Exception as e:
1356
- print(f"โŒ Failed to create directory {output_dir}: {e}")
1357
- return False
1358
102
 
1359
- return True
103
+ return True
104
+
105
+ except Exception as e:
106
+ print(f"โŒ Error validating output directory: {e}")
107
+ return False
1360
108
 
1361
109
 
1362
110
  def check_ports_available() -> bool:
1363
111
  """
1364
- Check if all required test ports are available.
1365
- Returns True if all ports are free, False otherwise.
112
+ Check if required ports are available.
113
+
114
+ Returns:
115
+ True if ports are available, False otherwise
1366
116
  """
1367
117
  import socket
1368
118
 
1369
- # Ports used by the test suite - UPDATED with dedicated ports
1370
- test_ports = [
1371
- 20010, # proxy_port
1372
- 20020, # basic_http (http_simple)
1373
- 20021, # http_token
1374
- 20022, # https_simple
1375
- 20023, # https_token
1376
- 20024, # mtls_no_roles
1377
- 20025, # mtls_simple
1378
- 20026, # mtls_with_roles
1379
- 20005, # test_proxy_server
1380
- 3006, # proxy registration
1381
- ]
119
+ ports_to_check = [8080, 8443, 20005, 3005]
120
+ unavailable_ports = []
1382
121
 
1383
- occupied_ports = []
1384
-
1385
- print("๐Ÿ” Checking port availability...")
1386
- for port in test_ports:
122
+ for port in ports_to_check:
1387
123
  try:
1388
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
1389
- sock.settimeout(1)
1390
- result = sock.connect_ex(("127.0.0.1", port))
124
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
125
+ s.settimeout(1)
126
+ result = s.connect_ex(('localhost', port))
1391
127
  if result == 0:
1392
- occupied_ports.append(port)
1393
- print(f" โŒ Port {port} is occupied")
1394
- else:
1395
- print(f" โœ… Port {port} is available")
1396
- except Exception as e:
1397
- print(f" โš ๏ธ Could not check port {port}: {e}")
1398
- occupied_ports.append(port)
128
+ unavailable_ports.append(port)
129
+ except Exception:
130
+ # If we can't check, assume it's available
131
+ pass
1399
132
 
1400
- if occupied_ports:
1401
- print(
1402
- f"\nโŒ CRITICAL: {len(occupied_ports)} ports are occupied: {occupied_ports}"
1403
- )
1404
- print("๐Ÿ’ก Please free these ports before running the test suite:")
1405
- for port in occupied_ports:
1406
- print(f" - Port {port}: kill processes using this port")
1407
- print("\n๐Ÿ”ง You can use these commands to free ports:")
1408
- for port in occupied_ports:
1409
- print(f" fuser -k {port}/tcp")
1410
- return False
133
+ if unavailable_ports:
134
+ print(f"โš ๏ธ Warning: The following ports are in use: {unavailable_ports}")
135
+ print(" This may cause issues when running the examples")
136
+ response = input(" Continue anyway? (y/N): ").strip().lower()
137
+ return response in ['y', 'yes']
1411
138
 
1412
- print(f"โœ… All {len(test_ports)} required ports are available")
1413
139
  return True
1414
140
 
1415
141
 
1416
142
  def main() -> int:
1417
- """Main function for command line execution."""
143
+ """
144
+ Main function to set up the test environment.
145
+
146
+ Returns:
147
+ Exit code (0 for success, 1 for failure)
148
+ """
1418
149
  parser = argparse.ArgumentParser(
1419
- description="Setup enhanced test environment for MCP Proxy Adapter and run full test suite"
150
+ description="Set up test environment for MCP Proxy Adapter",
151
+ formatter_class=argparse.RawDescriptionHelpFormatter,
152
+ epilog="""
153
+ Examples:
154
+ python setup_test_environment.py # Setup in current directory
155
+ python setup_test_environment.py -o /path/to/test # Setup in specific directory
156
+ python setup_test_environment.py --no-certs # Skip certificate generation
157
+ python setup_test_environment.py --run-tests # Run tests after setup
158
+ """
159
+ )
160
+
161
+ parser.add_argument(
162
+ "-o", "--output-dir",
163
+ type=Path,
164
+ default=Path.cwd(),
165
+ help="Output directory for test environment (default: current directory)"
1420
166
  )
167
+
1421
168
  parser.add_argument(
1422
- "output_dir",
1423
- nargs="?",
1424
- type=str,
1425
- default=None,
1426
- help=(
1427
- "Target directory to create the test environment "
1428
- "(default: auto-generated directory in /tmp)"
1429
- ),
169
+ "--no-certs",
170
+ action="store_true",
171
+ help="Skip certificate generation"
1430
172
  )
173
+
1431
174
  parser.add_argument(
1432
- "--skip-certs", action="store_true", help="Skip certificate generation"
175
+ "--run-tests",
176
+ action="store_true",
177
+ help="Run tests after setup"
1433
178
  )
179
+
1434
180
  parser.add_argument(
1435
- "--skip-tests", action="store_true", help="Skip running the full test suite"
181
+ "--verbose",
182
+ action="store_true",
183
+ help="Enable verbose output"
1436
184
  )
185
+
1437
186
  args = parser.parse_args()
1438
187
 
1439
- # FIRST: Check port availability - if this fails, don't proceed
1440
- print("๐Ÿ” STEP 1: Port Availability Check")
188
+ print("๐Ÿš€ MCP Proxy Adapter Test Environment Setup")
189
+ print("=" * 50)
190
+
191
+ # Validate output directory
192
+ if not validate_output_directory(args.output_dir):
193
+ print("โŒ Setup failed: Invalid output directory")
194
+ return 1
195
+
196
+ # Check ports
1441
197
  if not check_ports_available():
1442
- print("\nโŒ FAILED: Required ports are occupied. Aborting setup.")
1443
- print("๐Ÿ’ก Please free the occupied ports and try again.")
198
+ print("โŒ Setup cancelled: Port conflicts detected")
1444
199
  return 1
1445
200
 
1446
201
  try:
1447
- # Determine target directory
1448
- if args.output_dir is None:
1449
- # Create auto-generated directory in /tmp
1450
- import tempfile
1451
- import time
1452
-
1453
- timestamp = int(time.time())
1454
- target_root = Path(tempfile.gettempdir()) / f"mcp_test_env_{timestamp}"
1455
- print(f"๐Ÿ”ง Auto-generating test environment directory: {target_root}")
1456
- else:
1457
- target_root = Path(args.output_dir)
1458
-
1459
- # Validate output directory
1460
- print(f"๐Ÿ” Validating output directory: {target_root}")
1461
- if not validate_output_directory(target_root):
1462
- print("\nโŒ Directory validation failed. Exiting.")
202
+ # Run setup
203
+ success = setup_test_environment(args.output_dir)
204
+
205
+ if not success:
206
+ print("โŒ Setup failed")
1463
207
  return 1
1464
208
 
1465
- print(f"โœ… Directory validation passed: {target_root}")
1466
- setup_test_environment(target_root)
1467
-
1468
- # Generate certificates if framework is available and not skipped
1469
- if not args.skip_certs and SECURITY_FRAMEWORK_AVAILABLE:
1470
- generate_certificates_with_framework(target_root)
1471
- elif args.skip_certs:
1472
- print("โš ๏ธ Skipping certificate generation (--skip-certs specified)")
1473
- else:
1474
- print(
1475
- "โš ๏ธ Skipping certificate generation (mcp_security_framework "
1476
- "not available)"
1477
- )
209
+ print("โœ… Test environment setup completed successfully!")
210
+ print(f"๐Ÿ“ Output directory: {args.output_dir.absolute()}")
1478
211
 
1479
- # Run full test suite if not skipped
1480
- if not args.skip_tests:
1481
- test_success = run_full_test_suite(target_root)
212
+ # Run tests if requested
213
+ if args.run_tests:
214
+ print("\\n๐Ÿงช Running tests...")
215
+ test_success = run_full_test_suite(args.output_dir)
1482
216
  if not test_success:
1483
- print("\nโŒ TEST SUITE FAILED - Check the output above for details")
217
+ print("โš ๏ธ Some tests failed, but setup completed")
1484
218
  return 1
1485
- else:
1486
- print("โš ๏ธ Skipping test suite execution (--skip-tests specified)")
1487
219
 
220
+ print("\\n๐ŸŽ‰ Setup complete! You can now run the examples.")
221
+ return 0
222
+
223
+ except KeyboardInterrupt:
224
+ print("\\nโš ๏ธ Setup interrupted by user")
225
+ return 1
1488
226
  except Exception as e:
1489
- print(
1490
- "โŒ Error setting up test environment: {}".format(e),
1491
- file=sys.stderr,
1492
- )
1493
- print("\n๐Ÿ”ง TROUBLESHOOTING:")
1494
- print("1. Check if output directory is writable")
1495
- print("2. Verify mcp_security_framework installation")
1496
- print("3. Check available disk space")
227
+ print(f"\\nโŒ Setup failed with error: {e}")
228
+ if args.verbose:
229
+ import traceback
230
+ traceback.print_exc()
1497
231
  return 1
1498
232
 
1499
- print("\n" + "=" * 60)
1500
- print("โœ… ENHANCED TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
1501
- print("=" * 60)
1502
-
1503
- if not args.skip_tests:
1504
- print("\n๐ŸŽ‰ ALL TESTS PASSED - Environment is ready for use!")
1505
- else:
1506
- print("\n๐Ÿ“‹ NEXT STEPS:")
1507
- print("1. Review configuration documentation:")
1508
- print(" cat docs/CONFIGURATION_GUIDE.md")
1509
- print("\n2. Check available configurations:")
1510
- print(" ls -la configs/")
1511
- print("\n3. Run the full test suite:")
1512
- print(" python run_full_test_suite.py")
1513
- print("\n4. Test proxy registration SSL fix:")
1514
- print(" python test_proxy_registration.py")
1515
- print("\n5. Start server with a specific configuration:")
1516
- print(" python -m mcp_proxy_adapter --config configs/production_https.json")
1517
- print("\n6. Run security tests:")
1518
- print(" python -m mcp_proxy_adapter.examples.run_security_tests")
1519
- print("\n7. Generate additional certificates (if needed):")
1520
- print(" python scripts/create_certificates_simple.py")
1521
-
1522
- print("=" * 60)
1523
- return 0
1524
-
1525
233
 
1526
234
  if __name__ == "__main__":
1527
- exit(main())
235
+ sys.exit(main())