mcp-proxy-adapter 6.4.36__py3-none-any.whl → 6.4.38__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.
@@ -175,7 +175,8 @@ class TestConfigGenerator:
175
175
  "security.auth.methods": ["certificate"],
176
176
  "security.permissions.enabled": False,
177
177
  "proxy_registration.enabled": False,
178
- "protocols.allowed_protocols": ["https", "mtls"]
178
+ "protocols.allowed_protocols": ["https", "mtls"],
179
+ "protocols.default_protocol": "mtls"
179
180
  })
180
181
 
181
182
  # 7. mTLS with Proxy Registration
@@ -196,37 +197,11 @@ class TestConfigGenerator:
196
197
  "protocols.allowed_protocols": ["https", "mtls"]
197
198
  })
198
199
 
199
- # 8. HTTP with Token Auth (for security tests)
200
- self.create_config("http_token", {
201
- "server.port": 8010,
202
- "ssl.enabled": False,
203
- "security.enabled": True,
204
- "security.auth.enabled": True,
205
- "security.auth.methods": ["api_key"],
206
- "security.auth.api_keys": {
207
- "admin": "admin-secret-key",
208
- "user": "user-secret-key"
209
- },
210
- "proxy_registration.enabled": False,
211
- "protocols.allowed_protocols": ["http"]
212
- })
200
+ # 8. HTTP with Token Auth (for security tests) - REMOVED DUPLICATE
201
+ # This is already created above with correct port 20021
213
202
 
214
- # 9. HTTPS with Token Auth (for security tests)
215
- self.create_config("https_token", {
216
- "server.port": 8011,
217
- "ssl.enabled": True,
218
- "ssl.cert_file": "certs/localhost_server.crt",
219
- "ssl.key_file": "keys/localhost_server.key",
220
- "security.enabled": True,
221
- "security.auth.enabled": True,
222
- "security.auth.methods": ["api_key"],
223
- "security.auth.api_keys": {
224
- "admin": "admin-secret-key",
225
- "user": "user-secret-key"
226
- },
227
- "proxy_registration.enabled": False,
228
- "protocols.allowed_protocols": ["https"]
229
- })
203
+ # 9. HTTPS with Token Auth (for security tests) - REMOVED DUPLICATE
204
+ # This is already created above with correct port 20023
230
205
 
231
206
  # 10. Full Featured (everything enabled)
232
207
  self.create_config("full_featured", {
@@ -8,9 +8,7 @@ Automates the complete testing workflow.
8
8
  import os
9
9
  import sys
10
10
  import subprocess
11
- import time
12
11
  from pathlib import Path
13
- from typing import List, Dict, Optional
14
12
 
15
13
 
16
14
  class FullTestSuiteRunner:
@@ -26,9 +24,9 @@ class FullTestSuiteRunner:
26
24
 
27
25
  def print_step(self, step: str, description: str):
28
26
  """Print a formatted step header."""
29
- print(f"\n{'='*60}")
27
+ print(f"\n{'=' * 60}")
30
28
  print(f"🔧 STEP {step}: {description}")
31
- print(f"{'='*60}")
29
+ print(f"{'=' * 60}")
32
30
 
33
31
  def print_success(self, message: str):
34
32
  """Print a success message."""
@@ -114,8 +112,19 @@ class FullTestSuiteRunner:
114
112
  self.print_step("3", "Certificate Generation")
115
113
 
116
114
  try:
115
+ # Check if certificate generation script exists
116
+ cert_script = self.working_dir / "scripts" / "create_certificates_simple.py"
117
+ if not cert_script.exists():
118
+ # Try alternative path
119
+ cert_script = self.working_dir / "create_certificates_simple.py"
120
+ if not cert_script.exists():
121
+ self.print_error(
122
+ f"Certificate generation script not found: {cert_script}"
123
+ )
124
+ return False
125
+
117
126
  # Run certificate generation script
118
- cmd = [sys.executable, "scripts/create_certificates_simple.py"]
127
+ cmd = [sys.executable, str(cert_script)]
119
128
  self.print_info("Running certificate generation script...")
120
129
 
121
130
  result = subprocess.run(
@@ -152,18 +161,29 @@ class FullTestSuiteRunner:
152
161
  # Check if comprehensive_config.json exists
153
162
  comprehensive_config = self.working_dir / "comprehensive_config.json"
154
163
  if not comprehensive_config.exists():
155
- self.print_error(f"Comprehensive config not found: {comprehensive_config}")
164
+ self.print_error(
165
+ f"Comprehensive config not found: {comprehensive_config}"
166
+ )
156
167
  return False
157
168
 
158
- self.print_info("Generating test configurations from comprehensive config...")
169
+ self.print_info(
170
+ "Generating test configurations from comprehensive config..."
171
+ )
159
172
  self.print_info("This will create:")
160
173
  self.print_info(" - HTTP configurations (simple and with auth)")
161
174
  self.print_info(" - HTTPS configurations (simple and with auth)")
162
- self.print_info(" - mTLS configurations (simple, with roles, with proxy registration)")
175
+ self.print_info(
176
+ " - mTLS configurations (simple, with roles, with proxy registration)"
177
+ )
163
178
  self.print_info(" - Full featured configuration (everything enabled)")
164
179
 
165
180
  # Run the configuration generator
166
- cmd = [sys.executable, "create_test_configs.py", "--comprehensive-config", "comprehensive_config.json"]
181
+ cmd = [
182
+ sys.executable,
183
+ "create_test_configs.py",
184
+ "--comprehensive-config",
185
+ "comprehensive_config.json",
186
+ ]
167
187
  result = subprocess.run(
168
188
  cmd, capture_output=True, text=True, cwd=self.working_dir
169
189
  )
@@ -173,36 +193,37 @@ class FullTestSuiteRunner:
173
193
  if result.stdout:
174
194
  print("Generator output:")
175
195
  print(result.stdout)
176
-
196
+
177
197
  # Create roles.json file
178
198
  self.print_info("Creating roles.json file...")
179
199
  roles_content = {
180
200
  "roles": {
181
201
  "admin": {
182
202
  "permissions": ["*"],
183
- "description": "Full administrative access"
203
+ "description": "Full administrative access",
184
204
  },
185
205
  "user": {
186
206
  "permissions": ["read", "write"],
187
- "description": "Standard user access"
207
+ "description": "Standard user access",
188
208
  },
189
209
  "readonly": {
190
210
  "permissions": ["read"],
191
- "description": "Read-only access"
211
+ "description": "Read-only access",
192
212
  },
193
213
  "guest": {
194
214
  "permissions": ["read"],
195
- "description": "Limited guest access"
196
- }
215
+ "description": "Limited guest access",
216
+ },
197
217
  }
198
218
  }
199
-
219
+
200
220
  roles_file = self.configs_dir / "roles.json"
201
221
  import json
202
- with open(roles_file, 'w', encoding='utf-8') as f:
222
+
223
+ with open(roles_file, "w", encoding="utf-8") as f:
203
224
  json.dump(roles_content, f, indent=2, ensure_ascii=False)
204
225
  self.print_success(f"Created roles.json: {roles_file}")
205
-
226
+
206
227
  return True
207
228
  else:
208
229
  self.print_error("Configuration generation failed!")
@@ -287,13 +308,12 @@ class FullTestSuiteRunner:
287
308
  # Create test_proxy_registration.json config if it doesn't exist
288
309
  test_config = self.configs_dir / "test_proxy_registration.json"
289
310
  if not test_config.exists():
290
- self.print_info("Creating test_proxy_registration.json configuration...")
311
+ self.print_info(
312
+ "Creating test_proxy_registration.json configuration..."
313
+ )
291
314
  test_config_content = {
292
315
  "uuid": "550e8400-e29b-41d4-a716-446655440001",
293
- "server": {
294
- "host": "127.0.0.1",
295
- "port": 20005
296
- },
316
+ "server": {"host": "127.0.0.1", "port": 20005},
297
317
  "ssl": {
298
318
  "enabled": True,
299
319
  "cert_file": "certs/localhost_server.crt",
@@ -301,7 +321,7 @@ class FullTestSuiteRunner:
301
321
  "ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
302
322
  "client_cert_file": "certs/admin_cert.pem",
303
323
  "client_key_file": "certs/admin_key.pem",
304
- "verify_client": True
324
+ "verify_client": True,
305
325
  },
306
326
  "registration": {
307
327
  "enabled": True,
@@ -309,7 +329,7 @@ class FullTestSuiteRunner:
309
329
  "server_url": "http://127.0.0.1:3006/proxy",
310
330
  "token": {
311
331
  "enabled": True,
312
- "token": "proxy_registration_token_123"
332
+ "token": "proxy_registration_token_123",
313
333
  },
314
334
  "proxy_info": {
315
335
  "name": "mcp_test_server",
@@ -317,50 +337,42 @@ class FullTestSuiteRunner:
317
337
  "jsonrpc",
318
338
  "rest",
319
339
  "security",
320
- "proxy_registration"
340
+ "proxy_registration",
321
341
  ],
322
342
  "endpoints": {
323
343
  "jsonrpc": "/api/jsonrpc",
324
344
  "rest": "/cmd",
325
- "health": "/health"
326
- }
345
+ "health": "/health",
346
+ },
327
347
  },
328
- "heartbeat": {
329
- "enabled": True,
330
- "interval": 30
331
- }
348
+ "heartbeat": {"enabled": True, "interval": 30},
332
349
  },
333
350
  "security": {
334
351
  "enabled": True,
335
- "auth": {
336
- "enabled": True,
337
- "methods": [
338
- "certificate"
339
- ]
340
- },
352
+ "auth": {"enabled": True, "methods": ["certificate"]},
341
353
  "permissions": {
342
354
  "enabled": True,
343
- "roles_file": "configs/roles.json"
344
- }
355
+ "roles_file": "configs/roles.json",
356
+ },
345
357
  },
