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,270 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module with API schema definitions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional, Union, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ErrorResponse(BaseModel):
|
|
11
|
+
"""
|
|
12
|
+
Error response model.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
code: int = Field(..., description="Error code")
|
|
16
|
+
message: str = Field(..., description="Error message")
|
|
17
|
+
details: Optional[Dict[str, Any]] = Field(
|
|
18
|
+
None, description="Additional error details"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ErrorWrapper(BaseModel):
|
|
23
|
+
"""
|
|
24
|
+
Wrapper for error response.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
error: ErrorResponse
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class JsonRpcRequest(BaseModel):
|
|
31
|
+
"""
|
|
32
|
+
JSON-RPC request model.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
|
36
|
+
method: str = Field(..., description="Method name")
|
|
37
|
+
params: Optional[Union[Dict[str, Any], List[Any]]] = Field(
|
|
38
|
+
None, description="Method parameters"
|
|
39
|
+
)
|
|
40
|
+
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class JsonRpcError(BaseModel):
|
|
44
|
+
"""
|
|
45
|
+
JSON-RPC error model.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
code: int = Field(..., description="Error code")
|
|
49
|
+
message: str = Field(..., description="Error message")
|
|
50
|
+
data: Optional[Dict[str, Any]] = Field(None, description="Additional error data")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class JsonRpcSuccessResponse(BaseModel):
|
|
54
|
+
"""
|
|
55
|
+
JSON-RPC success response model.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
|
59
|
+
result: Dict[str, Any] = Field(..., description="Method result")
|
|
60
|
+
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class JsonRpcErrorResponse(BaseModel):
|
|
64
|
+
"""
|
|
65
|
+
JSON-RPC error response model.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
|
69
|
+
error: JsonRpcError = Field(..., description="Error information")
|
|
70
|
+
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class CommandResponse(BaseModel):
|
|
74
|
+
"""
|
|
75
|
+
Command response model.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
success: bool = Field(..., description="Command execution success flag")
|
|
79
|
+
data: Optional[Dict[str, Any]] = Field(None, description="Result data")
|
|
80
|
+
message: Optional[str] = Field(None, description="Result message")
|
|
81
|
+
error: Optional[ErrorResponse] = Field(None, description="Error information")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class HealthResponse(BaseModel):
|
|
85
|
+
"""
|
|
86
|
+
Health response model.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
status: str = Field(..., description="Server status")
|
|
90
|
+
version: str = Field(..., description="Server version")
|
|
91
|
+
uptime: float = Field(..., description="Server uptime in seconds")
|
|
92
|
+
components: Dict[str, Any] = Field(..., description="Components health")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class CommandListResponse(BaseModel):
|
|
96
|
+
"""
|
|
97
|
+
Command list response model.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
commands: Dict[str, Dict[str, Any]] = Field(..., description="Available commands")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class CommandRequest(BaseModel):
|
|
104
|
+
"""
|
|
105
|
+
Command request model for /cmd endpoint.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
command: str = Field(..., description="Command name to execute")
|
|
109
|
+
params: Optional[Dict[str, Any]] = Field({}, description="Command parameters")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class CommandSuccessResponse(BaseModel):
|
|
113
|
+
"""
|
|
114
|
+
Command success response model for /cmd endpoint.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
result: Dict[str, Any] = Field(..., description="Command execution result")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class CommandErrorResponse(BaseModel):
|
|
121
|
+
"""
|
|
122
|
+
Command error response model for /cmd endpoint.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
error: JsonRpcError = Field(..., description="Error information")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class APIToolDescription:
|
|
129
|
+
"""
|
|
130
|
+
Генератор описаний для инструментов API на основе метаданных команд.
|
|
131
|
+
|
|
132
|
+
Класс предоставляет функциональность для создания подробных и понятных
|
|
133
|
+
описаний инструментов API, которые помогают пользователям сразу понять
|
|
134
|
+
как использовать API.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def generate_tool_description(cls, name: str, registry) -> Dict[str, Any]:
|
|
139
|
+
"""
|
|
140
|
+
Генерирует подробное описание инструмента API на основе имени и реестра команд.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
name: Имя инструмента API
|
|
144
|
+
registry: Реестр команд
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Словарь с полным описанием инструмента
|
|
148
|
+
"""
|
|
149
|
+
# Получаем все метаданные из реестра команд
|
|
150
|
+
all_metadata = registry.get_all_metadata()
|
|
151
|
+
|
|
152
|
+
# Базовое описание инструмента
|
|
153
|
+
description = {
|
|
154
|
+
"name": name,
|
|
155
|
+
"description": f"Выполняет команды через JSON-RPC протокол на сервере проекта.",
|
|
156
|
+
"supported_commands": {},
|
|
157
|
+
"examples": [],
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# Добавляем информацию о поддерживаемых командах
|
|
161
|
+
for cmd_name, metadata in all_metadata.items():
|
|
162
|
+
command_info = {
|
|
163
|
+
"summary": metadata["summary"],
|
|
164
|
+
"description": metadata["description"],
|
|
165
|
+
"params": {},
|
|
166
|
+
"required_params": [],
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# Добавляем информацию о параметрах
|
|
170
|
+
for param_name, param_info in metadata["params"].items():
|
|
171
|
+
param_type = param_info.get("type", "any").replace("typing.", "")
|
|
172
|
+
|
|
173
|
+
# Определяем тип параметра для документации
|
|
174
|
+
simple_type = cls._simplify_type(param_type)
|
|
175
|
+
|
|
176
|
+
command_info["params"][param_name] = {
|
|
177
|
+
"type": simple_type,
|
|
178
|
+
"description": cls._extract_param_description(
|
|
179
|
+
metadata["description"], param_name
|
|
180
|
+
),
|
|
181
|
+
"required": param_info.get("required", False),
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# Если параметр обязательный, добавляем его в список обязательных
|
|
185
|
+
if param_info.get("required", False):
|
|
186
|
+
command_info["required_params"].append(param_name)
|
|
187
|
+
|
|
188
|
+
description["supported_commands"][cmd_name] = command_info
|
|
189
|
+
|
|
190
|
+
# Добавляем примеры из метаданных команды
|
|
191
|
+
for example in metadata.get("examples", []):
|
|
192
|
+
description["examples"].append(
|
|
193
|
+
{
|
|
194
|
+
"command": example.get("command", cmd_name),
|
|
195
|
+
"params": example.get("params", {}),
|
|
196
|
+
"description": example.get(
|
|
197
|
+
"description", f"Пример использования команды {cmd_name}"
|
|
198
|
+
),
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
return description
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
|
|
206
|
+
@classmethod
|
|
207
|
+
def _simplify_type(cls, type_str: str) -> str:
|
|
208
|
+
"""
|
|
209
|
+
Упрощает строковое представление типа для документации.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
type_str: Строковое представление типа
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Упрощенное строковое представление типа
|
|
216
|
+
"""
|
|
217
|
+
# Удаляем префиксы из строки типа
|
|
218
|
+
type_str = type_str.replace("<class '", "").replace("'>", "")
|
|
219
|
+
|
|
220
|
+
# Преобразование стандартных типов
|
|
221
|
+
if "str" in type_str:
|
|
222
|
+
return "строка"
|
|
223
|
+
elif "int" in type_str:
|
|
224
|
+
return "целое число"
|
|
225
|
+
elif "float" in type_str:
|
|
226
|
+
return "число"
|
|
227
|
+
elif "bool" in type_str:
|
|
228
|
+
return "логическое значение"
|
|
229
|
+
elif "List" in type_str or "list" in type_str:
|
|
230
|
+
return "список"
|
|
231
|
+
elif "Dict" in type_str or "dict" in type_str:
|
|
232
|
+
return "объект"
|
|
233
|
+
elif "Optional" in type_str:
|
|
234
|
+
# Извлекаем тип из Optional[X]
|
|
235
|
+
inner_type = type_str.split("[")[1].split("]")[0]
|
|
236
|
+
return cls._simplify_type(inner_type)
|
|
237
|
+
else:
|
|
238
|
+
return "значение"
|
|
239
|
+
|
|
240
|
+
@classmethod
|
|
241
|
+
def _extract_param_description(cls, doc_string: str, param_name: str) -> str:
|
|
242
|
+
"""
|
|
243
|
+
Извлекает описание параметра из строки документации.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
doc_string: Строка документации
|
|
247
|
+
param_name: Имя параметра
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Описание параметра или пустая строка, если описание не найдено
|
|
251
|
+
"""
|
|
252
|
+
# Проверяем, есть ли в документации секция Args или Parameters
|
|
253
|
+
if "Args:" in doc_string:
|
|
254
|
+
args_section = doc_string.split("Args:")[1].split("\n\n")[0]
|
|
255
|
+
elif "Parameters:" in doc_string:
|
|
256
|
+
args_section = doc_string.split("Parameters:")[1].split("\n\n")[0]
|
|
257
|
+
else:
|
|
258
|
+
return ""
|
|
259
|
+
|
|
260
|
+
# Ищем описание параметра
|
|
261
|
+
for line in args_section.split("\n"):
|
|
262
|
+
line = line.strip()
|
|
263
|
+
if line.startswith(param_name + ":") or line.startswith(param_name + " :"):
|
|
264
|
+
return line.split(":", 1)[1].strip()
|
|
265
|
+
|
|
266
|
+
return ""
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# Create dictionary mapping command names to their schemas
|
|
270
|
+
command_schemas: Dict[str, Dict[str, Any]] = {}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Модуль для интеграции метаданных команд с внешними API инструментами.
|
|
3
|
+
|
|
4
|
+
Этот модуль обеспечивает преобразование метаданных команд микросервиса
|
|
5
|
+
в форматы, понятные для внешних систем, таких как OpenAPI, JSON-RPC,
|
|
6
|
+
и других API интерфейсов.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from mcp_proxy_adapter.api.schemas import APIToolDescription
|
|
13
|
+
from mcp_proxy_adapter.commands.command_registry import CommandRegistry
|
|
14
|
+
|
|
15
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ToolIntegration:
|
|
20
|
+
"""
|
|
21
|
+
Класс для интеграции метаданных команд с внешними инструментами API.
|
|
22
|
+
|
|
23
|
+
Обеспечивает генерацию описаний инструментов API для различных систем
|
|
24
|
+
на основе метаданных команд микросервиса.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def generate_tool_schema(
|
|
29
|
+
cls,
|
|
30
|
+
tool_name: str,
|
|
31
|
+
registry: CommandRegistry,
|
|
32
|
+
description: Optional[str] = None,
|
|
33
|
+
) -> Dict[str, Any]:
|
|
34
|
+
"""
|
|
35
|
+
Генерирует схему инструмента API для использования в OpenAPI и других системах.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
tool_name: Имя инструмента API
|
|
39
|
+
registry: Реестр команд
|
|
40
|
+
description: Дополнительное описание инструмента (опционально)
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Словарь с описанием инструмента в формате OpenAPI
|
|
44
|
+
"""
|
|
45
|
+
# Получаем базовое описание инструмента
|
|
46
|
+
base_description = APIToolDescription.generate_tool_description(
|
|
47
|
+
tool_name, registry
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Получаем типы параметров
|
|
51
|
+
parameter_types = cls._extract_parameter_types(
|
|
52
|
+
base_description["supported_commands"]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Формируем схему инструмента
|
|
56
|
+
schema = {
|
|
57
|
+
"name": tool_name,
|
|
58
|
+
"description": description or base_description["description"],
|
|
59
|
+
"parameters": {
|
|
60
|
+
"properties": {
|
|
61
|
+
"command": {
|
|
62
|
+
"description": "Команда для выполнения",
|
|
63
|
+
"type": "string",
|
|
64
|
+
"enum": list(base_description["supported_commands"].keys()),
|
|
65
|
+
},
|
|
66
|
+
"params": {
|
|
67
|
+
"description": "Параметры команды",
|
|
68
|
+
"type": "object",
|
|
69
|
+
"additionalProperties": True,
|
|
70
|
+
"properties": parameter_types,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
"required": ["command"],
|
|
74
|
+
"type": "object",
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return schema
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def _extract_parameter_types(
|
|
86
|
+
cls, commands: Dict[str, Dict[str, Any]]
|
|
87
|
+
) -> Dict[str, Dict[str, Any]]:
|
|
88
|
+
"""
|
|
89
|
+
Извлекает типы параметров из описания команд для формирования схемы.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
commands: Словарь с описанием команд
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Словарь с типами параметров для схемы OpenAPI
|
|
96
|
+
"""
|
|
97
|
+
parameter_types = {}
|
|
98
|
+
|
|
99
|
+
# Формируем словарь типов для всех параметров всех команд
|
|
100
|
+
for cmd_name, cmd_info in commands.items():
|
|
101
|
+
params = cmd_info.get("params", {})
|
|
102
|
+
if params is None:
|
|
103
|
+
continue
|
|
104
|
+
for param_name, param_info in params.items():
|
|
105
|
+
param_type = param_info.get("type", "значение")
|
|
106
|
+
|
|
107
|
+
# Преобразуем русские типы в типы JSON Schema
|
|
108
|
+
if param_type == "строка":
|
|
109
|
+
json_type = "string"
|
|
110
|
+
elif param_type == "целое число":
|
|
111
|
+
json_type = "integer"
|
|
112
|
+
elif param_type == "число":
|
|
113
|
+
json_type = "number"
|
|
114
|
+
elif param_type == "логическое значение":
|
|
115
|
+
json_type = "boolean"
|
|
116
|
+
elif param_type == "список":
|
|
117
|
+
json_type = "array"
|
|
118
|
+
elif param_type == "объект":
|
|
119
|
+
json_type = "object"
|
|
120
|
+
else:
|
|
121
|
+
json_type = "string"
|
|
122
|
+
|
|
123
|
+
# Добавляем тип в общий словарь
|
|
124
|
+
parameter_types[param_name] = {
|
|
125
|
+
"type": json_type,
|
|
126
|
+
"description": param_info.get("description", ""),
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return parameter_types
|
|
130
|
+
|
|
131
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Модуль с реализацией инструментов API для внешних систем.
|
|
3
|
+
|
|
4
|
+
Этот модуль содержит классы инструментов API, которые могут быть
|
|
5
|
+
интегрированы с внешними системами для выполнения команд микросервиса.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, Optional, Union, List
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from mcp_proxy_adapter.api.tool_integration import ToolIntegration
|
|
13
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
|
14
|
+
from mcp_proxy_adapter.core.errors import NotFoundError, InvalidParamsError
|
|
15
|
+
|
|
16
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TSTCommandExecutor:
|
|
21
|
+
"""
|
|
22
|
+
Инструмент для выполнения команд через JSON-RPC протокол на сервере проекта.
|
|
23
|
+
|
|
24
|
+
Этот класс предоставляет функциональность для выполнения команд микросервиса
|
|
25
|
+
через внешний интерфейс TST (Tool-System-Transport).
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
name = "tst_execute_command"
|
|
29
|
+
description = "Выполняет команду через JSON-RPC протокол."
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
async def execute(
|
|
33
|
+
cls, command: str, params: Optional[Dict[str, Any]] = None
|
|
34
|
+
) -> Dict[str, Any]:
|
|
35
|
+
"""
|
|
36
|
+
Выполняет команду с указанными параметрами.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
command: Имя команды для выполнения
|
|
40
|
+
params: Параметры команды (опционально)
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Результат выполнения команды
|
|
44
|
+
|
|
45
|
+
Raises:
|
|
46
|
+
NotFoundError: Если команда не найдена
|
|
47
|
+
InvalidParamsError: Если переданы некорректные параметры
|
|
48
|
+
"""
|
|
49
|
+
if not params:
|
|
50
|
+
params = {}
|
|
51
|
+
|
|
52
|
+
get_global_logger().info(f"Executing command via TST: {command}, params: {params}")
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
# Проверяем существование команды
|
|
56
|
+
if not registry.command_exists_with_priority(command):
|
|
57
|
+
raise NotFoundError(f"Команда '{command}' не найдена")
|
|
58
|
+
|
|
59
|
+
# Получаем класс команды
|
|
60
|
+
command_class = registry.get_command_with_priority(command)
|
|
61
|
+
|
|
62
|
+
# Выполняем команду
|
|
63
|
+
result = await command_class.execute(**params)
|
|
64
|
+
|
|
65
|
+
# Возвращаем результат
|
|
66
|
+
return result.to_dict()
|
|
67
|
+
except NotFoundError as e:
|
|
68
|
+
get_global_logger().error(f"Command not found: {command}")
|
|
69
|
+
raise
|
|
70
|
+
except Exception as e:
|
|
71
|
+
get_global_logger().exception(f"Error executing command {command}: {e}")
|
|
72
|
+
raise
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def get_description(cls, format: str = "json") -> Union[Dict[str, Any], str]:
|
|
78
|
+
"""
|
|
79
|
+
Возвращает полное описание инструмента в указанном формате.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
format: Формат описания (json, markdown, html)
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Описание инструмента в указанном формате
|
|
86
|
+
"""
|
|
87
|
+
if format.lower() == "json":
|
|
88
|
+
# Получаем базовое описание инструмента
|
|
89
|
+
base_description = ToolIntegration.generate_tool_schema(
|
|
90
|
+
cls.name, registry, cls.description
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Добавляем дополнительную информацию
|
|
94
|
+
base_description["examples"] = cls._generate_examples()
|
|
95
|
+
base_description["error_codes"] = cls._generate_error_codes()
|
|
96
|
+
|
|
97
|
+
return base_description
|
|
98
|
+
elif format.lower() in ["markdown", "text", "html"]:
|
|
99
|
+
return ToolIntegration.generate_tool_documentation(
|
|
100
|
+
cls.name, registry, format
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
# По умолчанию возвращаем JSON формат
|
|
104
|
+
return ToolIntegration.generate_tool_schema(
|
|
105
|
+
cls.name, registry, cls.description
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def _generate_examples(cls) -> List[Dict[str, Any]]:
|
|
110
|
+
"""
|
|
111
|
+
Генерирует примеры использования инструмента.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Список примеров использования
|
|
115
|
+
"""
|
|
116
|
+
examples = []
|
|
117
|
+
|
|
118
|
+
# Получаем метаданные всех команд
|
|
119
|
+
all_metadata = registry.get_all_metadata()
|
|
120
|
+
|
|
121
|
+
# Добавляем по одному примеру для каждой команды
|
|
122
|
+
for cmd_name, metadata in all_metadata.items():
|
|
123
|
+
if metadata.get("examples"):
|
|
124
|
+
# Берем первый пример из метаданных
|
|
125
|
+
example = metadata["examples"][0]
|
|
126
|
+
|
|
127
|
+
# Формируем пример использования инструмента
|
|
128
|
+
examples.append(
|
|
129
|
+
{
|
|
130
|
+
"command": cls.name,
|
|
131
|
+
"params": {
|
|
132
|
+
"command": example.get("command", cmd_name),
|
|
133
|
+
"params": example.get("params", {}),
|
|
134
|
+
},
|
|
135
|
+
"description": f"Выполнение команды {cmd_name}",
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return examples
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def _generate_error_codes(cls) -> Dict[str, str]:
|
|
143
|
+
"""
|
|
144
|
+
Генерирует словарь возможных кодов ошибок.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Словарь с кодами ошибок и их описаниями
|
|
148
|
+
"""
|
|
149
|
+
return {
|
|
150
|
+
"-32600": "Некорректный запрос",
|
|
151
|
+
"-32601": "Команда не найдена",
|
|
152
|
+
"-32602": "Некорректные параметры",
|
|
153
|
+
"-32603": "Внутренняя ошибка",
|
|
154
|
+
"-32000": "Ошибка выполнения команды",
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# Экспортируем доступные инструменты API
|
|
159
|
+
available_tools = {TSTCommandExecutor.name: TSTCommandExecutor}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Commands Module
|
|
3
|
+
|
|
4
|
+
This module contains all CLI commands for MCP Proxy Adapter.
|
|
5
|
+
|
|
6
|
+
Author: Vasiliy Zdanovskiy
|
|
7
|
+
email: vasilyvz@gmail.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .generate import GenerateCommand
|
|
11
|
+
from .testconfig import TestConfigCommand
|
|
12
|
+
from .server import ServerCommand
|
|
13
|
+
from .sets import SetsCommand
|
|
14
|
+
|
|
15
|
+
__all__ = ['GenerateCommand', 'TestConfigCommand', 'ServerCommand', 'SetsCommand']
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP Client Command
|
|
3
|
+
|
|
4
|
+
Client CLI for calling health and JSON-RPC endpoints in various modes.
|
|
5
|
+
|
|
6
|
+
Author: Vasiliy Zdanovskiy
|
|
7
|
+
email: vasilyvz@gmail.com
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Dict, Optional
|
|
13
|
+
|
|
14
|
+
import requests
|
|
15
|
+
from mcp_proxy_adapter.client.proxy import ProxyClient
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _build_base_url(protocol: str, host: str, port: int) -> str:
|
|
19
|
+
scheme = "https" if protocol == "https" else "http"
|
|
20
|
+
return f"{scheme}://{host}:{port}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _request_kwargs(protocol: str, token_header: Optional[str], token: Optional[str],
|
|
24
|
+
cert: Optional[str], key: Optional[str], ca: Optional[str]) -> Dict[str, Any]:
|
|
25
|
+
headers: Dict[str, str] = {"Content-Type": "application/json"}
|
|
26
|
+
if token_header and token:
|
|
27
|
+
headers[token_header] = token
|
|
28
|
+
|
|
29
|
+
kwargs: Dict[str, Any] = {"headers": headers, "timeout": 10}
|
|
30
|
+
|
|
31
|
+
if protocol == "https":
|
|
32
|
+
if cert and key:
|
|
33
|
+
kwargs["cert"] = (cert, key)
|
|
34
|
+
# For examples we allow self-signed; if CA provided, use it, otherwise disable verification
|
|
35
|
+
if ca:
|
|
36
|
+
kwargs["verify"] = str(Path(ca))
|
|
37
|
+
else:
|
|
38
|
+
kwargs["verify"] = False
|
|
39
|
+
|
|
40
|
+
return kwargs
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def client_command(args) -> int:
|
|
44
|
+
"""Dispatch client subcommands."""
|
|
45
|
+
protocol = args.protocol
|
|
46
|
+
host = args.host
|
|
47
|
+
port = args.port
|
|
48
|
+
base = _build_base_url(protocol, host, port)
|
|
49
|
+
kwargs = _request_kwargs(
|
|
50
|
+
protocol,
|
|
51
|
+
getattr(args, "token_header", None),
|
|
52
|
+
getattr(args, "token", None),
|
|
53
|
+
getattr(args, "cert", None),
|
|
54
|
+
getattr(args, "key", None),
|
|
55
|
+
getattr(args, "ca", None),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
if args.client_command == "health":
|
|
60
|
+
resp = requests.get(f"{base}/health", **kwargs)
|
|
61
|
+
print(json.dumps(resp.json(), ensure_ascii=False))
|
|
62
|
+
return 0 if resp.ok else 1
|
|
63
|
+
|
|
64
|
+
if args.client_command == "jsonrpc":
|
|
65
|
+
payload: Dict[str, Any] = {
|
|
66
|
+
"jsonrpc": "2.0",
|
|
67
|
+
"method": args.method,
|
|
68
|
+
"params": json.loads(args.params) if args.params else {},
|
|
69
|
+
"id": args.id,
|
|
70
|
+
}
|
|
71
|
+
resp = requests.post(f"{base}/api/jsonrpc", data=json.dumps(payload), **kwargs)
|
|
72
|
+
print(json.dumps(resp.json(), ensure_ascii=False))
|
|
73
|
+
return 0 if resp.ok else 1
|
|
74
|
+
|
|
75
|
+
if args.client_command == "proxy-register":
|
|
76
|
+
pc = ProxyClient(args.proxy_url)
|
|
77
|
+
res = pc.register(args.name, args.url, capabilities=args.capabilities or [], metadata=None)
|
|
78
|
+
print(json.dumps(res, ensure_ascii=False))
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
if args.client_command == "proxy-unregister":
|
|
82
|
+
pc = ProxyClient(args.proxy_url)
|
|
83
|
+
res = pc.unregister(args.name)
|
|
84
|
+
print(json.dumps(res, ensure_ascii=False))
|
|
85
|
+
return 0
|
|
86
|
+
|
|
87
|
+
if args.client_command == "proxy-list":
|
|
88
|
+
pc = ProxyClient(args.proxy_url)
|
|
89
|
+
res = pc.list_servers()
|
|
90
|
+
print(json.dumps(res, ensure_ascii=False))
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
print("Available: client health|jsonrpc")
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
except Exception as exc: # noqa: BLE001 (keep simple CLI handling)
|
|
97
|
+
print(f"❌ Client error: {exc}")
|
|
98
|
+
return 1
|
|
99
|
+
|
|
100
|
+
|