mcp-proxy-adapter 6.3.11__py3-none-any.whl → 6.3.13__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.
@@ -2,20 +2,28 @@
2
2
  """
3
3
  Author: Vasiliy Zdanovskiy
4
4
  email: vasilyvz@gmail.com
5
- Script for setting up test environment for MCP Proxy Adapter.
6
- Prepares the test environment with all necessary files and directories.
7
- Uses mcp_security_framework for certificate generation.
5
+ Enhanced script for setting up test environment for MCP Proxy Adapter.
6
+ Prepares the test environment with all necessary files, directories, and configurations.
7
+ Includes comprehensive documentation and validation for configuration settings.
8
8
 
9
9
  This script accepts an output directory and copies required example files
10
10
  and helper scripts into that directory, creating a ready-to-use workspace.
11
11
  By default, the current working directory is used, so end-users can run
12
12
  it in their project root after installing this framework in a virtual
13
13
  environment.
14
+
15
+ Features:
16
+ - Comprehensive configuration documentation
17
+ - Validation of mutually exclusive settings
18
+ - Protocol-aware configuration generation
19
+ - Enhanced error handling and troubleshooting
14
20
  """
15
21
  import shutil
16
22
  import sys
17
23
  import argparse
24
+ import json
18
25
  from pathlib import Path
26
+ from typing import Dict, List, Any, Optional, Tuple
19
27
 
20
28
  # Import mcp_security_framework
21
29
  try:
@@ -33,6 +41,145 @@ except ImportError:
33
41
  print("Warning: mcp_security_framework not available")
34
42
 
35
43
 
44
+ class ConfigurationValidator:
45
+ """
46
+ Validates MCP Proxy Adapter configurations for mutually exclusive settings
47
+ and protocol compatibility.
48
+ """
49
+
50
+ def __init__(self):
51
+ self.errors: List[str] = []
52
+ self.warnings: List[str] = []
53
+
54
+ def validate_config(
55
+ self, config: Dict[str, Any], config_name: str
56
+ ) -> Tuple[bool, List[str], List[str]]:
57
+ """
58
+ Validate a configuration for mutually exclusive settings and protocol compatibility.
59
+
60
+ Args:
61
+ config: Configuration dictionary to validate
62
+ config_name: Name of the configuration for error reporting
63
+
64
+ Returns:
65
+ Tuple of (is_valid, errors, warnings)
66
+ """
67
+ self.errors = []
68
+ self.warnings = []
69
+
70
+ # Validate protocol settings
71
+ self._validate_protocol_settings(config, config_name)
72
+
73
+ # Validate SSL/TLS settings
74
+ self._validate_ssl_settings(config, config_name)
75
+
76
+ # Validate mTLS settings
77
+ self._validate_mtls_settings(config, config_name)
78
+
79
+ # Validate authentication settings
80
+ self._validate_auth_settings(config, config_name)
81
+
82
+ return len(self.errors) == 0, self.errors, self.warnings
83
+
84
+ def _validate_protocol_settings(
85
+ self, config: Dict[str, Any], config_name: str
86
+ ) -> None:
87
+ """Validate protocol configuration settings."""
88
+ protocols = config.get("protocols", {})
89
+
90
+ if not protocols.get("enabled", False):
91
+ self.warnings.append(
92
+ f"⚠️ {config_name}: Protocol middleware is disabled - all protocols will be allowed"
93
+ )
94
+ return
95
+
96
+ allowed_protocols = protocols.get("allowed_protocols", [])
97
+ if not allowed_protocols:
98
+ self.errors.append(
99
+ f"❌ {config_name}: No allowed protocols specified when protocol middleware is enabled"
100
+ )
101
+ return
102
+
103
+ # Check for invalid protocol combinations
104
+ if "http" in allowed_protocols and "https" in allowed_protocols:
105
+ self.warnings.append(
106
+ f"⚠️ {config_name}: Both HTTP and HTTPS protocols are allowed - consider security implications"
107
+ )
108
+
109
+ if "mtls" in allowed_protocols and "http" in allowed_protocols:
110
+ self.errors.append(
111
+ f"❌ {config_name}: mTLS and HTTP protocols are mutually exclusive - mTLS requires HTTPS"
112
+ )
113
+
114
+ def _validate_ssl_settings(self, config: Dict[str, Any], config_name: str) -> None:
115
+ """Validate SSL/TLS configuration settings."""
116
+ security = config.get("security", {})
117
+ ssl = security.get("ssl", {})
118
+
119
+ if not ssl.get("enabled", False):
120
+ return
121
+
122
+ # Check certificate file requirements
123
+ cert_file = ssl.get("server_cert_file")
124
+ key_file = ssl.get("server_key_file")
125
+
126
+ if not cert_file or not key_file:
127
+ self.errors.append(
128
+ f"❌ {config_name}: SSL enabled but server certificate or key file not specified"
129
+ )
130
+
131
+ # Check CA certificate requirements
132
+ ca_cert_file = ssl.get("ca_cert_file")
133
+ verify_server = ssl.get("verify_server", True)
134
+
135
+ if verify_server and not ca_cert_file:
136
+ self.warnings.append(
137
+ f"⚠️ {config_name}: Server verification enabled but no CA certificate specified"
138
+ )
139
+
140
+ def _validate_mtls_settings(self, config: Dict[str, Any], config_name: str) -> None:
141
+ """Validate mTLS configuration settings."""
142
+ security = config.get("security", {})
143
+ ssl = security.get("ssl", {})
144
+
145
+ if not ssl.get("enabled", False):
146
+ return
147
+
148
+ # Check if mTLS is configured
149
+ client_cert_file = ssl.get("client_cert_file")
150
+ client_key_file = ssl.get("client_key_file")
151
+ verify_client = ssl.get("verify_client", False)
152
+
153
+ if verify_client and (not client_cert_file or not client_key_file):
154
+ self.errors.append(
155
+ f"❌ {config_name}: Client verification enabled but client certificate or key file not specified"
156
+ )
157
+
158
+ # Check protocol compatibility
159
+ protocols = config.get("protocols", {})
160
+ if protocols.get("enabled", False):
161
+ allowed_protocols = protocols.get("allowed_protocols", [])
162
+ if verify_client and "mtls" not in allowed_protocols:
163
+ self.warnings.append(
164
+ f"⚠️ {config_name}: Client verification enabled but 'mtls' not in allowed protocols"
165
+ )
166
+
167
+ def _validate_auth_settings(self, config: Dict[str, Any], config_name: str) -> None:
168
+ """Validate authentication configuration settings."""
169
+ security = config.get("security", {})
170
+ auth = security.get("auth", {})
171
+
172
+ if not auth.get("enabled", False):
173
+ return
174
+
175
+ # Check token requirements
176
+ token_required = auth.get("token_required", False)
177
+ if token_required and not auth.get("token_secret"):
178
+ self.errors.append(
179
+ f"❌ {config_name}: Token authentication enabled but no token secret specified"
180
+ )
181
+
182
+
36
183
  def _get_package_paths() -> tuple[Path, Path]:
