mcp-proxy-adapter 4.1.1__py3-none-any.whl ā 6.1.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/__main__.py +12 -0
- mcp_proxy_adapter/api/app.py +254 -33
- mcp_proxy_adapter/api/handlers.py +32 -6
- mcp_proxy_adapter/api/middleware/__init__.py +36 -30
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
- mcp_proxy_adapter/api/middleware/factory.py +243 -0
- mcp_proxy_adapter/api/middleware/logging.py +32 -6
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +152 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
- mcp_proxy_adapter/commands/__init__.py +19 -4
- mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
- mcp_proxy_adapter/commands/base.py +66 -32
- mcp_proxy_adapter/commands/builtin_commands.py +95 -0
- mcp_proxy_adapter/commands/catalog_manager.py +838 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
- mcp_proxy_adapter/commands/command_registry.py +711 -354
- mcp_proxy_adapter/commands/dependency_manager.py +245 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +7 -0
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/hooks.py +200 -167
- mcp_proxy_adapter/commands/key_management_command.py +506 -0
- mcp_proxy_adapter/commands/load_command.py +176 -0
- mcp_proxy_adapter/commands/plugins_command.py +235 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
- mcp_proxy_adapter/commands/reload_command.py +48 -50
- mcp_proxy_adapter/commands/result.py +1 -0
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/roles_management_command.py +697 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
- mcp_proxy_adapter/commands/token_management_command.py +529 -0
- mcp_proxy_adapter/commands/transport_management_command.py +144 -0
- mcp_proxy_adapter/commands/unload_command.py +158 -0
- mcp_proxy_adapter/config.py +159 -2
- mcp_proxy_adapter/core/app_factory.py +326 -0
- mcp_proxy_adapter/core/auth_validator.py +606 -0
- mcp_proxy_adapter/core/certificate_utils.py +827 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/config_converter.py +405 -0
- mcp_proxy_adapter/core/config_validator.py +218 -0
- mcp_proxy_adapter/core/logging.py +19 -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 +235 -0
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +522 -0
- mcp_proxy_adapter/core/role_utils.py +426 -0
- mcp_proxy_adapter/core/security_adapter.py +370 -0
- mcp_proxy_adapter/core/security_factory.py +239 -0
- mcp_proxy_adapter/core/security_integration.py +277 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/settings.py +1 -0
- mcp_proxy_adapter/core/ssl_utils.py +233 -0
- mcp_proxy_adapter/core/transport_manager.py +292 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/custom_openapi.py +22 -11
- 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/__pycache__/security_configurations.cpython-312.pyc +0 -0
- mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -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 +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -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_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +186 -0
- mcp_proxy_adapter/utils/config_generator.py +639 -0
- mcp_proxy_adapter/version.py +2 -1
- mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
- mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-4.1.1.dist-info ā mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
- 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 -35
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -103
- 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 -250
- 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/config.json +0 -35
- 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/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- 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/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- 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 -217
- mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
- mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
- {mcp_proxy_adapter-4.1.1.dist-info ā mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-4.1.1.dist-info ā mcp_proxy_adapter-6.1.0.dist-info}/top_level.txt +0 -0
@@ -1,152 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Middleware for rate limiting.
|
3
|
-
"""
|
4
|
-
|
5
|
-
import time
|
6
|
-
from typing import Dict, List, Callable, Awaitable
|
7
|
-
from collections import defaultdict
|
8
|
-
|
9
|
-
from fastapi import Request, Response
|
10
|
-
from starlette.responses import JSONResponse
|
11
|
-
|
12
|
-
from mcp_proxy_adapter.core.logging import logger
|
13
|
-
from .base import BaseMiddleware
|
14
|
-
|
15
|
-
class RateLimitMiddleware(BaseMiddleware):
|
16
|
-
"""
|
17
|
-
Middleware for limiting request rate.
|
18
|
-
"""
|
19
|
-
|
20
|
-
def __init__(self, app, rate_limit: int = 100, time_window: int = 60,
|
21
|
-
by_ip: bool = True, by_user: bool = True,
|
22
|
-
public_paths: List[str] = None):
|
23
|
-
"""
|
24
|
-
Initializes middleware for rate limiting.
|
25
|
-
|
26
|
-
Args:
|
27
|
-
app: FastAPI application
|
28
|
-
rate_limit: Maximum number of requests in the specified time period
|
29
|
-
time_window: Time period in seconds
|
30
|
-
by_ip: Limit requests by IP address
|
31
|
-
by_user: Limit requests by user
|
32
|
-
public_paths: List of paths for which rate limiting is not applied
|
33
|
-
"""
|
34
|
-
super().__init__(app)
|
35
|
-
self.rate_limit = rate_limit
|
36
|
-
self.time_window = time_window
|
37
|
-
self.by_ip = by_ip
|
38
|
-
self.by_user = by_user
|
39
|
-
self.public_paths = public_paths or [
|
40
|
-
"/docs",
|
41
|
-
"/redoc",
|
42
|
-
"/openapi.json",
|
43
|
-
"/health"
|
44
|
-
]
|
45
|
-
|
46
|
-
# Storage for requests by IP
|
47
|
-
self.ip_requests = defaultdict(list)
|
48
|
-
|
49
|
-
# Storage for requests by user
|
50
|
-
self.user_requests = defaultdict(list)
|
51
|
-
|
52
|
-
async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
|
53
|
-
"""
|
54
|
-
Processes request and checks rate limit.
|
55
|
-
|
56
|
-
Args:
|
57
|
-
request: Request.
|
58
|
-
call_next: Next handler.
|
59
|
-
|
60
|
-
Returns:
|
61
|
-
Response.
|
62
|
-
"""
|
63
|
-
# Check if path is public
|
64
|
-
path = request.url.path
|
65
|
-
if self._is_public_path(path):
|
66
|
-
# If path is public, skip rate limiting
|
67
|
-
return await call_next(request)
|
68
|
-
|
69
|
-
# Current time
|
70
|
-
current_time = time.time()
|
71
|
-
|
72
|
-
# Get client IP address
|
73
|
-
client_ip = request.client.host if request.client else "unknown"
|
74
|
-
|
75
|
-
# Get user from request state (if any)
|
76
|
-
username = getattr(request.state, "username", None)
|
77
|
-
|
78
|
-
# Check limit by IP
|
79
|
-
if self.by_ip and client_ip != "unknown":
|
80
|
-
# Clean old requests
|
81
|
-
self._clean_old_requests(self.ip_requests[client_ip], current_time)
|
82
|
-
|
83
|
-
# Check number of requests
|
84
|
-
if len(self.ip_requests[client_ip]) >= self.rate_limit:
|
85
|
-
logger.warning(f"Rate limit exceeded for IP: {client_ip} | Path: {path}")
|
86
|
-
return self._create_error_response("Rate limit exceeded", 429)
|
87
|
-
|
88
|
-
# Add current request
|
89
|
-
self.ip_requests[client_ip].append(current_time)
|
90
|
-
|
91
|
-
# Check limit by user
|
92
|
-
if self.by_user and username:
|
93
|
-
# Clean old requests
|
94
|
-
self._clean_old_requests(self.user_requests[username], current_time)
|
95
|
-
|
96
|
-
# Check number of requests
|
97
|
-
if len(self.user_requests[username]) >= self.rate_limit:
|
98
|
-
logger.warning(f"Rate limit exceeded for user: {username} | Path: {path}")
|
99
|
-
return self._create_error_response("Rate limit exceeded", 429)
|
100
|
-
|
101
|
-
# Add current request
|
102
|
-
self.user_requests[username].append(current_time)
|
103
|
-
|
104
|
-
# Call the next middleware or main handler
|
105
|
-
return await call_next(request)
|
106
|
-
|
107
|
-
def _clean_old_requests(self, requests: List[float], current_time: float) -> None:
|
108
|
-
"""
|
109
|
-
Cleans old requests that are outside the time window.
|
110
|
-
|
111
|
-
Args:
|
112
|
-
requests: List of request timestamps.
|
113
|
-
current_time: Current time.
|
114
|
-
"""
|
115
|
-
min_time = current_time - self.time_window
|
116
|
-
while requests and requests[0] < min_time:
|
117
|
-
requests.pop(0)
|
118
|
-
|
119
|
-
def _is_public_path(self, path: str) -> bool:
|
120
|
-
"""
|
121
|
-
Checks if the path is public.
|
122
|
-
|
123
|
-
Args:
|
124
|
-
path: Path to check.
|
125
|
-
|
126
|
-
Returns:
|
127
|
-
True if path is public, False otherwise.
|
128
|
-
"""
|
129
|
-
return any(path.startswith(public_path) for public_path in self.public_paths)
|
130
|
-
|
131
|
-
def _create_error_response(self, message: str, status_code: int) -> Response:
|
132
|
-
"""
|
133
|
-
Creates error response in JSON-RPC format.
|
134
|
-
|
135
|
-
Args:
|
136
|
-
message: Error message.
|
137
|
-
status_code: HTTP status code.
|
138
|
-
|
139
|
-
Returns:
|
140
|
-
JSON response with error.
|
141
|
-
"""
|
142
|
-
return JSONResponse(
|
143
|
-
status_code=status_code,
|
144
|
-
content={
|
145
|
-
"jsonrpc": "2.0",
|
146
|
-
"error": {
|
147
|
-
"code": -32000,
|
148
|
-
"message": message
|
149
|
-
},
|
150
|
-
"id": None
|
151
|
-
}
|
152
|
-
)
|
@@ -1,125 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Reload Settings Command
|
3
|
-
|
4
|
-
This command allows reloading configuration settings from files and environment variables.
|
5
|
-
"""
|
6
|
-
|
7
|
-
from typing import Dict, Any
|
8
|
-
from mcp_proxy_adapter.commands.base import Command
|
9
|
-
from mcp_proxy_adapter.core.settings import reload_settings, get_custom_settings
|
10
|
-
from mcp_proxy_adapter.core.logging import get_logger
|
11
|
-
|
12
|
-
|
13
|
-
class ReloadSettingsResult:
|
14
|
-
"""
|
15
|
-
Result class for reload settings command.
|
16
|
-
"""
|
17
|
-
|
18
|
-
def __init__(
|
19
|
-
self,
|
20
|
-
success: bool,
|
21
|
-
message: str,
|
22
|
-
custom_settings: Dict[str, Any] = None,
|
23
|
-
error_message: str = None
|
24
|
-
):
|
25
|
-
self.success = success
|
26
|
-
self.message = message
|
27
|
-
self.custom_settings = custom_settings or {}
|
28
|
-
self.error_message = error_message
|
29
|
-
|
30
|
-
def to_dict(self) -> Dict[str, Any]:
|
31
|
-
"""Convert result to dictionary."""
|
32
|
-
result = {
|
33
|
-
"success": self.success,
|
34
|
-
"message": self.message,
|
35
|
-
"custom_settings": self.custom_settings
|
36
|
-
}
|
37
|
-
if self.error_message:
|
38
|
-
result["error_message"] = self.error_message
|
39
|
-
return result
|
40
|
-
|
41
|
-
def get_schema(self) -> Dict[str, Any]:
|
42
|
-
"""Get JSON schema for the result."""
|
43
|
-
return {
|
44
|
-
"type": "object",
|
45
|
-
"properties": {
|
46
|
-
"success": {
|
47
|
-
"type": "boolean",
|
48
|
-
"description": "Whether the operation was successful"
|
49
|
-
},
|
50
|
-
"message": {
|
51
|
-
"type": "string",
|
52
|
-
"description": "Operation result message"
|
53
|
-
},
|
54
|
-
"custom_settings": {
|
55
|
-
"type": "object",
|
56
|
-
"description": "Current custom settings after reload",
|
57
|
-
"additionalProperties": True
|
58
|
-
},
|
59
|
-
"error_message": {
|
60
|
-
"type": "string",
|
61
|
-
"description": "Error message if operation failed"
|
62
|
-
}
|
63
|
-
},
|
64
|
-
"required": ["success", "message", "custom_settings"]
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
class ReloadSettingsCommand(Command):
|
69
|
-
"""
|
70
|
-
Command to reload configuration settings.
|
71
|
-
"""
|
72
|
-
|
73
|
-
name = "reload_settings"
|
74
|
-
description = "Reload configuration settings from files and environment variables"
|
75
|
-
|
76
|
-
async def execute(self, **params) -> ReloadSettingsResult:
|
77
|
-
"""
|
78
|
-
Execute the reload settings command.
|
79
|
-
|
80
|
-
Args:
|
81
|
-
**params: Command parameters (not used)
|
82
|
-
|
83
|
-
Returns:
|
84
|
-
ReloadSettingsResult with operation status
|
85
|
-
"""
|
86
|
-
logger = get_logger("reload_settings_command")
|
87
|
-
|
88
|
-
try:
|
89
|
-
logger.info("š Starting settings reload...")
|
90
|
-
|
91
|
-
# Reload configuration from files and environment variables
|
92
|
-
reload_settings()
|
93
|
-
|
94
|
-
# Get current custom settings
|
95
|
-
custom_settings = get_custom_settings()
|
96
|
-
|
97
|
-
logger.info("ā
Settings reloaded successfully")
|
98
|
-
logger.info(f"š Current custom settings: {custom_settings}")
|
99
|
-
|
100
|
-
return ReloadSettingsResult(
|
101
|
-
success=True,
|
102
|
-
message="Settings reloaded successfully from configuration files and environment variables",
|
103
|
-
custom_settings=custom_settings
|
104
|
-
)
|
105
|
-
|
106
|
-
except Exception as e:
|
107
|
-
error_msg = f"Failed to reload settings: {str(e)}"
|
108
|
-
logger.error(f"ā {error_msg}")
|
109
|
-
|
110
|
-
return ReloadSettingsResult(
|
111
|
-
success=False,
|
112
|
-
message="Failed to reload settings",
|
113
|
-
custom_settings=get_custom_settings(),
|
114
|
-
error_message=error_msg
|
115
|
-
)
|
116
|
-
|
117
|
-
@classmethod
|
118
|
-
def get_schema(cls) -> Dict[str, Any]:
|
119
|
-
"""Get JSON schema for the command parameters."""
|
120
|
-
return {
|
121
|
-
"type": "object",
|
122
|
-
"description": "Reload configuration settings from files and environment variables",
|
123
|
-
"properties": {},
|
124
|
-
"additionalProperties": False
|
125
|
-
}
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# Basic Server Example
|
2
|
-
|
3
|
-
A minimal example of MCP Proxy Adapter server without additional commands.
|
4
|
-
|
5
|
-
## Features
|
6
|
-
|
7
|
-
This example demonstrates:
|
8
|
-
- Basic server setup
|
9
|
-
- Built-in commands only (help, health)
|
10
|
-
- Default configuration
|
11
|
-
- No custom commands
|
12
|
-
|
13
|
-
## Available Commands
|
14
|
-
|
15
|
-
- `help` - Get information about available commands
|
16
|
-
- `health` - Get server health status
|
17
|
-
|
18
|
-
## Usage
|
19
|
-
|
20
|
-
### Run the server
|
21
|
-
|
22
|
-
```bash
|
23
|
-
python server.py
|
24
|
-
```
|
25
|
-
|
26
|
-
### Test the server
|
27
|
-
|
28
|
-
```bash
|
29
|
-
# Get help
|
30
|
-
curl -X POST http://localhost:8000/cmd \
|
31
|
-
-H "Content-Type: application/json" \
|
32
|
-
-d '{"command": "help"}'
|
33
|
-
|
34
|
-
# Get health status
|
35
|
-
curl -X POST http://localhost:8000/cmd \
|
36
|
-
-H "Content-Type: application/json" \
|
37
|
-
-d '{"command": "health"}'
|
38
|
-
```
|
39
|
-
|
40
|
-
## API Endpoints
|
41
|
-
|
42
|
-
- `POST /cmd` - Execute commands
|
43
|
-
- `GET /health` - Health check
|
44
|
-
- `GET /commands` - List available commands
|
45
|
-
- `GET /docs` - API documentation
|
46
|
-
|
47
|
-
## Configuration
|
48
|
-
|
49
|
-
The server uses default configuration. You can customize it by:
|
50
|
-
|
51
|
-
1. Creating a `config.json` file
|
52
|
-
2. Setting environment variables
|
53
|
-
3. Passing configuration to `create_app()`
|
54
|
-
|
55
|
-
## Notes
|
56
|
-
|
57
|
-
- This is the simplest possible setup
|
58
|
-
- No custom commands are registered
|
59
|
-
- Uses framework defaults
|
60
|
-
- Good starting point for understanding the framework
|
@@ -1,39 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"application": {
|
3
|
-
"name": "Basic MCP Proxy Server with Custom Settings",
|
4
|
-
"version": "1.1.0",
|
5
|
-
"environment": "development",
|
6
|
-
"description": "Basic server demonstrating custom settings usage"
|
7
|
-
},
|
8
|
-
"features": {
|
9
|
-
"basic_logging": true,
|
10
|
-
"simple_commands": true,
|
11
|
-
"custom_settings_demo": true,
|
12
|
-
"file_based_config": true
|
13
|
-
},
|
14
|
-
"server_info": {
|
15
|
-
"description": "Basic server with file-based custom settings",
|
16
|
-
"author": "MCP Proxy Adapter Team",
|
17
|
-
"contact": "support@example.com",
|
18
|
-
"documentation": "https://example.com/docs"
|
19
|
-
},
|
20
|
-
"demo_settings": {
|
21
|
-
"welcome_message": "Welcome to Basic MCP Proxy Server with Custom Settings!",
|
22
|
-
"max_connections": 150,
|
23
|
-
"timeout": 45,
|
24
|
-
"debug_mode": true,
|
25
|
-
"log_level": "INFO"
|
26
|
-
},
|
27
|
-
"performance": {
|
28
|
-
"enable_caching": true,
|
29
|
-
"cache_ttl": 300,
|
30
|
-
"max_cache_size": 1000
|
31
|
-
},
|
32
|
-
"security": {
|
33
|
-
"enable_rate_limiting": false,
|
34
|
-
"max_request_size": "5MB",
|
35
|
-
"allowed_origins": [
|
36
|
-
"*"
|
37
|
-
]
|
38
|
-
}
|
39
|
-
}
|
@@ -1,35 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"server": {
|
3
|
-
"host": "127.0.0.1",
|
4
|
-
"port": 8000,
|
5
|
-
"debug": true,
|
6
|
-
"log_level": "DEBUG"
|
7
|
-
},
|
8
|
-
"logging": {
|
9
|
-
"level": "DEBUG",
|
10
|
-
"log_dir": "./logs/basic_server",
|
11
|
-
"log_file": "basic_server.log",
|
12
|
-
"error_log_file": "basic_server_error.log",
|
13
|
-
"access_log_file": "basic_server_access.log",
|
14
|
-
"max_file_size": "5MB",
|
15
|
-
"backup_count": 3,
|
16
|
-
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
17
|
-
"date_format": "%Y-%m-%d %H:%M:%S",
|
18
|
-
"console_output": true,
|
19
|
-
"file_output": true
|
20
|
-
},
|
21
|
-
"commands": {
|
22
|
-
"auto_discovery": true,
|
23
|
-
"discovery_path": "mcp_proxy_adapter.commands",
|
24
|
-
"custom_commands_path": null
|
25
|
-
},
|
26
|
-
"custom": {
|
27
|
-
"server_name": "Basic MCP Proxy Server",
|
28
|
-
"description": "Simple example server with basic configuration",
|
29
|
-
"features": {
|
30
|
-
"hooks_enabled": false,
|
31
|
-
"custom_commands_enabled": false,
|
32
|
-
"advanced_logging": false
|
33
|
-
}
|
34
|
-
}
|
35
|
-
}
|
@@ -1,238 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Custom Settings Example for Basic Server
|
3
|
-
|
4
|
-
This example demonstrates how to use custom settings in a basic server.
|
5
|
-
"""
|
6
|
-
|
7
|
-
import json
|
8
|
-
import os
|
9
|
-
from mcp_proxy_adapter.core.settings import (
|
10
|
-
add_custom_settings,
|
11
|
-
get_custom_setting_value,
|
12
|
-
set_custom_setting_value,
|
13
|
-
get_custom_settings
|
14
|
-
)
|
15
|
-
from mcp_proxy_adapter.core.logging import get_logger
|
16
|
-
|
17
|
-
|
18
|
-
def setup_basic_custom_settings():
|
19
|
-
"""
|
20
|
-
Setup basic custom settings for the basic server example.
|
21
|
-
|
22
|
-
This demonstrates how to add custom settings to the framework
|
23
|
-
and access them throughout the application.
|
24
|
-
"""
|
25
|
-
logger = get_logger("basic_server_custom_settings")
|
26
|
-
|
27
|
-
# Define basic custom settings
|
28
|
-
basic_settings = {
|
29
|
-
"application": {
|
30
|
-
"name": "Basic MCP Proxy Server",
|
31
|
-
"version": "1.0.0",
|
32
|
-
"environment": "development"
|
33
|
-
},
|
34
|
-
"features": {
|
35
|
-
"basic_logging": True,
|
36
|
-
"simple_commands": True,
|
37
|
-
"custom_settings_demo": True
|
38
|
-
},
|
39
|
-
"server_info": {
|
40
|
-
"description": "Basic server with custom settings example",
|
41
|
-
"author": "MCP Proxy Adapter Team",
|
42
|
-
"contact": "support@example.com"
|
43
|
-
},
|
44
|
-
"demo_settings": {
|
45
|
-
"welcome_message": "Welcome to Basic MCP Proxy Server!",
|
46
|
-
"max_connections": 100,
|
47
|
-
"timeout": 30,
|
48
|
-
"debug_mode": True
|
49
|
-
}
|
50
|
-
}
|
51
|
-
|
52
|
-
# Add settings to the framework
|
53
|
-
add_custom_settings(basic_settings)
|
54
|
-
|
55
|
-
logger.info("ā
Basic custom settings loaded")
|
56
|
-
logger.info(f"š Application: {basic_settings['application']['name']} v{basic_settings['application']['version']}")
|
57
|
-
logger.info(f"š§ Features: {list(basic_settings['features'].keys())}")
|
58
|
-
|
59
|
-
return basic_settings
|
60
|
-
|
61
|
-
|
62
|
-
def demonstrate_custom_settings_usage():
|
63
|
-
"""
|
64
|
-
Demonstrate how to use custom settings in the application.
|
65
|
-
"""
|
66
|
-
logger = get_logger("basic_server_custom_settings")
|
67
|
-
|
68
|
-
# Get specific settings
|
69
|
-
app_name = get_custom_setting_value("application.name", "Unknown")
|
70
|
-
app_version = get_custom_setting_value("application.version", "0.0.0")
|
71
|
-
welcome_msg = get_custom_setting_value("demo_settings.welcome_message", "Hello!")
|
72
|
-
max_connections = get_custom_setting_value("demo_settings.max_connections", 50)
|
73
|
-
|
74
|
-
logger.info(f"š·ļø Application: {app_name} v{app_version}")
|
75
|
-
logger.info(f"š¬ Welcome Message: {welcome_msg}")
|
76
|
-
logger.info(f"š Max Connections: {max_connections}")
|
77
|
-
|
78
|
-
# Check if features are enabled
|
79
|
-
features = get_custom_setting_value("features", {})
|
80
|
-
enabled_features = [name for name, enabled in features.items() if enabled]
|
81
|
-
|
82
|
-
logger.info(f"ā
Enabled Features: {', '.join(enabled_features)}")
|
83
|
-
|
84
|
-
# Set a new custom setting
|
85
|
-
set_custom_setting_value("demo_settings.last_updated", "2025-08-08")
|
86
|
-
logger.info("š§ Set new custom setting: demo_settings.last_updated")
|
87
|
-
|
88
|
-
# Get all custom settings
|
89
|
-
all_custom_settings = get_custom_settings()
|
90
|
-
logger.info(f"š Total custom settings: {len(all_custom_settings)} sections")
|
91
|
-
|
92
|
-
return {
|
93
|
-
"app_name": app_name,
|
94
|
-
"app_version": app_version,
|
95
|
-
"welcome_message": welcome_msg,
|
96
|
-
"max_connections": max_connections,
|
97
|
-
"enabled_features": enabled_features,
|
98
|
-
"total_settings_sections": len(all_custom_settings)
|
99
|
-
}
|
100
|
-
|
101
|
-
|
102
|
-
def create_custom_settings_file():
|
103
|
-
"""
|
104
|
-
Create a custom settings JSON file for the basic server.
|
105
|
-
"""
|
106
|
-
custom_settings = {
|
107
|
-
"application": {
|
108
|
-
"name": "Basic MCP Proxy Server with Custom Settings",
|
109
|
-
"version": "1.1.0",
|
110
|
-
"environment": "development",
|
111
|
-
"description": "Basic server demonstrating custom settings usage"
|
112
|
-
},
|
113
|
-
"features": {
|
114
|
-
"basic_logging": True,
|
115
|
-
"simple_commands": True,
|
116
|
-
"custom_settings_demo": True,
|
117
|
-
"file_based_config": True
|
118
|
-
},
|
119
|
-
"server_info": {
|
120
|
-
"description": "Basic server with file-based custom settings",
|
121
|
-
"author": "MCP Proxy Adapter Team",
|
122
|
-
"contact": "support@example.com",
|
123
|
-
"documentation": "https://example.com/docs"
|
124
|
-
},
|
125
|
-
"demo_settings": {
|
126
|
-
"welcome_message": "Welcome to Basic MCP Proxy Server with Custom Settings!",
|
127
|
-
"max_connections": 150,
|
128
|
-
"timeout": 45,
|
129
|
-
"debug_mode": True,
|
130
|
-
"log_level": "INFO"
|
131
|
-
},
|
132
|
-
"performance": {
|
133
|
-
"enable_caching": True,
|
134
|
-
"cache_ttl": 300,
|
135
|
-
"max_cache_size": 1000
|
136
|
-
},
|
137
|
-
"security": {
|
138
|
-
"enable_rate_limiting": False,
|
139
|
-
"max_request_size": "5MB",
|
140
|
-
"allowed_origins": ["*"]
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
# Write to file
|
145
|
-
settings_file = "basic_custom_settings.json"
|
146
|
-
with open(settings_file, 'w', encoding='utf-8') as f:
|
147
|
-
json.dump(custom_settings, f, indent=2, ensure_ascii=False)
|
148
|
-
|
149
|
-
print(f"ā
Created custom settings file: {settings_file}")
|
150
|
-
return settings_file
|
151
|
-
|
152
|
-
|
153
|
-
def load_custom_settings_from_file(file_path: str = "basic_custom_settings.json"):
|
154
|
-
"""
|
155
|
-
Load custom settings from a JSON file.
|
156
|
-
|
157
|
-
Args:
|
158
|
-
file_path: Path to the custom settings JSON file
|
159
|
-
"""
|
160
|
-
logger = get_logger("basic_server_custom_settings")
|
161
|
-
|
162
|
-
try:
|
163
|
-
if os.path.exists(file_path):
|
164
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
165
|
-
custom_settings = json.load(f)
|
166
|
-
|
167
|
-
# Add to framework
|
168
|
-
add_custom_settings(custom_settings)
|
169
|
-
|
170
|
-
logger.info(f"š Loaded custom settings from: {file_path}")
|
171
|
-
logger.info(f"š Application: {custom_settings.get('application', {}).get('name', 'Unknown')}")
|
172
|
-
|
173
|
-
return custom_settings
|
174
|
-
else:
|
175
|
-
logger.warning(f"ā ļø Custom settings file not found: {file_path}")
|
176
|
-
return None
|
177
|
-
|
178
|
-
except Exception as e:
|
179
|
-
logger.error(f"ā Failed to load custom settings from {file_path}: {e}")
|
180
|
-
return None
|
181
|
-
|
182
|
-
|
183
|
-
def print_custom_settings_summary():
|
184
|
-
"""
|
185
|
-
Print a summary of current custom settings.
|
186
|
-
"""
|
187
|
-
logger = get_logger("basic_server_custom_settings")
|
188
|
-
|
189
|
-
all_settings = get_custom_settings()
|
190
|
-
|
191
|
-
logger.info("š Custom Settings Summary:")
|
192
|
-
|
193
|
-
# Application info
|
194
|
-
app_name = get_custom_setting_value("application.name", "Unknown")
|
195
|
-
app_version = get_custom_setting_value("application.version", "0.0.0")
|
196
|
-
logger.info(f" Application: {app_name} v{app_version}")
|
197
|
-
|
198
|
-
# Features
|
199
|
-
features = get_custom_setting_value("features", {})
|
200
|
-
enabled_features = [name for name, enabled in features.items() if enabled]
|
201
|
-
logger.info(f" Enabled Features: {', '.join(enabled_features) if enabled_features else 'None'}")
|
202
|
-
|
203
|
-
# Demo settings
|
204
|
-
welcome_msg = get_custom_setting_value("demo_settings.welcome_message", "Hello!")
|
205
|
-
max_connections = get_custom_setting_value("demo_settings.max_connections", 50)
|
206
|
-
logger.info(f" Welcome Message: {welcome_msg}")
|
207
|
-
logger.info(f" Max Connections: {max_connections}")
|
208
|
-
|
209
|
-
# Performance
|
210
|
-
caching_enabled = get_custom_setting_value("performance.enable_caching", False)
|
211
|
-
logger.info(f" Caching: {'Enabled' if caching_enabled else 'Disabled'}")
|
212
|
-
|
213
|
-
# Security
|
214
|
-
rate_limiting = get_custom_setting_value("security.enable_rate_limiting", False)
|
215
|
-
logger.info(f" Rate Limiting: {'Enabled' if rate_limiting else 'Disabled'}")
|
216
|
-
|
217
|
-
logger.info(f" Total Settings Sections: {len(all_settings)}")
|
218
|
-
|
219
|
-
|
220
|
-
if __name__ == "__main__":
|
221
|
-
# Setup basic custom settings
|
222
|
-
setup_basic_custom_settings()
|
223
|
-
|
224
|
-
# Demonstrate usage
|
225
|
-
demo_info = demonstrate_custom_settings_usage()
|
226
|
-
|
227
|
-
# Create custom settings file
|
228
|
-
settings_file = create_custom_settings_file()
|
229
|
-
|
230
|
-
# Load from file
|
231
|
-
load_custom_settings_from_file(settings_file)
|
232
|
-
|
233
|
-
# Print summary
|
234
|
-
print_custom_settings_summary()
|
235
|
-
|
236
|
-
print("\nš Custom settings demonstration completed!")
|
237
|
-
print(f"š Custom settings file: {settings_file}")
|
238
|
-
print("š§ You can now use these settings in your basic server application.")
|