346
358
  "protocols": {
347
359
  "enabled": True,
348
360
  "default_protocol": "mtls",
349
- "allowed_protocols": [
350
- "https",
351
- "mtls"
352
- ]
353
- }
361
+ "allowed_protocols": ["https", "mtls"],
362
+ },
354
363
  }
355
-
364
+
356
365
  import json
357
- with open(test_config, 'w', encoding='utf-8') as f:
366
+
367
+ with open(test_config, "w", encoding="utf-8") as f:
358
368
  json.dump(test_config_content, f, indent=2)
359
369
  self.print_success(f"Created test configuration: {test_config}")
360
370
 
361
371
  self.print_info("Running mTLS proxy registration test...")
362
372
  self.print_info("This test verifies:")
363
- self.print_info(" - mTLS server startup with client certificate verification")
373
+ self.print_info(
374
+ " - mTLS server startup with client certificate verification"
375
+ )
364
376
  self.print_info(" - Proxy registration functionality")
365
377
  self.print_info(" - SSL configuration validation")
366
378
 
@@ -371,7 +383,9 @@ class FullTestSuiteRunner:
371
383
  )
372
384
 
373
385
  if result.returncode == 0:
374
- self.print_success("mTLS proxy registration test completed successfully!")
386
+ self.print_success(
387
+ "mTLS proxy registration test completed successfully!"
388
+ )
375
389
  if result.stdout:
376
390
  print("Test output:")
377
391
  print(result.stdout)
@@ -461,7 +475,7 @@ class FullTestSuiteRunner:
461
475
  return False
462
476
 
463
477
  # All steps completed successfully
464
- print(f"\n{'='*60}")
478
+ print(f"\n{'=' * 60}")
465
479
  print("🎉 FULL TEST SUITE COMPLETED SUCCESSFULLY!")
466
480
  print("=" * 60)
467
481
  print("✅ Environment validated")
@@ -25,10 +25,19 @@ import psutil
25
25
  import requests
26
26
 
27
27
  # Import security test client with proper module path
28
- from mcp_proxy_adapter.examples.security_test_client import (
29
- SecurityTestClient,
30
- TestResult,
31
- )
28
+ try:
29
+ from mcp_proxy_adapter.examples.security_test_client import (
30
+ SecurityTestClient,
31
+ TestResult,
32
+ )
33
+ except ImportError:
34
+ # Fallback to local import if package import fails
35
+ current_dir = Path(__file__).parent
36
+ sys.path.insert(0, str(current_dir))
37
+ from security_test_client import (
38
+ SecurityTestClient,
39
+ TestResult,
40
+ )
32
41
 
33
42
 
34
43
  class SecurityTestRunner:
@@ -49,31 +58,31 @@ class SecurityTestRunner:
49
58
  "basic_http": {
50
59
  "config": "configs/http_simple.json",
51
60
  "port": 20020, # Dedicated port
52
- "url": f"http://127.0.0.1:20020",
61
+ "url": "http://127.0.0.1:20020",
53
62
  "auth": "none",
54
63
  },
55
64
  "http_token": {
56
65
  "config": "configs/http_token.json",
57
66
  "port": 20021, # Dedicated port
58
- "url": f"http://127.0.0.1:20021",
67
+ "url": "http://127.0.0.1:20021",
59
68
  "auth": "api_key",
60
69
  },
61
70
  "https": {
62
71
  "config": "configs/https_simple.json",
63
72
  "port": 20022, # Dedicated port
64
- "url": f"https://127.0.0.1:20022",
73
+ "url": "https://127.0.0.1:20022",
65
74
  "auth": "none",
66
75
  },
