mcp-proxy-adapter 6.7.2__py3-none-any.whl → 6.8.0__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.
@@ -156,6 +156,20 @@ def create_lifespan(config_path: Optional[str] = None):
156
156
  if not server_port:
157
157
  raise ValueError("server.port is required")
158
158
 
159
+ # Check port availability BEFORE starting registration manager
160
+ from mcp_proxy_adapter.core.utils import check_port_availability, handle_port_conflict
161
+
162
+ server_config = config.get("server", {})
163
+ server_host = server_config.get("host", "0.0.0.0")
164
+ server_port = server_config.get("port", 8000)
165
+
166
+ print(f"🔍 Checking external server port availability: {server_host}:{server_port}")
167
+ if not check_port_availability(server_host, server_port):
168
+ print(f"❌ CRITICAL: External server port {server_port} is occupied")
169
+ handle_port_conflict(server_host, server_port)
170
+ return # Exit the function immediately
171
+ print(f"✅ External server port {server_port} is available")
172
+
159
173
  # Determine registration URL using unified logic
160
174
  early_server_url = _determine_registration_url(config)
161
175
  try:
@@ -19,6 +19,11 @@ from mcp_proxy_adapter.config import config
19
19
  from mcp_proxy_adapter.commands.builtin_commands import (
20
20
  register_builtin_commands,
21
21
  )
22
+ from mcp_proxy_adapter.core.utils import (
23
+ check_port_availability,
24
+ handle_port_conflict,
25
+ find_port_for_internal_server,
26
+ )
22
27
 
23
28
  logger = get_logger("app_factory")
24
29
 
@@ -265,6 +270,7 @@ async def create_and_run_server(
265
270
  )
266
271
  print(f"🔌 Port: {server_port}")
267
272
 
273
+
268
274
  server_config = {
269
275
  "host": host,
270
276
  "port": server_port,
@@ -277,30 +283,6 @@ async def create_and_run_server(
277
283
  f"🔍 Debug: app_config keys: {list(app_config.keys()) if app_config else 'None'}"
278
284
  )
279
285
 
280
- # Check for SSL config in root section first (higher priority)
281
- if app_config and "ssl" in app_config:
282
- print(f"🔍 Debug: SSL config found in root: {app_config['ssl']}")
283
- print(
284
- f"🔍 Debug: SSL enabled: {app_config['ssl'].get('enabled', False)}"
285
- )
286
- if app_config["ssl"].get("enabled", False):
287
- ssl_config = app_config["ssl"]
288
- # Add SSL config directly to server_config for Hypercorn
289
- server_config["certfile"] = ssl_config.get("cert_file")
290
- server_config["keyfile"] = ssl_config.get("key_file")
291
- server_config["ca_certs"] = ssl_config.get(
292
- "ca_cert_file", ssl_config.get("ca_cert")
293
- )
294
- # Set verify_client based on verify_client setting
295
- verify_client = ssl_config.get("verify_client", False)
296
- server_config["verify_client"] = verify_client
297
- print(f"🔒 SSL enabled: {ssl_config.get('cert_file', 'N/A')}")
298
- print(
299
- f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}"
300
- )
301
- print(
302
- f"🔒 Server config SSL: certfile={server_config.get('certfile')}, keyfile={server_config.get('keyfile')}, ca_certs={server_config.get('ca_certs')}, verify_mode={server_config.get('verify_mode')}"
303
- )
304
286
 
305
287
  # Check for SSL config in security section (fallback)
306
288
  if app_config and "security" in app_config:
@@ -331,28 +313,6 @@ async def create_and_run_server(
331
313
  print(
332
314
  f"🔒 Server config SSL: certfile={server_config.get('certfile')}, keyfile={server_config.get('keyfile')}, ca_certs={server_config.get('ca_certs')}, verify_mode={server_config.get('verify_mode')}"
333
315
  )
334
- print(f"🔍 Debug: SSL config found in root: {app_config['ssl']}")
335
- print(
336
- f"🔍 Debug: SSL enabled: {app_config['ssl'].get('enabled', False)}"
337
- )
338
- if app_config["ssl"].get("enabled", False):
339
- ssl_config = app_config["ssl"]
340
- # Add SSL config directly to server_config for Hypercorn
341
- server_config["certfile"] = ssl_config.get("cert_file")
342
- server_config["keyfile"] = ssl_config.get("key_file")
343
- server_config["ca_certs"] = ssl_config.get(
344
- "ca_cert_file", ssl_config.get("ca_cert")
345
- )
346
- # Set verify_client based on verify_client setting
347
- verify_client = ssl_config.get("verify_client", False)
348
- server_config["verify_client"] = verify_client
349
- print(f"🔒 SSL enabled: {ssl_config.get('cert_file', 'N/A')}")
350
- print(
351
- f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}"
352
- )
353
- print(
354
- f"🔒 Server config SSL: certfile={server_config.get('certfile')}, keyfile={server_config.get('keyfile')}, ca_certs={server_config.get('ca_certs')}, verify_mode={server_config.get('verify_mode')}"
355
- )
356
316
 
