mcp-proxy-adapter 6.2.36__py3-none-any.whl → 6.3.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.
@@ -8,7 +8,6 @@ Author: Vasiliy Zdanovskiy
8
8
  email: vasilyvz@gmail.com
9
9
  """
10
10
 
11
- import logging
12
11
  import sys
13
12
  from pathlib import Path
14
13
  from typing import Optional, Dict, Any
@@ -30,14 +29,14 @@ def create_and_run_server(
30
29
  version: str = "1.0.0",
31
30
  host: str = "0.0.0.0",
32
31
  log_level: str = "info",
33
- engine: Optional[str] = None
32
+ engine: Optional[str] = None,
34
33
  ) -> None:
35
34
  """
36
35
  Create and run MCP Proxy Adapter server with proper validation.
37
-
36
+
38
37
  This factory function validates all configuration files, sets up logging,
39
38
  initializes the application, and starts the server with optimal settings.
40
-
39
+
41
40
  Args:
42
41
  config_path: Path to configuration file (JSON)
43
42
  log_config_path: Path to logging configuration file (optional)
@@ -48,7 +47,7 @@ def create_and_run_server(
48
47
  port: Server port
49
48
  log_level: Logging level
50
49
  engine: Specific server engine to use (optional)
51
-
50
+
52
51
  Raises:
53
52
  SystemExit: If configuration validation fails or server cannot start
54
53
  """
@@ -61,7 +60,7 @@ def create_and_run_server(
61
60
  print(f"📊 Log Level: {log_level}")
62
61
  print("=" * 60)
63
62
  print()
64
-
63
+
65
64
  # 1. Validate and load configuration file
66
65
  app_config = None
67
66
  if config_path:
@@ -70,42 +69,69 @@ def create_and_run_server(
70
69
  print(f"❌ Configuration file not found: {config_path}")
71
70
  print(" Please provide a valid path to config.json")
72
71
  sys.exit(1)
73
-
72
+
74
73
  try:
75
74
  config.load_from_file(str(config_file))
76
75
  app_config = config.get_all()
77
76
  print(f"✅ Configuration loaded from: {config_path}")
78
-
77
+
78
+ # Validate UUID configuration (mandatory)
79
+ from mcp_proxy_adapter.core.config_validator import ConfigValidator
80
+
81
+ validator = ConfigValidator(app_config)
82
+ if not validator.validate_all():
83
+ print("❌ Configuration validation failed:")
84
+ for error in validator.get_errors():
85
+ print(f" - {error}")
86
+ sys.exit(1)
87
+ print("✅ Configuration validation passed")
88
+
79
89
  # Debug: Check what config.get_all() actually returns
80
90
  print(f"🔍 Debug: config.get_all() keys: {list(app_config.keys())}")
81
91
  if "security" in app_config:
82
92
  security_ssl = app_config["security"].get("ssl", {})
83
93
  print(f"🔍 Debug: config.get_all() security.ssl: {security_ssl}")
84
-
94
+
85
95
  # Debug: Check if root ssl section exists after loading
86
96
  if "ssl" in app_config:
87
- print(f"🔍 Debug: Root SSL section after loading: enabled={app_config['ssl'].get('enabled', False)}")
88
- print(f"🔍 Debug: Root SSL section after loading: cert_file={app_config['ssl'].get('cert_file')}")
89
- print(f"🔍 Debug: Root SSL section after loading: key_file={app_config['ssl'].get('key_file')}")
97
+ print(
98
+ f"🔍 Debug: Root SSL section after loading: enabled={app_config['ssl'].get('enabled', False)}"
99
+ )
100
+ print(
101
+ f"🔍 Debug: Root SSL section after loading: cert_file={app_config['ssl'].get('cert_file')}"
102
+ )
103
+ print(
104
+ f"🔍 Debug: Root SSL section after loading: key_file={app_config['ssl'].get('key_file')}"
105
+ )
90
106
  else:
91
107
  print(f"🔍 Debug: No root SSL section after loading")
92
-
108
+
93
109
  # Debug: Check app_config immediately after get_all()
94
110
  if app_config and "security" in app_config:
95
111
  ssl_config = app_config["security"].get("ssl", {})
96
- print(f"🔍 Debug: app_config after get_all(): SSL enabled={ssl_config.get('enabled', False)}")
97
- print(f"🔍 Debug: app_config after get_all(): SSL cert_file={ssl_config.get('cert_file')}")
98
- print(f"🔍 Debug: app_config after get_all(): SSL key_file={ssl_config.get('key_file')}")
99
-
112
+ print(
113
+ f"🔍 Debug: app_config after get_all(): SSL enabled={ssl_config.get('enabled', False)}"
114
+ )
115
+ print(
116
+ f"🔍 Debug: app_config after get_all(): SSL cert_file={ssl_config.get('cert_file')}"
117
+ )
118
+ print(
119
+ f"🔍 Debug: app_config after get_all(): SSL key_file={ssl_config.get('key_file')}"
120
+ )
121
+
100
122
  # Debug: Check SSL configuration after loading
101
123
  if app_config and "security" in app_config:
102
124
  ssl_config = app_config["security"].get("ssl", {})
103
- print(f"🔍 Debug: SSL config after loading: enabled={ssl_config.get('enabled', False)}")
104
- print(f"🔍 Debug: SSL config after loading: cert_file={ssl_config.get('cert_file')}")
125
+ print(
126
+ f"🔍 Debug: SSL config after loading: enabled={ssl_config.get('enabled', False)}"
127
+ )
128
+ print(
129
+ f"🔍 Debug: SSL config after loading: cert_file={ssl_config.get('cert_file')}"
130
+ )
105
131
  print(f"🔍 Debug: SSL config after loading: key_file={ssl_config.get('key_file')}")
106
-
132
+
107
133
  # Debug: Check if SSL config is correct
108
- if ssl_config.get('enabled', False):
134
+ if ssl_config.get("enabled", False):
109
135
  print(f"🔍 Debug: SSL config is enabled and correct")
110
136
  else:
111
137
  print(f"🔍 Debug: SSL config is disabled or incorrect")
@@ -114,48 +140,53 @@ def create_and_run_server(
114
140
  print(f"🔍 Debug: Root SSL config: enabled={root_ssl.get('enabled', False)}")
115
141
  print(f"🔍 Debug: Root SSL config: cert_file={root_ssl.get('cert_file')}")
116
142
  print(f"🔍 Debug: Root SSL config: key_file={root_ssl.get('key_file')}")
117
-
143
+
118
144
  # Validate security framework configuration only if enabled
119
145
  security_config = app_config.get("security", {})
120
146
  if security_config.get("enabled", False):
121
147
  framework = security_config.get("framework", "mcp_security_framework")
122
148
  print(f"🔒 Security framework: {framework}")
123
-
149
+
124
150
  # Debug: Check SSL config before validation
125
151
  ssl_config = security_config.get("ssl", {})
126
- print(f"🔍 Debug: SSL config before validation: enabled={ssl_config.get('enabled', False)}")
127
-
152
+ print(
153
+ f"🔍 Debug: SSL config before validation: enabled={ssl_config.get('enabled', False)}"
154
+ )
155
+
128
156
  # Validate security configuration
129
157
  from mcp_proxy_adapter.core.unified_config_adapter import UnifiedConfigAdapter
158
+
130
159
  adapter = UnifiedConfigAdapter()
131
160
  validation_result = adapter.validate_configuration(app_config)
132
-
161
+
133
162
  # Debug: Check SSL config after validation
134
163
  ssl_config = app_config.get("security", {}).get("ssl", {})
135
- print(f"🔍 Debug: SSL config after validation: enabled={ssl_config.get('enabled', False)}")
136
-
164
+ print(
165
+ f"🔍 Debug: SSL config after validation: enabled={ssl_config.get('enabled', False)}"
166
+ )
167
+
137
168
  if not validation_result.is_valid:
138
169
  print("❌ Security configuration validation failed:")
139
170
  for error in validation_result.errors:
140
171
  print(f" - {error}")
141
172
  sys.exit(1)
142
-
173
+
143
174
  if validation_result.warnings:
144
175
  print("⚠️ Security configuration warnings:")
145
176
  for warning in validation_result.warnings:
146
177
  print(f" - {warning}")
147
-
178
+
148
179
  print("✅ Security configuration validated successfully")
149
180
  else:
150
181
  print("🔓 Security framework disabled")
151
-
182
+
152
183
  except Exception as e:
153
184
  print(f"❌ Failed to load configuration from {config_path}: {e}")
154
185
  sys.exit(1)
155
186
  else:
156
187
  print("⚠️ No configuration file provided, using defaults")
157
188
  app_config = config.get_all()
158
-
189
+
159
190
  # 2. Setup logging
160
191
  try:
161
192
  if log_config_path:
@@ -171,7 +202,7 @@ def create_and_run_server(
171
202
  except Exception as e:
172
203
  print(f"❌ Failed to setup logging: {e}")
173
204
  sys.exit(1)
174
-
205
+
175
206
  # 3. Register built-in commands
176
207
  try:
177
208
  builtin_count = register_builtin_commands()
@@ -179,43 +210,44 @@ def create_and_run_server(
179
210
  except Exception as e:
180
211
  print(f"❌ Failed to register built-in commands: {e}")
181
212
  sys.exit(1)
182
-
213
+
183
214
  # 4. Create FastAPI application with configuration
184
215
  try:
185
216
  # Debug: Check app_config before passing to create_app
186
217
  if app_config and "security" in app_config:
187
218
  ssl_config = app_config["security"].get("ssl", {})
188
- print(f"🔍 Debug: app_config before create_app: SSL enabled={ssl_config.get('enabled', False)}")
189
- print(f"🔍 Debug: app_config before create_app: SSL cert_file={ssl_config.get('cert_file')}")
190
- print(f"🔍 Debug: app_config before create_app: SSL key_file={ssl_config.get('key_file')}")
191
-
219
+ print(
220
+ f"🔍 Debug: app_config before create_app: SSL enabled={ssl_config.get('enabled', False)}"
221
+ )
222
+ print(
223
+ f"🔍 Debug: app_config before create_app: SSL cert_file={ssl_config.get('cert_file')}"
224
+ )
225
+ print(
226
+ f"🔍 Debug: app_config before create_app: SSL key_file={ssl_config.get('key_file')}"
227
+ )
228
+
192
229
  app = create_app(
193
230
  title=title,
194
231
  description=description,
195
232
  version=version,
196
233
  app_config=app_config, # Pass configuration to create_app
197
- config_path=config_path # Pass config path to preserve SSL settings
234
+ config_path=config_path, # Pass config path to preserve SSL settings
198
235
  )
199
236
  print("✅ FastAPI application created successfully")
200
237
  except Exception as e:
201
238
  print(f"❌ Failed to create FastAPI application: {e}")
202
239
  sys.exit(1)
203
-
240
+
204
241
  # 5. Create server configuration
205
242
  # Get port from config if available, otherwise use default
206
243
  server_port = app_config.get("server", {}).get("port", 8000) if app_config else 8000
207
244
  print(f"🔌 Port: {server_port}")
208
-
209
- server_config = {
210
- "host": host,
211
- "port": server_port,
212
- "log_level": log_level,
213
- "reload": False
214
- }
215
-
245
+
246
+ server_config = {"host": host, "port": server_port, "log_level": log_level, "reload": False}
247
+
216
248
  # Add SSL configuration if present
217
249
  print(f"🔍 Debug: app_config keys: {list(app_config.keys()) if app_config else 'None'}")
218
-
250
+
219
251
  # Check for SSL config in root section first (higher priority)
220
252
  if app_config and "ssl" in app_config:
221
253
  print(f"🔍 Debug: SSL config found in root: {app_config['ssl']}")
@@ -228,9 +260,13 @@ def create_and_run_server(
228
260
  server_config["ca_certs"] = ssl_config.get("ca_cert_file")
229
261
  server_config["verify_mode"] = ssl_config.get("verify_mode")
230
262
  print(f"🔒 SSL enabled: {ssl_config.get('cert_file', 'N/A')}")
231
- print(f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}")
232
- print(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')}")
233
-
263
+ print(
264
+ f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}"
265
+ )
266
+ print(
267
+ 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')}"
268
+ )
269
+
234
270
  # Check for SSL config in security section (fallback)
235
271
  if app_config and "security" in app_config:
236
272
  security_config = app_config["security"]
@@ -246,8 +282,12 @@ def create_and_run_server(
246
282
  server_config["ca_certs"] = ssl_config.get("ca_cert_file")
247
283
  server_config["verify_mode"] = ssl_config.get("verify_mode")
248
284
  print(f"🔒 SSL enabled: {ssl_config.get('cert_file', 'N/A')}")
249
- print(f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}")
250
- print(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')}")
285
+ print(
286
+ f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}"
287
+ )
288
+ print(
289
+ 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')}"
290
+ )
251
291
  print(f"🔍 Debug: SSL config found in root: {app_config['ssl']}")
252
292
  print(f"🔍 Debug: SSL enabled: {app_config['ssl'].get('enabled', False)}")
253
293
  if app_config["ssl"].get("enabled", False):
@@ -258,25 +298,29 @@ def create_and_run_server(
258
298
  server_config["ca_certs"] = ssl_config.get("ca_cert_file")
259
299
  server_config["verify_mode"] = ssl_config.get("verify_mode")
260
300
  print(f"🔒 SSL enabled: {ssl_config.get('cert_file', 'N/A')}")
261
- print(f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}")
262
- print(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')}")
263
-
301
+ print(
302
+ f"🔒 SSL enabled: cert={ssl_config.get('cert_file')}, key={ssl_config.get('key_file')}"
303
+ )
304
+ print(
305
+ 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')}"
306
+ )
307
+
264
308
  # 6. Start server
265
309
  try:
266
310
  print("🚀 Starting server...")
267
311
  print(" Use Ctrl+C to stop the server")
268
312
  print("=" * 60)
269
-
313
+
270
314
  # Use hypercorn directly
271
315
  import hypercorn.asyncio
272
316
  import hypercorn.config
273
317
  import asyncio
274
-
318
+
275
319
  # Configure hypercorn
276
320
  config_hypercorn = hypercorn.config.Config()
277
321
  config_hypercorn.bind = [f"{server_config['host']}:{server_config['port']}"]
278
322
  config_hypercorn.loglevel = server_config.get("log_level", "info")
279
-
323
+
280
324
  # Add SSL configuration if present
281
325
  if "certfile" in server_config:
282
326
  config_hypercorn.certfile = server_config["certfile"]
@@ -286,24 +330,26 @@ def create_and_run_server(
286
330
  config_hypercorn.ca_certs = server_config["ca_certs"]
287
331
  if "verify_mode" in server_config:
288
332
  import ssl
333
+
289
334
  config_hypercorn.verify_mode = ssl.CERT_REQUIRED
290
-
335
+
291
336
  # Determine if SSL is enabled
292
337
  ssl_enabled = any(key in server_config for key in ["certfile", "keyfile"])
293
-
338
+
294
339
  if ssl_enabled:
295
340
  print(f"🔐 Starting HTTPS server with hypercorn...")
296
341
  else:
297
342
  print(f"🌐 Starting HTTP server with hypercorn...")
298
-
343
+
299
344
  # Run the server
300
345
  asyncio.run(hypercorn.asyncio.serve(app, config_hypercorn))
301
-
346
+
302
347
  except KeyboardInterrupt:
303
348
  print("\n🛑 Server stopped by user")
304
349
  except Exception as e:
305
350
  print(f"\n❌ Failed to start server: {e}")
306
351
  import traceback
352
+
307
353
  traceback.print_exc()
308
354
  sys.exit(1)
309
355
 
@@ -311,10 +357,10 @@ def create_and_run_server(
311
357
  def validate_config_file(config_path: str) -> bool:
312
358
  """
313
359
  Validate configuration file exists and is readable.
314
-
360
+
315
361
  Args:
316
362
  config_path: Path to configuration file
317
-
363
+
318
364
  Returns:
319
365
  True if valid, False otherwise
320
366
  """
@@ -323,11 +369,11 @@ def validate_config_file(config_path: str) -> bool:
323
369
  if not config_file.exists():
324
370
  print(f"❌ Configuration file not found: {config_path}")
325
371
  return False
326
-
372
+
327
373
  # Try to load configuration to validate JSON format
328
374
  config.load_from_file(str(config_file))
329
375
  return True
330
-
376
+
331
377
  except Exception as e:
332
378
  print(f"❌ Configuration file validation failed: {e}")
333
379
  return False
@@ -336,10 +382,10 @@ def validate_config_file(config_path: str) -> bool:
336
382
  def validate_log_config_file(log_config_path: str) -> bool:
337
383
  """
338
384
  Validate logging configuration file exists and is readable.
339
-
385
+
340
386
  Args:
341
387
  log_config_path: Path to logging configuration file
342
-
388
+
343
389
  Returns:
344
390
  True if valid, False otherwise
345
391
  """
@@ -349,7 +395,7 @@ def validate_log_config_file(log_config_path: str) -> bool:
349
395
  print(f"❌ Log configuration file not found: {log_config_path}")
350
396
  return False
351
397
  return True
352
-
398
+
353
399
  except Exception as e:
354
400
  print(f"❌ Log configuration file validation failed: {e}")
355
401
  return False
@@ -359,17 +405,17 @@ def create_application(
359
405
  config: Dict[str, Any],
360
406
  title: str = "MCP Proxy Adapter",
361
407
  description: str = "JSON-RPC API for interacting with MCP Proxy",
362
- version: str = "1.0.0"
408
+ version: str = "1.0.0",
363
409
  ) -> FastAPI:
364
410
  """
365
411
  Creates and configures FastAPI application.
366
-
412
+
367
413
  Args:
368
414
  config: Application configuration dictionary
369
415
  title: Application title
370
416
  description: Application description
371
417
  version: Application version
372
-
418
+
373
419
  Returns:
374
420
  Configured FastAPI application
375
421
  """
@@ -377,21 +423,16 @@ def create_application(
377
423
  from mcp_proxy_adapter.api.app import create_app
378
424
  from mcp_proxy_adapter.core.logging import setup_logging
379
425
  from mcp_proxy_adapter.commands.builtin_commands import register_builtin_commands
380
-
426
+
381
427
  # Setup logging
382
428
  setup_logging()
383
-
429
+
384
430
  # Register built-in commands
385
431
  register_builtin_commands()
386
-
432
+
387
433
  # Create FastAPI application using existing create_app function
388
- app = create_app(
389
- title=title,
390
- description=description,
391
- version=version,
392
- app_config=config
393
- )
394
-
434
+ app = create_app(title=title, description=description, version=version, app_config=config)
435
+
395
436
  # Add CORS middleware
396
437
  app.add_middleware(
397
438
  CORSMiddleware,
@@ -400,11 +441,11 @@ def create_application(
400
441
  allow_methods=["*"],
401
442
  allow_headers=["*"],
402
443
  )
403
-
444
+
404
445
  # Add health endpoint
405
446
  @app.get("/health")
406
447
  async def health_check():
407
448
  """Health check endpoint."""
408
449
  return {"status": "healthy", "version": version}
409
-
450
+
410
451
  return app