67
76
  "https_token": {
68
77
  "config": "configs/https_token.json",
69
78
  "port": 20023, # Dedicated port
70
- "url": f"https://127.0.0.1:20023",
79
+ "url": "https://127.0.0.1:20023",
71
80
  "auth": "api_key",
72
81
  },
73
82
  "mtls": {
74
83
  "config": "configs/mtls_no_roles.json",
75
84
  "port": 20024, # Dedicated port
76
- "url": f"https://127.0.0.1:20024",
85
+ "url": "https://127.0.0.1:20024",
77
86
  "auth": "certificate",
78
87
  },
79
88
  }
@@ -146,6 +155,17 @@ class SecurityTestRunner:
146
155
  ports.append(cfg["port"])
147
156
  return list(sorted(set(ports)))
148
157
 
158
+ def check_ports_available(self, ports: List[int]) -> Tuple[bool, List[int]]:
159
+ """
160
+ Check if all ports in the list are available.
161
+ Returns (True, []) if all ports are free, (False, occupied_ports) otherwise.
162
+ """
163
+ occupied_ports = []
164
+ for port in ports:
165
+ if self._port_in_use(port):
166
+ occupied_ports.append(port)
167
+ return len(occupied_ports) == 0, occupied_ports
168
+
149
169
  def _validate_file(self, base: Path, path_value: Optional[str]) -> Tuple[bool, str]:
150
170
  if not path_value:
151
171
  return True, ""
@@ -229,13 +249,20 @@ class SecurityTestRunner:
229
249
  """Start a server in background."""
230
250
  try:
231
251
  print(f"🚀 Starting {name} server on port {port}...")
232
-
233
- # Check if port is still available (should be, since we checked at start)
252
+
253
+ # Always ensure port is free before starting server
234
254
  if self._port_in_use(port):
235
- print(f" Port {port} is unexpectedly in use, cannot start {name}")
236
- print("💡 This should not happen - ports were checked at startup")
237
- return None
238
-
255
+ print(f"🧹 Port {port} is in use, freeing it...")
256
+ self.ensure_ports_free([port])
257
+ time.sleep(1) # Give time for port to be freed
258
+
259
+ # Check again after freeing
260
+ if self._port_in_use(port):
261
+ print(
262
+ f"❌ Port {port} still in use after cleanup, cannot start {name}"
263
+ )
264
+ return None
265
+
239
266
  # Start server in background
240
267
  logs_dir = Path("logs")
241
268
  logs_dir.mkdir(exist_ok=True)
@@ -293,11 +320,25 @@ class SecurityTestRunner:
293
320
  """Start the proxy server for server registration."""
294
321
  try:
295
322
  print("🚀 Starting proxy server...")
323
+
324
+ # Ensure proxy port is free
325
+ if self._port_in_use(self.proxy_port):
326
+ print(f"🧹 Proxy port {self.proxy_port} is in use, freeing it...")
327
+ self.ensure_ports_free([self.proxy_port])
328
+ time.sleep(1)
329
+
330
+ if self._port_in_use(self.proxy_port):
331
+ print(f"❌ Proxy port {self.proxy_port} still in use after cleanup")
332
+ return False
333
+
296
334
  # Find the proxy server script
297
335
  proxy_script = Path(__file__).parent / "run_proxy_server.py"
298
336
  if not proxy_script.exists():
299
- print("❌ Proxy server script not found")
300
- return False
337
+ # Try alternative path
338
+ proxy_script = Path.cwd() / "run_proxy_server.py"
339
+ if not proxy_script.exists():
340
+ print("❌ Proxy server script not found")
341
+ return False
301
342
 
302
343
  # Start proxy server
303
344
  cmd = [
@@ -372,13 +413,27 @@ class SecurityTestRunner:
372
413
  # Override SSL context for mTLS
373
414
  client.create_ssl_context = client.create_ssl_context_for_mtls
374
415
  async with client as client_session:
375
- results = await client_session.run_security_tests(
376
- config["url"], config["auth"]
377
- )
416
+ # Pass correct token for api_key authentication
417
+ if config["auth"] == "api_key":
418
+ results = await client_session.run_security_tests(
419
+ config["url"], config["auth"], token="admin-secret-key"
420
+ )
421
+ else:
422
+ results = await client_session.run_security_tests(
423
+ config["url"], config["auth"]
424
+ )
378
425
  else:
379
426
  # For other auth types, use default SSL context
380
427
  async with SecurityTestClient(config["url"]) as client:
381
- results = await client.run_security_tests(config["url"], config["auth"])
428
+ # Pass correct token for api_key authentication
429
+ if config["auth"] == "api_key":
430
+ results = await client.run_security_tests(
431
+ config["url"], config["auth"], token="admin-secret-key"
432
+ )
433
+ else:
434
+ results = await client.run_security_tests(
435
+ config["url"], config["auth"]
436
+ )
382
437
  # Print summary for this server
383
438
  passed = sum(1 for r in results if r.success)
384
439
  total = len(results)
@@ -521,13 +576,13 @@ class SecurityTestRunner:
521
576
  print("\n🔍 STEP 1: Complete Port Availability Check")
522
577
  all_ports = self.get_all_ports()
523
578
  print(f"📋 Required ports: {all_ports}")
524
-
579
+
525
580
  # Check if ALL ports are available
526
581
  ports_available, occupied_ports = self.check_ports_available(all_ports)
527
582
  if not ports_available:
528
583
  print(f"❌ CRITICAL: Ports are occupied: {occupied_ports}")
529
584
  print("🧹 Attempting to free occupied ports...")
530
-
585
+
531
586
  if not self.ensure_ports_free(all_ports):
532
587
  print("❌ FAILED: Could not free occupied ports. Aborting tests.")
533
588
  print("💡 Manual cleanup required:")
@@ -584,7 +639,7 @@ def main():
584
639
  "--no-cleanup", action="store_true", help="Don't cleanup servers after tests"
585
640
  )
586
641
  parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
587
- args = parser.parse_args()
642
+ parser.parse_args()
588
643
 
589
644
  # Determine the correct configs directory
590
645
  current_dir = Path.cwd()
@@ -11,28 +11,26 @@ Author: Vasiliy Zdanovskiy
11
11
  email: vasilyvz@gmail.com