37
184
  """
38
185
  Resolve source paths for examples and utils relative to this file
@@ -42,6 +189,641 @@ def _get_package_paths() -> tuple[Path, Path]:
42
189
  return pkg_root / "examples", pkg_root / "utils"
43
190
 
44
191
 
192
+ def create_configuration_documentation(output_dir: Path) -> None:
193
+ """
194
+ Create comprehensive documentation for MCP Proxy Adapter configurations.
195
+ """
196
+ docs_dir = output_dir / "docs"
197
+ docs_dir.mkdir(parents=True, exist_ok=True)
198
+
199
+ # Create main configuration guide
200
+ config_guide = docs_dir / "CONFIGURATION_GUIDE.md"
201
+ with open(config_guide, "w", encoding="utf-8") as f:
202
+ f.write(
203
+ """# MCP Proxy Adapter Configuration Guide
204
+
205
+ ## Overview
206
+
207
+ This guide explains how to configure MCP Proxy Adapter for different deployment scenarios,
208
+ including HTTP, HTTPS, and mTLS configurations.
209
+
210
+ ## Configuration Structure
211
+
212
+ ```json
213
+ {
214
+ "server": {
215
+ "host": "0.0.0.0",
216
+ "port": 8000
217
+ },
218
+ "protocols": {
219
+ "enabled": true,
220
+ "allowed_protocols": ["https", "mtls"]
221
+ },
222
+ "security": {
223
+ "ssl": {
224
+ "enabled": true,
225
+ "server_cert_file": "path/to/server.crt",
226
+ "server_key_file": "path/to/server.key",
227
+ "ca_cert_file": "path/to/ca.crt",
228
+ "client_cert_file": "path/to/client.crt",
229
+ "client_key_file": "path/to/client.key",
230
+ "verify_server": true,
231
+ "verify_client": false,
232
+ "min_tls_version": "TLSv1.2"
233
+ },
234
+ "auth": {
235
+ "enabled": false,
236
+ "token_required": false,
237
+ "token_secret": "your-secret-key"
238
+ }
239
+ }
240
+ }
241
+ ```
242
+
243
+ ## Protocol Configuration
244
+
245
+ ### Protocol Middleware
246
+
247
+ The `protocols` section controls which protocols are allowed:
248
+
249
+ - `enabled: true` - Protocol validation is active
250
+ - `enabled: false` - All protocols are allowed (bypasses validation)
251
+
252
+ ### Allowed Protocols
253
+
254
+ - `"http"` - Plain HTTP (insecure)
255
+ - `"https"` - HTTPS with server certificate
256
+ - `"mtls"` - Mutual TLS (client and server certificates)
257
+
258
+ ### Protocol Combinations
259
+
260
+ **Valid combinations:**
261
+ - `["https"]` - HTTPS only
262
+ - `["https", "mtls"]` - HTTPS and mTLS
263
+ - `["http"]` - HTTP only (not recommended for production)
264
+
265
+ **Invalid combinations:**
266
+ - `["http", "mtls"]` - HTTP and mTLS are mutually exclusive
267
+ - `["http", "https"]` - Mixed HTTP/HTTPS (security risk)
268
+
269
+ ## SSL/TLS Configuration
270
+
271
+ ### Server Certificates
272
+
273
+ Required for HTTPS and mTLS:
274
+ - `server_cert_file` - Server certificate file
275
+ - `server_key_file` - Server private key file
276
+
277
+ ### CA Certificates
278
+
279
+ - `ca_cert_file` - CA certificate for server verification
280
+ - `verify_server: true` - Verify server certificate against CA
281
+ - `verify_server: false` - Disable server certificate verification
282
+
283
+ ### Client Certificates (mTLS)
284
+
285
+ - `client_cert_file` - Client certificate file
286
+ - `client_key_file` - Client private key file
287
+ - `verify_client: true` - Require client certificates
288
+ - `verify_client: false` - No client certificate required
289
+
290
+ ## Authentication
291
+
292
+ ### Token Authentication
293
+
294
+ - `auth.enabled: true` - Enable authentication
295
+ - `token_required: true` - Require authentication tokens
296
+ - `token_secret` - Secret key for token validation
297
+
298
+ ## Common Configuration Patterns
299
+
300
+ ### 1. Development (HTTP)
301
+ ```json
302
+ {
303
+ "protocols": {"enabled": false},
304
+ "security": {"ssl": {"enabled": false}}
305
+ }
306
+ ```
307
+
308
+ ### 2. Production HTTPS
309
+ ```json
310
+ {
311
+ "protocols": {
312
+ "enabled": true,
313
+ "allowed_protocols": ["https"]
314
+ },
315
+ "security": {
316
+ "ssl": {
317
+ "enabled": true,
318
+ "server_cert_file": "certs/server.crt",
319
+ "server_key_file": "keys/server.key",
320
+ "verify_server": true,
321
+ "ca_cert_file": "certs/ca.crt"
322
+ }
323
+ }
324
+ }
325
+ ```
326
+
327
+ ### 3. mTLS with Client Verification
328
+ ```json
329
+ {
330
+ "protocols": {
331
+ "enabled": true,
332
+ "allowed_protocols": ["https", "mtls"]
333
+ },
334
+ "security": {
335
+ "ssl": {
336
+ "enabled": true,
337
+ "server_cert_file": "certs/server.crt",
338
+ "server_key_file": "keys/server.key",
339
+ "ca_cert_file": "certs/ca.crt",
340
+ "client_cert_file": "certs/client.crt",
341
+ "client_key_file": "keys/client.key",
342
+ "verify_server": true,
343
+ "verify_client": true
344
+ }
345
+ }
346
+ }
347
+ ```
348
+
349
+ ## Validation Rules
350
+
351
+ The configuration validator checks for:
352
+
353
+ 1. **Mutually Exclusive Settings:**
354
+ - HTTP and mTLS protocols
355
+ - Client verification without client certificates
356
+ - Server verification without CA certificates
357
+
358
+ 2. **Required Dependencies:**
359
+ - SSL enabled requires server certificates
360
+ - mTLS requires both server and client certificates
361
+ - Protocol middleware enabled requires allowed protocols
362
+
363
+ 3. **Security Warnings:**
364
+ - HTTP and HTTPS in same configuration
365
+ - Server verification without CA certificate
366
+ - Client verification without mTLS protocol
367
+
368
+ ## Troubleshooting
369
+
370
+ ### Common Issues
371
+
372
+ 1. **"Protocol not allowed" errors:**
373
+ - Check `protocols.allowed_protocols` includes required protocol
374
+ - Ensure `protocols.enabled: true` for validation
375
+
376
+ 2. **SSL certificate errors:**
377
+ - Verify certificate file paths are correct
378
+ - Check certificate validity and format
379
+ - Ensure CA certificate matches server certificate
380
+
381
+ 3. **mTLS connection failures:**
382
+ - Verify client certificates are valid
383
+ - Check `verify_client: true` is set
384
+ - Ensure "mtls" is in allowed protocols
385
+
386
+ ### Debug Mode
387
+
388
+ Enable debug logging to troubleshoot issues:
389
+
390
+ ```json
391
+ {
392
+ "logging": {
393
+ "level": "DEBUG",
394
+ "handlers": ["console", "file"]
395
+ }
396
+ }
397
+ ```
398
+ """
399
+ )
400
+
401
+ print(f"✅ Created configuration documentation: {config_guide}")
402
+
403
+
404
+ def create_test_files(output_dir: Path) -> None:
405
+ """
406
+ Create additional test files for proxy registration testing.
407
+ """
408
+ # Create test proxy server script
409
+ test_proxy_server = output_dir / "test_proxy_server.py"
410
+ with open(test_proxy_server, "w", encoding="utf-8") as f:
411
+ f.write(
412
+ '''#!/usr/bin/env python3
413
+ """
414
+ Author: Vasiliy Zdanovskiy
415
+ email: vasilyvz@gmail.com
416
+
417
+ Simple mTLS proxy server for testing proxy registration SSL fix.
418
+ """
419
+ import asyncio
420
+ import ssl
421
+ from fastapi import FastAPI, Request
422
+ from fastapi.responses import JSONResponse
423
+ import uvicorn
424
+
425
+
426
+ app = FastAPI(title="Test mTLS Proxy Server", version="1.0.0")
427
+
428
+
429
+ @app.post("/register")
430
+ async def register_server(request: Request):
431
+ """Register server endpoint."""
432
+ try:
433
+ data = await request.json()
434
+ print(f"✅ Received registration request: {data}")
435
+
436
+ # Check if client certificate is present
437
+ client_cert = request.client
438
+ if client_cert:
439
+ print(f"✅ Client certificate verified: {client_cert}")
440
+
441
+ return JSONResponse(
442
+ status_code=200,
443
+ content={
444
+ "success": True,
445
+ "server_key": f"{data.get('server_id', 'unknown')}_1",
446
+ "message": "Server registered successfully"
447
+ }
448
+ )
449
+ except Exception as e:
450
+ print(f"❌ Registration error: {e}")
451
+ return JSONResponse(
452
+ status_code=500,
453
+ content={
454
+ "success": False,
455
+ "error": {
456
+ "message": str(e),
457
+ "code": "REGISTRATION_ERROR"
458
+ }
459
+ }
460
+ )
461
+
462
+
463
+ @app.get("/health")
464
+ async def health_check():
465
+ """Health check endpoint."""
466
+ return JSONResponse(
467
+ status_code=200,
468
+ content={
469
+ "status": "healthy",
470
+ "message": "mTLS Proxy Server is running"
471
+ }
472
+ )
473
+
474
+
475
+ def main():
476
+ """Run the mTLS proxy server."""
477
+ print("🚀 Starting Test mTLS Proxy Server...")
478
+ print("📡 Server URL: https://127.0.0.1:3004")
479
+ print("🔐 mTLS enabled with client certificate verification")
480
+ print("📋 Available endpoints:")
481
+ print(" POST /register - Register server")
482
+ print(" GET /health - Health check")
483
+ print("⚡ Press Ctrl+C to stop\\n")
484
+
485
+ # Run server with mTLS
486
+ uvicorn.run(
487
+ app,
488
+ host="127.0.0.1",
489
+ port=3004,
490
+ ssl_keyfile="mtls_certificates/server/mcp-proxy.key",
491
+ ssl_certfile="mtls_certificates/server/mcp-proxy.pem",
492
+ log_level="info"
493
+ )
494
+
495
+
496
+ if __name__ == "__main__":
497
+ main()
498
+ '''
499
+ )
500
+
501
+ # Make it executable
502
+ test_proxy_server.chmod(0o755)
503
+ print(f"✅ Created test proxy server: {test_proxy_server}")
504
+
505
+ # Create test script for proxy registration
506
+ test_script = output_dir / "test_proxy_registration.py"
507
+ with open(test_script, "w", encoding="utf-8") as f:
508
+ f.write(
509
+ '''#!/usr/bin/env python3
510
+ """
511
+ Author: Vasiliy Zdanovskiy
512
+ email: vasilyvz@gmail.com
513
+
514
+ Test script to verify proxy registration SSL configuration fix.
515
+ """
516
+ import sys
517
+ import subprocess
518
+ import time
519
+ import requests
520
+ from pathlib import Path
521
+
522
+
523
+ def test_proxy_registration():
524
+ """Test proxy registration with SSL configuration."""
525
+ print("🧪 Testing Proxy Registration SSL Configuration Fix")
526
+ print("=" * 60)
527
+
528
+ # Start proxy server
529
+ print("🚀 Starting test proxy server...")
530
+ proxy_process = subprocess.Popen([
531
+ sys.executable, "test_proxy_server.py"
532
+ ], cwd=Path(__file__).parent)
533
+
534
+ try:
535
+ # Wait for server to start
536
+ print("⏳ Waiting for proxy server to start...")
537
+ time.sleep(5)
538
+
539
+ # Test proxy server health
540
+ print("🔍 Testing proxy server health...")
541
+ try:
542
+ response = requests.get(
543
+ "https://127.0.0.1:3004/health",
544
+ verify=False,
545
+ timeout=10
546
+ )
547
+ if response.status_code == 200:
548
+ print("✅ Proxy server is running")
549
+ else:
550
+ print(f"❌ Proxy server health check failed: {response.status_code}")
551
+ return False
552
+ except Exception as e:
553
+ print(f"❌ Failed to connect to proxy server: {e}")
554
+ return False
555
+
556
+ # Test mTLS server with registration
557
+ print("🚀 Starting mTLS server with proxy registration...")
558
+ server_process = subprocess.Popen([
559
+ sys.executable, "-m", "mcp_proxy_adapter",
560
+ "--config", "configs/test_proxy_registration.json"
561
+ ], cwd=Path(__file__).parent)
562
+
563
+ try:
564
+ # Wait for server to start and attempt registration
565
+ print("⏳ Waiting for server to start and register...")
566
+ time.sleep(10)
567
+
568
+ # Check if server is running
569
+ if server_process.poll() is None:
570
+ print("✅ mTLS server started successfully")
571
+ print("✅ Proxy registration SSL configuration fix is working!")
572
+ return True
573
+ else:
574
+ print("❌ mTLS server failed to start")
575
+ return False
576
+
577
+ finally:
578
+ # Clean up server process
579
+ if server_process.poll() is None:
580
+ server_process.terminate()
581
+ server_process.wait()
582
+
583
+ finally:
584
+ # Clean up proxy process
585
+ if proxy_process.poll() is None:
586
+ proxy_process.terminate()
587
+ proxy_process.wait()
588
+
589
+
590
+ def main():
591
+ """Run the test."""
592
+ success = test_proxy_registration()
593
+
594
+ if success:
595
+ print("\\n🎉 All tests passed! Proxy registration SSL fix is working correctly.")
596
+ return 0
597
+ else:
598
+ print("\\n❌ Tests failed. Check the logs above for details.")
599
+ return 1
600
+
601
+
602
+ if __name__ == "__main__":
603
+ sys.exit(main())
604
+ '''
605
+ )
606
+
607
+ # Make it executable
608
+ test_script.chmod(0o755)
609
+ print(f"✅ Created test script: {test_script}")
610
+
611
+
612
+ def generate_enhanced_configurations(output_dir: Path) -> None:
613
+ """
614
+ Generate enhanced configurations with proper protocol settings and validation.
615
+ """
616
+ configs_dir = output_dir / "configs"
617
+ configs_dir.mkdir(parents=True, exist_ok=True)
618
+
619
+ validator = ConfigurationValidator()
620
+
621
+ # Configuration templates with proper protocol settings
622
+ configs = {
623
+ "development_http.json": {
624
+ "server": {"host": "0.0.0.0", "port": 8000},
625
+ "protocols": {"enabled": False},
626
+ "security": {"ssl": {"enabled": False}},
627
+ "logging": {"level": "DEBUG"},
628
+ },
629
+ "production_https.json": {
630
+ "server": {"host": "0.0.0.0", "port": 8443},
631
+ "protocols": {"enabled": True, "allowed_protocols": ["https"]},
632
+ "security": {
633
+ "ssl": {
634
+ "enabled": True,
635
+ "server_cert_file": "certs/server_cert.pem",
636
+ "server_key_file": "keys/server_key.pem",
637
+ "ca_cert_file": "certs/ca_cert.pem",
638
+ "verify_server": True,
639
+ "verify_client": False,
640
+ "min_tls_version": "TLSv1.2",
641
+ }
642
+ },
643
+ "logging": {"level": "INFO"},
644
+ },
645
+ "mtls_with_roles.json": {
646
+ "server": {"host": "0.0.0.0", "port": 8443},
647
+ "protocols": {"enabled": True, "allowed_protocols": ["https", "mtls"]},
648
+ "security": {
649
+ "ssl": {
650
+ "enabled": True,
651
+ "server_cert_file": "certs/server_cert.pem",
652
+ "server_key_file": "keys/server_key.pem",
653
+ "ca_cert_file": "certs/ca_cert.pem",
654
+ "client_cert_file": "certs/client_cert.pem",
655
+ "client_key_file": "keys/client_key.pem",
656
+ "verify_server": True,
657
+ "verify_client": True,
658
+ "min_tls_version": "TLSv1.2",
659
+ },
660
+ "auth": {
661
+ "enabled": True,
662
+ "token_required": False,
663
+ "token_secret": "your-secret-key",
664
+ },
665
+ },
666
+ "logging": {"level": "INFO"},
667
+ },
668
+ "mtls_no_roles.json": {
669
+ "server": {"host": "0.0.0.0", "port": 8443},
670
+ "protocols": {"enabled": True, "allowed_protocols": ["https", "mtls"]},
671
+ "security": {
672
+ "ssl": {
673
+ "enabled": True,
674
+ "server_cert_file": "certs/server_cert.pem",
675
+ "server_key_file": "keys/server_key.pem",
676
+ "ca_cert_file": "certs/ca_cert.pem",
677
+ "client_cert_file": "certs/client_cert.pem",
678
+ "client_key_file": "keys/client_key.pem",
679
+ "verify_server": True,
680
+ "verify_client": True,
681
+ "min_tls_version": "TLSv1.2",
682
+ }
683
+ },
684
+ "logging": {"level": "INFO"},
685
+ },
686
+ "https_simple.json": {
687
+ "server": {"host": "0.0.0.0", "port": 8443},
688
+ "protocols": {"enabled": True, "allowed_protocols": ["https"]},
689
+ "security": {
690
+ "ssl": {
691
+ "enabled": True,
692
+ "server_cert_file": "certs/server_cert.pem",
693
+ "server_key_file": "keys/server_key.pem",
694
+ "verify_server": False,
695
+ "verify_client": False,
696
+ "min_tls_version": "TLSv1.2",
697
+ }
698
+ },
699
+ "logging": {"level": "INFO"},
700
+ },
701
+ "https_with_auth.json": {
702
+ "server": {"host": "0.0.0.0", "port": 8443},
703
+ "protocols": {"enabled": True, "allowed_protocols": ["https"]},
704
+ "security": {
705
+ "ssl": {
706
+ "enabled": True,
707
+ "server_cert_file": "certs/server_cert.pem",
708
+ "server_key_file": "keys/server_key.pem",
709
+ "verify_server": True,
710
+ "ca_cert_file": "certs/ca_cert.pem",
711
+ "verify_client": False,
712
+ "min_tls_version": "TLSv1.2",
713
+ },
714
+ "auth": {
715
+ "enabled": True,
716
+ "token_required": True,
717
+ "token_secret": "your-secret-key",
718
+ },
719
+ },
720
+ "logging": {"level": "INFO"},
721
+ },
722
+ "test_proxy_registration.json": {
723
+ "server": {"host": "127.0.0.1", "port": 8010},
724
+ "protocols": {"enabled": True, "allowed_protocols": ["https", "mtls"]},
725
+ "security": {
726
+ "ssl": {
727
+ "enabled": True,
728
+ "server_cert_file": "certs/mtls/server/embedding-service.pem",
729
+ "server_key_file": "certs/mtls/server/embedding-service.key",
730
+ "ca_cert_file": "certs/mtls/truststore.pem",
731
+ "client_cert_file": "certs/mtls/client/embedding-service.pem",
732
+ "client_key_file": "certs/mtls/client/embedding-service.key",
733
+ "verify_server": True,
734
+ "verify_client": True,
735
+ "min_tls_version": "TLSv1.2",
736
+ }
737
+ },
738
+ "registration": {
739
+ "enabled": True,
740
+ "proxy_url": "https://127.0.0.1:3004",
741
+ "server_id": "test-proxy-registration",
742
+ "server_name": "Test Proxy Registration Service",
743
+ "description": "Test service for proxy registration SSL fix",
744
+ "auth_method": "certificate",
745
+ "certificate": {
746
+ "cert_file": "certs/mtls/client/embedding-service.pem",
747
+ "key_file": "certs/mtls/client/embedding-service.key",
748
+ },
749
+ "ssl": {
750
+ "verify_mode": "CERT_REQUIRED",
751
+ "ca_cert": "mtls_certificates/truststore.pem",
752
+ },
753
+ },
754
+ "logging": {"level": "DEBUG"},
755
+ },
756
+ }
757
+
758
+ # Generate and validate configurations
759
+ for config_name, config_data in configs.items():
760
+ config_path = configs_dir / config_name
761
+
762
+ # Validate configuration
763
+ is_valid, errors, warnings = validator.validate_config(config_data, config_name)
764
+
765
+ if not is_valid:
766
+ print(f"❌ Configuration {config_name} has errors:")
767
+ for error in errors:
768
+ print(f" {error}")
769
+ continue
770
+
771
+ if warnings:
772
+ print(f"⚠️ Configuration {config_name} has warnings:")
773
+ for warning in warnings:
774
+ print(f" {warning}")
775
+
776
+ # Write configuration file
777
+ with open(config_path, "w", encoding="utf-8") as f:
778
+ json.dump(config_data, f, indent=2)
779
+
780
+ print(f"✅ Generated configuration: {config_path}")
781
+
782
+ # Create configuration index
783
+ index_path = configs_dir / "README.md"
784
+ with open(index_path, "w", encoding="utf-8") as f:
785
+ f.write(
786
+ """# Configuration Files
787
+
788
+ This directory contains pre-configured examples for different deployment scenarios.
789
+
790
+ ## Available Configurations
791
+
792
+ ### Development
793
+ - `development_http.json` - HTTP development server (no SSL)
794
+
795
+ ### Production HTTPS
796
+ - `production_https.json` - HTTPS with server certificate verification
797
+ - `https_simple.json` - HTTPS without certificate verification
798
+ - `https_with_auth.json` - HTTPS with token authentication
799
+
800
+ ### mTLS (Mutual TLS)
801
+ - `mtls_with_roles.json` - mTLS with role-based authentication
802
+ - `mtls_no_roles.json` - mTLS without roles
803
+
804
+ ## Usage
805
+
806
+ Start the server with a specific configuration:
807
+
808
+ ```bash
809
+ python -m mcp_proxy_adapter --config configs/production_https.json
810
+ ```
811
+
812
+ ## Validation
813
+
814
+ All configurations are validated for:
815
+ - Mutually exclusive settings
816
+ - Required dependencies
817
+ - Protocol compatibility
818
+ - Security best practices
819
+
820
+ See `docs/CONFIGURATION_GUIDE.md` for detailed documentation.
821
+ """
822
+ )
823
+
824
+ print(f"✅ Created configuration index: {index_path}")
825
+
826
+
45
827
  def setup_test_environment(output_dir: Path) -> None:
46
828
  """
