mcp-proxy-adapter 6.4.44__py3-none-any.whl → 6.4.45__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. mcp_proxy_adapter/core/proxy_registration.py +100 -68
  2. mcp_proxy_adapter/examples/bugfix_certificate_config.py +284 -0
  3. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  4. mcp_proxy_adapter/examples/config_builder.py +574 -0
  5. mcp_proxy_adapter/examples/config_cli.py +283 -0
  6. mcp_proxy_adapter/examples/create_test_configs.py +169 -266
  7. mcp_proxy_adapter/examples/generate_certificates_bugfix.py +374 -0
  8. mcp_proxy_adapter/examples/generate_certificates_cli.py +406 -0
  9. mcp_proxy_adapter/examples/generate_certificates_fixed.py +313 -0
  10. mcp_proxy_adapter/examples/generate_certificates_framework.py +366 -0
  11. mcp_proxy_adapter/examples/generate_certificates_openssl.py +391 -0
  12. mcp_proxy_adapter/examples/required_certificates.py +210 -0
  13. mcp_proxy_adapter/examples/run_full_test_suite.py +117 -13
  14. mcp_proxy_adapter/examples/run_security_tests_fixed.py +42 -26
  15. mcp_proxy_adapter/examples/security_test_client.py +332 -85
  16. mcp_proxy_adapter/examples/test_config_builder.py +450 -0
  17. mcp_proxy_adapter/examples/update_config_certificates.py +136 -0
  18. mcp_proxy_adapter/version.py +1 -1
  19. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/METADATA +81 -1
  20. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/RECORD +23 -11
  21. mcp_proxy_adapter-6.4.45.dist-info/entry_points.txt +12 -0
  22. mcp_proxy_adapter-6.4.44.dist-info/entry_points.txt +0 -2
  23. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/WHEEL +0 -0
  24. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI Utility for MCP Proxy Adapter Configuration Builder