12
12
  """
13
13
  import asyncio
14
- import json
15
14
  import os
16
15
  import ssl
17
16
  import sys
18
17
  import time
19
18
  from pathlib import Path
20
- from typing import Dict, List, Optional, Any
19
+ from typing import Dict, List, Optional
21
20
  from dataclasses import dataclass
22
- import aiohttp
23
21
  from aiohttp import ClientSession, ClientTimeout, TCPConnector
24
22
 
25
23
  # Add project root to path for imports
26
- project_root = Path(__file__).parent.parent.parent
27
24
  current_dir = Path(__file__).parent
28
25
  parent_dir = current_dir.parent
29
- sys.path.insert(0, str(project_root))
26
+ # Only add paths that are likely to exist and be useful
27
+ if parent_dir.exists():
28
+ sys.path.insert(0, str(parent_dir))
30
29
  sys.path.insert(0, str(current_dir))
31
- sys.path.insert(0, str(parent_dir))
32
30
 
33
31
  # Import mcp_security_framework components
34
32
  try:
35
- from mcp_security_framework import SSLManager, CertificateManager
33
+ from mcp_security_framework import SSLManager
36
34
  from mcp_security_framework.schemas.config import SSLConfig
37
35
 
38
36
  _MCP_SECURITY_AVAILABLE = True
@@ -43,9 +41,6 @@ except ImportError:
43
41
 
44
42
  # Import cryptography components
45
43
  try:
46
- from cryptography import x509
47
- from cryptography.hazmat.primitives import serialization
48
-
49
44
  _CRYPTOGRAPHY_AVAILABLE = True
50
45
  print("✅ cryptography available")
51
46
  except ImportError:
@@ -111,19 +106,19 @@ class SecurityTestClient:
111
106
  "proxy": "proxy-token-123",
112
107
  "invalid": "invalid-token-999",
113
108
  }
114
- # Test certificates
109
+ # Test certificates - use relative paths
115
110
  self.test_certificates = {
116
111
  "admin": {
117
- "cert": "mcp_proxy_adapter/examples/certs/admin_cert.pem",
118
- "key": "mcp_proxy_adapter/examples/certs/admin_key.pem",
112
+ "cert": "certs/admin_cert.pem",
113
+ "key": "certs/admin_key.pem",
119
114
  },
120
115
  "user": {
121
- "cert": "mcp_proxy_adapter/examples/certs/user_cert.pem",
122
- "key": "mcp_proxy_adapter/examples/certs/user_key.pem",
116
+ "cert": "certs/user_cert.pem",
117
+ "key": "certs/user_key.pem",
123
118
  },
124
119
  "readonly": {
125
- "cert": "mcp_proxy_adapter/examples/certs/readonly_cert.pem",
126
- "key": "mcp_proxy_adapter/examples/certs/readonly_key.pem",
120
+ "cert": "certs/readonly_cert.pem",
121
+ "key": "certs/readonly_key.pem",
127
122
  },
128
123
  }
129
124
 
@@ -227,6 +222,7 @@ class SecurityTestClient:
227
222
  headers = {"Content-Type": "application/json"}
228
223
  if auth_type == "api_key":
229
224
  token = kwargs.get("token", "test-token-123")
225
+ print(f"🔍 DEBUG: Using token: {token}")
230
226
  # Provide both common header styles to maximize compatibility
231
227
  headers["X-API-Key"] = token
232
228
  headers["Authorization"] = f"Bearer {token}"
@@ -430,9 +426,7 @@ class SecurityTestClient:
430
426
  try:
431
427
  if auth_type == "certificate":
432
428
  # For mTLS, test with invalid/expired certificate or no certificate
433
- import aiohttp
434
429
  from aiohttp import ClientTimeout, TCPConnector
435
- import ssl
436
430
 
437
431
  # Create SSL context with wrong certificate (should be rejected)
438
432
  ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
@@ -450,6 +444,8 @@ class SecurityTestClient:
450
444
  timeout = ClientTimeout(total=10) # Shorter timeout
451
445
 
452
446
  try:
447
+ import aiohttp
448
+
453
449
  async with aiohttp.ClientSession(
454
450
  timeout=timeout, connector=connector
455
451
  ) as temp_session:
@@ -474,11 +470,7 @@ class SecurityTestClient:
474
470
  error_message=f"SECURITY ISSUE: mTLS server accepted connection without client certificate (status: {response.status})",
475
471
  duration=duration,
476
472
  )
477
- except (
478
- aiohttp.ClientError,
479
- aiohttp.ServerDisconnectedError,
480
- asyncio.TimeoutError,
481
- ) as e:
473
+ except (Exception,) as e:
482
474
  # This is expected - server should reject connections without proper certificate
483
475
  duration = time.time() - start_time
484
476
  return TestResult(
@@ -797,7 +789,7 @@ class SecurityTestClient:
797
789
  print(f"Total Tests: {total_tests}")
798
790
  print(f"Passed: {passed_tests} ✅")
799
791
  print(f"Failed: {failed_tests} ❌")
800
- print(f"Success Rate: {(passed_tests/total_tests*100):.1f}%")
792
+ print(f"Success Rate: {(passed_tests / total_tests * 100):.1f}%")
801
793
  if failed_tests > 0:
802
794
  print("\n❌ Failed Tests:")
803
795
  for result in self.test_results:
@@ -25,7 +25,7 @@ import sys
25
25
  import argparse
26
26
  import json
27
27
  from pathlib import Path
28
- from typing import Dict, List, Any, Optional, Tuple
28
+ from typing import Dict, List, Any, Tuple
29
29
 
30
30
  # Import mcp_security_framework
31
31
  try:
@@ -191,8 +191,10 @@ def _get_package_paths() -> tuple[Path, Path]:
191
191
  # We need to go up to the package root: .venv/lib/python3.x/site-packages/mcp_proxy_adapter/
192
192
  pkg_root = Path(__file__).resolve().parents[1]
193
193
  examples_path = pkg_root / "examples"
194
- utils_path = pkg_root / "examples" / "scripts" # utils scripts are in examples/scripts in the package
195
-
194
+ utils_path = (
195
+ pkg_root / "examples" / "scripts"
196
+ ) # utils scripts are in examples/scripts in the package
197
+
196
198
  return examples_path, utils_path
197
199
 
198
200
 
@@ -440,12 +442,12 @@ async def register_server(request: Request):
440
442
  try:
441
443
  data = await request.json()
442
444
  print(f"✅ Received registration request: {data}")
443
-
445
+
444
446
  # Check if client certificate is present
445
447
  client_cert = request.client
446
448
  if client_cert:
447
449
  print(f"✅ Client certificate verified: {client_cert}")
448
-
450
+
449
451
  return JSONResponse(
450
452
  status_code=200,
451
453
  content={
@@ -489,14 +491,14 @@ async def main():
489
491
  print(" POST /register - Register server")
490
492
  print(" GET /health - Health check")
491
493
  print("⚡ Press Ctrl+C to stop\\n")
492
-
494
+
493
495
  # Configure Hypercorn
494
496
  config = hypercorn.config.Config()
495
497
  config.bind = ["127.0.0.1:20005"]
496
498
  config.certfile = "certs/localhost_server.crt"
497
499
  config.keyfile = "keys/server_key.pem"
498
500
  config.loglevel = "info"
499
-
501
+
500
502
  # Run server with mTLS using Hypercorn
501
503
  await hypercorn.asyncio.serve(app, config)
502
504
 
@@ -532,7 +534,7 @@ def test_proxy_registration():
532
534
  """Test proxy registration with SSL configuration."""
533
535
  print("🧪 Testing Proxy Registration SSL Configuration Fix")
534
536
  print("=" * 60)
535
-
537
+
536
538
  # Kill any existing process on port 20005
537
539
  print("🧹 Killing any existing process on port 20005...")
538
540
  try:
@@ -540,21 +542,27 @@ def test_proxy_registration():
540
542
  except FileNotFoundError:
541
543
  # fuser not available, try with lsof
542
544
  try:
543
- subprocess.run(["lsof", "-ti:20005", "|", "xargs", "kill", "-9"], shell=True, check=False, capture_output=True)
545
+ # Get PIDs using lsof
546
+ result = subprocess.run(["lsof", "-ti:20005"], capture_output=True, text=True, check=False)
547
+ if result.returncode == 0 and result.stdout.strip():
548
+ pids = result.stdout.strip().split('\n')
549
+ for pid in pids:
550
+ if pid.strip():
551
+ subprocess.run(["kill", "-9", pid.strip()], check=False, capture_output=True)
544
552
  except:
545
553
  pass
546
-
554
+
547
555
  # Start proxy server
548
556
  print("🚀 Starting test proxy server...")
549
557
  proxy_process = subprocess.Popen([
550
558
  sys.executable, "test_proxy_server.py"
551
559
  ], cwd=Path(__file__).parent)
552
-
560
+
553
561
  try:
554
562
  # Wait for server to start
555
563
  print("⏳ Waiting for proxy server to start...")
556
564
  time.sleep(5)
557
-
565
+
558
566
  # Test proxy server health
559
567
  print("🔍 Testing proxy server health...")
560
568
  try:
@@ -571,19 +579,19 @@ def test_proxy_registration():
571
579
  except Exception as e:
572
580
  print(f"❌ Failed to connect to proxy server: {e}")
573
581
  return False
574
-
582
+
575
583
  # Test mTLS server with registration
576
584
  print("🚀 Starting mTLS server with proxy registration...")
577
585
  server_process = subprocess.Popen([
578
586
  sys.executable, "-m", "mcp_proxy_adapter",
579
587
  "--config", "configs/test_proxy_registration.json"
580
588
  ], cwd=Path(__file__).parent)
581
-
589
+
582
590
  try:
583
591
  # Wait for server to start and attempt registration
584
592
  print("⏳ Waiting for server to start and register...")
585
593
  time.sleep(10)
586
-
594
+
587
595
  # Check if server is running
588
596
  if server_process.poll() is None:
589
597
  print("✅ mTLS server started successfully")
@@ -592,13 +600,13 @@ def test_proxy_registration():
592
600
  else:
593
601
  print("❌ mTLS server failed to start")
594
602
  return False
595
-
603
+
596
604
  finally:
597
605
  # Clean up server process
598
606
  if server_process.poll() is None:
599
607
  server_process.terminate()
600
608
  server_process.wait()
601
-
609
+
602
610
  finally:
603
611
  # Clean up proxy process
604
612
  if proxy_process.poll() is None:
@@ -609,7 +617,7 @@ def test_proxy_registration():
609
617
  def main():
610
618
  """Run the test."""
611
619
  success = test_proxy_registration()
612
-
620
+
613
621
  if success:
614
622
  print("\\n🎉 All tests passed! Proxy registration SSL fix is working correctly.")
615
623
  return 0
@@ -647,30 +655,23 @@ def generate_enhanced_configurations(output_dir: Path) -> None:
647
655
  "debug": False,
648
656
  "log_level": "INFO",
649
657
  "workers": 1,
650
- "reload": False
651
- },
652
- "ssl": {
653
- "enabled": False
658
+ "reload": False,
654
659
  },
660
+ "ssl": {"enabled": False},
655
661
  "security": {
656
662
  "enabled": True,
657
663
  "auth": {
658
664
  "enabled": True,
659
- "methods": [
660
- "api_key"
661
- ],
665
+ "methods": ["api_key"],
662
666
  "api_keys": {
663
667
  "admin-token-123": "admin",
664
668
  "user-token-456": "user",
665
669
  "readonly-token-789": "readonly",
666
670
  "guest-token-abc": "guest",
667
- "proxy-token-def": "proxy"
668
- }
671
+ "proxy-token-def": "proxy",
672
+ },
669
673
  },
670
- "permissions": {
671
- "enabled": True,
672
- "roles_file": "configs/roles.json"
673
- }
674
+ "permissions": {"enabled": True, "roles_file": "configs/roles.json"},
674
675
  },
675
676
  "registration": {
676
677
  "enabled": True,
@@ -681,21 +682,13 @@ def generate_enhanced_configurations(output_dir: Path) -> None:
681
682
  "token_auth",
682
683
  "roles",
683
684
  "registration",
684
- "heartbeat"
685
+ "heartbeat",
685
686
  ],
686
687
  "retry_count": 3,
687
688
  "retry_delay": 5,
688
- "heartbeat": {
689
- "enabled": True,
690
- "interval": 30
691
- }
689
+ "heartbeat": {"enabled": True, "interval": 30},
692
690
  },
693
- "protocols": {
694
- "enabled": True,
695
- "allowed_protocols": [
696
- "http"
697
- ]
698
- }
691
+ "protocols": {"enabled": True, "allowed_protocols": ["http"]},
699
692
  }
700
693
  }
701
694
 
@@ -886,30 +879,27 @@ def setup_test_environment(output_dir: Path) -> None:
886
879
  test_files = [
887
880
  "create_test_configs.py",
888
881
  "run_security_tests.py",
889
- "run_proxy_server.py"
882
+ "run_proxy_server.py",
890
883
  ]
891
884
  for test_file in test_files:
892
885
  test_file_src = examples_src_root / test_file
893
886
  if test_file_src.exists():
894
887
  shutil.copy2(test_file_src, output_dir)
895
888
  print(f"✅ Copied {test_file}")
896
-
889
+
897
890
  # Create comprehensive_config.json if it doesn't exist
898
891
  comprehensive_config_dst = output_dir / "comprehensive_config.json"
899
892
  if not comprehensive_config_dst.exists():
900
893
  # Create a basic comprehensive config
901
894
  comprehensive_config = {
902
895
  "uuid": "79db1fa0-ff4e-4695-8c94-1d5ac470b613",
903
- "server": {
904
- "host": "127.0.0.1",
905
- "port": 20001
906
- },
896
+ "server": {"host": "127.0.0.1", "port": 20001},
907
897
  "ssl": {
908
898
  "enabled": False,
909
899
  "cert_file": "certs/localhost_server.crt",
910
900
  "key_file": "keys/localhost_server.key",
911
901
  "ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
912
- "verify_client": False
902
+ "verify_client": False,
913
903
  },
914
904
  "security": {
915
905
  "enabled": True,
@@ -919,22 +909,19 @@ def setup_test_environment(output_dir: Path) -> None:
919
909
  "api_keys": {
920
910
  "admin-token-123": "admin",
921
911
  "user-token-456": "user",
922
- "readonly-token-789": "readonly"
923
- }
912
+ "readonly-token-789": "readonly",
913
+ },
924
914
  },
925
- "permissions": {
926
- "enabled": True,
927
- "roles_file": "roles.json"
928
- }
915
+ "permissions": {"enabled": True, "roles_file": "roles.json"},
929
916
  },
930
917
  "protocols": {
931
918
  "enabled": True,
932
919
  "default_protocol": "http",
933
- "allowed_protocols": ["http"]
934
- }
920
+ "allowed_protocols": ["http"],
921
+ },
935
922
  }
936
-
937
- with open(comprehensive_config_dst, 'w', encoding='utf-8') as f:
923
+
924
+ with open(comprehensive_config_dst, "w", encoding="utf-8") as f:
938
925
  json.dump(comprehensive_config, f, indent=2)
939
926
  print("✅ Created comprehensive_config.json")
940
927
  else:
@@ -951,21 +938,21 @@ def setup_test_environment(output_dir: Path) -> None:
951
938
  "roles": {
952
939
  "admin": {
953
940
  "permissions": ["*"],
954
- "description": "Full access to all commands"
941
+ "description": "Full access to all commands",
955
942
  },
956
943
  "user": {
957
944
  "permissions": ["echo", "health", "help"],
958
- "description": "Basic user permissions"
945
+ "description": "Basic user permissions",
959
946
  },
960
947
  "readonly": {
961
948
  "permissions": ["health", "help"],
962
- "description": "Read-only access"
963
- }
949
+ "description": "Read-only access",
950
+ },
964
951
  }
965
952
  }
966
-
953
+
967
954
  roles_dst = output_dir / "roles.json"
968
- with open(roles_dst, 'w', encoding='utf-8') as f:
955
+ with open(roles_dst, "w", encoding="utf-8") as f:
969
956
  json.dump(roles_config, f, indent=2)
970
957
  print("✅ Created roles.json in root directory")
971
958
 
@@ -1102,10 +1089,10 @@ def generate_certificates_with_framework(output_dir: Path) -> bool:
1102
1089
  roles=roles,
1103
1090
  permissions=permissions,
1104
1091
  ca_cert_path=cert_pair.certificate_path,
1105
- ca_key_path=ca_key_path,
1092
+ ca_key_path=cert_pair.private_key_path,
1106
1093
  )
1107
- cert_pair = cert_manager.create_client_certificate(client_config)
1108
- if not cert_pair or not cert_pair.certificate_path:
1094
+ client_cert_pair = cert_manager.create_client_certificate(client_config)
1095
+ if not client_cert_pair or not client_cert_pair.certificate_path:
1109
1096
  print(
1110
1097
  (
1111
1098
  "❌ Failed to create client certificate {}: "
@@ -1134,33 +1121,36 @@ def run_full_test_suite(target_root: Path) -> bool:
1134
1121
  print("\n" + "=" * 60)
1135
1122
  print("🚀 AUTOMATICALLY RUNNING FULL TEST SUITE")
1136
1123
  print("=" * 60)
1137
-
1124
+
1138
1125
  try:
1139
1126
  # Change to target directory
1140
1127
  original_cwd = Path.cwd()
1141
1128
  os.chdir(target_root)
1142
-
1129
+
1143
1130
  # Run the full test suite
1144
- result = subprocess.run([
1145
- sys.executable, "run_full_test_suite.py"
1146
- ], capture_output=True, text=True, timeout=300) # 5 minute timeout
1147
-
1131
+ result = subprocess.run(
1132
+ [sys.executable, "run_full_test_suite.py"],
1133
+ capture_output=True,
1134
+ text=True,
1135
+ timeout=300,
1136
+ ) # 5 minute timeout
1137
+
1148
1138
  # Print output
1149
1139
  if result.stdout:
1150
1140
  print("📋 Test Suite Output:")
1151
1141
  print(result.stdout)
1152
-
1142
+
1153
1143
  if result.stderr:
1154
1144
  print("⚠️ Test Suite Warnings/Errors:")
1155
1145
  print(result.stderr)
1156
-
1146
+
1157
1147
  if result.returncode == 0:
1158
1148
  print("🎉 FULL TEST SUITE COMPLETED SUCCESSFULLY!")
1159
1149
  return True
1160
1150
  else:
1161
1151
  print(f"❌ FULL TEST SUITE FAILED (exit code: {result.returncode})")
1162
1152
  return False
1163
-
1153
+
1164
1154
  except subprocess.TimeoutExpired:
1165
1155
  print("⏰ Test suite timed out after 5 minutes")
1166
1156
  return False
@@ -1175,21 +1165,21 @@ def run_full_test_suite(target_root: Path) -> bool:
1175
1165
  def validate_output_directory(output_dir: Path) -> bool:
1176
1166
  """
