mcp-proxy-adapter 6.4.32__py3-none-any.whl → 6.4.35__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.
@@ -74,16 +74,17 @@ class TestConfigGenerator:
74
74
 
75
75
  # 1. HTTP Simple
76
76
  self.create_config("http_simple", {
77
- "server.port": 8001,
77
+ "server.port": 20020, # Dedicated port for basic_http
78
78
  "ssl.enabled": False,
79
79
  "security.enabled": False,
80
80
  "proxy_registration.enabled": False,
81
- "protocols.allowed_protocols": ["http"]
81
+ "protocols.allowed_protocols": ["http"],
82
+ "protocols.default_protocol": "http"
82
83
  })
83
84
 
84
- # 2. HTTP with Auth
85
- self.create_config("http_auth", {
86
- "server.port": 8002,
85
+ # 2. HTTP with Auth (renamed to http_token for security tests)
86
+ self.create_config("http_token", {
87
+ "server.port": 20021, # Dedicated port for http_token
87
88
  "ssl.enabled": False,
88
89
  "security.enabled": True,
89
90
  "security.auth.enabled": True,
@@ -93,26 +94,28 @@ class TestConfigGenerator:
93
94
  "user": "user-secret-key"
94
95
  },
95
96
  "proxy_registration.enabled": False,
96
- "protocols.allowed_protocols": ["http"]
97
+ "protocols.allowed_protocols": ["http"],
98
+ "protocols.default_protocol": "http"
97
99
  })
98
100
 
99
101
  # 3. HTTPS Simple
100
102
  self.create_config("https_simple", {
101
- "server.port": 8003,
103
+ "server.port": 20022, # Dedicated port for https
102
104
  "ssl.enabled": True,
103
105
  "ssl.cert_file": "certs/localhost_server.crt",
104
- "ssl.key_file": "keys/localhost_server.key",
106
+ "ssl.key_file": "keys/server_key.pem",
105
107
  "security.enabled": False,
106
108
  "proxy_registration.enabled": False,
107
- "protocols.allowed_protocols": ["https"]
109
+ "protocols.allowed_protocols": ["https"],
110
+ "protocols.default_protocol": "https"
108
111
  })
109
112
 
110
- # 4. HTTPS with Auth
111
- self.create_config("https_auth", {
112
- "server.port": 8004,
113
+ # 4. HTTPS with Auth (renamed to https_token for security tests)
114
+ self.create_config("https_token", {
115
+ "server.port": 20023, # Dedicated port for https_token
113
116
  "ssl.enabled": True,
114
117
  "ssl.cert_file": "certs/localhost_server.crt",
115
- "ssl.key_file": "keys/localhost_server.key",
118
+ "ssl.key_file": "keys/server_key.pem",
116
119
  "security.enabled": True,
117
120
  "security.auth.enabled": True,
118
121
  "security.auth.methods": ["api_key"],
@@ -121,30 +124,32 @@ class TestConfigGenerator:
121
124
  "user": "user-secret-key"
122
125
  },
123
126
  "proxy_registration.enabled": False,
124
- "protocols.allowed_protocols": ["https"]
127
+ "protocols.allowed_protocols": ["https"],
128
+ "protocols.default_protocol": "https"
125
129
  })
126
130
 
127
131
  # 5. mTLS Simple
128
132
  self.create_config("mtls_simple", {
129
- "server.port": 8005,
133
+ "server.port": 20025, # Different port for mtls_simple
130
134
  "ssl.enabled": True,
131
135
  "ssl.cert_file": "certs/localhost_server.crt",
132
- "ssl.key_file": "keys/localhost_server.key",
136
+ "ssl.key_file": "keys/server_key.pem",
133
137
  "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
134
138
  "ssl.verify_client": True,
135
139
  "security.enabled": True,
136
140
  "security.auth.enabled": True,
137
141
  "security.auth.methods": ["certificate"],
138
142
  "proxy_registration.enabled": False,
139
- "protocols.allowed_protocols": ["https", "mtls"]
143
+ "protocols.allowed_protocols": ["https", "mtls"],
144
+ "protocols.default_protocol": "mtls"
140
145
  })
141
146
 
142
147
  # 6. mTLS with Roles
143
148
  self.create_config("mtls_with_roles", {
144
- "server.port": 8006,
149
+ "server.port": 20026, # Different port for mtls_with_roles
145
150
  "ssl.enabled": True,
146
151
  "ssl.cert_file": "certs/localhost_server.crt",
147
- "ssl.key_file": "keys/localhost_server.key",
152
+ "ssl.key_file": "keys/server_key.pem",
148
153
  "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
149
154
  "ssl.verify_client": True,
150
155
  "security.enabled": True,
@@ -153,15 +158,16 @@ class TestConfigGenerator:
153
158
  "security.permissions.enabled": True,
154
159
  "security.permissions.roles_file": "configs/roles.json",
155
160
  "proxy_registration.enabled": False,
156
- "protocols.allowed_protocols": ["https", "mtls"]
161
+ "protocols.allowed_protocols": ["https", "mtls"],
162
+ "protocols.default_protocol": "mtls"
157
163
  })
158
164
 
159
165
  # 6a. mTLS without Roles (for security tests)
160
166
  self.create_config("mtls_no_roles", {
161
- "server.port": 8009,
167
+ "server.port": 20024, # Dedicated port for mtls
162
168
  "ssl.enabled": True,
163
169
  "ssl.cert_file": "certs/localhost_server.crt",
164
- "ssl.key_file": "keys/localhost_server.key",
170
+ "ssl.key_file": "keys/server_key.pem",
165
171
  "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
166
172
  "ssl.verify_client": True,
167
173
  "security.enabled": True,
@@ -41,39 +41,39 @@ class SecurityTestRunner:
41
41
  self.server_logs = {}
42
42
  self.proxy_log = None
43
43
  self.test_results = {}
44
- # Base and proxy ports
45
- self.base_port = 20000
44
+ # Base and proxy ports - each test gets its own port range
45
+ self.base_port = 20020
46
46
  self.proxy_port = 20010
47
- # Server configurations with ports starting from 20000
47
+ # Server configurations with SEPARATE ports for each test
48
48
  self.configs = {
49
49
  "basic_http": {
50
50
  "config": "configs/http_simple.json",
51
- "port": self.base_port + 0,
52
- "url": f"http://localhost:{self.base_port + 0}",
51
+ "port": 20020, # Dedicated port
52
+ "url": f"http://127.0.0.1:20020",
53
53
  "auth": "none",
54
54
  },
55
55
  "http_token": {
56
56
  "config": "configs/http_token.json",
57
- "port": self.base_port + 1,
58
- "url": f"http://localhost:{self.base_port + 1}",
57
+ "port": 20021, # Dedicated port
58
+ "url": f"http://127.0.0.1:20021",
59
59
  "auth": "api_key",
60
60
  },
61
61
  "https": {
62
62
  "config": "configs/https_simple.json",
63
- "port": self.base_port + 2,
64
- "url": f"https://localhost:{self.base_port + 2}",
63
+ "port": 20022, # Dedicated port
64
+ "url": f"https://127.0.0.1:20022",
65
65
  "auth": "none",
66
66
  },
67
67
  "https_token": {
68
68
  "config": "configs/https_token.json",
69
- "port": self.base_port + 3,
70
- "url": f"https://localhost:{self.base_port + 3}",
69
+ "port": 20023, # Dedicated port
70
+ "url": f"https://127.0.0.1:20023",
71
71
  "auth": "api_key",
72
72
  },
73
73
  "mtls": {
74
74
  "config": "configs/mtls_no_roles.json",
75
- "port": self.base_port + 4,
76
- "url": f"https://localhost:{self.base_port + 4}",
75
+ "port": 20024, # Dedicated port
76
+ "url": f"https://127.0.0.1:20024",
77
77
  "auth": "certificate",
78
78
  },
79
79
  }
@@ -229,17 +229,13 @@ class SecurityTestRunner:
229
229
  """Start a server in background."""
230
230
  try:
231
231
  print(f"🚀 Starting {name} server on port {port}...")
232
- # Ensure the port is free just before starting
233
- self.ensure_ports_free([port])
232
+
233
+ # Check if port is still available (should be, since we checked at start)
234
234
  if self._port_in_use(port):
235
- print(f"⚠️ Port {port} still busy, waiting...")
236
- if not self.wait_for_port(port, timeout_sec=1.5):
237
- # After wait_for_port True means busy; we invert logic here
238
- pass
239
- # If still busy after attempts, abort this server start
240
- if self._port_in_use(port):
241
- print(f"❌ Port {port} is in use, cannot start {name}")
235
+ print(f" Port {port} is unexpectedly in use, cannot start {name}")
236
+ print("💡 This should not happen - ports were checked at startup")
242
237
  return None
238
+
243
239
  # Start server in background
244
240
  logs_dir = Path("logs")
245
241
  logs_dir.mkdir(exist_ok=True)
@@ -521,14 +517,34 @@ class SecurityTestRunner:
521
517
  signal.signal(signal.SIGINT, self.signal_handler)
522
518
  signal.signal(signal.SIGTERM, self.signal_handler)
523
519
  try:
520
+ # FIRST: Check ALL ports at the very beginning
521
+ print("\n🔍 STEP 1: Complete Port Availability Check")
522
+ all_ports = self.get_all_ports()
523
+ print(f"📋 Required ports: {all_ports}")
524
+
525
+ # Check if ALL ports are available
526
+ ports_available, occupied_ports = self.check_ports_available(all_ports)
527
+ if not ports_available:
528
+ print(f"❌ CRITICAL: Ports are occupied: {occupied_ports}")
529
+ print("🧹 Attempting to free occupied ports...")
530
+
531
+ if not self.ensure_ports_free(all_ports):
532
+ print("❌ FAILED: Could not free occupied ports. Aborting tests.")
533
+ print("💡 Manual cleanup required:")
534
+ for port in occupied_ports:
535
+ pids = self._pids_on_port(port)
536
+ if pids:
537
+ print(f" Port {port}: PIDs {pids}")
538
+ return False
539
+ else:
540
+ print("✅ Ports freed successfully")
541
+ else:
542
+ print("✅ All required ports are available")
543
+
524
544
  # Check prerequisites
525
545
  if not self.check_prerequisites():
526
546
  return False
527
547
 
528
- # Free ports before run
529
- print("\n🧹 Freeing ports before startup...")
530
- self.ensure_ports_free(self.get_all_ports())
531
-
532
548
  # Validate config file paths
533
549
  if not self.validate_config_files():
534
550
  return False
@@ -1220,6 +1220,58 @@ def validate_output_directory(output_dir: Path) -> bool:
1220
1220
  return True
1221
1221
 
1222
1222
 
1223
+ def check_ports_available() -> bool:
1224
+ """
1225
+ Check if all required test ports are available.
1226
+ Returns True if all ports are free, False otherwise.
1227
+ """
1228
+ import socket
1229
+
1230
+ # Ports used by the test suite - UPDATED with dedicated ports
1231
+ test_ports = [
1232
+ 20010, # proxy_port
1233
+ 20020, # basic_http (http_simple)
1234
+ 20021, # http_token
1235
+ 20022, # https_simple
1236
+ 20023, # https_token
1237
+ 20024, # mtls_no_roles
1238
+ 20025, # mtls_simple
1239
+ 20026, # mtls_with_roles
1240
+ 20005, # test_proxy_server
1241
+ 3006, # proxy registration
1242
+ ]
1243
+
1244
+ occupied_ports = []
1245
+
1246
+ print("🔍 Checking port availability...")
1247
+ for port in test_ports:
1248
+ try:
1249
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
1250
+ sock.settimeout(1)
1251
+ result = sock.connect_ex(('127.0.0.1', port))
1252
+ if result == 0:
1253
+ occupied_ports.append(port)
1254
+ print(f" ❌ Port {port} is occupied")
1255
+ else:
1256
+ print(f" ✅ Port {port} is available")
1257
+ except Exception as e:
1258
+ print(f" ⚠️ Could not check port {port}: {e}")
1259
+ occupied_ports.append(port)
1260
+
1261
+ if occupied_ports:
1262
+ print(f"\n❌ CRITICAL: {len(occupied_ports)} ports are occupied: {occupied_ports}")
1263
+ print("💡 Please free these ports before running the test suite:")
1264
+ for port in occupied_ports:
1265
+ print(f" - Port {port}: kill processes using this port")
1266
+ print("\n🔧 You can use these commands to free ports:")
1267
+ for port in occupied_ports:
1268
+ print(f" fuser -k {port}/tcp")
1269
+ return False
1270
+
1271
+ print(f"✅ All {len(test_ports)} required ports are available")
1272
+ return True
1273
+
1274
+
1223
1275
  def main() -> int:
1224
1276
  """Main function for command line execution."""
1225
1277
  parser = argparse.ArgumentParser(
@@ -1243,6 +1295,13 @@ def main() -> int:
1243
1295
  )
1244
1296
  args = parser.parse_args()
1245
1297
 
1298
+ # FIRST: Check port availability - if this fails, don't proceed
1299
+ print("🔍 STEP 1: Port Availability Check")
1300
+ if not check_ports_available():
1301
+ print("\n❌ FAILED: Required ports are occupied. Aborting setup.")
1302
+ print("💡 Please free the occupied ports and try again.")
1303
+ return 1
1304
+
1246
1305
  try:
1247
1306
  # Determine target directory
1248
1307
  if args.output_dir is None:
@@ -2,4 +2,4 @@
2
2
  Version information for MCP Proxy Adapter.
3
3
  """
4
4
 
5
- __version__ = "6.4.32"
5
+ __version__ = "6.4.35"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.4.32
3
+ Version: 6.4.35
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
@@ -35,7 +35,7 @@ Requires-Dist: docstring-parser<1.0.0,>=0.15
35
35
  Requires-Dist: typing-extensions<5.0.0,>=4.5.0
36
36
  Requires-Dist: jsonrpc>=1.2.0
37
37
  Requires-Dist: psutil>=5.9.0
38
- Requires-Dist: mcp_security_framework>=1.1.2
38
+ Requires-Dist: mcp_security_framework>=1.2.1
39
39
  Requires-Dist: packaging>=20.0
40
40
  Requires-Dist: aiohttp<4.0.0,>=3.8.0
41
41
  Requires-Dist: requests<3.0.0,>=2.28.0
@@ -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=G8Mkv1ON69SwlRpVikxEDT03qz6aIVBcCRYSeHSyiik,75
7
+ mcp_proxy_adapter/version.py,sha256=LFDbVSqlv2GQEWrW78mO5mZZoLvzaZLrXBXPzmBBZSs,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=lFO27tn0V7fUM7i3xa7liV3a-0nXvm12RXe9AiOLs5g,11545
87
+ mcp_proxy_adapter/examples/create_test_configs.py,sha256=GRCmGM9xXTEz3iB7cq3yH-tJCQHuVxrqu0uHuuSSark,12140
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
@@ -96,10 +96,10 @@ mcp_proxy_adapter/examples/proxy_registration_example.py,sha256=vemRhftnjbiOBCJk
96
96
  mcp_proxy_adapter/examples/run_example.py,sha256=yp-a6HIrSk3ddQmbn0KkuKwErId0aNfj028TE6U-zmY,2626
97
97
  mcp_proxy_adapter/examples/run_full_test_suite.py,sha256=HuiNTOey2zwk4KSSgh7l3JZlymMHv2yPTCvX0XNAxCY,19827
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=0vjaUdWC-rLyviQuNxM3PtfiU9TzSRuxGxWMehrFA_w,23311
99
+ mcp_proxy_adapter/examples/run_security_tests.py,sha256=ePekKblBbrfz5-Xe5hgs5OLL4rSd9QiIUlnm9dER8Bo,24082
100
100
  mcp_proxy_adapter/examples/run_security_tests_fixed.py,sha256=2BKMT0_-FhmcZA73hdQOt2XR7Cgb9Sq8qBI88BkwAAA,10934
101
101
  mcp_proxy_adapter/examples/security_test_client.py,sha256=K5gEVat1SJS2pBVxqLl5c9-uiiG12k8UT3ULQDXZ2Uc,35713
102
- mcp_proxy_adapter/examples/setup_test_environment.py,sha256=mzuBgvbkSOCYee5FVvILKmFeL1MU0LYelj6jZoXYsrA,43414
102
+ mcp_proxy_adapter/examples/setup_test_environment.py,sha256=QN_WYiZxQ_XqyX5fAw5-8iaLZSmGGwKon7_tp17ihX8,45654
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.32.dist-info/METADATA,sha256=l7MvcMPoyBl-F3SMW31RQYnRb0OlIYK0Ejig1AkavBo,6087
125
- mcp_proxy_adapter-6.4.32.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
126
- mcp_proxy_adapter-6.4.32.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
127
- mcp_proxy_adapter-6.4.32.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
128
- mcp_proxy_adapter-6.4.32.dist-info/RECORD,,
124
+ mcp_proxy_adapter-6.4.35.dist-info/METADATA,sha256=wkUzSe0jyswNRF0JTkDouQG4d091T7zgzvAm8v4MMvk,6087
125
+ mcp_proxy_adapter-6.4.35.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
126
+ mcp_proxy_adapter-6.4.35.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
127
+ mcp_proxy_adapter-6.4.35.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
128
+ mcp_proxy_adapter-6.4.35.dist-info/RECORD,,