mcp-proxy-adapter 6.2.24__py3-none-any.whl → 6.2.26__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/api/app.py +0 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +10 -10
- mcp_proxy_adapter/commands/health_command.py +1 -1
- mcp_proxy_adapter/config.py +234 -23
- mcp_proxy_adapter/core/protocol_manager.py +9 -9
- mcp_proxy_adapter/examples/create_certificates_simple.py +7 -17
- mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +70 -33
- mcp_proxy_adapter/examples/run_full_test_suite.py +302 -109
- mcp_proxy_adapter/examples/run_security_tests.py +14 -5
- mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/main.py +0 -2
- mcp_proxy_adapter/utils/config_generator.py +275 -7
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/RECORD +33 -17
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.26.dist-info}/top_level.txt +0 -0
mcp_proxy_adapter/api/app.py
CHANGED
@@ -350,9 +350,6 @@ def create_app(title: Optional[str] = None, description: Optional[str] = None, v
|
|
350
350
|
)
|
351
351
|
|
352
352
|
# Setup middleware using the new middleware package
|
353
|
-
print(f"DEBUG create_app: calling setup_middleware with config type: {type(current_config)}")
|
354
|
-
if hasattr(current_config, 'keys'):
|
355
|
-
print(f"DEBUG create_app: current_config keys: {list(current_config.keys())}")
|
356
353
|
setup_middleware(app, current_config)
|
357
354
|
|
358
355
|
# Use custom OpenAPI schema
|
@@ -87,7 +87,7 @@ class ProtocolMiddleware(BaseHTTPMiddleware):
|
|
87
87
|
Returns:
|
88
88
|
Response object
|
89
89
|
"""
|
90
|
-
logger.
|
90
|
+
logger.debug(f"ProtocolMiddleware.dispatch called for {request.method} {request.url.path}")
|
91
91
|
try:
|
92
92
|
# Get protocol from request
|
93
93
|
protocol = self._get_request_protocol(request)
|
@@ -169,32 +169,32 @@ def setup_protocol_middleware(app, app_config: Optional[Dict[str, Any]] = None):
|
|
169
169
|
app: FastAPI application
|
170
170
|
app_config: Application configuration dictionary (optional)
|
171
171
|
"""
|
172
|
-
logger.
|
172
|
+
logger.debug(f"setup_protocol_middleware - app_config type: {type(app_config)}")
|
173
173
|
|
174
174
|
# Check if protocol management is enabled
|
175
175
|
if app_config is None:
|
176
176
|
from mcp_proxy_adapter.config import config
|
177
177
|
app_config = config.get_all()
|
178
|
-
logger.
|
178
|
+
logger.debug(f"setup_protocol_middleware - loaded from global config, type: {type(app_config)}")
|
179
179
|
|
180
|
-
logger.
|
180
|
+
logger.debug(f"setup_protocol_middleware - final app_config type: {type(app_config)}")
|
181
181
|
|
182
182
|
if hasattr(app_config, 'get'):
|
183
|
-
logger.
|
183
|
+
logger.debug(f"setup_protocol_middleware - app_config keys: {list(app_config.keys()) if hasattr(app_config, 'keys') else 'no keys'}")
|
184
184
|
protocols_config = app_config.get("protocols", {})
|
185
|
-
logger.
|
185
|
+
logger.debug(f"setup_protocol_middleware - protocols_config type: {type(protocols_config)}")
|
186
186
|
enabled = protocols_config.get("enabled", True) if hasattr(protocols_config, 'get') else True
|
187
187
|
else:
|
188
|
-
logger.
|
188
|
+
logger.debug(f"setup_protocol_middleware - app_config is not dict-like: {repr(app_config)}")
|
189
189
|
enabled = True
|
190
190
|
|
191
|
-
logger.
|
191
|
+
logger.debug(f"setup_protocol_middleware - protocol management enabled: {enabled}")
|
192
192
|
|
193
193
|
if enabled:
|
194
194
|
# Create protocol middleware with current configuration
|
195
|
-
logger.
|
195
|
+
logger.debug(f"setup_protocol_middleware - creating ProtocolMiddleware with config type: {type(app_config)}")
|
196
196
|
middleware = ProtocolMiddleware(app, app_config)
|
197
|
-
logger.
|
197
|
+
logger.debug(f"setup_protocol_middleware - adding middleware to app")
|
198
198
|
app.add_middleware(ProtocolMiddleware, app_config=app_config)
|
199
199
|
logger.info("Protocol middleware added to application")
|
200
200
|
else:
|
mcp_proxy_adapter/config.py
CHANGED
@@ -7,14 +7,14 @@ email: vasilyvz@gmail.com
|
|
7
7
|
|
8
8
|
import json
|
9
9
|
import os
|
10
|
-
from
|
11
|
-
from typing import Any, Dict, Optional
|
10
|
+
from typing import Any, Dict, Optional, List
|
12
11
|
|
13
12
|
|
14
13
|
class Config:
|
15
14
|
"""
|
16
15
|
Configuration management class for the microservice.
|
17
16
|
Allows loading settings from configuration file and environment variables.
|
17
|
+
Supports optional features that can be enabled/disabled.
|
18
18
|
"""
|
19
19
|
|
20
20
|
def __init__(self, config_path: Optional[str] = None):
|
@@ -22,7 +22,8 @@ class Config:
|
|
22
22
|
Initialize configuration.
|
23
23
|
|
24
24
|
Args:
|
25
|
-
config_path: Path to configuration file. If not specified,
|
25
|
+
config_path: Path to configuration file. If not specified,
|
26
|
+
"./config.json" is used.
|
26
27
|
"""
|
27
28
|
self.config_path = config_path or "./config.json"
|
28
29
|
self.config_data: Dict[str, Any] = {}
|
@@ -56,10 +57,13 @@ class Config:
|
|
56
57
|
},
|
57
58
|
"commands": {
|
58
59
|
"auto_discovery": True,
|
59
|
-
"commands_directory": "./commands",
|
60
|
-
"catalog_directory": "./catalog",
|
61
|
-
"plugin_servers": [],
|
62
|
-
"auto_install_dependencies": True
|
60
|
+
"commands_directory": "./commands",
|
61
|
+
"catalog_directory": "./catalog",
|
62
|
+
"plugin_servers": [],
|
63
|
+
"auto_install_dependencies": True,
|
64
|
+
"enabled_commands": ["health", "echo", "list", "help"],
|
65
|
+
"disabled_commands": [],
|
66
|
+
"custom_commands_path": "./commands"
|
63
67
|
},
|
64
68
|
"ssl": {
|
65
69
|
"enabled": False,
|
@@ -69,7 +73,10 @@ class Config:
|
|
69
73
|
"ca_cert": None,
|
70
74
|
"verify_client": False,
|
71
75
|
"client_cert_required": False,
|
72
|
-
"cipher_suites": [
|
76
|
+
"cipher_suites": [
|
77
|
+
"TLS_AES_256_GCM_SHA384",
|
78
|
+
"TLS_CHACHA20_POLY1305_SHA256"
|
79
|
+
],
|
73
80
|
"min_tls_version": "TLSv1.2",
|
74
81
|
"max_tls_version": "1.3",
|
75
82
|
"token_auth": {
|
@@ -118,12 +125,6 @@ class Config:
|
|
118
125
|
"auto_register_on_startup": True,
|
119
126
|
"auto_unregister_on_shutdown": True
|
120
127
|
},
|
121
|
-
"commands": {
|
122
|
-
"auto_discovery": True,
|
123
|
-
"enabled_commands": ["health", "echo", "list", "help"],
|
124
|
-
"disabled_commands": [],
|
125
|
-
"custom_commands_path": "./commands"
|
126
|
-
},
|
127
128
|
"debug": {
|
128
129
|
"enabled": False,
|
129
130
|
"level": "WARNING"
|
@@ -226,7 +227,7 @@ class Config:
|
|
226
227
|
"auto_discovery": True
|
227
228
|
}
|
228
229
|
}
|
229
|
-
|
230
|
+
|
230
231
|
# Try to load configuration from file
|
231
232
|
if os.path.exists(self.config_path):
|
232
233
|
try:
|
@@ -235,7 +236,7 @@ class Config:
|
|
235
236
|
self._update_nested_dict(self.config_data, file_config)
|
236
237
|
except Exception as e:
|
237
238
|
print(f"Error loading config from {self.config_path}: {e}")
|
238
|
-
|
239
|
+
|
239
240
|
# Load configuration from environment variables
|
240
241
|
self._load_env_variables()
|
241
242
|
|
@@ -300,14 +301,14 @@ class Config:
|
|
300
301
|
Configuration value
|
301
302
|
"""
|
302
303
|
parts = key.split(".")
|
303
|
-
|
304
|
+
|
304
305
|
# Get value from config
|
305
306
|
value = self.config_data
|
306
307
|
for part in parts:
|
307
308
|
if not isinstance(value, dict) or part not in value:
|
308
309
|
return default
|
309
310
|
value = value[part]
|
310
|
-
|
311
|
+
|
311
312
|
return value
|
312
313
|
|
313
314
|
def get_all(self) -> Dict[str, Any]:
|
@@ -332,17 +333,17 @@ class Config:
|
|
332
333
|
self.config_data[key] = value
|
333
334
|
else:
|
334
335
|
section = parts[0]
|
335
|
-
|
336
|
-
|
336
|
+
param_key = ".".join(parts[1:])
|
337
|
+
|
337
338
|
if section not in self.config_data:
|
338
339
|
self.config_data[section] = {}
|
339
|
-
|
340
|
+
|
340
341
|
current = self.config_data[section]
|
341
342
|
for part in parts[1:-1]:
|
342
343
|
if part not in current:
|
343
344
|
current[part] = {}
|
344
345
|
current = current[part]
|
345
|
-
|
346
|
+
|
346
347
|
current[parts[-1]] = value
|
347
348
|
|
348
349
|
def save(self, path: Optional[str] = None) -> None:
|
@@ -350,7 +351,8 @@ class Config:
|
|
350
351
|
Save configuration to file.
|
351
352
|
|
352
353
|
Args:
|
353
|
-
path: Path to configuration file. If not specified,
|
354
|
+
path: Path to configuration file. If not specified,
|
355
|
+
self.config_path is used.
|
354
356
|
"""
|
355
357
|
save_path = path or self.config_path
|
356
358
|
with open(save_path, 'w', encoding='utf-8') as f:
|
@@ -374,6 +376,215 @@ class Config:
|
|
374
376
|
d[k] = v
|
375
377
|
return d
|
376
378
|
|
379
|
+
def enable_feature(self, feature: str) -> None:
|
380
|
+
"""
|
381
|
+
Enable a specific feature in the configuration.
|
382
|
+
|
383
|
+
Args:
|
384
|
+
feature: Feature to enable (ssl, auth, roles, proxy_registration,
|
385
|
+
security)
|
386
|
+
"""
|
387
|
+
if feature == "ssl":
|
388
|
+
self.set("ssl.enabled", True)
|
389
|
+
self.set("security.ssl.enabled", True)
|
390
|
+
elif feature == "auth":
|
391
|
+
self.set("security.auth.enabled", True)
|
392
|
+
elif feature == "roles":
|
393
|
+
self.set("security.permissions.enabled", True)
|
394
|
+
self.set("roles.enabled", True)
|
395
|
+
elif feature == "proxy_registration":
|
396
|
+
self.set("proxy_registration.enabled", True)
|
397
|
+
elif feature == "security":
|
398
|
+
self.set("security.enabled", True)
|
399
|
+
elif feature == "rate_limit":
|
400
|
+
self.set("security.rate_limit.enabled", True)
|
401
|
+
elif feature == "certificates":
|
402
|
+
self.set("security.certificates.enabled", True)
|
403
|
+
else:
|
404
|
+
raise ValueError(f"Unknown feature: {feature}")
|
405
|
+
|
406
|
+
def disable_feature(self, feature: str) -> None:
|
407
|
+
"""
|
408
|
+
Disable a specific feature in the configuration.
|
409
|
+
|
410
|
+
Args:
|
411
|
+
feature: Feature to disable (ssl, auth, roles, proxy_registration,
|
412
|
+
security)
|
413
|
+
"""
|
414
|
+
if feature == "ssl":
|
415
|
+
self.set("ssl.enabled", False)
|
416
|
+
self.set("security.ssl.enabled", False)
|
417
|
+
elif feature == "auth":
|
418
|
+
self.set("security.auth.enabled", False)
|
419
|
+
elif feature == "roles":
|
420
|
+
self.set("security.permissions.enabled", False)
|
421
|
+
self.set("roles.enabled", False)
|
422
|
+
elif feature == "proxy_registration":
|
423
|
+
self.set("proxy_registration.enabled", False)
|
424
|
+
elif feature == "security":
|
425
|
+
self.set("security.enabled", False)
|
426
|
+
elif feature == "rate_limit":
|
427
|
+
self.set("security.rate_limit.enabled", False)
|
428
|
+
elif feature == "certificates":
|
429
|
+
self.set("security.certificates.enabled", False)
|
430
|
+
else:
|
431
|
+
raise ValueError(f"Unknown feature: {feature}")
|
432
|
+
|
433
|
+
def is_feature_enabled(self, feature: str) -> bool:
|
434
|
+
"""
|
435
|
+
Check if a specific feature is enabled.
|
436
|
+
|
437
|
+
Args:
|
438
|
+
feature: Feature to check (ssl, auth, roles, proxy_registration,
|
439
|
+
security)
|
440
|
+
|
441
|
+
Returns:
|
442
|
+
True if feature is enabled, False otherwise
|
443
|
+
"""
|
444
|
+
if feature == "ssl":
|
445
|
+
return (self.get("ssl.enabled", False) or
|
446
|
+
self.get("security.ssl.enabled", False))
|
447
|
+
elif feature == "auth":
|
448
|
+
return self.get("security.auth.enabled", False)
|
449
|
+
elif feature == "roles":
|
450
|
+
return (self.get("security.permissions.enabled", False) or
|
451
|
+
self.get("roles.enabled", False))
|
452
|
+
elif feature == "proxy_registration":
|
453
|
+
return self.get("proxy_registration.enabled", False)
|
454
|
+
elif feature == "security":
|
455
|
+
return self.get("security.enabled", False)
|
456
|
+
elif feature == "rate_limit":
|
457
|
+
return self.get("security.rate_limit.enabled", False)
|
458
|
+
elif feature == "certificates":
|
459
|
+
return self.get("security.certificates.enabled", False)
|
460
|
+
else:
|
461
|
+
raise ValueError(f"Unknown feature: {feature}")
|
462
|
+
|
463
|
+
def get_enabled_features(self) -> List[str]:
|
464
|
+
"""
|
465
|
+
Get list of all enabled features.
|
466
|
+
|
467
|
+
Returns:
|
468
|
+
List of enabled feature names
|
469
|
+
"""
|
470
|
+
features = []
|
471
|
+
if self.is_feature_enabled("ssl"):
|
472
|
+
features.append("ssl")
|
473
|
+
if self.is_feature_enabled("auth"):
|
474
|
+
features.append("auth")
|
475
|
+
if self.is_feature_enabled("roles"):
|
476
|
+
features.append("roles")
|
477
|
+
if self.is_feature_enabled("proxy_registration"):
|
478
|
+
features.append("proxy_registration")
|
479
|
+
if self.is_feature_enabled("security"):
|
480
|
+
features.append("security")
|
481
|
+
if self.is_feature_enabled("rate_limit"):
|
482
|
+
features.append("rate_limit")
|
483
|
+
if self.is_feature_enabled("certificates"):
|
484
|
+
features.append("certificates")
|
485
|
+
return features
|
486
|
+
|
487
|
+
def configure_auth_mode(self, mode: str, **kwargs) -> None:
|
488
|
+
"""
|
489
|
+
Configure authentication mode.
|
490
|
+
|
491
|
+
Args:
|
492
|
+
mode: Authentication mode (api_key, jwt, certificate, basic, oauth2)
|
493
|
+
**kwargs: Additional configuration parameters
|
494
|
+
"""
|
495
|
+
if mode == "api_key":
|
496
|
+
self.set("security.auth.methods", ["api_key"])
|
497
|
+
if "api_keys" in kwargs:
|
498
|
+
self.set("security.auth.api_keys", kwargs["api_keys"])
|
499
|
+
elif mode == "jwt":
|
500
|
+
self.set("security.auth.methods", ["jwt"])
|
501
|
+
if "jwt_secret" in kwargs:
|
502
|
+
self.set("security.auth.jwt_secret", kwargs["jwt_secret"])
|
503
|
+
elif mode == "certificate":
|
504
|
+
self.set("security.auth.methods", ["certificate"])
|
505
|
+
self.set("security.auth.certificate_auth", True)
|
506
|
+
elif mode == "basic":
|
507
|
+
self.set("security.auth.methods", ["basic"])
|
508
|
+
self.set("security.auth.basic_auth", True)
|
509
|
+
elif mode == "oauth2":
|
510
|
+
self.set("security.auth.methods", ["oauth2"])
|
511
|
+
if "oauth2_config" in kwargs:
|
512
|
+
self.set("security.auth.oauth2_config", kwargs["oauth2_config"])
|
513
|
+
else:
|
514
|
+
raise ValueError(f"Unknown authentication mode: {mode}")
|
515
|
+
|
516
|
+
def configure_proxy_registration_mode(self, mode: str, **kwargs) -> None:
|
517
|
+
"""
|
518
|
+
Configure proxy registration mode.
|
519
|
+
|
520
|
+
Args:
|
521
|
+
mode: Registration mode (token, certificate, api_key, none)
|
522
|
+
**kwargs: Additional configuration parameters
|
523
|
+
"""
|
524
|
+
if mode == "none":
|
525
|
+
self.set("proxy_registration.enabled", False)
|
526
|
+
else:
|
527
|
+
self.set("proxy_registration.enabled", True)
|
528
|
+
|
529
|
+
if mode == "token":
|
530
|
+
self.set("proxy_registration.auth_method", "token")
|
531
|
+
if "token" in kwargs:
|
532
|
+
self.set("proxy_registration.token.token", kwargs["token"])
|
533
|
+
elif mode == "certificate":
|
534
|
+
self.set("proxy_registration.auth_method", "certificate")
|
535
|
+
if "cert_file" in kwargs:
|
536
|
+
self.set("proxy_registration.certificate.cert_file",
|
537
|
+
kwargs["cert_file"])
|
538
|
+
if "key_file" in kwargs:
|
539
|
+
self.set("proxy_registration.certificate.key_file",
|
540
|
+
kwargs["key_file"])
|
541
|
+
elif mode == "api_key":
|
542
|
+
self.set("proxy_registration.auth_method", "api_key")
|
543
|
+
if "key" in kwargs:
|
544
|
+
self.set("proxy_registration.api_key.key", kwargs["key"])
|
545
|
+
|
546
|
+
def create_minimal_config(self) -> Dict[str, Any]:
|
547
|
+
"""
|
548
|
+
Create minimal configuration with only essential features.
|
549
|
+
|
550
|
+
Returns:
|
551
|
+
Minimal configuration dictionary
|
552
|
+
"""
|
553
|
+
minimal_config = self.config_data.copy()
|
554
|
+
|
555
|
+
# Disable all optional features
|
556
|
+
minimal_config["ssl"]["enabled"] = False
|
557
|
+
minimal_config["security"]["enabled"] = False
|
558
|
+
minimal_config["security"]["auth"]["enabled"] = False
|
559
|
+
minimal_config["security"]["permissions"]["enabled"] = False
|
560
|
+
minimal_config["security"]["rate_limit"]["enabled"] = False
|
561
|
+
minimal_config["security"]["certificates"]["enabled"] = False
|
562
|
+
minimal_config["proxy_registration"]["enabled"] = False
|
563
|
+
minimal_config["roles"]["enabled"] = False
|
564
|
+
|
565
|
+
return minimal_config
|
566
|
+
|
567
|
+
def create_secure_config(self) -> Dict[str, Any]:
|
568
|
+
"""
|
569
|
+
Create secure configuration with all security features enabled.
|
570
|
+
|
571
|
+
Returns:
|
572
|
+
Secure configuration dictionary
|
573
|
+
"""
|
574
|
+
secure_config = self.config_data.copy()
|
575
|
+
|
576
|
+
# Enable all security features
|
577
|
+
secure_config["ssl"]["enabled"] = True
|
578
|
+
secure_config["security"]["enabled"] = True
|
579
|
+
secure_config["security"]["auth"]["enabled"] = True
|
580
|
+
secure_config["security"]["permissions"]["enabled"] = True
|
581
|
+
secure_config["security"]["rate_limit"]["enabled"] = True
|
582
|
+
secure_config["security"]["certificates"]["enabled"] = True
|
583
|
+
secure_config["proxy_registration"]["enabled"] = True
|
584
|
+
secure_config["roles"]["enabled"] = True
|
585
|
+
|
586
|
+
return secure_config
|
587
|
+
|
377
588
|
|
378
589
|
# Singleton instance
|
379
590
|
config = Config()
|
@@ -35,28 +35,28 @@ class ProtocolManager:
|
|
35
35
|
"""Load protocol configuration from config."""
|
36
36
|
# Use provided config or fallback to global config; normalize types
|
37
37
|
current_config = self.app_config if self.app_config is not None else config.get_all()
|
38
|
-
logger.
|
38
|
+
logger.debug(f"ProtocolManager._load_config - current_config type: {type(current_config)}")
|
39
39
|
|
40
40
|
if not hasattr(current_config, 'get'):
|
41
41
|
# Not a dict-like config, fallback to global
|
42
|
-
logger.
|
42
|
+
logger.debug(f"ProtocolManager._load_config - current_config is not dict-like, falling back to global config")
|
43
43
|
current_config = config.get_all()
|
44
44
|
|
45
|
-
logger.
|
45
|
+
logger.debug(f"ProtocolManager._load_config - final current_config type: {type(current_config)}")
|
46
46
|
if hasattr(current_config, 'get'):
|
47
|
-
logger.
|
47
|
+
logger.debug(f"ProtocolManager._load_config - current_config keys: {list(current_config.keys()) if hasattr(current_config, 'keys') else 'no keys'}")
|
48
48
|
|
49
49
|
# Get protocols configuration
|
50
|
-
logger.
|
50
|
+
logger.debug(f"ProtocolManager._load_config - before getting protocols")
|
51
51
|
try:
|
52
52
|
self.protocols_config = current_config.get("protocols", {})
|
53
|
-
logger.
|
53
|
+
logger.debug(f"ProtocolManager._load_config - protocols_config type: {type(self.protocols_config)}")
|
54
54
|
if hasattr(self.protocols_config, 'get'):
|
55
|
-
logger.
|
55
|
+
logger.debug(f"ProtocolManager._load_config - protocols_config is dict-like")
|
56
56
|
else:
|
57
|
-
logger.
|
57
|
+
logger.debug(f"ProtocolManager._load_config - protocols_config is NOT dict-like: {repr(self.protocols_config)}")
|
58
58
|
except Exception as e:
|
59
|
-
logger.
|
59
|
+
logger.debug(f"ProtocolManager._load_config - ERROR getting protocols: {e}")
|
60
60
|
self.protocols_config = {}
|
61
61
|
|
62
62
|
self.enabled = self.protocols_config.get("enabled", True) if hasattr(self.protocols_config, 'get') else True
|
@@ -466,18 +466,13 @@ class SimpleCertificateCreator:
|
|
466
466
|
shutil.copy2(ca_cert, expected_ca_cert)
|
467
467
|
print(f"✅ Created CA certificate copy: {expected_ca_cert}")
|
468
468
|
|
469
|
-
# Server certificate
|
469
|
+
# Server certificate copy
|
470
470
|
server_cert = self.certs_dir / "server_cert.pem"
|
471
471
|
expected_server_cert = self.certs_dir / "localhost_server.crt"
|
472
472
|
if server_cert.exists() and not expected_server_cert.exists():
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
except OSError:
|
477
|
-
# On Windows, symlink might require admin privileges, copy instead
|
478
|
-
import shutil
|
479
|
-
shutil.copy2(server_cert, expected_server_cert)
|
480
|
-
print(f"✅ Created server certificate copy: {expected_server_cert}")
|
473
|
+
import shutil
|
474
|
+
shutil.copy2(server_cert, expected_server_cert)
|
475
|
+
print(f"✅ Created server certificate copy: {expected_server_cert}")
|
481
476
|
|
482
477
|
# Server key symlink - check if it's in certs or keys directory
|
483
478
|
server_key_certs = self.certs_dir / "server_key.pem"
|
@@ -492,14 +487,9 @@ class SimpleCertificateCreator:
|
|
492
487
|
if server_key_keys.exists():
|
493
488
|
expected_server_key = self.keys_dir / "localhost_server.key"
|
494
489
|
if not expected_server_key.exists():
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
except OSError:
|
499
|
-
# On Windows, symlink might require admin privileges, copy instead
|
500
|
-
import shutil
|
501
|
-
shutil.copy2(server_key_keys, expected_server_key)
|
502
|
-
print(f"✅ Created server key copy: {expected_server_key}")
|
490
|
+
import shutil
|
491
|
+
shutil.copy2(server_key_keys, expected_server_key)
|
492
|
+
print(f"✅ Created server key copy: {expected_server_key}")
|
503
493
|
|
504
494
|
# Print summary
|
505
495
|
print("\n" + "=" * 60)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"""Basic Framework Example.
|
2
|
+
|
3
|
+
This example demonstrates the fundamental usage of MCP Proxy Adapter
|
4
|
+
with minimal configuration and basic command registration.
|
5
|
+
|
6
|
+
Note: This package provides a basic example of MCP Proxy Adapter usage.
|
7
|
+
The main application is created dynamically in main.py and not exported
|
8
|
+
as a global variable for this example.
|
9
|
+
"""
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Basic Framework Example
|
4
|
+
This example demonstrates the basic usage of the MCP Proxy Adapter framework
|
5
|
+
with minimal configuration and built-in commands.
|
6
|
+
Author: Vasiliy Zdanovskiy
|
7
|
+
email: vasilyvz@gmail.com
|
8
|
+
"""
|
9
|
+
import sys
|
10
|
+
import argparse
|
11
|
+
from pathlib import Path
|
12
|
+
# Add the framework to the path
|
13
|
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
14
|
+
from mcp_proxy_adapter.core.app_factory import create_and_run_server
|
15
|
+
def main():
|
16
|
+
"""Main entry point for the basic framework example."""
|
17
|
+
parser = argparse.ArgumentParser(description="Basic Framework Example")
|
18
|
+
parser.add_argument("--config", "-c", required=True, help="Path to configuration file")
|
19
|
+
parser.add_argument("--host", help="Server host")
|
20
|
+
parser.add_argument("--port", type=int, help="Server port")
|
21
|
+
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
22
|
+
args = parser.parse_args()
|
23
|
+
# Override configuration if specified
|
24
|
+
config_overrides = {}
|
25
|
+
if args.host:
|
26
|
+
config_overrides["host"] = args.host
|
27
|
+
if args.port:
|
28
|
+
config_overrides["port"] = args.port
|
29
|
+
if args.debug:
|
30
|
+
config_overrides["debug"] = True
|
31
|
+
print(f"🚀 Starting Basic Framework Example")
|
32
|
+
print(f"📋 Configuration: {args.config}")
|
33
|
+
print("=" * 50)
|
34
|
+
# Use the factory method to create and run the server
|
35
|
+
create_and_run_server(
|
36
|
+
config_path=args.config,
|
37
|
+
title="Basic Framework Example",
|
38
|
+
description="Basic MCP Proxy Adapter with minimal configuration",
|
39
|
+
version="1.0.0",
|
40
|
+
host=config_overrides.get("host", "0.0.0.0"),
|
41
|
+
log_level="debug" if config_overrides.get("debug", False) else "info"
|
42
|
+
)
|
43
|
+
if __name__ == "__main__":
|
44
|
+
main()
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"""Full Application Example.
|
2
|
+
|
3
|
+
This example demonstrates advanced usage of MCP Proxy Adapter including:
|
4
|
+
- Proxy registration endpoints
|
5
|
+
- Custom command hooks
|
6
|
+
- Advanced security configurations
|
7
|
+
- Role-based access control
|
8
|
+
"""
|
9
|
+
|
10
|
+
from .main import get_app
|
11
|
+
app = get_app()
|
12
|
+
from .proxy_endpoints import router as proxy_router
|