1177
1167
  Validate output directory for test environment setup.
1178
-
1168
+
1179
1169
  Args:
1180
1170
  output_dir: Path to the target directory
1181
-
1171
+
1182
1172
  Returns:
1183
1173
  True if directory is valid for setup, False otherwise
1184
1174
  """
1185
1175
  output_dir = output_dir.resolve()
1186
-
1176
+
1187
1177
  # Check if directory exists
1188
1178
  if output_dir.exists():
1189
1179
  if not output_dir.is_dir():
1190
1180
  print(f"❌ Path exists but is not a directory: {output_dir}")
1191
1181
  return False
1192
-
1182
+
1193
1183
  # Check if directory is empty
1194
1184
  try:
1195
1185
  contents = list(output_dir.iterdir())
@@ -1216,7 +1206,7 @@ def validate_output_directory(output_dir: Path) -> bool:
1216
1206
  except Exception as e:
1217
1207
  print(f"❌ Failed to create directory {output_dir}: {e}")
1218
1208
  return False
1219
-
1209
+
1220
1210
  return True
1221
1211
 
1222
1212
 
@@ -1226,7 +1216,7 @@ def check_ports_available() -> bool:
1226
1216
  Returns True if all ports are free, False otherwise.
1227
1217
  """
1228
1218
  import socket