357
317
  # 6. Start mTLS server if needed
358
318
  mtls_server = None
@@ -362,18 +322,21 @@ async def create_and_run_server(
362
322
  verify_client = ssl_config.get("verify_client", False)
363
323
 
364
324
  if verify_client:
365
- print("🔐 mTLS enabled - starting separate mTLS server...")
325
+ print("🔐 mTLS enabled - starting internal mTLS server...")
326
+ print(" External port: mTLS proxy (hypercorn)")
327
+ print(" Internal port: mTLS server (http.server)")
366
328
  from mcp_proxy_adapter.core.mtls_server import (
367
329
  start_mtls_server_thread,
368
330
  )
369
331
 
370
- # Start mTLS server in separate thread
332
+ # Start internal mTLS server in separate thread
333
+ # This server will find available port automatically if needed
371
334
  mtls_server = start_mtls_server_thread(app_config, main_app=app)
372
335
  if mtls_server:
373
- print(f"✅ mTLS server started on port {mtls_server.port}")
336
+ print(f"✅ Internal mTLS server started on port {mtls_server.port}")
374
337
  else:
375
338
  print(
376
- "⚠️ Failed to start mTLS server, continuing with regular HTTPS"
339
+ "⚠️ Failed to start internal mTLS server, continuing with regular HTTPS"
377
340
  )
378
341
  else:
379
342
  print("🔓 mTLS disabled - using regular HTTPS")
@@ -387,6 +350,8 @@ async def create_and_run_server(
387
350
  print(" Use Ctrl+C to stop the server")
388
351
  print("=" * 60)
389
352
 
353
+ # Port availability is already checked in api/app.py before registration manager starts
354
+
390
355
  # Use hypercorn directly
391
356
  import hypercorn.asyncio
392
357
  import hypercorn.config
@@ -428,13 +393,21 @@ async def create_and_run_server(
428
393
  if ssl_enabled:
429
394
  if verify_client:
430
395
  print(
431
- f"🔐 Starting HTTPS server with hypercorn (mTLS on separate port)..."
396
+ f"🔐 Starting external mTLS proxy with hypercorn (internal server on port {mtls_server.port if mtls_server else 'N/A'})..."
432
397
  )
433
398
  else:
434
399
  print(f"🔐 Starting HTTPS server with hypercorn...")
435
400
  else:
436
401
  print(f"🌐 Starting HTTP server with hypercorn...")
437
402
 
403
+ # Final port check before starting hypercorn
404
+ print(f"🔍 Final port check before starting hypercorn: {host}:{server_port}")
405
+ if not check_port_availability(host, server_port):
406
+ print(f"❌ CRITICAL: Port {server_port} is occupied during final check")
407
+ handle_port_conflict(host, server_port)
408
+ return # Exit immediately
409
+ print(f"✅ Final port check passed: {host}:{server_port}")
410
+
438
411
  # Run the server
439
412
  # hypercorn.asyncio.serve() should be run with asyncio.run(), not awaited
440
413
  # The function is designed to be the main entry point, not a coroutine to await
@@ -442,15 +415,28 @@ async def create_and_run_server(
442
415
 
443
416
  except KeyboardInterrupt:
444
417
  print("\n🛑 Server stopped by user")
445
- # Stop mTLS server if running
418
+ # Stop internal mTLS server if running
446
419
  if mtls_server:
447
- print("🛑 Stopping mTLS server...")
420
+ print("🛑 Stopping internal mTLS server...")
448
421
  mtls_server.stop()
422
+ except OSError as e:
423
+ if e.errno == 98: # Address already in use
424
+ print(f"\n❌ Port conflict detected: {e}")
425
+ handle_port_conflict(host, server_port)
426
+ else:
427
+ print(f"\n❌ Failed to start server: {e}")
428
+ # Stop mTLS server if running
429
+ if mtls_server:
430
+ print("🛑 Stopping mTLS server...")
431
+ mtls_server.stop()
432
+ import traceback
433
+ traceback.print_exc()
434
+ sys.exit(1)
449
435
  except Exception as e:
450
436
  print(f"\n❌ Failed to start server: {e}")
451
- # Stop mTLS server if running
437
+ # Stop internal mTLS server if running
452
438
  if mtls_server:
453
- print("🛑 Stopping mTLS server...")
439
+ print("🛑 Stopping internal mTLS server...")
454
440
  mtls_server.stop()
455
441
  import traceback
456
442
 
@@ -286,7 +286,11 @@ def start_mtls_server_thread(
286
286
  # Get server configuration
287
287
  server_config = config.get("server", {})
288
288
  host = server_config.get("host", "127.0.0.1")
289
- port = ssl_config.get("mtls_port", 8443) # Different port for mTLS
289
+ preferred_port = ssl_config.get("mtls_port", 8443) # Different port for mTLS
290
+
291
+ # For internal servers (mTLS), find available port if preferred is occupied
292
+ from mcp_proxy_adapter.core.utils import find_port_for_internal_server
293
+ port = find_port_for_internal_server(host, preferred_port)
290
294
 
291
295
  # Get certificate paths
292
296
  cert_file = ssl_config.get("cert_file", "certs/localhost_server.crt")
@@ -79,10 +79,12 @@ class SignalHandler:
79
79
  except Exception as e:
80
80
  logger.error(f"❌ Shutdown callback failed: {e}")
81
81
 
82
- # If this is SIGINT (Ctrl+C), we might want to exit immediately after a delay
83
- if signum == signal.SIGINT:
84
- logger.info("⏰ SIGINT received, will exit in 5 seconds if not stopped gracefully...")
85
- threading.Timer(5.0, self._force_exit).start()
82
+ # Force exit immediately to avoid server hang
83
+ logger.info("🔄 Force exiting to avoid server hang...")
84
+ import os
85
+ # Use os._exit for immediate termination
86
+ logger.warning("⚠️ Using os._exit for immediate termination...")
87
+ os._exit(0)
86
88
 
87
89
  def _force_exit(self):
88
90
  """Force exit if graceful shutdown takes too long."""
@@ -5,6 +5,7 @@ Module with utility functions for the microservice.
5
5
  import hashlib
6
6
  import json
7
7
  import os
8
+ import socket
8
9
  import sys
9
10
  import time
10
11
  import uuid
@@ -138,3 +139,144 @@ def ensure_directory(path: str) -> bool:
138
139
  except Exception as e:
139
140
  logger.error(f"Error creating directory {path}: {e}")
140
141
  return False
142
+
143
+
144
+ def check_port_availability(host: str, port: int, timeout: float = 1.0) -> bool:
145
+ """
146
+ Checks if a port is available for binding.
147
+
148
+ Args:
149
+ host: Host address to check
150
+ port: Port number to check
151
+ timeout: Connection timeout in seconds
152
+
153
+ Returns:
154
+ True if port is available, False if port is in use
155
+ """
156
+ try:
157
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
158
+ sock.settimeout(timeout)
159
+ result = sock.connect_ex((host, port))
160
+ return result != 0 # True if connection failed (port is free)
161
+ except Exception as e:
162
+ logger.warning(f"Error checking port {port} on {host}: {e}")
163
+ return True # Assume port is available if check fails
164
+
165
+
166
+ def find_available_port(host: str, start_port: int, max_attempts: int = 100) -> Optional[int]:
167
+ """
168
+ Finds an available port starting from the specified port.
169
+
170
+ Args:
171
+ host: Host address to check
172
+ start_port: Starting port number
173
+ max_attempts: Maximum number of ports to check
174
+
175
+ Returns:
176
+ Available port number or None if no port found
177
+ """
178
+ for port in range(start_port, start_port + max_attempts):
179
+ if check_port_availability(host, port):
180
+ return port
181
+ return None
182
+
183
+
184
+ def get_port_usage_info(port: int) -> str:
185
+ """
186
+ Gets information about what process is using a port.
187
+
188
+ Args:
189
+ port: Port number to check
190
+
191
+ Returns:
192
+ String with port usage information
193
+ """
194
+ try:
195
+ import subprocess
196
+ result = subprocess.run(
197
+ ["lsof", "-i", f":{port}"],
198
+ capture_output=True,
199
+ text=True,
200
+ timeout=5
201
+ )
202
+ if result.returncode == 0 and result.stdout.strip():
203
+ return f"Port {port} is used by:\n{result.stdout.strip()}"
204
+ else:
205
+ return f"Port {port} appears to be in use but process info unavailable"
206
+ except Exception as e:
207
+ return f"Port {port} is in use (unable to get process info: {e})"
208
+
209
+
210
+ def handle_port_conflict(host: str, port: int) -> None:
211
+ """
212
+ Handles port conflict with user-friendly error message and suggestions.
213
+ This is for MAIN server port conflicts - application must exit.
214
+
215
+ Args:
216
+ host: Host address
217
+ port: Port number that's in conflict
218
+ """
219
+ print(f"❌ ERROR: Port {port} is already in use on {host}")
220
+ print(f"💡 Suggestions:")
221
+ print(f" 1. Choose a different port: --port <different_port>")
222
+ print(f" 2. Stop the conflicting service")
223
+ print(f" 3. Check what's using the port:")
224
+ print(f" lsof -i :{port}")
225
+ print(f" netstat -tulpn | grep :{port}")
226
+
227
+ # Try to get more detailed info about port usage
228
+ usage_info = get_port_usage_info(port)
229
+ print(f"🔍 Port usage details:")
230
+ print(f" {usage_info}")
231
+
232
+ # Try to find an alternative port
233
+ alt_port = find_available_port(host, port + 1, 10)
234
+ if alt_port:
235
+ print(f"💡 Alternative port suggestion: {alt_port}")
236
+ print(f" Try: --port {alt_port}")
237
+ else:
238
+ print(f"💡 Try ports in range {port + 1}-{port + 20}")
239
+
240
+ print(f"🛑 Application cannot start due to port conflict")
241
+ sys.exit(1)
242
+
243
+
244
+ def find_port_for_internal_server(host: str, preferred_port: int) -> int:
245
+ """
246
+ Finds an available port for internal server (mTLS, etc.).
247
+ If preferred port is occupied, finds any available port.
248
+
249
+ Args:
250
+ host: Host address
251
+ preferred_port: Preferred port number
252
+
253
+ Returns:
254
+ Available port number
255
+ """
256
+ # First try the preferred port
257
+ if check_port_availability(host, preferred_port):
258
+ print(f"✅ Internal server port {preferred_port} is available")
259
+ return preferred_port
260
+
261
+ # If preferred port is occupied, find any available port
262
+ print(f"⚠️ Internal server preferred port {preferred_port} is occupied, searching for alternative...")
263
+
264
+ alt_port = find_available_port(host, preferred_port + 1, 50)
265
+ if alt_port:
266
+ print(f"✅ Found alternative port for internal server: {alt_port}")
267
+ return alt_port
268
+
269
+ # If no port found in range, try from 9000
270
+ alt_port = find_available_port(host, 9000, 100)
271
+ if alt_port:
272
+ print(f"✅ Found alternative port for internal server: {alt_port}")
273
+ return alt_port
274
+
275
+ # Last resort - try from 10000
276
+ alt_port = find_available_port(host, 10000, 100)
277
+ if alt_port:
278
+ print(f"✅ Found alternative port for internal server: {alt_port}")
279
+ return alt_port
280
+
281
+ # If still no port found, raise error
282
+ raise RuntimeError(f"Unable to find available port for internal server on {host}")
@@ -25,27 +25,26 @@ def main():
25
25
  parser.add_argument("--port", type=int, help="Server port")
26
26
  parser.add_argument("--debug", action="store_true", help="Enable debug mode")
27
27
  args = parser.parse_args()
28
- # Override configuration if specified
29
- config_overrides = {}
28
+ print(f"🚀 Starting Basic Framework Example")
29
+ print(f"📋 Configuration: {args.config}")
30
30
  if args.host:
31
- config_overrides["host"] = args.host
31
+ print(f"🌐 Host override: {args.host}")
32
32
  if args.port:
33
- config_overrides["port"] = args.port
33
+ print(f"🔌 Port override: {args.port}")
34
34
  if args.debug:
35
- config_overrides["debug"] = True
36
- print(f"🚀 Starting Basic Framework Example")
37
- print(f"📋 Configuration: {args.config}")
35
+ print(f"🔧 Debug mode: enabled")
38
36
  print("=" * 50)
39
- # Use the factory method to create and run the server
37
+
38
+ # Note: Host and port overrides should be handled in configuration file
39
+ # or by modifying the configuration before passing to create_and_run_server
40
40
  import asyncio
41
41
  asyncio.run(create_and_run_server(
42
42
  config_path=args.config,
43
43
  title="Basic Framework Example",
44
44
  description="Basic MCP Proxy Adapter with minimal configuration",
45
45
  version="1.0.0",
46
- host=config_overrides.get("host"),
47
- port=config_overrides.get("port"),
48
- debug=config_overrides.get("debug", False),
46
+ host=args.host or "0.0.0.0",
47
+ log_level="debug" if args.debug else "info"
49
48
  ))
50
49
 
51
50
 
@@ -93,74 +93,24 @@ class FullApplication:
93
93
  self.logger.info("✅ Application created successfully")
94
94
 
95
95
  def run(self, host: str = None, port: int = None, debug: bool = False):
96
- """Run the application using the factory method."""
97
- # Override configuration if specified
98
- config_overrides = {}
99
- if host:
100
- config_overrides["host"] = host
101
- if port:
102
- config_overrides["port"] = port
103
- if debug:
104
- config_overrides["debug"] = True
96
+ """Run the application using the factory method with port checking."""
105
97
  print(f"🚀 Starting Full Application Example")
106
98
  print(f"📋 Configuration: {self.config_path}")
107
99
  print(
108
100
  f"🔧 Features: Built-in commands, Custom commands, Dynamic commands, Hooks, Proxy endpoints"
109
101
  )
110
102
  print("=" * 60)
111
- # Create application with configuration
112
- self.create_application()
113
- # Get server configuration
114
- server_host = self.config.get("server.host", "0.0.0.0")
115
- server_port = self.config.get("server.port", 8000)
116
- server_debug = self.config.get("server.debug", False)
117
- # Get SSL configuration
118
- ssl_enabled = self.config.get("ssl.enabled", False)
119
- ssl_cert_file = self.config.get("ssl.cert_file")
120
- ssl_key_file = self.config.get("ssl.key_file")
121
- ssl_ca_cert = self.config.get("ssl.ca_cert")
122
- verify_client = self.config.get("ssl.verify_client", False)
123
- print(f"🌐 Server: {server_host}:{server_port}")
124
- print(f"🔧 Debug: {server_debug}")
125
- if ssl_enabled:
126
- print(f"🔐 SSL: Enabled")
127
- print(f" Certificate: {ssl_cert_file}")
128
- print(f" Key: {ssl_key_file}")
129
- if ssl_ca_cert:
130
- print(f" CA: {ssl_ca_cert}")
131
- print(f" Client verification: {verify_client}")
132
- print("=" * 60)
133
- # Use hypercorn directly to run the application with proxy endpoints
134
- try:
135
- import hypercorn.asyncio
136
- import hypercorn.config
137
- import asyncio
138
-
139
- # Configure hypercorn
140
- config_hypercorn = hypercorn.config.Config()
141
- config_hypercorn.bind = [f"{server_host}:{server_port}"]
142
- config_hypercorn.loglevel = "debug" if server_debug else "info"
143
- if ssl_enabled and ssl_cert_file and ssl_key_file:
144
- config_hypercorn.certfile = ssl_cert_file
145
- config_hypercorn.keyfile = ssl_key_file
146
- if ssl_ca_cert:
147
- config_hypercorn.ca_certs = ssl_ca_cert
148
- if verify_client:
149
- import ssl
150
-
151
- config_hypercorn.verify_mode = ssl.CERT_REQUIRED
152
- print(f"🔐 Starting HTTPS server with hypercorn...")
153
- else:
154
- print(f"🌐 Starting HTTP server with hypercorn...")
155
- # Run the server
156
- asyncio.run(hypercorn.asyncio.serve(self.app, config_hypercorn))
157
- except ImportError:
158
- print("❌ hypercorn not installed. Installing...")
159
- import subprocess
160
-
161
- subprocess.run([sys.executable, "-m", "pip", "install", "hypercorn"])
162
- print("✅ hypercorn installed. Please restart the application.")
163
- return
103
+
104
+ # Use the factory method to create and run the server with port checking
105
+ import asyncio
106
+ asyncio.run(create_and_run_server(
107
+ config_path=self.config_path,
108
+ title="Full Application Example",
109
+ description="Complete MCP Proxy Adapter with all features",
110
+ version="1.0.0",
111
+ host=host or "0.0.0.0",
112
+ log_level="debug" if debug else "info"
113
+ ))
164
114
 
165
115
 
166
116
  def main():
mcp_proxy_adapter/main.py CHANGED
@@ -22,6 +22,11 @@ from mcp_proxy_adapter.api.app import create_app
22
22
  from mcp_proxy_adapter.config import Config
23
23
  from mcp_proxy_adapter.core.config_validator import ConfigValidator
24
24
  from mcp_proxy_adapter.core.signal_handler import setup_signal_handling, is_shutdown_requested
25
+ from mcp_proxy_adapter.core.utils import (
26
+ check_port_availability,
27
+ handle_port_conflict,
28
+ find_port_for_internal_server,
29
+ )
25
30
 
26
31
 
27
32
  def main():
@@ -84,6 +89,13 @@ def main():
84
89
  host = config.get("server.host", "0.0.0.0")
85
90
  port = config.get("server.port", 8000)
86
91
 
92
+ # Check external port availability - this is critical, must exit if occupied
93
+ print(f"🔍 Checking external server port availability: {host}:{port}")
94
+ if not check_port_availability(host, port):
95
+ print(f"❌ CRITICAL: External server port {port} is occupied")
96
+ handle_port_conflict(host, port)
97
+ print(f"✅ External server port {port} is available")
98
+
87
99
  # Get protocol and SSL configuration
88
100
  protocol = config.get("server.protocol", "http")
89
101
  verify_client = config.get("transport.verify_client", False)
@@ -98,6 +110,16 @@ def main():
98
110
  hypercorn_port = port + 1000 # internal port
99
111
  mtls_proxy_port = port # external port
100
112
  ssl_enabled = True
113
+
114
+ # Check internal port availability (flexible - find alternative if occupied)
115
+ print(f"🔍 Checking internal server port availability: {hypercorn_host}:{hypercorn_port}")
116
+ if not check_port_availability(hypercorn_host, hypercorn_port):
117
+ print(f"⚠️ Internal server preferred port {hypercorn_port} is occupied, searching for alternative...")
118
+ hypercorn_port = find_port_for_internal_server(hypercorn_host, hypercorn_port)
119
+ print(f"✅ Internal server will use port: {hypercorn_port}")
120
+ else:
121
+ print(f"✅ Internal server port {hypercorn_port} is available")
122
+
101
123
  print(f"🔐 mTLS Mode: hypercorn on {hypercorn_host}:{hypercorn_port}, mTLS proxy on {host}:{mtls_proxy_port}")
102
124
  else:
103
125
  # Regular mode: hypercorn on external port (no proxy needed)
@@ -2,4 +2,4 @@
2
2
  Version information for MCP Proxy Adapter.
3
3
  """
4
4
 
5
- __version__ = "6.7.2"
5
+ __version__ = "6.8.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-proxy-adapter
3
- Version: 6.7.2
3
+ Version: 6.8.0
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
@@ -2,11 +2,11 @@ mcp_proxy_adapter/__init__.py,sha256=iH0EBBsRj_cfZJpAIsgN_8tTdfefhnl6uUKHjLHhWDQ
2
2
  mcp_proxy_adapter/__main__.py,sha256=sq3tANRuTd18euamt0Bmn1sJeAyzXENZ5VvsMwbrDFA,579
3
3
  mcp_proxy_adapter/config.py,sha256=QpoPaUKcWJ-eu6HYphhIZmkc2M-p1JgpLFAgolf_l5s,20161
4
4
  mcp_proxy_adapter/custom_openapi.py,sha256=XRviX-C-ZkSKdBhORhDTdeN_1FWyEfXZADiASft3t9I,28149
5
- mcp_proxy_adapter/main.py,sha256=ILdGeikcZls2y9Uro0bQLi53FPSuJv_yZBio-3WD2zM,9233
5
+ mcp_proxy_adapter/main.py,sha256=NFcSW7WaEnimRWe5zj28D0CH9otHlRZ92d2Um6XiGjE,10399
6
6
  mcp_proxy_adapter/openapi.py,sha256=2UZOI09ZDRJuBYBjKbMyb2U4uASszoCMD5o_4ktRpvg,13480
7
- mcp_proxy_adapter/version.py,sha256=8BW2GJtsmlLZwL8XRvuPQimNVnKFme-0iHrLwWsvEpM,74
7
+ mcp_proxy_adapter/version.py,sha256=w-T-AD4G77RDBgrZmgrms3YSfVxVCwAp18S8uPaF7gA,74
8
8
  mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- mcp_proxy_adapter/api/app.py,sha256=GGhA5X7HQPLJFxeaWHu5YUwi2ldPvPvJD2YcaL9Nbo0,37874
9
+ mcp_proxy_adapter/api/app.py,sha256=-kEeQraHghvYgJ2A3y0pAg-otpRlo0dWONlLV-pNrEA,38646
10
10
  mcp_proxy_adapter/api/handlers.py,sha256=X-hcMNVeTAu4yVkKJEChEsj2bFptUS6sLNN-Wysjkow,10011
11
11
  mcp_proxy_adapter/api/schemas.py,sha256=mevUvQnYgWQfkJAs3-vq3HalBzh6-Saa-Au1VVf0peE,12377
12
12
  mcp_proxy_adapter/api/tool_integration.py,sha256=AeUyvJVN-c3FrX5fHdagHL51saRH5d1ZKqc2YEx0rTE,10147
@@ -54,9 +54,8 @@ mcp_proxy_adapter/commands/token_management_command.py,sha256=tCVjhWqAQ3KhcwSsZU
54
54
  mcp_proxy_adapter/commands/transport_management_command.py,sha256=HEnUyL4S014jheyBwO90u9gnzk0qxBlOJdC_0Sxhq9E,4585
55
55
  mcp_proxy_adapter/commands/unload_command.py,sha256=6CUM9B9c-mNxw7uvt2vcvZSnxMySfoMT5UmDhzNXq38,4984
56
56
  mcp_proxy_adapter/core/__init__.py,sha256=3yt0CFZdsIG8Ln4bg-r4ISYzipm3ZUAxTn0twYTs9FI,867
57
- mcp_proxy_adapter/core/app_factory.py,sha256=Ywq-RN2o5B86nJpqImnaXNf_g366lVK1fXeIbIr49DM,21625
57
+ mcp_proxy_adapter/core/app_factory.py,sha256=OuxUjGpOp5mOPIQ5iumBW42bxAD0H6o2HM8UICgpUvA,20492
58
58
  mcp_proxy_adapter/core/app_runner.py,sha256=n8_rBojzKUpHLN5ksiXcR8UWoBYk6Tt5OtWk-X2kVPc,11868
59
- mcp_proxy_adapter/core/async_proxy_registration.py,sha256=hM_ZV2YoKM8n0MakVMBd2KnYTJBh1igDeb4DYutfHnE,11387
60
59
  mcp_proxy_adapter/core/auth_validator.py,sha256=q8TNkdolvP-gM6Bvecc6nrVG9al5J31pocdwhguhTBk,19742
61
60
  mcp_proxy_adapter/core/certificate_utils.py,sha256=yeDwi-j42CxK_g-r5_ragGFY_HdSgDfTWHVUjDHF6nI,38480
62
61
  mcp_proxy_adapter/core/client.py,sha256=qIbPl8prEwK2U65kl-vGJW2_imo1E4i6HxG_VpPeWpQ,21168
@@ -70,7 +69,7 @@ mcp_proxy_adapter/core/logging.py,sha256=gNI6vfPQC7jrUtVu6NeDsmU72JPlrRRBhtJipL1
70
69
  mcp_proxy_adapter/core/mtls_asgi.py,sha256=tvk0P9024s18dcCHY9AaQIecT4ojOTv21EuQWXwooU0,5200
71
70
  mcp_proxy_adapter/core/mtls_asgi_app.py,sha256=DT_fTUH1RkvBa3ThbyCyNb-XUHyCb4DqaKA1gcZC6z4,6538
72
71
  mcp_proxy_adapter/core/mtls_proxy.py,sha256=5APlWs0ImiHGEC65W_7F-PbVO3NZ2BVSj9r14AcUtTE,6011
73
- mcp_proxy_adapter/core/mtls_server.py,sha256=_hj6QWuExKX2LRohYvjPGFC2qTutS7ObegpEc09QijM,10117
72
+ mcp_proxy_adapter/core/mtls_server.py,sha256=GBNhLezDYSXFP1xcNaThEhBqZlxXUGp0q0OT2Ibb2M0,10366
74
73
  mcp_proxy_adapter/core/protocol_manager.py,sha256=iaXWsfm1XSfemz5QQBesMluc4cwf-LtuZVi9bm1uj28,14680
75
74
  mcp_proxy_adapter/core/proxy_client.py,sha256=CB6KBhV3vH2GU5nZ27VZ_xlNbYTAU_tnYFrkuK5He58,6094
76
75
  mcp_proxy_adapter/core/proxy_registration.py,sha256=QlQFHnjIN8ETWcasPDUXNMfMsU_-KdrvLTYJiDua_wI,41237
@@ -81,11 +80,11 @@ mcp_proxy_adapter/core/security_integration.py,sha256=-5I4i9so_yMjc-zuGO-7zzIsMX
81
80
  mcp_proxy_adapter/core/server_adapter.py,sha256=jz8ztIfe82N5DE3XHRYpD6CwNcJy7ksh0l8l-towHBE,9755
82
81
  mcp_proxy_adapter/core/server_engine.py,sha256=qmxdkBv-YsQsvxVVQ-_xiAyDshxtnrKBquPJoUjo2fw,9471
83
82
  mcp_proxy_adapter/core/settings.py,sha256=D6cF4R_5gJ0XFGxzXUIzeqe-_muu6HL561TAei9wwZ0,10521
84
- mcp_proxy_adapter/core/signal_handler.py,sha256=ryL4bLzV6ERrXPx19K4ApFGMzFI8iwlI0timj-GQ1YI,5324
83
+ mcp_proxy_adapter/core/signal_handler.py,sha256=TwBftsPAkMNcCSrE1ZA5qKnazcCVRpt_UGQzn6ITDHQ,5327
85
84
  mcp_proxy_adapter/core/ssl_utils.py,sha256=Rjl79d5LdhDzxiMtaIRd9OFh0hTeRANItYFXk-7c5pA,9498
86
85
  mcp_proxy_adapter/core/transport_manager.py,sha256=eJbGa3gDVFUBFUzMK5KEmpbUDXOOShtzszUIEf7Jk0A,9292
87
86
  mcp_proxy_adapter/core/unified_config_adapter.py,sha256=zBGYdLDZ3G8f3Y9tmtm0Ne0UXIfEaNHR4Ik2W3ErkLc,22814
88
- mcp_proxy_adapter/core/utils.py,sha256=wBdDYBDWQ6zbwrnl9tykHjo0FjJVsLT_x8Bjk1lZX60,3270
87
+ mcp_proxy_adapter/core/utils.py,sha256=StTL44fNXYcQfIwc68LTNTDgjyQ0feGCsYSBI0ly6qE,8047
89
88
  mcp_proxy_adapter/examples/__init__.py,sha256=k1F-EotAFbJ3JvK_rNgiH4bUztmxIWtYn0AfbAZ1ZGs,450
90
89
  mcp_proxy_adapter/examples/bugfix_certificate_config.py,sha256=YGBE_SI6wYZUJLWl7-fP1OWXiSH4mHJAZHApgQWvG7s,10529
91
90
  mcp_proxy_adapter/examples/cert_manager_bugfix.py,sha256=UWUwItjqHqSnOMHocsz40_3deoZE8-vdROLW9y2fEns,7259
@@ -96,7 +95,6 @@ mcp_proxy_adapter/examples/create_test_configs.py,sha256=9TrvLa4-bWLPu0SB1JXwWuC
96
95
  mcp_proxy_adapter/examples/debug_request_state.py,sha256=Z3Gy2-fWtu7KIV9OkzGDLVz7TpL_h9V_99ica40uQBU,4489
97
96
  mcp_proxy_adapter/examples/debug_role_chain.py,sha256=GLVXC2fJUwP8UJnXHchd1t-H53cjWLJI3RqTPrKmaak,8750
98
97
  mcp_proxy_adapter/examples/demo_client.py,sha256=en2Rtb70B1sQmhL-vdQ4PDpKNNl_mfll2YCFT_jFCAg,10191
99
- mcp_proxy_adapter/examples/generate_certificates.py,sha256=cIfTHBziGiOTy9vldAmaULD6bXBpl2a5KfB8MLIRSww,16391
100
98
  mcp_proxy_adapter/examples/generate_config.py,sha256=9zImMfIM88OQz12mE5k0_RnVV5ZmhlIKO2fRldiNCok,12709
101
99
  mcp_proxy_adapter/examples/proxy_registration_example.py,sha256=vemRhftnjbiOBCJkmtDGqlWQ8syTG0a8755GCOnaQsg,12503
102
100
  mcp_proxy_adapter/examples/required_certificates.py,sha256=YW9-V78oFiZ-FmHlGP-8FQFS569VdDVyq9hfvCv31pk,7133
@@ -117,12 +115,12 @@ mcp_proxy_adapter/examples/test_protocol_examples.py,sha256=yCZzZrJ9ICXMkF1bAMoz
117
115
  mcp_proxy_adapter/examples/universal_client.py,sha256=n1-cBPOiCipA86Zcc_mI_jMywDMZS1p3u5JT3AqTsrQ,27577
118
116
  mcp_proxy_adapter/examples/update_config_certificates.py,sha256=ObGF5oNQ9OStryUvFDXxrN-olRMKdSOrl5KSwARF7EY,4608
119
117
  mcp_proxy_adapter/examples/basic_framework/__init__.py,sha256=4aYD--R6hy9n9CUxj7Osb9HcdVUMJ6_cfpu4ujkbCwI,345
120
- mcp_proxy_adapter/examples/basic_framework/main.py,sha256=XdGrD_52hhCVHwqx4XmfVmd7tlfp6WE-qZ0gw05SyB0,1792
118
+ mcp_proxy_adapter/examples/basic_framework/main.py,sha256=2bpT-zrekpzzbhOx6wOOYXYE1mejWXkT617zpSN7m70,1790
121
119
  mcp_proxy_adapter/examples/basic_framework/commands/__init__.py,sha256=_VQNLUEdsxUG-4yt9BZI_vtOxHAdGG0OUSsP6Wj-Vz4,76
122
120
  mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py,sha256=IE_EIXMnkdXuakZn7wLD9kBFyfDF5lYi56ejgiBeb-A,70
123
121
  mcp_proxy_adapter/examples/commands/__init__.py,sha256=zvY_OpH_B1bVc_khrNIl6O8vqCw1FH6gGMAsJAkGWGY,170
124
122
  mcp_proxy_adapter/examples/full_application/__init__.py,sha256=xGiPYhRAzs1Fh9wA8HoowV-Gg9QMLaMZn-OamExq1TI,320
125
- mcp_proxy_adapter/examples/full_application/main.py,sha256=ogL3Bil_5puGnwvMh3YNOjrW76FIzzoggKEp-04HSfo,7855
123
+ mcp_proxy_adapter/examples/full_application/main.py,sha256=ZJmXe6WU-4q-U0AKIAdDm9HNREBgWwZz26ohY511xHs,5603
126
124
  mcp_proxy_adapter/examples/full_application/proxy_endpoints.py,sha256=Kt_WAsG61HLTMkKQ1mQqjvlX9I4TcfwYq0NaRR9HKvM,6179
127
125
  mcp_proxy_adapter/examples/full_application/commands/__init__.py,sha256=yQHxVSFkAyFLUOdk42QOebUODPlQV9IbydPgF3UKsGM,217
128
126
  mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py,sha256=H7FPJmVJNWT61rPWxep06-7hsYRt8XYBUSBiwqpBurU,3096
@@ -134,8 +132,8 @@ mcp_proxy_adapter/schemas/base_schema.json,sha256=v9G9cGMd4dRhCZsOQ_FMqOi5VFyVbI
134
132
  mcp_proxy_adapter/schemas/openapi_schema.json,sha256=C3yLkwmDsvnLW9B5gnKKdBGl4zxkeU-rEmjTrNVsQU0,8405
135
133
  mcp_proxy_adapter/schemas/roles.json,sha256=pgf_ZyqKyXbfGUxvobpiLiSJz9zzxrMuoVWEkEpz3N8,764
136
134
  mcp_proxy_adapter/schemas/roles_schema.json,sha256=deHgI7L6GwfBXacOlNtDgDJelDThppClC3Ti4Eh8rJY,5659
137
- mcp_proxy_adapter-6.7.2.dist-info/METADATA,sha256=Xg6ENQrj-kv2GZ0TXmwW3OBxzje9tBsWKclciTZDjnE,8510
138
- mcp_proxy_adapter-6.7.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
139
- mcp_proxy_adapter-6.7.2.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
140
- mcp_proxy_adapter-6.7.2.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
141
- mcp_proxy_adapter-6.7.2.dist-info/RECORD,,
135
+ mcp_proxy_adapter-6.8.0.dist-info/METADATA,sha256=PX886Dr7QaN1S-XzB0MiNXHgp53l5XFGpLGeGRnjgPs,8510
136
+ mcp_proxy_adapter-6.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
+ mcp_proxy_adapter-6.8.0.dist-info/entry_points.txt,sha256=Bf-O5Aq80n22Ayu9fI9BgidzWqwzIVaqextAddTuHZw,563
138
+ mcp_proxy_adapter-6.8.0.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
139
+ mcp_proxy_adapter-6.8.0.dist-info/RECORD,,