mcp-proxy-adapter 6.0.0__py3-none-any.whl ā 6.1.1__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 +174 -80
- mcp_proxy_adapter/api/handlers.py +16 -5
- mcp_proxy_adapter/api/middleware/__init__.py +9 -4
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/factory.py +36 -12
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +32 -13
- mcp_proxy_adapter/api/middleware/unified_security.py +160 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
- mcp_proxy_adapter/commands/__init__.py +7 -1
- mcp_proxy_adapter/commands/base.py +7 -4
- mcp_proxy_adapter/commands/builtin_commands.py +8 -2
- mcp_proxy_adapter/commands/command_registry.py +8 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +2 -2
- mcp_proxy_adapter/commands/token_management_command.py +1 -1
- mcp_proxy_adapter/config.py +81 -21
- mcp_proxy_adapter/core/app_factory.py +326 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/logging.py +8 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +139 -8
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +299 -47
- mcp_proxy_adapter/core/security_adapter.py +12 -15
- mcp_proxy_adapter/core/security_integration.py +285 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/examples/README.md +230 -97
- mcp_proxy_adapter/examples/README_EN.md +258 -0
- mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +43 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +36 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +29 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +34 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +35 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
- mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
- mcp_proxy_adapter/examples/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/admin.key +52 -0
- mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
- mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
- mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/client.crt +32 -0
- mcp_proxy_adapter/examples/certs/client.key +52 -0
- mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
- mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_user.key +52 -0
- mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
- mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
- mcp_proxy_adapter/examples/certs/readonly.key +52 -0
- mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/server.crt +32 -0
- mcp_proxy_adapter/examples/certs/server.key +52 -0
- mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
- mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
- mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
- mcp_proxy_adapter/examples/certs/user.crt +32 -0
- mcp_proxy_adapter/examples/certs/user.key +52 -0
- mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
- mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
- mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
- mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
- mcp_proxy_adapter/examples/commands/__init__.py +1 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
- mcp_proxy_adapter/examples/debug_request_state.py +144 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
- mcp_proxy_adapter/examples/demo_client.py +341 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
- mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
- mcp_proxy_adapter/examples/full_application/main.py +138 -0
- mcp_proxy_adapter/examples/full_application/roles.json +21 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
- mcp_proxy_adapter/examples/generate_certificates.py +121 -0
- mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
- mcp_proxy_adapter/examples/roles.json +38 -0
- mcp_proxy_adapter/examples/run_example.py +81 -0
- mcp_proxy_adapter/examples/run_security_tests.py +326 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
- mcp_proxy_adapter/examples/security_test_client.py +743 -0
- mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
- mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
- mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
- mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
- mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
- mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
- mcp_proxy_adapter/examples/test_config_generator.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +21 -10
- mcp_proxy_adapter/utils/config_generator.py +727 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.1.1.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.1.dist-info/RECORD +197 -0
- mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-6.0.0.dist-info ā mcp_proxy_adapter-6.1.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
- mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
- mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
- mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
- mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
- mcp_proxy_adapter/api/middleware/security.py +0 -376
- mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
- mcp_proxy_adapter/examples/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
- mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
- mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -114
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
- mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
- mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
- mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
- mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
- mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
- mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
- mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
- mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
- mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
- mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
- mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/schemas/roles_schema.json +0 -162
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -270
- mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
- mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
- {mcp_proxy_adapter-6.0.0.dist-info ā mcp_proxy_adapter-6.1.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.0.0.dist-info ā mcp_proxy_adapter-6.1.1.dist-info}/top_level.txt +0 -0
mcp_proxy_adapter/config.py
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
"""
|
2
2
|
Module for microservice configuration management.
|
3
|
+
|
4
|
+
Author: Vasiliy Zdanovskiy
|
5
|
+
email: vasilyvz@gmail.com
|
3
6
|
"""
|
4
7
|
|
5
8
|
import json
|
@@ -67,7 +70,7 @@ class Config:
|
|
67
70
|
"verify_client": False,
|
68
71
|
"client_cert_required": False,
|
69
72
|
"cipher_suites": ["TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"],
|
70
|
-
"min_tls_version": "
|
73
|
+
"min_tls_version": "TLSv1.2",
|
71
74
|
"max_tls_version": "1.3",
|
72
75
|
"token_auth": {
|
73
76
|
"enabled": False,
|
@@ -80,16 +83,16 @@ class Config:
|
|
80
83
|
}
|
81
84
|
},
|
82
85
|
"roles": {
|
83
|
-
"enabled":
|
84
|
-
"config_file":
|
86
|
+
"enabled": False,
|
87
|
+
"config_file": None,
|
85
88
|
"default_policy": {
|
86
|
-
"deny_by_default":
|
87
|
-
"require_role_match":
|
89
|
+
"deny_by_default": False,
|
90
|
+
"require_role_match": False,
|
88
91
|
"case_sensitive": False,
|
89
|
-
"allow_wildcard":
|
92
|
+
"allow_wildcard": False
|
90
93
|
},
|
91
|
-
"auto_load":
|
92
|
-
"validation_enabled":
|
94
|
+
"auto_load": False,
|
95
|
+
"validation_enabled": False
|
93
96
|
},
|
94
97
|
"transport": {
|
95
98
|
"type": "http",
|
@@ -122,35 +125,92 @@ class Config:
|
|
122
125
|
"security": {
|
123
126
|
"framework": "mcp_security_framework",
|
124
127
|
"enabled": True,
|
128
|
+
"debug": False,
|
129
|
+
"environment": "dev",
|
130
|
+
"version": "1.0.0",
|
125
131
|
"auth": {
|
126
132
|
"enabled": True,
|
127
133
|
"methods": ["api_key"],
|
128
134
|
"api_keys": {},
|
135
|
+
"user_roles": {},
|
129
136
|
"jwt_secret": "",
|
130
|
-
"jwt_algorithm": "HS256"
|
137
|
+
"jwt_algorithm": "HS256",
|
138
|
+
"jwt_expiry_hours": 24,
|
139
|
+
"certificate_auth": False,
|
140
|
+
"certificate_roles_oid": "1.3.6.1.4.1.99999.1.1",
|
141
|
+
"certificate_permissions_oid": "1.3.6.1.4.1.99999.1.2",
|
142
|
+
"basic_auth": False,
|
143
|
+
"oauth2_config": None,
|
144
|
+
"public_paths": ["/health", "/docs", "/openapi.json"],
|
145
|
+
"security_headers": None
|
131
146
|
},
|
132
147
|
"ssl": {
|
133
148
|
"enabled": False,
|
134
149
|
"cert_file": None,
|
135
150
|
"key_file": None,
|
136
|
-
"
|
151
|
+
"ca_cert_file": None,
|
152
|
+
"client_cert_file": None,
|
153
|
+
"client_key_file": None,
|
154
|
+
"verify_mode": "CERT_NONE",
|
137
155
|
"min_tls_version": "TLSv1.2",
|
138
|
-
"
|
139
|
-
"
|
156
|
+
"max_tls_version": None,
|
157
|
+
"cipher_suite": None,
|
158
|
+
"check_hostname": True,
|
159
|
+
"check_expiry": True,
|
160
|
+
"expiry_warning_days": 30
|
161
|
+
},
|
162
|
+
"certificates": {
|
163
|
+
"enabled": False,
|
164
|
+
"ca_cert_path": None,
|
165
|
+
"ca_key_path": None,
|
166
|
+
"cert_storage_path": "./certs",
|
167
|
+
"key_storage_path": "./keys",
|
168
|
+
"default_validity_days": 365,
|
169
|
+
"key_size": 2048,
|
170
|
+
"hash_algorithm": "sha256",
|
171
|
+
"crl_enabled": False,
|
172
|
+
"crl_path": None,
|
173
|
+
"crl_validity_days": 30,
|
174
|
+
"auto_renewal": False,
|
175
|
+
"renewal_threshold_days": 30
|
140
176
|
},
|
141
177
|
"permissions": {
|
142
|
-
"enabled":
|
143
|
-
"roles_file":
|
144
|
-
"default_role": "
|
145
|
-
"
|
178
|
+
"enabled": False,
|
179
|
+
"roles_file": None,
|
180
|
+
"default_role": "guest",
|
181
|
+
"admin_role": "admin",
|
182
|
+
"role_hierarchy": {},
|
183
|
+
"permission_cache_enabled": False,
|
184
|
+
"permission_cache_ttl": 300,
|
185
|
+
"wildcard_permissions": False,
|
186
|
+
"strict_mode": False,
|
187
|
+
"roles": None
|
146
188
|
},
|
147
189
|
"rate_limit": {
|
148
190
|
"enabled": True,
|
149
|
-
"
|
150
|
-
"
|
151
|
-
"burst_limit":
|
152
|
-
"
|
153
|
-
"
|
191
|
+
"default_requests_per_minute": 60,
|
192
|
+
"default_requests_per_hour": 1000,
|
193
|
+
"burst_limit": 2,
|
194
|
+
"window_size_seconds": 60,
|
195
|
+
"storage_backend": "memory",
|
196
|
+
"redis_config": None,
|
197
|
+
"cleanup_interval": 300,
|
198
|
+
"exempt_paths": ["/health", "/docs", "/openapi.json"],
|
199
|
+
"exempt_roles": ["admin"]
|
200
|
+
},
|
201
|
+
"logging": {
|
202
|
+
"enabled": True,
|
203
|
+
"level": "INFO",
|
204
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
205
|
+
"date_format": "%Y-%m-%d %H:%M:%S",
|
206
|
+
"file_path": None,
|
207
|
+
"max_file_size": 10,
|
208
|
+
"backup_count": 5,
|
209
|
+
"console_output": True,
|
210
|
+
"json_format": False,
|
211
|
+
"include_timestamp": True,
|
212
|
+
"include_level": True,
|
213
|
+
"include_module": True
|
154
214
|
}
|
155
215
|
}
|
156
216
|
}
|
@@ -0,0 +1,326 @@
|
|
1
|
+
"""
|
2
|
+
Application Factory for MCP Proxy Adapter
|
3
|
+
|
4
|
+
This module provides a factory function for creating and running MCP Proxy Adapter servers
|
5
|
+
with proper configuration validation and initialization.
|
6
|
+
|
7
|
+
Author: Vasiliy Zdanovskiy
|
8
|
+
email: vasilyvz@gmail.com
|
9
|
+
"""
|
10
|
+
|
11
|
+
import logging
|
12
|
+
import sys
|
13
|
+
from pathlib import Path
|
14
|
+
from typing import Optional, Dict, Any
|
15
|
+
|
16
|
+
from mcp_proxy_adapter.api.app import create_app
|
17
|
+
from mcp_proxy_adapter.core.logging import setup_logging, get_logger
|
18
|
+
from mcp_proxy_adapter.core.server_adapter import UnifiedServerRunner
|
19
|
+
from mcp_proxy_adapter.config import config
|
20
|
+
from mcp_proxy_adapter.commands.builtin_commands import register_builtin_commands
|
21
|
+
|
22
|
+
logger = get_logger("app_factory")
|
23
|
+
|
24
|
+
|
25
|
+
def create_and_run_server(
|
26
|
+
config_path: Optional[str] = None,
|
27
|
+
log_config_path: Optional[str] = None,
|
28
|
+
title: str = "MCP Proxy Adapter Server",
|
29
|
+
description: str = "Model Context Protocol Proxy Adapter with Security Framework",
|
30
|
+
version: str = "1.0.0",
|
31
|
+
host: str = "0.0.0.0",
|
32
|
+
log_level: str = "info",
|
33
|
+
engine: Optional[str] = None
|
34
|
+
) -> None:
|
35
|
+
"""
|
36
|
+
Create and run MCP Proxy Adapter server with proper validation.
|
37
|
+
|
38
|
+
This factory function validates all configuration files, sets up logging,
|
39
|
+
initializes the application, and starts the server with optimal settings.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
config_path: Path to configuration file (JSON)
|
43
|
+
log_config_path: Path to logging configuration file (optional)
|
44
|
+
title: Application title for OpenAPI schema
|
45
|
+
description: Application description for OpenAPI schema
|
46
|
+
version: Application version
|
47
|
+
host: Server host address
|
48
|
+
port: Server port
|
49
|
+
log_level: Logging level
|
50
|
+
engine: Specific server engine to use (optional)
|
51
|
+
|
52
|
+
Raises:
|
53
|
+
SystemExit: If configuration validation fails or server cannot start
|
54
|
+
"""
|
55
|
+
print("š MCP Proxy Adapter Server Factory")
|
56
|
+
print("=" * 60)
|
57
|
+
print(f"š Title: {title}")
|
58
|
+
print(f"š Description: {description}")
|
59
|
+
print(f"š¢ Version: {version}")
|
60
|
+
print(f"š Host: {host}")
|
61
|
+
print(f"š Log Level: {log_level}")
|
62
|
+
print("=" * 60)
|
63
|
+
print()
|
64
|
+
|
65
|
+
# 1. Validate and load configuration file
|
66
|
+
app_config = None
|
67
|
+
if config_path:
|
68
|
+
config_file = Path(config_path)
|
69
|
+
if not config_file.exists():
|
70
|
+
print(f"ā Configuration file not found: {config_path}")
|
71
|
+
print(" Please provide a valid path to config.json")
|
72
|
+
sys.exit(1)
|
73
|
+
|
74
|
+
try:
|
75
|
+
config.load_from_file(str(config_file))
|
76
|
+
app_config = config.get_all()
|
77
|
+
print(f"ā
Configuration loaded from: {config_path}")
|
78
|
+
|
79
|
+
# Debug: Check what config.get_all() actually returns
|
80
|
+
print(f"š Debug: config.get_all() keys: {list(app_config.keys())}")
|
81
|
+
if "security" in app_config:
|
82
|
+
security_ssl = app_config["security"].get("ssl", {})
|
83
|
+
print(f"š Debug: config.get_all() security.ssl: {security_ssl}")
|
84
|
+
|
85
|
+
# Debug: Check if root ssl section exists after loading
|
86
|
+
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')}")
|
90
|
+
else:
|
91
|
+
print(f"š Debug: No root SSL section after loading")
|
92
|
+
|
93
|
+
# Debug: Check app_config immediately after get_all()
|
94
|
+
if app_config and "security" in app_config:
|
95
|
+
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
|
+
|
100
|
+
# Debug: Check SSL configuration after loading
|
101
|
+
if app_config and "security" in app_config:
|
102
|
+
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')}")
|
105
|
+
print(f"š Debug: SSL config after loading: key_file={ssl_config.get('key_file')}")
|
106
|
+
|
107
|
+
# Debug: Check if SSL config is correct
|
108
|
+
if ssl_config.get('enabled', False):
|
109
|
+
print(f"š Debug: SSL config is enabled and correct")
|
110
|
+
else:
|
111
|
+
print(f"š Debug: SSL config is disabled or incorrect")
|
112
|
+
# Try to get SSL config from root level
|
113
|
+
root_ssl = app_config.get("ssl", {})
|
114
|
+
print(f"š Debug: Root SSL config: enabled={root_ssl.get('enabled', False)}")
|
115
|
+
print(f"š Debug: Root SSL config: cert_file={root_ssl.get('cert_file')}")
|
116
|
+
print(f"š Debug: Root SSL config: key_file={root_ssl.get('key_file')}")
|
117
|
+
|
118
|
+
# Validate security framework configuration only if enabled
|
119
|
+
security_config = app_config.get("security", {})
|
120
|
+
if security_config.get("enabled", False):
|
121
|
+
framework = security_config.get("framework", "mcp_security_framework")
|
122
|
+
print(f"š Security framework: {framework}")
|
123
|
+
|
124
|
+
# Debug: Check SSL config before validation
|
125
|
+
ssl_config = security_config.get("ssl", {})
|
126
|
+
print(f"š Debug: SSL config before validation: enabled={ssl_config.get('enabled', False)}")
|
127
|
+
|
128
|
+
# Validate security configuration
|
129
|
+
from mcp_proxy_adapter.core.unified_config_adapter import UnifiedConfigAdapter
|
130
|
+
adapter = UnifiedConfigAdapter()
|
131
|
+
validation_result = adapter.validate_configuration(app_config)
|
132
|
+
|
133
|
+
# Debug: Check SSL config after validation
|
134
|
+
ssl_config = app_config.get("security", {}).get("ssl", {})
|
135
|
+
print(f"š Debug: SSL config after validation: enabled={ssl_config.get('enabled', False)}")
|
136
|
+
|
137
|
+
if not validation_result.is_valid:
|
138
|
+
print("ā Security configuration validation failed:")
|
139
|
+
for error in validation_result.errors:
|
140
|
+
print(f" - {error}")
|
141
|
+
sys.exit(1)
|
142
|
+
|
143
|
+
if validation_result.warnings:
|
144
|
+
print("ā ļø Security configuration warnings:")
|
145
|
+
for warning in validation_result.warnings:
|
146
|
+
print(f" - {warning}")
|
147
|
+
|
148
|
+
print("ā
Security configuration validated successfully")
|
149
|
+
else:
|
150
|
+
print("š Security framework disabled")
|
151
|
+
|
152
|
+
except Exception as e:
|
153
|
+
print(f"ā Failed to load configuration from {config_path}: {e}")
|
154
|
+
sys.exit(1)
|
155
|
+
else:
|
156
|
+
print("ā ļø No configuration file provided, using defaults")
|
157
|
+
app_config = config.get_all()
|
158
|
+
|
159
|
+
# 2. Setup logging
|
160
|
+
try:
|
161
|
+
if log_config_path:
|
162
|
+
log_config_file = Path(log_config_path)
|
163
|
+
if not log_config_file.exists():
|
164
|
+
print(f"ā Log configuration file not found: {log_config_path}")
|
165
|
+
sys.exit(1)
|
166
|
+
setup_logging(log_config_path=str(log_config_file))
|
167
|
+
print(f"ā
Logging configured from: {log_config_path}")
|
168
|
+
else:
|
169
|
+
setup_logging()
|
170
|
+
print("ā
Logging configured with defaults")
|
171
|
+
except Exception as e:
|
172
|
+
print(f"ā Failed to setup logging: {e}")
|
173
|
+
sys.exit(1)
|
174
|
+
|
175
|
+
# 3. Register built-in commands
|
176
|
+
try:
|
177
|
+
builtin_count = register_builtin_commands()
|
178
|
+
print(f"ā
Registered {builtin_count} built-in commands")
|
179
|
+
except Exception as e:
|
180
|
+
print(f"ā Failed to register built-in commands: {e}")
|
181
|
+
sys.exit(1)
|
182
|
+
|
183
|
+
# 4. Create FastAPI application with configuration
|
184
|
+
try:
|
185
|
+
# Debug: Check app_config before passing to create_app
|
186
|
+
if app_config and "security" in app_config:
|
187
|
+
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
|
+
|
192
|
+
app = create_app(
|
193
|
+
title=title,
|
194
|
+
description=description,
|
195
|
+
version=version,
|
196
|
+
app_config=app_config, # Pass configuration to create_app
|
197
|
+
config_path=config_path # Pass config path to preserve SSL settings
|
198
|
+
)
|
199
|
+
print("ā
FastAPI application created successfully")
|
200
|
+
except Exception as e:
|
201
|
+
print(f"ā Failed to create FastAPI application: {e}")
|
202
|
+
sys.exit(1)
|
203
|
+
|
204
|
+
# 5. Create server configuration
|
205
|
+
# Get port from config if available, otherwise use default
|
206
|
+
server_port = app_config.get("server", {}).get("port", 8000) if app_config else 8000
|
207
|
+
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
|
+
|
216
|
+
# Add SSL configuration if present
|
217
|
+
print(f"š Debug: app_config keys: {list(app_config.keys()) if app_config else 'None'}")
|
218
|
+
|
219
|
+
# Check for SSL config in root section first (higher priority)
|
220
|
+
if app_config and "ssl" in app_config:
|
221
|
+
print(f"š Debug: SSL config found in root: {app_config['ssl']}")
|
222
|
+
print(f"š Debug: SSL enabled: {app_config['ssl'].get('enabled', False)}")
|
223
|
+
if app_config["ssl"].get("enabled", False):
|
224
|
+
ssl_config = app_config["ssl"]
|
225
|
+
# Add SSL config directly to server_config for Hypercorn
|
226
|
+
server_config["certfile"] = ssl_config.get("cert_file")
|
227
|
+
server_config["keyfile"] = ssl_config.get("key_file")
|
228
|
+
server_config["ca_certs"] = ssl_config.get("ca_cert_file")
|
229
|
+
server_config["verify_mode"] = ssl_config.get("verify_mode")
|
230
|
+
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
|
+
|
234
|
+
# Check for SSL config in security section (fallback)
|
235
|
+
if app_config and "security" in app_config:
|
236
|
+
security_config = app_config["security"]
|
237
|
+
print(f"š Debug: security_config keys: {list(security_config.keys())}")
|
238
|
+
if "ssl" in security_config:
|
239
|
+
print(f"š Debug: SSL config found in security: {security_config['ssl']}")
|
240
|
+
print(f"š Debug: SSL enabled: {security_config['ssl'].get('enabled', False)}")
|
241
|
+
if security_config["ssl"].get("enabled", False):
|
242
|
+
ssl_config = security_config["ssl"]
|
243
|
+
# Add SSL config directly to server_config for Hypercorn
|
244
|
+
server_config["certfile"] = ssl_config.get("cert_file")
|
245
|
+
server_config["keyfile"] = ssl_config.get("key_file")
|
246
|
+
server_config["ca_certs"] = ssl_config.get("ca_cert_file")
|
247
|
+
server_config["verify_mode"] = ssl_config.get("verify_mode")
|
248
|
+
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')}")
|
251
|
+
print(f"š Debug: SSL config found in root: {app_config['ssl']}")
|
252
|
+
print(f"š Debug: SSL enabled: {app_config['ssl'].get('enabled', False)}")
|
253
|
+
if app_config["ssl"].get("enabled", False):
|
254
|
+
ssl_config = app_config["ssl"]
|
255
|
+
# Add SSL config directly to server_config for Hypercorn
|
256
|
+
server_config["certfile"] = ssl_config.get("cert_file")
|
257
|
+
server_config["keyfile"] = ssl_config.get("key_file")
|
258
|
+
server_config["ca_certs"] = ssl_config.get("ca_cert_file")
|
259
|
+
server_config["verify_mode"] = ssl_config.get("verify_mode")
|
260
|
+
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
|
+
|
264
|
+
# 6. Start server
|
265
|
+
try:
|
266
|
+
print("š Starting server...")
|
267
|
+
print(" Use Ctrl+C to stop the server")
|
268
|
+
print("=" * 60)
|
269
|
+
|
270
|
+
server_runner = UnifiedServerRunner()
|
271
|
+
server_runner.run_server(app, server_config, "hypercorn")
|
272
|
+
|
273
|
+
except KeyboardInterrupt:
|
274
|
+
print("\nš Server stopped by user")
|
275
|
+
except Exception as e:
|
276
|
+
print(f"\nā Failed to start server: {e}")
|
277
|
+
import traceback
|
278
|
+
traceback.print_exc()
|
279
|
+
sys.exit(1)
|
280
|
+
|
281
|
+
|
282
|
+
def validate_config_file(config_path: str) -> bool:
|
283
|
+
"""
|
284
|
+
Validate configuration file exists and is readable.
|
285
|
+
|
286
|
+
Args:
|
287
|
+
config_path: Path to configuration file
|
288
|
+
|
289
|
+
Returns:
|
290
|
+
True if valid, False otherwise
|
291
|
+
"""
|
292
|
+
try:
|
293
|
+
config_file = Path(config_path)
|
294
|
+
if not config_file.exists():
|
295
|
+
print(f"ā Configuration file not found: {config_path}")
|
296
|
+
return False
|
297
|
+
|
298
|
+
# Try to load configuration to validate JSON format
|
299
|
+
config.load_from_file(str(config_file))
|
300
|
+
return True
|
301
|
+
|
302
|
+
except Exception as e:
|
303
|
+
print(f"ā Configuration file validation failed: {e}")
|
304
|
+
return False
|
305
|
+
|
306
|
+
|
307
|
+
def validate_log_config_file(log_config_path: str) -> bool:
|
308
|
+
"""
|
309
|
+
Validate logging configuration file exists and is readable.
|
310
|
+
|
311
|
+
Args:
|
312
|
+
log_config_path: Path to logging configuration file
|
313
|
+
|
314
|
+
Returns:
|
315
|
+
True if valid, False otherwise
|
316
|
+
"""
|
317
|
+
try:
|
318
|
+
log_config_file = Path(log_config_path)
|
319
|
+
if not log_config_file.exists():
|
320
|
+
print(f"ā Log configuration file not found: {log_config_path}")
|
321
|
+
return False
|
322
|
+
return True
|
323
|
+
|
324
|
+
except Exception as e:
|
325
|
+
print(f"ā Log configuration file validation failed: {e}")
|
326
|
+
return False
|