1229
-
1219
+
1230
1220
  # Ports used by the test suite - UPDATED with dedicated ports
1231
1221
  test_ports = [
1232
1222
  20010, # proxy_port
@@ -1238,17 +1228,17 @@ def check_ports_available() -> bool:
1238
1228
  20025, # mtls_simple
1239
1229
  20026, # mtls_with_roles
1240
1230
  20005, # test_proxy_server
1241
- 3006, # proxy registration
1231
+ 3006, # proxy registration
1242
1232
  ]
1243
-
1233
+
1244
1234
  occupied_ports = []
1245
-
1235
+
1246
1236
  print("🔍 Checking port availability...")
1247
1237
  for port in test_ports:
1248
1238
  try:
1249
1239
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
1250
1240
  sock.settimeout(1)
1251
- result = sock.connect_ex(('127.0.0.1', port))
1241
+ result = sock.connect_ex(("127.0.0.1", port))
1252
1242
  if result == 0:
1253
1243
  occupied_ports.append(port)
1254
1244
  print(f" ❌ Port {port} is occupied")
@@ -1257,9 +1247,11 @@ def check_ports_available() -> bool:
1257
1247
  except Exception as e:
1258
1248
  print(f" ⚠️ Could not check port {port}: {e}")
1259
1249
  occupied_ports.append(port)
