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
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI Argument Parser for MCP Proxy Adapter
4
+ Multi-level help system with detailed parameter descriptions
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import argparse
11
+
12
+
13
+ def create_main_parser() -> argparse.ArgumentParser:
14
+ """Create top-level CLI parser with subcommands."""
15
+ parser = argparse.ArgumentParser(prog="mcp-cli", description="MCP Proxy Adapter CLI")
16
+ subparsers = parser.add_subparsers(dest='command', metavar='command')
17
+
18
+ # generate
19
+ generate_parser = subparsers.add_parser('generate', help='Generate configuration (legacy)')
20
+ _setup_generate_parser(generate_parser)
21
+
22
+ # testconfig
23
+ testconfig_parser = subparsers.add_parser('testconfig', help='Validate configuration (legacy)')
24
+ _setup_testconfig_parser(testconfig_parser)
25
+
26
+ # sets
27
+ sets_parser = subparsers.add_parser('sets', help='Generate preset configuration set (legacy)')
28
+ _setup_sets_parser(sets_parser)
29
+
30
+ # server
31
+ server_parser = subparsers.add_parser('server', help='Run server (legacy)')
32
+ _setup_server_parser(server_parser)
33
+
34
+ # simple config commands (new)
35
+ config_parser = subparsers.add_parser('config', help='Simple config utilities')
36
+ config_sub = config_parser.add_subparsers(dest='config_command')
37
+
38
+ # config generate
39
+ cfg_gen = config_sub.add_parser('generate', help='Generate simple configuration')
40
+ cfg_gen.add_argument('--protocol', required=True, choices=['http', 'https', 'mtls'], help='Server/proxy protocol')
41
+ cfg_gen.add_argument('--with-proxy', action='store_true', help='Include proxy_client section')
42
+ cfg_gen.add_argument('--out', default='config.json', help='Output config path (default: config.json)')
43
+
44
+ # config validate
45
+ cfg_val = config_sub.add_parser('validate', help='Validate simple configuration file')
46
+ cfg_val.add_argument('--file', required=True, help='Path to configuration file')
47
+
48
+ # client
49
+ client_parser = subparsers.add_parser('client', help='HTTP/HTTPS/mTLS client for health and JSON-RPC')
50
+ _setup_client_parser(client_parser)
51
+
52
+ return parser
53
+
54
+
55
+ def _setup_generate_parser(parser: argparse.ArgumentParser):
56
+ """Setup generate command parser"""
57
+
58
+ # Protocol selection
59
+ protocol_group = parser.add_argument_group(
60
+ 'Protocol Configuration',
61
+ 'Select the communication protocol and security level'
62
+ )
63
+ protocol_group.add_argument(
64
+ '--protocol',
65
+ choices=['http', 'https', 'mtls'],
66
+ required=True,
67
+ help='''Communication protocol:
68
+ http - Plain HTTP (no encryption)
69
+ https - HTTP with SSL/TLS encryption
70
+ mtls - Mutual TLS with client certificate verification'''
71
+ )
72
+
73
+ # Security options
74
+ security_group = parser.add_argument_group(
75
+ 'Security Configuration',
76
+ 'Configure authentication and authorization'
77
+ )
78
+ security_group.add_argument(
79
+ '--token',
80
+ action='store_true',
81
+ help='Enable token-based authentication (API keys)'
82
+ )
83
+ security_group.add_argument(
84
+ '--roles',
85
+ action='store_true',
86
+ help='Enable role-based access control (requires --token)'
87
+ )
88
+
89
+ # Server configuration
90
+ server_group = parser.add_argument_group(
91
+ 'Server Configuration',
92
+ 'Configure server host and port settings'
93
+ )
94
+ server_group.add_argument(
95
+ '--host',
96
+ default='127.0.0.1',
97
+ help='Server host address (default: 127.0.0.1)'
98
+ )
99
+ server_group.add_argument(
100
+ '--port',
101
+ type=int,
102
+ default=8000,
103
+ help='Server port number (default: 8000)'
104
+ )
105
+
106
+ # SSL/TLS configuration
107
+ ssl_group = parser.add_argument_group(
108
+ 'SSL/TLS Configuration',
109
+ 'Configure SSL certificates and keys (required for https/mtls)'
110
+ )
111
+ ssl_group.add_argument(
112
+ '--cert-dir',
113
+ default='./certs',
114
+ help='Directory containing SSL certificates (default: ./certs)'
115
+ )
116
+ ssl_group.add_argument(
117
+ '--key-dir',
118
+ default='./keys',
119
+ help='Directory containing SSL private keys (default: ./keys)'
120
+ )
121
+
122
+ # Proxy registration
123
+ proxy_group = parser.add_argument_group(
124
+ 'Proxy Registration',
125
+ 'Configure automatic registration with MCP proxy'
126
+ )
127
+ proxy_group.add_argument(
128
+ '--proxy-registration',
129
+ action='store_true',
130
+ help='Enable automatic proxy registration'
131
+ )
132
+ proxy_group.add_argument(
133
+ '--proxy-url',
134
+ help='Proxy URL for registration (required with --proxy-registration)'
135
+ )
136
+ proxy_group.add_argument(
137
+ '--server-id',
138
+ default='mcp_proxy_adapter',
139
+ help='Server ID for proxy registration (default: mcp_proxy_adapter)'
140
+ )
141
+
142
+ # Output options
143
+ output_group = parser.add_argument_group(
144
+ 'Output Configuration',
145
+ 'Configure output file and directory settings'
146
+ )
147
+ output_group.add_argument(
148
+ '--output-dir',
149
+ default='./configs',
150
+ help='Output directory for configuration files (default: ./configs)'
151
+ )
152
+ output_group.add_argument(
153
+ '--output',
154
+ help='Output filename (without extension, auto-generated if not specified)'
155
+ )
156
+ output_group.add_argument(
157
+ '--stdout',
158
+ action='store_true',
159
+ help='Output configuration to stdout instead of file'
160
+ )
161
+ output_group.add_argument(
162
+ '--no-validate',
163
+ action='store_true',
164
+ help='Skip configuration validation after generation'
165
+ )
166
+
167
+
168
+ def _setup_testconfig_parser(parser: argparse.ArgumentParser):
169
+ """Setup testconfig command parser"""
170
+
171
+ parser.add_argument(
172
+ '--config',
173
+ required=True,
174
+ help='Path to configuration file to validate'
175
+ )
176
+ parser.add_argument(
177
+ '--verbose',
178
+ action='store_true',
179
+ help='Enable verbose output with detailed validation results'
180
+ )
181
+ parser.add_argument(
182
+ '--fix',
183
+ action='store_true',
184
+ help='Attempt to fix common configuration issues automatically'
185
+ )
186
+
187
+
188
+ def _setup_sets_parser(parser: argparse.ArgumentParser):
189
+ """Setup sets command parser"""
190
+
191
+ # Mode selection (positional argument)
192
+ parser.add_argument(
193
+ 'set_name',
194
+ choices=['http', 'https', 'mtls'],
195
+ help='''Configuration mode:
196
+ http - HTTP basic configuration
197
+ https - HTTPS with SSL/TLS
198
+ mtls - Mutual TLS with client certificates'''
199
+ )
200
+
201
+ # Modifiers
202
+ parser.add_argument(
203
+ '--modifiers',
204
+ nargs='+',
205
+ choices=['token', 'roles'],
206
+ help='''Configuration modifiers:
207
+ token - Add token authentication
208
+ roles - Add role-based access control (requires token)'''
209
+ )
210
+ parser.add_argument(
211
+ '--no-dns-check',
212
+ action='store_true',
213
+ help='Disable DNS hostname checking (useful for Docker networks)'
214
+ )
215
+
216
+ # SSL configuration for https/mtls
217
+ ssl_group = parser.add_argument_group('SSL Configuration')
218
+ ssl_group.add_argument(
219
+ '--cert-dir',
220
+ default='./mtls_certificates/server',
221
+ help='Directory containing SSL certificates (default: ./mtls_certificates/server)'
222
+ )
223
+ ssl_group.add_argument(
224
+ '--key-dir',
225
+ default='./mtls_certificates/server',
226
+ help='Directory containing SSL private keys (default: ./mtls_certificates/server)'
227
+ )
228
+
229
+ # Output options
230
+ output_group = parser.add_argument_group('Output Options')
231
+ output_group.add_argument(
232
+ '--output-dir',
233
+ default='./configs',
234
+ help='Output directory for configuration files (default: ./configs)'
235
+ )
236
+ output_group.add_argument(
237
+ '--host',
238
+ default='127.0.0.1',
239
+ help='Server host address (default: 127.0.0.1)'
240
+ )
241
+ output_group.add_argument(
242
+ '--port',
243
+ type=int,
244
+ default=8000,
245
+ help='Server port number (default: 8000)'
246
+ )
247
+ output_group.add_argument(
248
+ '--proxy-url',
249
+ help='Proxy URL for registration (auto-generated if not specified)'
250
+ )
251
+
252
+
253
+ def _setup_server_parser(parser: argparse.ArgumentParser):
254
+ """Setup server command parser"""
255
+
256
+ parser.add_argument(
257
+ '--config',
258
+ required=True,
259
+ help='Path to configuration file'
260
+ )
261
+ parser.add_argument(
262
+ '--host',
263
+ help='Override server host from configuration'
264
+ )
265
+ parser.add_argument(
266
+ '--port',
267
+ type=int,
268
+ help='Override server port from configuration'
269
+ )
270
+ parser.add_argument(
271
+ '--debug',
272
+ action='store_true',
273
+ help='Enable debug mode with verbose logging'
274
+ )
275
+ parser.add_argument(
276
+ '--reload',
277
+ action='store_true',
278
+ help='Enable auto-reload on configuration changes'
279
+ )
280
+
281
+
282
+ def _setup_client_parser(parser: argparse.ArgumentParser):
283
+ """Setup client command parser"""
284
+
285
+ sub = parser.add_subparsers(dest='client_command')
286
+
287
+ # health
288
+ health = sub.add_parser('health', help='Call GET /health')
289
+ health.add_argument('--protocol', choices=['http', 'https'], required=True, help='Connection protocol')
290
+ health.add_argument('--host', default='127.0.0.1', help='Server host (default: 127.0.0.1)')
291
+ health.add_argument('--port', type=int, required=True, help='Server port')
292
+ health.add_argument('--token-header', default='X-API-Key', help='API key header name (default: X-API-Key)')
293
+ health.add_argument('--token', help='API key token value')
294
+ health.add_argument('--cert', help='Client cert path (for mTLS/HTTPS testing)')
295
+ health.add_argument('--key', help='Client key path (for mTLS/HTTPS testing)')
296
+ health.add_argument('--ca', help='CA cert path (verify server with this CA)')
297
+
298
+ # jsonrpc
299
+ j = sub.add_parser('jsonrpc', help='Call POST /api/jsonrpc')
300
+ j.add_argument('--protocol', choices=['http', 'https'], required=True, help='Connection protocol')
301
+ j.add_argument('--host', default='127.0.0.1', help='Server host (default: 127.0.0.1)')
302
+ j.add_argument('--port', type=int, required=True, help='Server port')
303
+ j.add_argument('--token-header', default='X-API-Key', help='API key header name (default: X-API-Key)')
304
+ j.add_argument('--token', help='API key token value')
305
+ j.add_argument('--cert', help='Client cert path (for mTLS/HTTPS testing)')
306
+ j.add_argument('--key', help='Client key path (for mTLS/HTTPS testing)')
307
+ j.add_argument('--ca', help='CA cert path (verify server with this CA)')
308
+ j.add_argument('--method', required=True, help='JSON-RPC method')
309
+ j.add_argument('--params', help='JSON string with params, default {}')
310
+ j.add_argument('--id', type=int, default=1, help='Request id (default: 1)')
311
+
312
+ # proxy register/unregister/list
313
+ preg = sub.add_parser('proxy-register', help='Register adapter on registry')
314
+ preg.add_argument('--proxy-url', required=True, help='Registry base URL, e.g. http://localhost:3005')
315
+ preg.add_argument('--name', required=True, help='Adapter name')
316
+ preg.add_argument('--url', required=True, help='Adapter base URL')
317
+ preg.add_argument('--capabilities', nargs='*', help='Capabilities list')
318
+
319
+ punreg = sub.add_parser('proxy-unregister', help='Unregister adapter from registry')
320
+ punreg.add_argument('--proxy-url', required=True)
321
+ punreg.add_argument('--name', required=True)
322
+
323
+ plist = sub.add_parser('proxy-list', help='List registered adapters')
324
+ plist.add_argument('--proxy-url', required=True)
@@ -0,0 +1,231 @@
1
+ """
2
+ CLI Parameter Validators
3
+
4
+ This module provides validation functions for CLI parameters and their combinations.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import sys
11
+ from pathlib import Path
12
+
13
+
14
+ class ValidationError(Exception):
15
+ """Exception raised when parameter validation fails."""
16
+ pass
17
+
18
+
19
+ class ParameterValidator:
20
+ """Validates CLI parameters and their combinations."""
21
+
22
+ @staticmethod
23
+ def validate_protocol(protocol: str) -> bool:
24
+ """
25
+ Validate protocol parameter.
26
+
27
+ Args:
28
+ protocol: Protocol string to validate
29
+
30
+ Returns:
31
+ True if valid
32
+
33
+ Raises:
34
+ ValidationError: If protocol is invalid
35
+ """
36
+ valid_protocols = ['http', 'https', 'mtls']
37
+ if protocol not in valid_protocols:
38
+ raise ValidationError(
39
+ f"Invalid protocol '{protocol}'. Must be one of: {', '.join(valid_protocols)}"
40
+ )
41
+ return True
42
+
43
+ @staticmethod
44
+ def validate_token_with_protocol(token: bool, protocol: str) -> bool:
45
+ """
46
+ Validate token parameter with protocol.
47
+
48
+ Args:
49
+ token: Whether token authentication is enabled
50
+ protocol: Protocol being used
51
+
52
+ Returns:
53
+ True if valid
54
+
55
+ Raises:
56
+ ValidationError: If token is not compatible with protocol
57
+ """
58
+ if token and protocol == 'mtls':
59
+ raise ValidationError(
60
+ "Token authentication is not supported with mTLS protocol. "
61
+ "mTLS uses client certificates for authentication."
62
+ )
63
+ return True
64
+
65
+ @staticmethod
66
+ def validate_roles_with_auth(roles: bool, token: bool, protocol: str) -> bool:
67
+ """
68
+ Validate roles parameter with authentication method.
69
+
70
+ Args:
71
+ roles: Whether roles are enabled
72
+ token: Whether token authentication is enabled
73
+ protocol: Protocol being used
74
+
75
+ Returns:
76
+ True if valid
77
+
78
+ Raises:
79
+ ValidationError: If roles are not compatible with authentication method
80
+ """
81
+ if roles and protocol in ['http', 'https'] and not token:
82
+ raise ValidationError(
83
+ f"Roles require token authentication for {protocol} protocol. "
84
+ "Use --token flag when enabling --roles."
85
+ )
86
+ return True
87
+
88
+ @staticmethod
89
+ def validate_port(port: int) -> bool:
90
+ """
91
+ Validate port number.
92
+
93
+ Args:
94
+ port: Port number to validate
95
+
96
+ Returns:
97
+ True if valid
98
+
99
+ Raises:
100
+ ValidationError: If port is invalid
101
+ """
102
+ if not isinstance(port, int) or port < 1 or port > 65535:
103
+ raise ValidationError(f"Invalid port '{port}'. Must be an integer between 1 and 65535.")
104
+ return True
105
+
106
+ @staticmethod
107
+ def validate_host(host: str) -> bool:
108
+ """
109
+ Validate host address.
110
+
111
+ Args:
112
+ host: Host address to validate
113
+
114
+ Returns:
115
+ True if valid
116
+
117
+ Raises:
118
+ ValidationError: If host is invalid
119
+ """
120
+ if not host or not isinstance(host, str):
121
+ raise ValidationError("Host must be a non-empty string.")
122
+ return True
123
+
124
+ @staticmethod
125
+ def validate_file_path(file_path: str, must_exist: bool = False) -> bool:
126
+ """
127
+ Validate file path.
128
+
129
+ Args:
130
+ file_path: File path to validate
131
+ must_exist: Whether file must exist
132
+
133
+ Returns:
134
+ True if valid
135
+
136
+ Raises:
137
+ ValidationError: If file path is invalid
138
+ """
139
+ if not file_path or not isinstance(file_path, str):
140
+ raise ValidationError("File path must be a non-empty string.")
141
+
142
+ if must_exist and not Path(file_path).exists():
143
+ raise ValidationError(f"File does not exist: {file_path}")
144
+
145
+ return True
146
+
147
+ @staticmethod
148
+ def validate_directory_path(dir_path: str, must_exist: bool = False) -> bool:
149
+ """
150
+ Validate directory path.
151
+
152
+ Args:
153
+ dir_path: Directory path to validate
154
+ must_exist: Whether directory must exist
155
+
156
+ Returns:
157
+ True if valid
158
+
159
+ Raises:
160
+ ValidationError: If directory path is invalid
161
+ """
162
+ if not dir_path or not isinstance(dir_path, str):
163
+ raise ValidationError("Directory path must be a non-empty string.")
164
+
165
+ if must_exist and not Path(dir_path).exists():
166
+ raise ValidationError(f"Directory does not exist: {dir_path}")
167
+
168
+ return True
169
+
170
+ @staticmethod
171
+ def validate_url(url: str) -> bool:
172
+ """
173
+ Validate URL format.
174
+
175
+ Args:
176
+ url: URL to validate
177
+
178
+ Returns:
179
+ True if valid
180
+
181
+ Raises:
182
+ ValidationError: If URL is invalid
183
+ """
184
+ if not url or not isinstance(url, str):
185
+ raise ValidationError("URL must be a non-empty string.")
186
+
187
+ # Basic URL validation
188
+ if not (url.startswith('http://') or url.startswith('https://')):
189
+ raise ValidationError("URL must start with 'http://' or 'https://'")
190
+
191
+ return True
192
+
193
+ @staticmethod
194
+ def validate_server_id(server_id: str) -> bool:
195
+ """
196
+ Validate server ID.
197
+
198
+ Args:
199
+ server_id: Server ID to validate
200
+
201
+ Returns:
202
+ True if valid
203
+
204
+ Raises:
205
+ ValidationError: If server ID is invalid
206
+ """
207
+ if not server_id or not isinstance(server_id, str):
208
+ raise ValidationError("Server ID must be a non-empty string.")
209
+
210
+ # Check for valid characters (alphanumeric, hyphens, underscores)
211
+ import re
212
+ if not re.match(r'^[a-zA-Z0-9_-]+$', server_id):
213
+ raise ValidationError(
214
+ "Server ID must contain only alphanumeric characters, hyphens, and underscores."
215
+ )
216
+
217
+ return True
218
+
219
+
220
+ class ConfigurationValidator:
221
+ """Validates configuration combinations and dependencies."""
222
+
223
+ @staticmethod
224
+
225
+ @staticmethod
226
+
227
+ @staticmethod
228
+
229
+ @staticmethod
230
+
231
+