47
829
  Setup test environment under output_dir with required files
@@ -50,9 +832,10 @@ def setup_test_environment(output_dir: Path) -> None:
50
832
  All created directories and copied files are rooted at output_dir
51
833
  so users can run scripts relative to that directory.
52
834
  """
53
- print("🔧 Setting up test environment...")
835
+ print("🔧 Setting up enhanced test environment...")
54
836
  output_dir = output_dir.resolve()
55
837
  output_dir.mkdir(parents=True, exist_ok=True)
838
+
56
839
  # Create test environment directory structure
57
840
  directories = [
58
841
  "examples/basic_framework",
@@ -63,13 +846,16 @@ def setup_test_environment(output_dir: Path) -> None:
63
846
  "keys",
64
847
  "tokens",
65
848
  "logs",
849
+ "docs",
66
850
  ]
67
851
  for directory in directories:
68
852
  target_dir = output_dir / directory
69
853
  target_dir.mkdir(parents=True, exist_ok=True)
70
854
  print(f"✅ Created directory: {target_dir}")
855
+
71
856
  # Resolve package paths
72
857
  examples_src_root, utils_src_root = _get_package_paths()
858
+
73
859
  # Copy example files
74
860
  basic_framework_src = examples_src_root / "basic_framework"
75
861
  if basic_framework_src.exists():
@@ -79,6 +865,7 @@ def setup_test_environment(output_dir: Path) -> None:
79
865
  dirs_exist_ok=True,
80
866
  )
81
867
  print("✅ Copied basic_framework examples")
868
+
82
869
  full_application_src = examples_src_root / "full_application"
83
870
  if full_application_src.exists():
84
871
  shutil.copytree(
@@ -87,16 +874,19 @@ def setup_test_environment(output_dir: Path) -> None:
87
874
  dirs_exist_ok=True,
88
875
  )
89
876
  print("✅ Copied full_application examples")
877
+
90
878
  # Copy utility scripts
91
879
  config_generator_src = utils_src_root / "config_generator.py"
92
880
  if config_generator_src.exists():
93
881
  shutil.copy2(config_generator_src, output_dir / "scripts/")
94
882
  print("✅ Copied config_generator.py")
883
+
95
884
  # Copy certificate generation scripts
96
885
  create_certs_src = examples_src_root / "create_certificates_simple.py"
97
886
  if create_certs_src.exists():
98
887
  shutil.copy2(create_certs_src, output_dir / "scripts/")
99
888
  print("✅ Copied create_certificates_simple.py")
889
+
100
890
  cert_tokens_src = examples_src_root / "generate_certificates_and_tokens.py"
101
891
  if cert_tokens_src.exists():
102
892
  shutil.copy2(cert_tokens_src, output_dir / "scripts/")
@@ -113,7 +903,21 @@ def setup_test_environment(output_dir: Path) -> None:
113
903
  if roles_configs_src.exists():
114
904
  shutil.copy2(roles_configs_src, output_dir / "roles.json")
115
905
  print("✅ Updated roles.json from configs directory")
116
- print("🎉 Test environment setup completed successfully at: {}".format(output_dir))
906
+
907
+ # Create configuration documentation
908
+ create_configuration_documentation(output_dir)
909
+
910
+ # Generate enhanced configurations
911
+ generate_enhanced_configurations(output_dir)
912
+
913
+ # Create test files
914
+ create_test_files(output_dir)
915
+
916
+ print(
917
+ "🎉 Enhanced test environment setup completed successfully at: {}".format(
918
+ output_dir
919
+ )
920
+ )
117
921
 
118
922
 
119
923
  def generate_certificates_with_framework(output_dir: Path) -> bool:
@@ -257,7 +1061,7 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
257
1061
  def main() -> int:
258
1062
  """Main function for command line execution."""
259
1063
  parser = argparse.ArgumentParser(
260
- description="Setup test environment for MCP Proxy Adapter"
1064
+ description="Setup enhanced test environment for MCP Proxy Adapter"
261
1065
  )
262
1066
  parser.add_argument(
263
1067
  "--output-dir",
@@ -269,13 +1073,19 @@ def main() -> int:
269
1073
  "(default: current directory)"
270
1074
  ),
271
1075
  )
1076
+ parser.add_argument(
1077
+ "--skip-certs", action="store_true", help="Skip certificate generation"
1078
+ )
272
1079
  args = parser.parse_args()
273
1080
  try:
274
1081
  target_root = Path(args.output_dir)
275
1082
  setup_test_environment(target_root)
276
- # Generate certificates if framework is available
277
- if SECURITY_FRAMEWORK_AVAILABLE:
1083
+
1084
+ # Generate certificates if framework is available and not skipped
1085
+ if not args.skip_certs and SECURITY_FRAMEWORK_AVAILABLE:
278
1086
  generate_certificates_with_framework(target_root)
1087
+ elif args.skip_certs:
1088
+ print("⚠️ Skipping certificate generation (--skip-certs specified)")
279
1089
  else:
280
1090
  print(
281
1091
  "⚠️ Skipping certificate generation (mcp_security_framework "
@@ -293,21 +1103,21 @@ def main() -> int:
293
1103
  return 1
294
1104
 
295
1105
  print("\n" + "=" * 60)
296
- print("✅ TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
1106
+ print("✅ ENHANCED TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
297
1107
  print("=" * 60)
298
1108
  print("\n📋 NEXT STEPS:")
299
- print("1. Generate test configurations:")
300
- print(
301
- " python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs"
302
- )
303
- print("\n2. Generate additional certificates (if needed):")
304
- print(" python -m mcp_proxy_adapter.examples.generate_certificates")
305
- print("\n3. Run security tests:")
1109
+ print("1. Review configuration documentation:")
1110
+ print(" cat docs/CONFIGURATION_GUIDE.md")
1111
+ print("\n2. Check available configurations:")
1112
+ print(" ls -la configs/")
1113
+ print("\n3. Test proxy registration SSL fix:")
1114
+ print(" python test_proxy_registration.py")
1115
+ print("\n4. Start server with a specific configuration:")
1116
+ print(" python -m mcp_proxy_adapter --config configs/production_https.json")
1117
+ print("\n5. Run security tests:")
306
1118
  print(" python -m mcp_proxy_adapter.examples.run_security_tests")
307
- print("\n4. Start basic framework example:")
308
- print(
309
- " python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json"
310
- )
1119
+ print("\n6. Generate additional certificates (if needed):")
1120
+ print(" python scripts/create_certificates_simple.py")
311
1121
  print("=" * 60)
312
1122
  return 0
313
1123