1260
-
1250
+
1261
1251
  if occupied_ports:
1262
- print(f"\n❌ CRITICAL: {len(occupied_ports)} ports are occupied: {occupied_ports}")
1252
+ print(
1253
+ f"\n❌ CRITICAL: {len(occupied_ports)} ports are occupied: {occupied_ports}"
1254
+ )
1263
1255
  print("💡 Please free these ports before running the test suite:")
1264
1256
  for port in occupied_ports:
1265
1257
  print(f" - Port {port}: kill processes using this port")
@@ -1267,7 +1259,7 @@ def check_ports_available() -> bool:
1267
1259
  for port in occupied_ports:
1268
1260
  print(f" fuser -k {port}/tcp")
1269
1261
  return False
1270
-
1262
+
1271
1263
  print(f"✅ All {len(test_ports)} required ports are available")
1272
1264
  return True
1273
1265
 
@@ -1294,32 +1286,33 @@ def main() -> int:
1294
1286
  "--skip-tests", action="store_true", help="Skip running the full test suite"
1295
1287
  )
1296
1288
  args = parser.parse_args()
1297
-
1289
+
1298
1290
  # FIRST: Check port availability - if this fails, don't proceed
1299
1291
  print("🔍 STEP 1: Port Availability Check")
1300
1292
  if not check_ports_available():
1301
1293
  print("\n❌ FAILED: Required ports are occupied. Aborting setup.")
1302
1294
  print("💡 Please free the occupied ports and try again.")
1303
1295
  return 1
1304
-
1296
+
1305
1297
  try:
1306
1298
  # Determine target directory
1307
1299
  if args.output_dir is None:
1308
1300
  # Create auto-generated directory in /tmp
1309
1301
  import tempfile
1310
1302
  import time
1303
+
1311
1304
  timestamp = int(time.time())
1312
1305
  target_root = Path(tempfile.gettempdir()) / f"mcp_test_env_{timestamp}"
1313
1306
  print(f"🔧 Auto-generating test environment directory: {target_root}")
1314
1307
  else:
1315
1308
  target_root = Path(args.output_dir)
1316
-
1309
+
1317
1310
  # Validate output directory
1318
1311
  print(f"🔍 Validating output directory: {target_root}")
1319
1312
  if not validate_output_directory(target_root):
1320
1313
  print("\n❌ Directory validation failed. Exiting.")
1321
1314
  return 1
1322
-
1315
+
1323
1316
  print(f"✅ Directory validation passed: {target_root}")
1324
1317
  setup_test_environment(target_root)
1325
1318
 
@@ -1333,7 +1326,7 @@ def main() -> int:
1333
1326
  "⚠️ Skipping certificate generation (mcp_security_framework "
1334
1327
  "not available)"
1335
1328
  )
1336
-
1329
+
1337
1330
  # Run full test suite if not skipped
1338
1331
  if not args.skip_tests:
1339
1332
  test_success = run_full_test_suite(target_root)
@@ -1342,7 +1335,7 @@ def main() -> int:
1342
1335
  return 1
1343
1336
  else:
1344
1337
  print("⚠️ Skipping test suite execution (--skip-tests specified)")
1345
-
1338
+
1346
1339
  except Exception as e:
