mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.
Potentially problematic release.
This version of mcp-proxy-adapter might be problematic. Click here for more details.
- mcp_proxy_adapter/__init__.py +47 -0
- mcp_proxy_adapter/__main__.py +13 -0
- mcp_proxy_adapter/api/__init__.py +0 -0
- mcp_proxy_adapter/api/app.py +66 -0
- mcp_proxy_adapter/api/core/__init__.py +18 -0
- mcp_proxy_adapter/api/core/app_factory.py +400 -0
- mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
- mcp_proxy_adapter/api/core/registration_context.py +356 -0
- mcp_proxy_adapter/api/core/registration_manager.py +307 -0
- mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
- mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
- mcp_proxy_adapter/api/handlers.py +181 -0
- mcp_proxy_adapter/api/middleware/__init__.py +21 -0
- mcp_proxy_adapter/api/middleware/base.py +54 -0
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
- mcp_proxy_adapter/api/middleware/factory.py +147 -0
- mcp_proxy_adapter/api/middleware/logging.py +31 -0
- mcp_proxy_adapter/api/middleware/performance.py +51 -0
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
- mcp_proxy_adapter/api/openapi/__init__.py +21 -0
- mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
- mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
- mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
- mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
- mcp_proxy_adapter/api/schemas.py +270 -0
- mcp_proxy_adapter/api/tool_integration.py +131 -0
- mcp_proxy_adapter/api/tools.py +163 -0
- mcp_proxy_adapter/cli/__init__.py +12 -0
- mcp_proxy_adapter/cli/commands/__init__.py +15 -0
- mcp_proxy_adapter/cli/commands/client.py +100 -0
- mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
- mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
- mcp_proxy_adapter/cli/commands/generate.py +259 -0
- mcp_proxy_adapter/cli/commands/server.py +174 -0
- mcp_proxy_adapter/cli/commands/sets.py +132 -0
- mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
- mcp_proxy_adapter/cli/examples/__init__.py +8 -0
- mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
- mcp_proxy_adapter/cli/examples/https_token.py +96 -0
- mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
- mcp_proxy_adapter/cli/main.py +63 -0
- mcp_proxy_adapter/cli/parser.py +338 -0
- mcp_proxy_adapter/cli/validators.py +231 -0
- mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
- mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
- mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
- mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
- mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
- mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
- mcp_proxy_adapter/client/proxy.py +123 -0
- mcp_proxy_adapter/commands/__init__.py +66 -0
- mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
- mcp_proxy_adapter/commands/base.py +389 -0
- mcp_proxy_adapter/commands/builtin_commands.py +30 -0
- mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
- mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
- mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
- mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
- mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
- mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
- mcp_proxy_adapter/commands/catalog_manager.py +97 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
- mcp_proxy_adapter/commands/command_registry.py +298 -0
- mcp_proxy_adapter/commands/config_command.py +102 -0
- mcp_proxy_adapter/commands/dependency_container.py +40 -0
- mcp_proxy_adapter/commands/dependency_manager.py +143 -0
- mcp_proxy_adapter/commands/echo_command.py +48 -0
- mcp_proxy_adapter/commands/health_command.py +142 -0
- mcp_proxy_adapter/commands/help_command.py +175 -0
- mcp_proxy_adapter/commands/hooks.py +172 -0
- mcp_proxy_adapter/commands/key_management_command.py +484 -0
- mcp_proxy_adapter/commands/load_command.py +123 -0
- mcp_proxy_adapter/commands/plugins_command.py +246 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
- mcp_proxy_adapter/commands/queue_commands.py +750 -0
- mcp_proxy_adapter/commands/registration_status_command.py +76 -0
- mcp_proxy_adapter/commands/registry/__init__.py +18 -0
- mcp_proxy_adapter/commands/registry/command_info.py +103 -0
- mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
- mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
- mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
- mcp_proxy_adapter/commands/reload_command.py +136 -0
- mcp_proxy_adapter/commands/result.py +157 -0
- mcp_proxy_adapter/commands/role_test_command.py +99 -0
- mcp_proxy_adapter/commands/roles_management_command.py +502 -0
- mcp_proxy_adapter/commands/security_command.py +472 -0
- mcp_proxy_adapter/commands/settings_command.py +113 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
- mcp_proxy_adapter/commands/token_management_command.py +500 -0
- mcp_proxy_adapter/commands/transport_management_command.py +129 -0
- mcp_proxy_adapter/commands/unload_command.py +92 -0
- mcp_proxy_adapter/config.py +32 -0
- mcp_proxy_adapter/core/__init__.py +8 -0
- mcp_proxy_adapter/core/app_factory.py +560 -0
- mcp_proxy_adapter/core/app_runner.py +318 -0
- mcp_proxy_adapter/core/auth_validator.py +508 -0
- mcp_proxy_adapter/core/certificate/__init__.py +20 -0
- mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
- mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
- mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
- mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
- mcp_proxy_adapter/core/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/client.py +608 -0
- mcp_proxy_adapter/core/client_manager.py +271 -0
- mcp_proxy_adapter/core/client_security.py +411 -0
- mcp_proxy_adapter/core/config/__init__.py +18 -0
- mcp_proxy_adapter/core/config/config.py +237 -0
- mcp_proxy_adapter/core/config/config_factory.py +22 -0
- mcp_proxy_adapter/core/config/config_loader.py +66 -0
- mcp_proxy_adapter/core/config/feature_manager.py +31 -0
- mcp_proxy_adapter/core/config/simple_config.py +204 -0
- mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
- mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
- mcp_proxy_adapter/core/config_converter.py +252 -0
- mcp_proxy_adapter/core/config_validator.py +211 -0
- mcp_proxy_adapter/core/crl_utils.py +362 -0
- mcp_proxy_adapter/core/errors.py +276 -0
- mcp_proxy_adapter/core/job_manager.py +54 -0
- mcp_proxy_adapter/core/logging.py +250 -0
- mcp_proxy_adapter/core/mtls_asgi.py +140 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/mtls_proxy.py +229 -0
- mcp_proxy_adapter/core/mtls_server.py +154 -0
- mcp_proxy_adapter/core/protocol_manager.py +232 -0
- mcp_proxy_adapter/core/proxy/__init__.py +19 -0
- mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
- mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
- mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
- mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
- mcp_proxy_adapter/core/proxy_client.py +184 -0
- mcp_proxy_adapter/core/proxy_registration.py +80 -0
- mcp_proxy_adapter/core/role_utils.py +103 -0
- mcp_proxy_adapter/core/security_adapter.py +343 -0
- mcp_proxy_adapter/core/security_factory.py +96 -0
- mcp_proxy_adapter/core/security_integration.py +342 -0
- mcp_proxy_adapter/core/server_adapter.py +251 -0
- mcp_proxy_adapter/core/server_engine.py +217 -0
- mcp_proxy_adapter/core/settings.py +260 -0
- mcp_proxy_adapter/core/signal_handler.py +107 -0
- mcp_proxy_adapter/core/ssl_utils.py +161 -0
- mcp_proxy_adapter/core/transport_manager.py +153 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
- mcp_proxy_adapter/core/utils.py +101 -0
- mcp_proxy_adapter/core/validation/__init__.py +21 -0
- mcp_proxy_adapter/core/validation/config_validator.py +219 -0
- mcp_proxy_adapter/core/validation/file_validator.py +131 -0
- mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
- mcp_proxy_adapter/core/validation/security_validator.py +140 -0
- mcp_proxy_adapter/core/validation/validation_result.py +27 -0
- mcp_proxy_adapter/custom_openapi.py +58 -0
- mcp_proxy_adapter/examples/__init__.py +16 -0
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
- mcp_proxy_adapter/examples/check_config.py +413 -0
- mcp_proxy_adapter/examples/client_usage_example.py +164 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/config_builder.py +234 -0
- mcp_proxy_adapter/examples/config_cli.py +282 -0
- mcp_proxy_adapter/examples/create_test_configs.py +174 -0
- mcp_proxy_adapter/examples/debug_request_state.py +130 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
- mcp_proxy_adapter/examples/demo_client.py +287 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
- mcp_proxy_adapter/examples/full_application/main.py +311 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
- mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
- mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
- mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
- mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
- mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
- mcp_proxy_adapter/examples/generate_config.py +502 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
- mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
- mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
- mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
- mcp_proxy_adapter/examples/queue_server_example.py +85 -0
- mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
- mcp_proxy_adapter/examples/required_certificates.py +208 -0
- mcp_proxy_adapter/examples/run_example.py +77 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
- mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
- mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
- mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
- mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
- mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
- mcp_proxy_adapter/examples/security_test_client.py +72 -0
- mcp_proxy_adapter/examples/setup/__init__.py +24 -0
- mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
- mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
- mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
- mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
- mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
- mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
- mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
- mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
- mcp_proxy_adapter/examples/test_config.py +205 -0
- mcp_proxy_adapter/examples/test_config_builder.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +308 -0
- mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
- mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
- mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
- mcp_proxy_adapter/examples/universal_client.py +674 -0
- mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
- mcp_proxy_adapter/integrations/__init__.py +25 -0
- mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
- mcp_proxy_adapter/main.py +311 -0
- mcp_proxy_adapter/openapi.py +375 -0
- mcp_proxy_adapter/schemas/base_schema.json +114 -0
- mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
- mcp_proxy_adapter/schemas/roles.json +37 -0
- mcp_proxy_adapter/schemas/roles_schema.json +162 -0
- mcp_proxy_adapter/version.py +5 -0
- mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
- mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
- {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
- mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
- mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
- adapters/__init__.py +0 -16
- analyzers/__init__.py +0 -14
- analyzers/docstring_analyzer.py +0 -199
- analyzers/type_analyzer.py +0 -151
- cli/__init__.py +0 -12
- cli/__main__.py +0 -79
- cli/command_runner.py +0 -233
- dispatchers/__init__.py +0 -14
- dispatchers/base_dispatcher.py +0 -85
- dispatchers/json_rpc_dispatcher.py +0 -198
- generators/__init__.py +0 -14
- generators/endpoint_generator.py +0 -172
- generators/openapi_generator.py +0 -254
- generators/rest_api_generator.py +0 -207
- mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
- mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
- mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
- mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
- openapi_schema/__init__.py +0 -38
- openapi_schema/command_registry.py +0 -312
- openapi_schema/rest_schema.py +0 -510
- openapi_schema/rpc_generator.py +0 -307
- openapi_schema/rpc_schema.py +0 -416
- validators/__init__.py +0 -14
- validators/base_validator.py +0 -23
- validators/docstring_validator.py +0 -75
- validators/metadata_validator.py +0 -76
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"""Proxy registration helpers for JsonRpcClient.
|
|
2
|
+
|
|
3
|
+
Author: Vasiliy Zdanovskiy
|
|
4
|
+
email: vasilyvz@gmail.com
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import re
|
|
11
|
+
from typing import Any, Dict, List, Optional, Tuple, Union, cast
|
|
12
|
+
|
|
13
|
+
import httpx
|
|
14
|
+
|
|
15
|
+
from mcp_proxy_adapter.client.jsonrpc_client.transport import JsonRpcTransport
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ProxyApiMixin(JsonRpcTransport):
|
|
19
|
+
"""Mixin providing proxy registration helpers."""
|
|
20
|
+
|
|
21
|
+
async def register_with_proxy(
|
|
22
|
+
self,
|
|
23
|
+
proxy_url: str,
|
|
24
|
+
server_name: str,
|
|
25
|
+
server_url: str,
|
|
26
|
+
capabilities: Optional[List[str]] = None,
|
|
27
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
28
|
+
cert: Optional[Tuple[str, str]] = None,
|
|
29
|
+
verify: Optional[Union[bool, str]] = None,
|
|
30
|
+
) -> Dict[str, Any]:
|
|
31
|
+
payload: Dict[str, Any] = {
|
|
32
|
+
"server_id": server_name,
|
|
33
|
+
"server_url": server_url,
|
|
34
|
+
"capabilities": capabilities or [],
|
|
35
|
+
"metadata": metadata or {},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
ssl_verify = verify if verify is not None else self.verify
|
|
39
|
+
ssl_cert = cert if cert is not None else self.cert
|
|
40
|
+
|
|
41
|
+
proxy_base = proxy_url.rstrip("/")
|
|
42
|
+
register_url = (
|
|
43
|
+
proxy_base if proxy_base.endswith("/register") else f"{proxy_base}/register"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
logger = logging.getLogger(__name__)
|
|
47
|
+
logger.debug(
|
|
48
|
+
"Registering with proxy: %s, cert=%s, verify=%s",
|
|
49
|
+
register_url,
|
|
50
|
+
ssl_cert is not None,
|
|
51
|
+
ssl_verify,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
async with httpx.AsyncClient(
|
|
56
|
+
verify=ssl_verify, cert=ssl_cert, timeout=10.0
|
|
57
|
+
) as client:
|
|
58
|
+
response = await client.post(register_url, json=payload)
|
|
59
|
+
|
|
60
|
+
if response.status_code == 400:
|
|
61
|
+
error_data = cast(Dict[str, Any], response.json())
|
|
62
|
+
error_msg = error_data.get("error", "").lower()
|
|
63
|
+
if "already registered" in error_msg:
|
|
64
|
+
await self._retry_registration_after_unregister(
|
|
65
|
+
client,
|
|
66
|
+
proxy_base,
|
|
67
|
+
register_url,
|
|
68
|
+
server_name,
|
|
69
|
+
server_url,
|
|
70
|
+
capabilities,
|
|
71
|
+
metadata,
|
|
72
|
+
error_data,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if response.status_code >= 400:
|
|
76
|
+
try:
|
|
77
|
+
error_data = cast(Dict[str, Any], response.json())
|
|
78
|
+
error_msg = error_data.get(
|
|
79
|
+
"error",
|
|
80
|
+
error_data.get("message", f"HTTP {response.status_code}"),
|
|
81
|
+
)
|
|
82
|
+
raise httpx.HTTPStatusError(
|
|
83
|
+
f"Registration failed: {error_msg}",
|
|
84
|
+
request=response.request,
|
|
85
|
+
response=response,
|
|
86
|
+
)
|
|
87
|
+
except (ValueError, KeyError):
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
|
|
90
|
+
response.raise_for_status()
|
|
91
|
+
return cast(Dict[str, Any], response.json())
|
|
92
|
+
except httpx.ConnectError as exc: # noqa: BLE001
|
|
93
|
+
error_msg = f"Connection failed to {register_url}"
|
|
94
|
+
if hasattr(exc, "request"):
|
|
95
|
+
error_msg += f" (request: {exc.request.url})"
|
|
96
|
+
raise ConnectionError(error_msg) from exc
|
|
97
|
+
except httpx.TimeoutException as exc: # noqa: BLE001
|
|
98
|
+
raise TimeoutError(f"Request timeout to {register_url}") from exc
|
|
99
|
+
except httpx.HTTPError as exc: # noqa: BLE001
|
|
100
|
+
raise ConnectionError(
|
|
101
|
+
f"HTTP error connecting to {register_url}: {exc}"
|
|
102
|
+
) from exc
|
|
103
|
+
|
|
104
|
+
async def unregister_from_proxy(
|
|
105
|
+
self,
|
|
106
|
+
proxy_url: str,
|
|
107
|
+
server_name: str,
|
|
108
|
+
cert: Optional[Tuple[str, str]] = None,
|
|
109
|
+
verify: Optional[Union[bool, str]] = None,
|
|
110
|
+
) -> Dict[str, Any]:
|
|
111
|
+
payload: Dict[str, Any] = {
|
|
112
|
+
"server_id": server_name,
|
|
113
|
+
"server_url": "",
|
|
114
|
+
"capabilities": [],
|
|
115
|
+
"metadata": {},
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ssl_verify = verify if verify is not None else self.verify
|
|
119
|
+
ssl_cert = cert if cert is not None else self.cert
|
|
120
|
+
|
|
121
|
+
proxy_base = proxy_url.rstrip("/")
|
|
122
|
+
unregister_url = (
|
|
123
|
+
proxy_base
|
|
124
|
+
if proxy_base.endswith("/unregister")
|
|
125
|
+
else f"{proxy_base}/unregister"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
async with httpx.AsyncClient(
|
|
129
|
+
verify=ssl_verify, cert=ssl_cert, timeout=10.0
|
|
130
|
+
) as client:
|
|
131
|
+
response = await client.post(unregister_url, json=payload)
|
|
132
|
+
response.raise_for_status()
|
|
133
|
+
return cast(Dict[str, Any], response.json())
|
|
134
|
+
|
|
135
|
+
async def heartbeat_to_proxy(
|
|
136
|
+
self,
|
|
137
|
+
proxy_url: str,
|
|
138
|
+
server_name: str,
|
|
139
|
+
server_url: str,
|
|
140
|
+
capabilities: Optional[List[str]] = None,
|
|
141
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
142
|
+
cert: Optional[Tuple[str, str]] = None,
|
|
143
|
+
verify: Optional[Union[bool, str]] = None,
|
|
144
|
+
) -> None:
|
|
145
|
+
payload: Dict[str, Any] = {
|
|
146
|
+
"server_id": server_name,
|
|
147
|
+
"server_url": server_url,
|
|
148
|
+
"capabilities": capabilities or [],
|
|
149
|
+
"metadata": metadata or {},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
ssl_verify = verify if verify is not None else self.verify
|
|
153
|
+
ssl_cert = cert if cert is not None else self.cert
|
|
154
|
+
|
|
155
|
+
proxy_base = proxy_url.rstrip("/")
|
|
156
|
+
async with httpx.AsyncClient(
|
|
157
|
+
verify=ssl_verify, cert=ssl_cert, timeout=10.0
|
|
158
|
+
) as client:
|
|
159
|
+
response = await client.post(
|
|
160
|
+
f"{proxy_base}/proxy/heartbeat",
|
|
161
|
+
json=payload,
|
|
162
|
+
)
|
|
163
|
+
response.raise_for_status()
|
|
164
|
+
|
|
165
|
+
async def list_proxy_servers(self, proxy_url: str) -> Dict[str, Any]:
|
|
166
|
+
proxy_base = proxy_url.rstrip("/")
|
|
167
|
+
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
168
|
+
response = await client.get(f"{proxy_base}/proxy/list")
|
|
169
|
+
response.raise_for_status()
|
|
170
|
+
return cast(Dict[str, Any], response.json())
|
|
171
|
+
|
|
172
|
+
async def get_proxy_health(self, proxy_url: str) -> Dict[str, Any]:
|
|
173
|
+
proxy_base = proxy_url.rstrip("/")
|
|
174
|
+
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
175
|
+
response = await client.get(f"{proxy_base}/proxy/health")
|
|
176
|
+
response.raise_for_status()
|
|
177
|
+
return cast(Dict[str, Any], response.json())
|
|
178
|
+
|
|
179
|
+
async def _retry_registration_after_unregister(
|
|
180
|
+
self,
|
|
181
|
+
client: httpx.AsyncClient,
|
|
182
|
+
proxy_base: str,
|
|
183
|
+
register_url: str,
|
|
184
|
+
server_name: str,
|
|
185
|
+
server_url: str,
|
|
186
|
+
capabilities: Optional[List[str]],
|
|
187
|
+
metadata: Optional[Dict[str, Any]],
|
|
188
|
+
error_data: Dict[str, Any],
|
|
189
|
+
) -> None:
|
|
190
|
+
match = re.search(
|
|
191
|
+
r"already registered as ([^\s,]+)",
|
|
192
|
+
error_data.get("error", ""),
|
|
193
|
+
re.IGNORECASE,
|
|
194
|
+
)
|
|
195
|
+
if not match:
|
|
196
|
+
return
|
|
197
|
+
|
|
198
|
+
registered_server_key = match.group(1)
|
|
199
|
+
original_server_id = (
|
|
200
|
+
re.sub(r"_\d+$", "", registered_server_key)
|
|
201
|
+
if "_" in registered_server_key
|
|
202
|
+
else registered_server_key
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
unregister_payload: Dict[str, Any] = {
|
|
206
|
+
"server_id": original_server_id,
|
|
207
|
+
"server_url": "",
|
|
208
|
+
"capabilities": [],
|
|
209
|
+
"metadata": {},
|
|
210
|
+
}
|
|
211
|
+
unregister_response = await client.post(
|
|
212
|
+
f"{proxy_base}/unregister",
|
|
213
|
+
json=unregister_payload,
|
|
214
|
+
)
|
|
215
|
+
if unregister_response.status_code != 200:
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
retry_payload: Dict[str, Any] = {
|
|
219
|
+
"server_id": server_name,
|
|
220
|
+
"server_url": server_url,
|
|
221
|
+
"capabilities": capabilities or [],
|
|
222
|
+
"metadata": metadata or {},
|
|
223
|
+
}
|
|
224
|
+
await client.post(register_url, json=retry_payload)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Queue management helpers for JsonRpcClient.
|
|
2
|
+
|
|
3
|
+
Author: Vasiliy Zdanovskiy
|
|
4
|
+
email: vasilyvz@gmail.com
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
|
|
11
|
+
from mcp_proxy_adapter.client.jsonrpc_client.transport import JsonRpcTransport
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QueueApiMixin(JsonRpcTransport):
|
|
15
|
+
"""Mixin with queue-related JSON-RPC shortcuts."""
|
|
16
|
+
|
|
17
|
+
async def queue_health(self) -> Dict[str, Any]:
|
|
18
|
+
response = await self.jsonrpc_call("queue_health", {})
|
|
19
|
+
return self._extract_result(response)
|
|
20
|
+
|
|
21
|
+
async def queue_add_job(
|
|
22
|
+
self,
|
|
23
|
+
job_type: str,
|
|
24
|
+
job_id: str,
|
|
25
|
+
params: Dict[str, Any],
|
|
26
|
+
) -> Dict[str, Any]:
|
|
27
|
+
payload = {"job_type": job_type, "job_id": job_id, "params": params}
|
|
28
|
+
response = await self.jsonrpc_call("queue_add_job", payload)
|
|
29
|
+
return self._extract_result(response)
|
|
30
|
+
|
|
31
|
+
async def queue_start_job(self, job_id: str) -> Dict[str, Any]:
|
|
32
|
+
response = await self.jsonrpc_call("queue_start_job", {"job_id": job_id})
|
|
33
|
+
return self._extract_result(response)
|
|
34
|
+
|
|
35
|
+
async def queue_stop_job(self, job_id: str) -> Dict[str, Any]:
|
|
36
|
+
response = await self.jsonrpc_call("queue_stop_job", {"job_id": job_id})
|
|
37
|
+
return self._extract_result(response)
|
|
38
|
+
|
|
39
|
+
async def queue_delete_job(self, job_id: str) -> Dict[str, Any]:
|
|
40
|
+
response = await self.jsonrpc_call("queue_delete_job", {"job_id": job_id})
|
|
41
|
+
return self._extract_result(response)
|
|
42
|
+
|
|
43
|
+
async def queue_get_job_status(self, job_id: str) -> Dict[str, Any]:
|
|
44
|
+
response = await self.jsonrpc_call(
|
|
45
|
+
"queue_get_job_status", {"job_id": job_id}
|
|
46
|
+
)
|
|
47
|
+
return self._extract_result(response)
|
|
48
|
+
|
|
49
|
+
async def queue_list_jobs(
|
|
50
|
+
self,
|
|
51
|
+
status: Optional[str] = None,
|
|
52
|
+
job_type: Optional[str] = None,
|
|
53
|
+
) -> Dict[str, Any]:
|
|
54
|
+
params: Dict[str, Any] = {}
|
|
55
|
+
if status:
|
|
56
|
+
params["status"] = status
|
|
57
|
+
if job_type:
|
|
58
|
+
params["job_type"] = job_type
|
|
59
|
+
response = await self.jsonrpc_call("queue_list_jobs", params)
|
|
60
|
+
return self._extract_result(response)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Transport utilities for asynchronous JSON-RPC client.
|
|
2
|
+
|
|
3
|
+
Author: Vasiliy Zdanovskiy
|
|
4
|
+
email: vasilyvz@gmail.com
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Dict, Optional, Tuple, Union, cast
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class JsonRpcTransport:
|
|
16
|
+
"""Base transport class providing HTTP primitives."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
protocol: str = "http",
|
|
21
|
+
host: str = "127.0.0.1",
|
|
22
|
+
port: int = 8080,
|
|
23
|
+
token_header: Optional[str] = None,
|
|
24
|
+
token: Optional[str] = None,
|
|
25
|
+
cert: Optional[str] = None,
|
|
26
|
+
key: Optional[str] = None,
|
|
27
|
+
ca: Optional[str] = None,
|
|
28
|
+
) -> None:
|
|
29
|
+
scheme = "https" if protocol in ("https", "mtls") else "http"
|
|
30
|
+
self.base_url = f"{scheme}://{host}:{port}"
|
|
31
|
+
|
|
32
|
+
self.headers: Dict[str, str] = {"Content-Type": "application/json"}
|
|
33
|
+
if token_header and token:
|
|
34
|
+
self.headers[token_header] = token
|
|
35
|
+
|
|
36
|
+
self.verify: Union[bool, str] = True
|
|
37
|
+
self.cert: Optional[Tuple[str, str]] = None
|
|
38
|
+
|
|
39
|
+
if protocol in ("https", "mtls"):
|
|
40
|
+
if cert and key:
|
|
41
|
+
self.cert = (str(Path(cert)), str(Path(key)))
|
|
42
|
+
if ca:
|
|
43
|
+
self.verify = str(Path(ca))
|
|
44
|
+
else:
|
|
45
|
+
self.verify = False
|
|
46
|
+
|
|
47
|
+
self.timeout = 30.0
|
|
48
|
+
self._client: Optional[httpx.AsyncClient] = None
|
|
49
|
+
|
|
50
|
+
async def _get_client(self) -> httpx.AsyncClient:
|
|
51
|
+
"""Return cached async HTTP client or create it lazily."""
|
|
52
|
+
|
|
53
|
+
if self._client is None:
|
|
54
|
+
self._client = httpx.AsyncClient(
|
|
55
|
+
verify=self.verify,
|
|
56
|
+
cert=self.cert,
|
|
57
|
+
timeout=self.timeout,
|
|
58
|
+
)
|
|
59
|
+
return self._client
|
|
60
|
+
|
|
61
|
+
async def close(self) -> None:
|
|
62
|
+
"""Close underlying HTTPX client."""
|
|
63
|
+
|
|
64
|
+
if self._client:
|
|
65
|
+
await self._client.aclose()
|
|
66
|
+
self._client = None
|
|
67
|
+
|
|
68
|
+
async def health(self) -> Dict[str, Any]:
|
|
69
|
+
"""Fetch health information from service."""
|
|
70
|
+
|
|
71
|
+
client = await self._get_client()
|
|
72
|
+
response = await client.get(f"{self.base_url}/health", headers=self.headers)
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
return cast(Dict[str, Any], response.json())
|
|
75
|
+
|
|
76
|
+
async def jsonrpc_call(
|
|
77
|
+
self,
|
|
78
|
+
method: str,
|
|
79
|
+
params: Dict[str, Any],
|
|
80
|
+
req_id: int = 1,
|
|
81
|
+
) -> Dict[str, Any]:
|
|
82
|
+
"""Perform JSON-RPC request and return raw response payload."""
|
|
83
|
+
|
|
84
|
+
payload: Dict[str, Any] = {
|
|
85
|
+
"jsonrpc": "2.0",
|
|
86
|
+
"method": method,
|
|
87
|
+
"params": params,
|
|
88
|
+
"id": req_id,
|
|
89
|
+
}
|
|
90
|
+
client = await self._get_client()
|
|
91
|
+
response = await client.post(
|
|
92
|
+
f"{self.base_url}/api/jsonrpc",
|
|
93
|
+
json=payload,
|
|
94
|
+
headers=self.headers,
|
|
95
|
+
)
|
|
96
|
+
response.raise_for_status()
|
|
97
|
+
return cast(Dict[str, Any], response.json())
|
|
98
|
+
|
|
99
|
+
def _extract_result(self, response: Dict[str, Any]) -> Dict[str, Any]:
|
|
100
|
+
"""Extract ``result`` part from JSON-RPC reply raising on error."""
|
|
101
|
+
|
|
102
|
+
if "error" in response:
|
|
103
|
+
error = response["error"]
|
|
104
|
+
message = error.get("message", "Unknown error")
|
|
105
|
+
code = error.get("code", -1)
|
|
106
|
+
raise RuntimeError(f"JSON-RPC error: {message} (code: {code})")
|
|
107
|
+
result_data = response.get("result", {})
|
|
108
|
+
return cast(Dict[str, Any], result_data)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Vasiliy Zdanovskiy
|
|
3
|
+
email: vasilyvz@gmail.com
|
|
4
|
+
|
|
5
|
+
Lightweight asynchronous client library for registry (proxy) server used in examples.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
import httpx
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProxyClient:
|
|
14
|
+
"""Asynchronous client for proxy server."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, base_url: str):
|
|
17
|
+
"""
|
|
18
|
+
Initialize proxy client.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
base_url: Base URL of the proxy server
|
|
22
|
+
"""
|
|
23
|
+
self.base_url = base_url.rstrip("/")
|
|
24
|
+
self._client: Optional[httpx.AsyncClient] = None
|
|
25
|
+
|
|
26
|
+
async def _get_client(self) -> httpx.AsyncClient:
|
|
27
|
+
"""Get or create async HTTP client."""
|
|
28
|
+
if self._client is None:
|
|
29
|
+
self._client = httpx.AsyncClient(timeout=5.0)
|
|
30
|
+
return self._client
|
|
31
|
+
|
|
32
|
+
async def close(self) -> None:
|
|
33
|
+
"""Close the HTTP client."""
|
|
34
|
+
if self._client:
|
|
35
|
+
await self._client.aclose()
|
|
36
|
+
self._client = None
|
|
37
|
+
|
|
38
|
+
async def health(self) -> Dict[str, Any]:
|
|
39
|
+
"""
|
|
40
|
+
Get proxy server health status.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Health status information
|
|
44
|
+
"""
|
|
45
|
+
client = await self._get_client()
|
|
46
|
+
r = await client.get(f"{self.base_url}/proxy/health")
|
|
47
|
+
r.raise_for_status()
|
|
48
|
+
return r.json() # type: ignore[no-any-return]
|
|
49
|
+
|
|
50
|
+
async def register(
|
|
51
|
+
self,
|
|
52
|
+
name: str,
|
|
53
|
+
url: str,
|
|
54
|
+
capabilities: Optional[List[str]] = None,
|
|
55
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
56
|
+
) -> Dict[str, Any]:
|
|
57
|
+
"""
|
|
58
|
+
Register a server with the proxy.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
name: Server name
|
|
62
|
+
url: Server URL
|
|
63
|
+
capabilities: Optional list of capabilities
|
|
64
|
+
metadata: Optional metadata dictionary
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Registration result
|
|
68
|
+
"""
|
|
69
|
+
payload = {
|
|
70
|
+
"name": name,
|
|
71
|
+
"url": url,
|
|
72
|
+
"capabilities": capabilities or [],
|
|
73
|
+
"metadata": metadata or {},
|
|
74
|
+
}
|
|
75
|
+
client = await self._get_client()
|
|
76
|
+
r = await client.post(f"{self.base_url}/register", json=payload)
|
|
77
|
+
r.raise_for_status()
|
|
78
|
+
return r.json() # type: ignore[no-any-return]
|
|
79
|
+
|
|
80
|
+
async def unregister(self, name: str) -> Dict[str, Any]:
|
|
81
|
+
"""
|
|
82
|
+
Unregister a server from the proxy.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
name: Server name
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Unregistration result
|
|
89
|
+
"""
|
|
90
|
+
payload = {"name": name, "url": "", "capabilities": [], "metadata": {}}
|
|
91
|
+
client = await self._get_client()
|
|
92
|
+
r = await client.post(f"{self.base_url}/unregister", json=payload)
|
|
93
|
+
r.raise_for_status()
|
|
94
|
+
return r.json() # type: ignore[no-any-return]
|
|
95
|
+
|
|
96
|
+
async def list_servers(self) -> Dict[str, Any]:
|
|
97
|
+
"""
|
|
98
|
+
List all servers registered with the proxy.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
List of registered servers
|
|
102
|
+
"""
|
|
103
|
+
client = await self._get_client()
|
|
104
|
+
r = await client.get(f"{self.base_url}/proxy/list")
|
|
105
|
+
r.raise_for_status()
|
|
106
|
+
return r.json() # type: ignore[no-any-return]
|
|
107
|
+
|
|
108
|
+
async def heartbeat(self, name: str, url: str) -> Dict[str, Any]:
|
|
109
|
+
"""
|
|
110
|
+
Send heartbeat to the proxy.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
name: Server name
|
|
114
|
+
url: Server URL
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Heartbeat result
|
|
118
|
+
"""
|
|
119
|
+
payload = {"name": name, "url": url, "capabilities": [], "metadata": {}}
|
|
120
|
+
client = await self._get_client()
|
|
121
|
+
r = await client.post(f"{self.base_url}/proxy/heartbeat", json=payload)
|
|
122
|
+
r.raise_for_status()
|
|
123
|
+
return r.json() # type: ignore[no-any-return]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Commands module initialization file.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from mcp_proxy_adapter.commands.base import Command
|
|
6
|
+
from mcp_proxy_adapter.commands.command_registry import registry, CommandRegistry
|
|
7
|
+
from mcp_proxy_adapter.commands.dependency_container import (
|
|
8
|
+
container,
|
|
9
|
+
DependencyContainer,
|
|
10
|
+
)
|
|
11
|
+
from mcp_proxy_adapter.commands.result import CommandResult, SuccessResult, ErrorResult
|
|
12
|
+
# from mcp_proxy_adapter.commands.auth_validation_command import AuthValidationCommand
|
|
13
|
+
# from mcp_proxy_adapter.commands.ssl_setup_command import SSLSetupCommand
|
|
14
|
+
# from mcp_proxy_adapter.commands.certificate_management_command import (
|
|
15
|
+
# CertificateManagementCommand,
|
|
16
|
+
# )
|
|
17
|
+
# from mcp_proxy_adapter.commands.key_management_command import KeyManagementCommand
|
|
18
|
+
# from mcp_proxy_adapter.commands.cert_monitor_command import CertMonitorCommand
|
|
19
|
+
# from mcp_proxy_adapter.commands.transport_management_command import (
|
|
20
|
+
# TransportManagementCommand,
|
|
21
|
+
# )
|
|
22
|
+
# from mcp_proxy_adapter.commands.role_test_command import RoleTestCommand
|
|
23
|
+
# from mcp_proxy_adapter.commands.echo_command import EchoCommand
|
|
24
|
+
# from mcp_proxy_adapter.commands.proxy_registration_command import (
|
|
25
|
+
# ProxyRegistrationCommand,
|
|
26
|
+
# )
|
|
27
|
+
# from mcp_proxy_adapter.commands.registration_status_command import (
|
|
28
|
+
# RegistrationStatusCommand,
|
|
29
|
+
# )
|
|
30
|
+
# from mcp_proxy_adapter.commands.queue_commands import (
|
|
31
|
+
# QueueAddJobCommand,
|
|
32
|
+
# QueueStartJobCommand,
|
|
33
|
+
# QueueStopJobCommand,
|
|
34
|
+
# QueueDeleteJobCommand,
|
|
35
|
+
# QueueGetJobStatusCommand,
|
|
36
|
+
# QueueListJobsCommand,
|
|
37
|
+
# QueueHealthCommand,
|
|
38
|
+
# )
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"Command",
|
|
42
|
+
"CommandResult",
|
|
43
|
+
"SuccessResult",
|
|
44
|
+
"ErrorResult",
|
|
45
|
+
"registry",
|
|
46
|
+
"CommandRegistry",
|
|
47
|
+
"container",
|
|
48
|
+
"DependencyContainer",
|
|
49
|
+
# "AuthValidationCommand",
|
|
50
|
+
# "SSLSetupCommand",
|
|
51
|
+
# "CertificateManagementCommand",
|
|
52
|
+
# "KeyManagementCommand",
|
|
53
|
+
# "CertMonitorCommand",
|
|
54
|
+
# "TransportManagementCommand",
|
|
55
|
+
# "RoleTestCommand",
|
|
56
|
+
# "EchoCommand",
|
|
57
|
+
# "ProxyRegistrationCommand",
|
|
58
|
+
# "RegistrationStatusCommand",
|
|
59
|
+
# "QueueAddJobCommand",
|
|
60
|
+
# "QueueStartJobCommand",
|
|
61
|
+
# "QueueStopJobCommand",
|
|
62
|
+
# "QueueDeleteJobCommand",
|
|
63
|
+
# "QueueGetJobStatusCommand",
|
|
64
|
+
# "QueueListJobsCommand",
|
|
65
|
+
# "QueueHealthCommand",
|
|
66
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication Validation Commands
|
|
3
|
+
|
|
4
|
+
This module provides commands for validating different types of authentication:
|
|
5
|
+
- Universal authentication validation
|
|
6
|
+
- Certificate validation
|
|
7
|
+
- Token validation
|
|
8
|
+
- mTLS validation
|
|
9
|
+
- SSL validation
|
|
10
|
+
|
|
11
|
+
Author: MCP Proxy Adapter Team
|
|
12
|
+
Version: 1.0.0
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
from typing import Union, Dict, Any
|
|
17
|
+
|
|
18
|
+
from ..commands.base import Command
|
|
19
|
+
from ..commands.result import SuccessResult, ErrorResult
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
23
|
+
class AuthValidationCommand(Command):
|
|
24
|
+
"""
|
|
25
|
+
Authentication validation commands.
|
|
26
|
+
|
|
27
|
+
Provides commands for validating different types of authentication
|
|
28
|
+
using the universal AuthValidator.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self):
|
|
32
|
+
"""Initialize authentication validation command."""
|
|
33
|
+
super().__init__()
|
|
34
|
+
self.validator = AuthValidator()
|
|
35
|
+
self.logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def execute(self, **kwargs) -> Union[SuccessResult, ErrorResult]:
|
|
43
|
+
"""
|
|
44
|
+
Execute authentication validation command.
|
|
45
|
+
|
|
46
|
+
This is a placeholder method to satisfy the abstract base class.
|
|
47
|
+
Individual validation methods should be called directly.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
**kwargs: Command parameters
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Command result
|
|
54
|
+
"""
|
|
55
|
+
return ErrorResult(
|
|
56
|
+
message="Method not found. Use specific validation methods instead.",
|
|
57
|
+
code=-32601,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def get_schema(cls) -> Dict[str, Any]:
|
|
62
|
+
"""Get JSON schema for auth validation command."""
|
|
63
|
+
return {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"properties": {
|
|
66
|
+
"method": {"type": "string", "enum": ["validate_token", "validate_certificate", "validate_mtls"]},
|
|
67
|
+
"params": {"type": "object"}
|
|
68
|
+
}
|
|
69
|
+
}
|