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.
- mcp_proxy_adapter/core/app_factory.py +127 -86
- mcp_proxy_adapter/core/config_validator.py +92 -55
- mcp_proxy_adapter/core/crl_utils.py +89 -76
- mcp_proxy_adapter/core/security_integration.py +110 -77
- mcp_proxy_adapter/main.py +19 -10
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/RECORD +12 -12
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.2.36.dist-info → mcp_proxy_adapter-6.3.0.dist-info}/top_level.txt +0 -0
@@ -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(
|
88
|
-
|
89
|
-
|
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(
|
97
|
-
|
98
|
-
|
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(
|
104
|
-
|
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(
|
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(
|
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(
|
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(
|
189
|
-
|
190
|
-
|
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
|
-
|
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(
|
232
|
-
|
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(
|
250
|
-
|
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(
|
262
|
-
|
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
|
-
|
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
|