1347
1340
  print(
1348
1341
  "❌ Error setting up test environment: {}".format(e),
@@ -1357,7 +1350,7 @@ def main() -> int:
1357
1350
  print("\n" + "=" * 60)
1358
1351
  print("✅ ENHANCED TEST ENVIRONMENT SETUP COMPLETED SUCCESSFULLY")
1359
1352
  print("=" * 60)
1360
-
1353
+
1361
1354
  if not args.skip_tests:
1362
1355
  print("\n🎉 ALL TESTS PASSED - Environment is ready for use!")
1363
1356
  else:
@@ -1376,7 +1369,7 @@ def main() -> int:
1376
1369
  print(" python -m mcp_proxy_adapter.examples.run_security_tests")
1377
1370
  print("\n7. Generate additional certificates (if needed):")
1378
1371
  print(" python scripts/create_certificates_simple.py")
1379
-
1372
+
1380
1373
  print("=" * 60)
1381
1374
  return 0
1382
1375
 
@@ -2,4 +2,4 @@
2
2
  Version information for MCP Proxy Adapter.
3
3
  """
4
4
 
5
- __version__ = "6.4.36"
5
+ __version__ = "6.4.38"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.4.36
3
+ Version: 6.4.38
4
4
  Summary: Powerful JSON-RPC microservices framework with built-in security, authentication, and proxy registration
5
5
  Home-page: https://github.com/maverikod/mcp-proxy-adapter
6
6
  Author: Vasiliy Zdanovskiy
@@ -4,7 +4,7 @@ mcp_proxy_adapter/config.py,sha256=-7iVS0mUWWKNeao7nqTAFlUD6FcMwRlDkchN7OwYsr0,2
4
4
  mcp_proxy_adapter/custom_openapi.py,sha256=yLle4CntYK9wpivgn9NflZyJhy-YNrmWjJzt0ai5nP0,14672
5
5
  mcp_proxy_adapter/main.py,sha256=idp3KUR7CT7kTXLVPvvclJlNnt8d_HYl8_jY98uknmo,4677
6
6
  mcp_proxy_adapter/openapi.py,sha256=2UZOI09ZDRJuBYBjKbMyb2U4uASszoCMD5o_4ktRpvg,13480
7
- mcp_proxy_adapter/version.py,sha256=0-LJHNTlgIHjMygnw5NBVzN35NC108daY2MZA3wdTjA,75
7
+ mcp_proxy_adapter/version.py,sha256=DxzXsdAR_ZarVXkLvOK5cPqZ5iDLG9jbqC9t2ps2FL8,75
8
8
  mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  mcp_proxy_adapter/api/app.py,sha256=UQ7_m-LbUzKuuPJPxS_69ahANUQ5rnPwoddQ2MMXNkg,33941
10
10
  mcp_proxy_adapter/api/handlers.py,sha256=iyFGoEuUS1wxbV1ELA0zmaxIyQR7j4zw-4MrD-uIO6E,8294
@@ -84,7 +84,7 @@ mcp_proxy_adapter/core/unified_config_adapter.py,sha256=zBGYdLDZ3G8f3Y9tmtm0Ne0U
84
84
  mcp_proxy_adapter/core/utils.py,sha256=wBdDYBDWQ6zbwrnl9tykHjo0FjJVsLT_x8Bjk1lZX60,3270
85
85
  mcp_proxy_adapter/examples/__init__.py,sha256=k1F-EotAFbJ3JvK_rNgiH4bUztmxIWtYn0AfbAZ1ZGs,450
86
86
  mcp_proxy_adapter/examples/create_certificates_simple.py,sha256=xoa4VtKzb9y7Mn8VqcK-uH2q7Bf89vrWG6G3LQmhJng,27086
87
- mcp_proxy_adapter/examples/create_test_configs.py,sha256=GRCmGM9xXTEz3iB7cq3yH-tJCQHuVxrqu0uHuuSSark,12140
87
+ mcp_proxy_adapter/examples/create_test_configs.py,sha256=k7-GycHP96CZFry7EXwkQCViPlr_7jq-f18I9kVWN6c,11253
88
88
  mcp_proxy_adapter/examples/debug_request_state.py,sha256=Z3Gy2-fWtu7KIV9OkzGDLVz7TpL_h9V_99ica40uQBU,4489
89
89
  mcp_proxy_adapter/examples/debug_role_chain.py,sha256=GLVXC2fJUwP8UJnXHchd1t-H53cjWLJI3RqTPrKmaak,8750
90
90
  mcp_proxy_adapter/examples/demo_client.py,sha256=en2Rtb70B1sQmhL-vdQ4PDpKNNl_mfll2YCFT_jFCAg,10191
@@ -94,12 +94,12 @@ mcp_proxy_adapter/examples/generate_certificates_and_tokens.py,sha256=hUCoJH3fy5
94
94
  mcp_proxy_adapter/examples/generate_test_configs.py,sha256=FWg_QFJAWinI1lw05RccX4_VbhsCBEKPpZA6I9v6KAs,14379
95
95
  mcp_proxy_adapter/examples/proxy_registration_example.py,sha256=vemRhftnjbiOBCJkmtDGqlWQ8syTG0a8755GCOnaQsg,12503
96
96
  mcp_proxy_adapter/examples/run_example.py,sha256=yp-a6HIrSk3ddQmbn0KkuKwErId0aNfj028TE6U-zmY,2626
97
- mcp_proxy_adapter/examples/run_full_test_suite.py,sha256=HuiNTOey2zwk4KSSgh7l3JZlymMHv2yPTCvX0XNAxCY,19827
97
+ mcp_proxy_adapter/examples/run_full_test_suite.py,sha256=8oTBT1HA8gGF_W-X5NRV9_k4IfjcFvLC4XyziK4b1nE,20147
98
98
  mcp_proxy_adapter/examples/run_proxy_server.py,sha256=SBLSSY2F_VEBQD3MsCE_Pa9xFE6Sszr3vHdE9QOEN4Y,5242
99
- mcp_proxy_adapter/examples/run_security_tests.py,sha256=ePekKblBbrfz5-Xe5hgs5OLL4rSd9QiIUlnm9dER8Bo,24082
99
+ mcp_proxy_adapter/examples/run_security_tests.py,sha256=3mgp6fbPknI2fljpuedvtwoY1DzT_-UlOR45fHrkO0A,26215
100
100
  mcp_proxy_adapter/examples/run_security_tests_fixed.py,sha256=2BKMT0_-FhmcZA73hdQOt2XR7Cgb9Sq8qBI88BkwAAA,10934
101
- mcp_proxy_adapter/examples/security_test_client.py,sha256=K5gEVat1SJS2pBVxqLl5c9-uiiG12k8UT3ULQDXZ2Uc,35713
102
- mcp_proxy_adapter/examples/setup_test_environment.py,sha256=_ecdyHvWq8yx5WMm7JJ25Z9mHVgnvQ7xcSCdsXI2fv4,45563
101
+ mcp_proxy_adapter/examples/security_test_client.py,sha256=o4XhXCDZPaGVNjOSc0qm8onouj_ZenACz9aSEkvzbRc,35313
102
+ mcp_proxy_adapter/examples/setup_test_environment.py,sha256=MeNUMY4O0qppXiNRsbBfndBXGGYu_eCtMVXgfx9WvZg,45333
103
103
  mcp_proxy_adapter/examples/test_config.py,sha256=ekEoUZe9q484vU_0IxOVhQdNMVJXG3IpmQpP--VmuDI,6491
104
104
  mcp_proxy_adapter/examples/test_config_generator.py,sha256=PBXk1V_awJ-iBlbE66Pme5sQwu6CJDxkmqgm8uPtM58,4091
105
105
  mcp_proxy_adapter/examples/test_examples.py,sha256=CYlVatdHUVC_rwv4NsvxFG3GXiKIyxPDUH43BOJHjrU,12330
@@ -121,8 +121,8 @@ mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py,sha25
121
121
  mcp_proxy_adapter/examples/scripts/config_generator.py,sha256=SKFlRRCE_pEHGbfjDuzfKpvV2DMwG6lRfK90uJwRlJM,33410
122
122
  mcp_proxy_adapter/examples/scripts/create_certificates_simple.py,sha256=yCWdUIhMSDPwoPhuLR9rhPdf7jLN5hCjzNfYYgVyHnw,27769
123
123
  mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py,sha256=hUCoJH3fy5WeR_YMHj-_W0mR0ZKUWqewH4FVN3yWyrM,17972
124
- mcp_proxy_adapter-6.4.36.dist-info/METADATA,sha256=moNhmhs_hqlfAVMLMXLdmLYsD-gN_fCTskeX4V-g8rc,6087
125
- mcp_proxy_adapter-6.4.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
126
- mcp_proxy_adapter-6.4.36.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
127
- mcp_proxy_adapter-6.4.36.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
128
- mcp_proxy_adapter-6.4.36.dist-info/RECORD,,
124
+ mcp_proxy_adapter-6.4.38.dist-info/METADATA,sha256=zfWx-xa0ZWihObBrf_yN09yb8wqiQbOR-Eco7STdsA0,6087
125
+ mcp_proxy_adapter-6.4.38.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
126
+ mcp_proxy_adapter-6.4.38.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
127
+ mcp_proxy_adapter-6.4.38.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
128
+ mcp_proxy_adapter-6.4.38.dist-info/RECORD,,