4
+ Command-line interface for creating configurations with various parameters.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+ import argparse
10
+ import json
11
+ import sys
12
+ from pathlib import Path
13
+ from typing import Dict, Any, List, Optional
14
+
15
+ from config_builder import ConfigBuilder, ConfigFactory, Protocol, AuthMethod
16
+
17
+
18
+ def parse_protocol(protocol_str: str) -> Protocol:
19
+ """Parse protocol string to Protocol enum."""
20
+ protocol_map = {
21
+ "http": Protocol.HTTP,
22
+ "https": Protocol.HTTPS,
23
+ "mtls": Protocol.MTLS
24
+ }
25
+ if protocol_str.lower() not in protocol_map:
26
+ raise ValueError(f"Invalid protocol: {protocol_str}. Must be one of: {list(protocol_map.keys())}")
27
+ return protocol_map[protocol_str.lower()]
28
+
29
+
30
+ def parse_auth_method(auth_str: str) -> AuthMethod:
31
+ """Parse authentication method string to AuthMethod enum."""
32
+ auth_map = {
33
+ "none": AuthMethod.NONE,
34
+ "token": AuthMethod.TOKEN,
35
+ "basic": AuthMethod.BASIC
36
+ }
37
+ if auth_str.lower() not in auth_map:
38
+ raise ValueError(f"Invalid auth method: {auth_str}. Must be one of: {list(auth_map.keys())}")
39
+ return auth_map[auth_str.lower()]
40
+
41
+
42
+ def parse_api_keys(api_keys_str: str) -> Dict[str, str]:
43
+ """Parse API keys from string format 'key1:value1,key2:value2'."""
44
+ if not api_keys_str:
45
+ return {}
46
+
47
+ api_keys = {}
48
+ for pair in api_keys_str.split(','):
49
+ if ':' not in pair:
50
+ raise ValueError(f"Invalid API key format: {pair}. Expected 'key:value'")
51
+ key, value = pair.split(':', 1)
52
+ api_keys[key.strip()] = value.strip()
53
+
54
+ return api_keys
55
+
56
+
57
+ def parse_roles(roles_str: str) -> Dict[str, List[str]]:
58
+ """Parse roles from string format 'role1:perm1,perm2;role2:perm3,perm4'."""
59
+ if not roles_str:
60
+ return {}
61
+
62
+ roles = {}
63
+ for role_def in roles_str.split(';'):
64
+ if ':' not in role_def:
65
+ raise ValueError(f"Invalid role format: {role_def}. Expected 'role:perm1,perm2'")
66
+ role, perms = role_def.split(':', 1)
67
+ roles[role.strip()] = [perm.strip() for perm in perms.split(',')]
68
+
69
+ return roles
70
+
71
+
72
+ def create_custom_config(args) -> Dict[str, Any]:
73
+ """Create custom configuration based on command line arguments."""
74
+ builder = ConfigBuilder()
75
+
76
+ # Set server configuration
77
+ builder.set_server(
78
+ host=args.host,
79
+ port=args.port,
80
+ debug=args.debug,
81
+ log_level=args.log_level
82
+ )
83
+
84
+ # Set logging configuration
85
+ builder.set_logging(
86
+ log_dir=args.log_dir,
87
+ level=args.log_level,
88
+ console_output=not args.no_console,
89
+ file_output=not args.no_file_log
90
+ )
91
+
92
+ # Set protocol
93
+ protocol = parse_protocol(args.protocol)
94
+ builder.set_protocol(
95
+ protocol,
96
+ cert_dir=args.cert_dir,
97
+ key_dir=args.key_dir
98
+ )
99
+
100
+ # Set authentication
101
+ auth_method = parse_auth_method(args.auth)
102
+ api_keys = parse_api_keys(args.api_keys) if args.api_keys else None
103
+ roles = parse_roles(args.roles) if args.roles else None
104
+
105
+ builder.set_auth(auth_method, api_keys=api_keys, roles=roles)
106
+
107
+ # Set proxy registration
108
+ if args.proxy_url:
109
+ builder.set_proxy_registration(
110
+ enabled=True,
111
+ proxy_url=args.proxy_url,
112
+ server_id=args.server_id,
113
+ cert_dir=args.cert_dir
114
+ )
115
+
116
+ # Set debug
117
+ if args.debug:
118
+ builder.set_debug(enabled=True, log_level=args.log_level)
119
+
120
+ # Set commands
121
+ if args.enabled_commands or args.disabled_commands:
122
+ enabled = args.enabled_commands.split(',') if args.enabled_commands else None
123
+ disabled = args.disabled_commands.split(',') if args.disabled_commands else None
124
+ builder.set_commands(enabled_commands=enabled, disabled_commands=disabled)
125
+
126
+ return builder.build()
127
+
128
+
129
+ def create_preset_config(preset: str, **kwargs) -> Dict[str, Any]:
130
+ """Create preset configuration."""
131
+ preset_map = {
132
+ "http_simple": ConfigFactory.create_http_simple,
133
+ "http_token": ConfigFactory.create_http_token,
134
+ "https_simple": ConfigFactory.create_https_simple,
135
+ "https_token": ConfigFactory.create_https_token,
136
+ "mtls_simple": ConfigFactory.create_mtls_simple,
137
+ "mtls_with_roles": ConfigFactory.create_mtls_with_roles,
138
+ "mtls_with_proxy": ConfigFactory.create_mtls_with_proxy,
139
+ "full_featured": ConfigFactory.create_full_featured,
140
+ }
141
+
142
+ if preset not in preset_map:
143
+ raise ValueError(f"Invalid preset: {preset}. Must be one of: {list(preset_map.keys())}")
144
+
145
+ return preset_map[preset](**kwargs)
146
+
147
+
148
+ def list_presets():
149
+ """List available presets."""
150
+ presets = [
151
+ ("http_simple", "Simple HTTP server without authentication"),
152
+ ("http_token", "HTTP server with token authentication"),
153
+ ("https_simple", "Simple HTTPS server without authentication"),
154
+ ("https_token", "HTTPS server with token authentication"),
155
+ ("mtls_simple", "Simple mTLS server without authentication"),
156
+ ("mtls_with_roles", "mTLS server with role-based access control"),
157
+ ("mtls_with_proxy", "mTLS server with proxy registration"),
158
+ ("full_featured", "Full-featured server with all options enabled"),
159
+ ]
160
+
161
+ print("📋 Available Configuration Presets:")
162
+ print("=" * 50)
163
+ for preset, description in presets:
164
+ print(f" {preset:<20} - {description}")
165
+
166
+
167
+ def main():
168
+ """Main CLI function."""
169
+ parser = argparse.ArgumentParser(
170
+ description="MCP Proxy Adapter Configuration Builder CLI",
171
+ formatter_class=argparse.RawDescriptionHelpFormatter,
172
+ epilog="""
173
+ Examples:
174
+ # Create HTTP simple configuration
175
+ python config_cli.py --preset http_simple --output configs/http_simple.json
176
+
177
+ # Create custom HTTPS configuration with token auth
178
+ python config_cli.py --protocol https --auth token --api-keys "admin:admin-key,user:user-key" --output configs/https_token.json
179
+
180
+ # Create mTLS configuration with proxy registration
181
+ python config_cli.py --protocol mtls --proxy-url "https://proxy.example.com:8080" --server-id "my_server" --output configs/mtls_proxy.json
182
+
183
+ # List all available presets
184
+ python config_cli.py --list-presets
185
+ """
186
+ )
187
+
188
+ # Main options
189
+ parser.add_argument("--preset", help="Use a preset configuration")
190
+ parser.add_argument("--list-presets", action="store_true", help="List available presets")
191
+ parser.add_argument("--output", "-o", help="Output file path (default: stdout)")
192
+
193
+ # Server configuration
194
+ parser.add_argument("--host", default="0.0.0.0", help="Server host (default: 0.0.0.0)")
195
+ parser.add_argument("--port", type=int, default=8000, help="Server port (default: 8000)")
196
+ parser.add_argument("--debug", action="store_true", help="Enable debug mode")
197
+ parser.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"], help="Log level (default: INFO)")
198
+
199
+ # Logging configuration
200
+ parser.add_argument("--log-dir", default="./logs", help="Log directory (default: ./logs)")
201
+ parser.add_argument("--no-console", action="store_true", help="Disable console output")
202
+ parser.add_argument("--no-file-log", action="store_true", help="Disable file logging")
203
+
204
+ # Protocol configuration
205
+ parser.add_argument("--protocol", choices=["http", "https", "mtls"], default="http", help="Protocol (default: http)")
206
+ parser.add_argument("--cert-dir", default="./certs", help="Certificate directory (default: ./certs)")
207
+ parser.add_argument("--key-dir", default="./keys", help="Key directory (default: ./keys)")
208
+
209
+ # Authentication configuration
210
+ parser.add_argument("--auth", choices=["none", "token", "basic"], default="none", help="Authentication method (default: none)")
211
+ parser.add_argument("--api-keys", help="API keys in format 'key1:value1,key2:value2'")
212
+ parser.add_argument("--roles", help="Roles in format 'role1:perm1,perm2;role2:perm3,perm4'")
213
+
214
+ # Proxy registration
215
+ parser.add_argument("--proxy-url", help="Proxy URL for registration")
216
+ parser.add_argument("--server-id", default="mcp_proxy_adapter", help="Server ID for proxy registration (default: mcp_proxy_adapter)")
217
+
218
+ # Commands configuration
219
+ parser.add_argument("--enabled-commands", help="Comma-separated list of enabled commands")
220
+ parser.add_argument("--disabled-commands", help="Comma-separated list of disabled commands")
221
+
222
+ # Preset-specific options
223
+ parser.add_argument("--preset-host", help="Host for preset configurations")
224
+ parser.add_argument("--preset-port", type=int, help="Port for preset configurations")
225
+ parser.add_argument("--preset-log-dir", help="Log directory for preset configurations")
226
+ parser.add_argument("--preset-cert-dir", help="Certificate directory for preset configurations")
227
+ parser.add_argument("--preset-key-dir", help="Key directory for preset configurations")
228
+ parser.add_argument("--preset-proxy-url", help="Proxy URL for preset configurations")
229
+ parser.add_argument("--preset-server-id", help="Server ID for preset configurations")
230
+
231
+ args = parser.parse_args()
232
+
233
+ try:
234
+ # Handle list presets
235
+ if args.list_presets:
236
+ list_presets()
237
+ return 0
238
+
239
+ # Create configuration
240
+ if args.preset:
241
+ # Use preset configuration
242
+ preset_kwargs = {}
243
+ if args.preset_host:
244
+ preset_kwargs["host"] = args.preset_host
245
+ if args.preset_port:
246
+ preset_kwargs["port"] = args.preset_port
247
+ if args.preset_log_dir:
248
+ preset_kwargs["log_dir"] = args.preset_log_dir
249
+ if args.preset_cert_dir:
250
+ preset_kwargs["cert_dir"] = args.preset_cert_dir
251
+ if args.preset_key_dir:
252
+ preset_kwargs["key_dir"] = args.preset_key_dir
253
+ if args.preset_proxy_url:
254
+ preset_kwargs["proxy_url"] = args.preset_proxy_url
255
+ if args.preset_server_id:
256
+ preset_kwargs["server_id"] = args.preset_server_id
257
+
258
+ config = create_preset_config(args.preset, **preset_kwargs)
259
+ else:
260
+ # Create custom configuration
261
+ config = create_custom_config(args)
262
+
263
+ # Output configuration
264
+ config_json = json.dumps(config, indent=2, ensure_ascii=False)
265
+
266
+ if args.output:
267
+ output_path = Path(args.output)
268
+ output_path.parent.mkdir(parents=True, exist_ok=True)
269
+ with open(output_path, 'w', encoding='utf-8') as f:
270
+ f.write(config_json)
271
+ print(f"✅ Configuration saved to: {output_path}")
272
+ else:
273
+ print(config_json)
274
+
275
+ return 0
276
+
277
+ except Exception as e:
278
+ print(f"❌ Error: {e}", file=sys.stderr)
279
+ return 1
280
+
281
+
282
+ if __name__ == "__main__":
283
+ sys.exit(main())