mcp-proxy-adapter 3.1.5__py3-none-any.whl → 4.0.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/api/app.py +86 -27
- mcp_proxy_adapter/api/handlers.py +1 -1
- mcp_proxy_adapter/api/middleware/error_handling.py +11 -10
- mcp_proxy_adapter/api/tool_integration.py +5 -2
- mcp_proxy_adapter/api/tools.py +3 -3
- mcp_proxy_adapter/commands/base.py +19 -1
- mcp_proxy_adapter/commands/command_registry.py +258 -6
- mcp_proxy_adapter/commands/help_command.py +54 -65
- mcp_proxy_adapter/commands/hooks.py +260 -0
- mcp_proxy_adapter/commands/reload_command.py +211 -0
- mcp_proxy_adapter/commands/reload_settings_command.py +125 -0
- mcp_proxy_adapter/commands/settings_command.py +189 -0
- mcp_proxy_adapter/config.py +16 -1
- mcp_proxy_adapter/core/__init__.py +44 -0
- mcp_proxy_adapter/core/logging.py +87 -34
- mcp_proxy_adapter/core/settings.py +376 -0
- mcp_proxy_adapter/core/utils.py +2 -2
- mcp_proxy_adapter/custom_openapi.py +81 -2
- mcp_proxy_adapter/examples/README.md +124 -0
- mcp_proxy_adapter/examples/__init__.py +7 -0
- mcp_proxy_adapter/examples/basic_server/README.md +60 -0
- mcp_proxy_adapter/examples/basic_server/__init__.py +7 -0
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +39 -0
- mcp_proxy_adapter/examples/basic_server/config.json +35 -0
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +238 -0
- mcp_proxy_adapter/examples/basic_server/server.py +98 -0
- mcp_proxy_adapter/examples/custom_commands/README.md +127 -0
- mcp_proxy_adapter/examples/custom_commands/__init__.py +27 -0
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +250 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +6 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +103 -0
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +111 -0
- mcp_proxy_adapter/examples/custom_commands/config.json +62 -0
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +169 -0
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +215 -0
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +76 -0
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +96 -0
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +241 -0
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +135 -0
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +122 -0
- mcp_proxy_adapter/examples/custom_commands/hooks.py +230 -0
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +123 -0
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +103 -0
- mcp_proxy_adapter/examples/custom_commands/server.py +223 -0
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +176 -0
- mcp_proxy_adapter/examples/deployment/README.md +49 -0
- mcp_proxy_adapter/examples/deployment/__init__.py +7 -0
- mcp_proxy_adapter/examples/deployment/config.development.json +8 -0
- {examples/basic_example → mcp_proxy_adapter/examples/deployment}/config.json +11 -7
- mcp_proxy_adapter/examples/deployment/config.production.json +12 -0
- mcp_proxy_adapter/examples/deployment/config.staging.json +11 -0
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +31 -0
- mcp_proxy_adapter/examples/deployment/run.sh +43 -0
- mcp_proxy_adapter/examples/deployment/run_docker.sh +84 -0
- mcp_proxy_adapter/openapi.py +3 -2
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +617 -0
- mcp_proxy_adapter/tests/api/test_handlers.py +522 -0
- mcp_proxy_adapter/tests/api/test_schemas.py +546 -0
- mcp_proxy_adapter/tests/api/test_tool_integration.py +531 -0
- mcp_proxy_adapter/tests/commands/test_help_command.py +8 -5
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +4 -5
- mcp_proxy_adapter/tests/test_command_registry.py +37 -1
- mcp_proxy_adapter/tests/unit/test_base_command.py +391 -85
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-4.0.0.dist-info/RECORD +110 -0
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/WHEEL +1 -1
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/top_level.txt +0 -1
- examples/__init__.py +0 -19
- examples/anti_patterns/README.md +0 -51
- examples/anti_patterns/__init__.py +0 -9
- examples/anti_patterns/bad_design/README.md +0 -72
- examples/anti_patterns/bad_design/global_state.py +0 -170
- examples/anti_patterns/bad_design/monolithic_command.py +0 -272
- examples/basic_example/README.md +0 -245
- examples/basic_example/__init__.py +0 -8
- examples/basic_example/commands/__init__.py +0 -5
- examples/basic_example/commands/echo_command.py +0 -95
- examples/basic_example/commands/math_command.py +0 -151
- examples/basic_example/commands/time_command.py +0 -152
- examples/basic_example/docs/EN/README.md +0 -177
- examples/basic_example/docs/RU/README.md +0 -177
- examples/basic_example/server.py +0 -151
- examples/basic_example/tests/conftest.py +0 -243
- examples/check_vstl_schema.py +0 -106
- examples/commands/echo_command.py +0 -52
- examples/commands/echo_command_di.py +0 -152
- examples/commands/echo_result.py +0 -65
- examples/commands/get_date_command.py +0 -98
- examples/commands/new_uuid4_command.py +0 -91
- examples/complete_example/Dockerfile +0 -24
- examples/complete_example/README.md +0 -92
- examples/complete_example/__init__.py +0 -8
- examples/complete_example/commands/__init__.py +0 -5
- examples/complete_example/commands/system_command.py +0 -328
- examples/complete_example/config.json +0 -41
- examples/complete_example/configs/config.dev.yaml +0 -40
- examples/complete_example/configs/config.docker.yaml +0 -40
- examples/complete_example/docker-compose.yml +0 -35
- examples/complete_example/requirements.txt +0 -20
- examples/complete_example/server.py +0 -113
- examples/di_example/.pytest_cache/README.md +0 -8
- examples/di_example/server.py +0 -249
- examples/fix_vstl_help.py +0 -123
- examples/minimal_example/README.md +0 -65
- examples/minimal_example/__init__.py +0 -8
- examples/minimal_example/config.json +0 -14
- examples/minimal_example/main.py +0 -136
- examples/minimal_example/simple_server.py +0 -163
- examples/minimal_example/tests/conftest.py +0 -171
- examples/minimal_example/tests/test_hello_command.py +0 -111
- examples/minimal_example/tests/test_integration.py +0 -181
- examples/patch_vstl_service.py +0 -105
- examples/patch_vstl_service_mcp.py +0 -108
- examples/server.py +0 -69
- examples/simple_server.py +0 -128
- examples/test_package_3.1.4.py +0 -177
- examples/test_server.py +0 -134
- examples/tool_description_example.py +0 -82
- mcp_proxy_adapter/py.typed +0 -0
- mcp_proxy_adapter-3.1.5.dist-info/RECORD +0 -118
- {mcp_proxy_adapter-3.1.5.dist-info → mcp_proxy_adapter-4.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,241 @@
|
|
1
|
+
"""
|
2
|
+
Custom Settings Manager Example
|
3
|
+
|
4
|
+
This module demonstrates how to create a custom settings manager
|
5
|
+
that extends the framework's settings system with application-specific settings.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import json
|
9
|
+
import os
|
10
|
+
from typing import Dict, Any, Optional
|
11
|
+
from mcp_proxy_adapter.core.settings import (
|
12
|
+
add_custom_settings,
|
13
|
+
get_custom_settings,
|
14
|
+
get_custom_setting_value,
|
15
|
+
set_custom_setting_value
|
16
|
+
)
|
17
|
+
from mcp_proxy_adapter.core.logging import get_logger
|
18
|
+
|
19
|
+
|
20
|
+
class CustomSettingsManager:
|
21
|
+
"""
|
22
|
+
Custom settings manager for the extended server example.
|
23
|
+
|
24
|
+
This class demonstrates how to:
|
25
|
+
1. Load custom settings from JSON files
|
26
|
+
2. Add them to the framework's settings system
|
27
|
+
3. Provide convenient access methods
|
28
|
+
4. Handle settings validation and defaults
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(self, config_file: str = "custom_settings.json"):
|
32
|
+
"""
|
33
|
+
Initialize the custom settings manager.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
config_file: Path to custom settings JSON file
|
37
|
+
"""
|
38
|
+
self.config_file = config_file
|
39
|
+
self.logger = get_logger("custom_settings_manager")
|
40
|
+
self._load_custom_settings()
|
41
|
+
|
42
|
+
def _load_custom_settings(self) -> None:
|
43
|
+
"""Load custom settings from JSON file."""
|
44
|
+
try:
|
45
|
+
if os.path.exists(self.config_file):
|
46
|
+
with open(self.config_file, 'r', encoding='utf-8') as f:
|
47
|
+
custom_settings = json.load(f)
|
48
|
+
|
49
|
+
self.logger.info(f"📁 Loaded custom settings from: {self.config_file}")
|
50
|
+
self.logger.debug(f"📋 Custom settings: {custom_settings}")
|
51
|
+
|
52
|
+
# Add to framework's settings system
|
53
|
+
add_custom_settings(custom_settings)
|
54
|
+
|
55
|
+
else:
|
56
|
+
self.logger.warning(f"⚠️ Custom settings file not found: {self.config_file}")
|
57
|
+
self.logger.info("📝 Using default custom settings")
|
58
|
+
|
59
|
+
# Use default settings
|
60
|
+
default_settings = self._get_default_settings()
|
61
|
+
add_custom_settings(default_settings)
|
62
|
+
|
63
|
+
except Exception as e:
|
64
|
+
self.logger.error(f"❌ Failed to load custom settings: {e}")
|
65
|
+
self.logger.info("📝 Using default custom settings")
|
66
|
+
|
67
|
+
# Use default settings on error
|
68
|
+
default_settings = self._get_default_settings()
|
69
|
+
add_custom_settings(default_settings)
|
70
|
+
|
71
|
+
def _get_default_settings(self) -> Dict[str, Any]:
|
72
|
+
"""Get default custom settings."""
|
73
|
+
return {
|
74
|
+
"application": {
|
75
|
+
"name": "Extended MCP Proxy Server",
|
76
|
+
"version": "2.0.0",
|
77
|
+
"environment": "development"
|
78
|
+
},
|
79
|
+
"features": {
|
80
|
+
"advanced_hooks": True,
|
81
|
+
"custom_commands": True,
|
82
|
+
"data_transformation": True,
|
83
|
+
"command_interception": True,
|
84
|
+
"performance_monitoring": False
|
85
|
+
},
|
86
|
+
"security": {
|
87
|
+
"enable_authentication": False,
|
88
|
+
"max_request_size": "10MB",
|
89
|
+
"rate_limiting": {
|
90
|
+
"enabled": False,
|
91
|
+
"requests_per_minute": 100
|
92
|
+
}
|
93
|
+
},
|
94
|
+
"monitoring": {
|
95
|
+
"enable_metrics": True,
|
96
|
+
"metrics_interval": 60,
|
97
|
+
"health_check_interval": 30
|
98
|
+
},
|
99
|
+
"custom_commands": {
|
100
|
+
"auto_echo": {
|
101
|
+
"enabled": True,
|
102
|
+
"max_length": 1000
|
103
|
+
},
|
104
|
+
"data_transform": {
|
105
|
+
"enabled": True,
|
106
|
+
"transform_types": ["uppercase", "lowercase", "reverse"]
|
107
|
+
},
|
108
|
+
"intercept": {
|
109
|
+
"enabled": True,
|
110
|
+
"bypass_conditions": ["input_value == 0"]
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
def get_application_name(self) -> str:
|
116
|
+
"""Get application name."""
|
117
|
+
return get_custom_setting_value("application.name", "Extended MCP Proxy Server")
|
118
|
+
|
119
|
+
def get_application_version(self) -> str:
|
120
|
+
"""Get application version."""
|
121
|
+
return get_custom_setting_value("application.version", "2.0.0")
|
122
|
+
|
123
|
+
def get_environment(self) -> str:
|
124
|
+
"""Get application environment."""
|
125
|
+
return get_custom_setting_value("application.environment", "development")
|
126
|
+
|
127
|
+
def is_feature_enabled(self, feature_name: str) -> bool:
|
128
|
+
"""Check if a feature is enabled."""
|
129
|
+
return get_custom_setting_value(f"features.{feature_name}", False)
|
130
|
+
|
131
|
+
def get_security_setting(self, setting_name: str, default: Any = None) -> Any:
|
132
|
+
"""Get security setting."""
|
133
|
+
return get_custom_setting_value(f"security.{setting_name}", default)
|
134
|
+
|
135
|
+
def get_monitoring_setting(self, setting_name: str, default: Any = None) -> Any:
|
136
|
+
"""Get monitoring setting."""
|
137
|
+
return get_custom_setting_value(f"monitoring.{setting_name}", default)
|
138
|
+
|
139
|
+
def get_custom_command_setting(self, command_name: str, setting_name: str, default: Any = None) -> Any:
|
140
|
+
"""Get custom command setting."""
|
141
|
+
return get_custom_setting_value(f"custom_commands.{command_name}.{setting_name}", default)
|
142
|
+
|
143
|
+
def set_custom_setting(self, key: str, value: Any) -> None:
|
144
|
+
"""Set a custom setting."""
|
145
|
+
set_custom_setting_value(key, value)
|
146
|
+
self.logger.info(f"🔧 Set custom setting: {key} = {value}")
|
147
|
+
|
148
|
+
def get_all_custom_settings(self) -> Dict[str, Any]:
|
149
|
+
"""Get all custom settings."""
|
150
|
+
return get_custom_settings()
|
151
|
+
|
152
|
+
def reload_settings(self) -> None:
|
153
|
+
"""Reload custom settings from file."""
|
154
|
+
self.logger.info("🔄 Reloading custom settings...")
|
155
|
+
self._load_custom_settings()
|
156
|
+
self.logger.info("✅ Custom settings reloaded")
|
157
|
+
|
158
|
+
def validate_settings(self) -> Dict[str, Any]:
|
159
|
+
"""
|
160
|
+
Validate current settings and return validation results.
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
Dictionary with validation results
|
164
|
+
"""
|
165
|
+
validation_results = {
|
166
|
+
"valid": True,
|
167
|
+
"errors": [],
|
168
|
+
"warnings": []
|
169
|
+
}
|
170
|
+
|
171
|
+
# Validate required settings
|
172
|
+
required_settings = [
|
173
|
+
"application.name",
|
174
|
+
"application.version",
|
175
|
+
"features.advanced_hooks"
|
176
|
+
]
|
177
|
+
|
178
|
+
for setting in required_settings:
|
179
|
+
if get_custom_setting_value(setting) is None:
|
180
|
+
validation_results["valid"] = False
|
181
|
+
validation_results["errors"].append(f"Missing required setting: {setting}")
|
182
|
+
|
183
|
+
# Validate feature dependencies
|
184
|
+
if self.is_feature_enabled("data_transformation"):
|
185
|
+
if not self.is_feature_enabled("custom_commands"):
|
186
|
+
validation_results["warnings"].append(
|
187
|
+
"data_transformation requires custom_commands to be enabled"
|
188
|
+
)
|
189
|
+
|
190
|
+
# Validate security settings
|
191
|
+
if self.get_security_setting("enable_authentication"):
|
192
|
+
if not self.get_security_setting("rate_limiting.enabled"):
|
193
|
+
validation_results["warnings"].append(
|
194
|
+
"Authentication enabled but rate limiting is disabled"
|
195
|
+
)
|
196
|
+
|
197
|
+
return validation_results
|
198
|
+
|
199
|
+
def print_settings_summary(self) -> None:
|
200
|
+
"""Print a summary of current settings."""
|
201
|
+
self.logger.info("📊 Custom Settings Summary:")
|
202
|
+
self.logger.info(f" Application: {self.get_application_name()} v{self.get_application_version()}")
|
203
|
+
self.logger.info(f" Environment: {self.get_environment()}")
|
204
|
+
|
205
|
+
# Features
|
206
|
+
features = []
|
207
|
+
for feature in ["advanced_hooks", "custom_commands", "data_transformation", "command_interception"]:
|
208
|
+
if self.is_feature_enabled(feature):
|
209
|
+
features.append(feature)
|
210
|
+
|
211
|
+
self.logger.info(f" Enabled Features: {', '.join(features) if features else 'None'}")
|
212
|
+
|
213
|
+
# Security
|
214
|
+
auth_enabled = self.get_security_setting("enable_authentication", False)
|
215
|
+
rate_limiting = self.get_security_setting("rate_limiting.enabled", False)
|
216
|
+
self.logger.info(f" Security: Auth={auth_enabled}, Rate Limiting={rate_limiting}")
|
217
|
+
|
218
|
+
# Monitoring
|
219
|
+
metrics_enabled = self.get_monitoring_setting("enable_metrics", False)
|
220
|
+
self.logger.info(f" Monitoring: Metrics={metrics_enabled}")
|
221
|
+
|
222
|
+
|
223
|
+
# Convenience functions for easy access
|
224
|
+
def get_app_name() -> str:
|
225
|
+
"""Get application name."""
|
226
|
+
return get_custom_setting_value("application.name", "Extended MCP Proxy Server")
|
227
|
+
|
228
|
+
|
229
|
+
def is_feature_enabled(feature_name: str) -> bool:
|
230
|
+
"""Check if a feature is enabled."""
|
231
|
+
return get_custom_setting_value(f"features.{feature_name}", False)
|
232
|
+
|
233
|
+
|
234
|
+
def get_security_setting(setting_name: str, default: Any = None) -> Any:
|
235
|
+
"""Get security setting."""
|
236
|
+
return get_custom_setting_value(f"security.{setting_name}", default)
|
237
|
+
|
238
|
+
|
239
|
+
def get_monitoring_setting(setting_name: str, default: Any = None) -> Any:
|
240
|
+
"""Get monitoring setting."""
|
241
|
+
return get_custom_setting_value(f"monitoring.{setting_name}", default)
|
@@ -0,0 +1,135 @@
|
|
1
|
+
"""
|
2
|
+
Data Transform Command Example
|
3
|
+
|
4
|
+
A command that demonstrates advanced hooks with data transformation.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Dict, Any, Optional
|
8
|
+
from mcp_proxy_adapter.commands.base import Command
|
9
|
+
from mcp_proxy_adapter.commands.result import CommandResult
|
10
|
+
|
11
|
+
|
12
|
+
class DataTransformResult(CommandResult):
|
13
|
+
"""
|
14
|
+
Result of the data transform command execution.
|
15
|
+
"""
|
16
|
+
|
17
|
+
def __init__(self, original_data: Dict[str, Any], transformed_data: Dict[str, Any],
|
18
|
+
processing_info: Dict[str, Any]):
|
19
|
+
"""
|
20
|
+
Initialize data transform command result.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
original_data: Original input data
|
24
|
+
transformed_data: Transformed output data
|
25
|
+
processing_info: Information about processing steps
|
26
|
+
"""
|
27
|
+
self.original_data = original_data
|
28
|
+
self.transformed_data = transformed_data
|
29
|
+
self.processing_info = processing_info
|
30
|
+
|
31
|
+
def to_dict(self) -> Dict[str, Any]:
|
32
|
+
"""
|
33
|
+
Convert result to dictionary.
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
Dict[str, Any]: Result as dictionary
|
37
|
+
"""
|
38
|
+
return {
|
39
|
+
"original_data": self.original_data,
|
40
|
+
"transformed_data": self.transformed_data,
|
41
|
+
"processing_info": self.processing_info,
|
42
|
+
"command_type": "data_transform"
|
43
|
+
}
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def get_schema(cls) -> Dict[str, Any]:
|
47
|
+
"""
|
48
|
+
Get JSON schema for the result.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
Dict[str, Any]: JSON schema
|
52
|
+
"""
|
53
|
+
return {
|
54
|
+
"type": "object",
|
55
|
+
"properties": {
|
56
|
+
"original_data": {"type": "object"},
|
57
|
+
"transformed_data": {"type": "object"},
|
58
|
+
"processing_info": {"type": "object"},
|
59
|
+
"command_type": {"type": "string"}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
class DataTransformCommand(Command):
|
65
|
+
"""
|
66
|
+
Data transform command for demonstrating advanced hooks.
|
67
|
+
"""
|
68
|
+
|
69
|
+
name = "data_transform"
|
70
|
+
result_class = DataTransformResult
|
71
|
+
|
72
|
+
async def execute(self, data: Optional[Dict[str, Any]] = None,
|
73
|
+
transform_type: Optional[str] = None, **kwargs) -> DataTransformResult:
|
74
|
+
"""
|
75
|
+
Execute data transform command.
|
76
|
+
|
77
|
+
Args:
|
78
|
+
data: Input data to transform
|
79
|
+
transform_type: Type of transformation to apply
|
80
|
+
**kwargs: Additional parameters
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
DataTransformResult: Data transform command result
|
84
|
+
"""
|
85
|
+
# Get original data (may be modified by hooks)
|
86
|
+
original_data = data or {}
|
87
|
+
transform_type = transform_type or "default"
|
88
|
+
|
89
|
+
# Apply transformation based on type
|
90
|
+
if transform_type == "uppercase":
|
91
|
+
transformed_data = {k: str(v).upper() for k, v in original_data.items()}
|
92
|
+
elif transform_type == "lowercase":
|
93
|
+
transformed_data = {k: str(v).lower() for k, v in original_data.items()}
|
94
|
+
elif transform_type == "reverse":
|
95
|
+
transformed_data = {k: str(v)[::-1] for k, v in original_data.items()}
|
96
|
+
else:
|
97
|
+
transformed_data = original_data.copy()
|
98
|
+
|
99
|
+
# Add processing info
|
100
|
+
processing_info = {
|
101
|
+
"transform_type": transform_type,
|
102
|
+
"input_keys": list(original_data.keys()),
|
103
|
+
"output_keys": list(transformed_data.keys()),
|
104
|
+
"hook_enhanced": kwargs.get("hook_enhanced", False),
|
105
|
+
"data_modified": kwargs.get("data_modified", False)
|
106
|
+
}
|
107
|
+
|
108
|
+
return DataTransformResult(
|
109
|
+
original_data=original_data,
|
110
|
+
transformed_data=transformed_data,
|
111
|
+
processing_info=processing_info
|
112
|
+
)
|
113
|
+
|
114
|
+
@classmethod
|
115
|
+
def get_schema(cls) -> Dict[str, Any]:
|
116
|
+
"""
|
117
|
+
Get JSON schema for command parameters.
|
118
|
+
|
119
|
+
Returns:
|
120
|
+
Dict[str, Any]: JSON schema
|
121
|
+
"""
|
122
|
+
return {
|
123
|
+
"type": "object",
|
124
|
+
"properties": {
|
125
|
+
"data": {
|
126
|
+
"type": "object",
|
127
|
+
"description": "Input data to transform"
|
128
|
+
},
|
129
|
+
"transform_type": {
|
130
|
+
"type": "string",
|
131
|
+
"enum": ["uppercase", "lowercase", "reverse", "default"],
|
132
|
+
"description": "Type of transformation to apply"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
"""
|
2
|
+
Echo Command Example
|
3
|
+
|
4
|
+
A simple echo command that returns the input message.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Dict, Any, Optional
|
8
|
+
from datetime import datetime
|
9
|
+
from mcp_proxy_adapter.commands.base import Command
|
10
|
+
from mcp_proxy_adapter.commands.result import SuccessResult
|
11
|
+
|
12
|
+
|
13
|
+
class EchoResult(SuccessResult):
|
14
|
+
"""
|
15
|
+
Result of the echo command execution.
|
16
|
+
"""
|
17
|
+
|
18
|
+
def __init__(self, message: str, timestamp: str):
|
19
|
+
"""
|
20
|
+
Initialize echo command result.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
message: The echoed message
|
24
|
+
timestamp: Timestamp of execution
|
25
|
+
"""
|
26
|
+
super().__init__(
|
27
|
+
data={
|
28
|
+
"message": message,
|
29
|
+
"timestamp": timestamp,
|
30
|
+
"echoed": True
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def get_schema(cls) -> Dict[str, Any]:
|
36
|
+
"""
|
37
|
+
Get JSON schema for result validation.
|
38
|
+
|
39
|
+
Returns:
|
40
|
+
Dict[str, Any]: JSON schema
|
41
|
+
"""
|
42
|
+
return {
|
43
|
+
"type": "object",
|
44
|
+
"properties": {
|
45
|
+
"data": {
|
46
|
+
"type": "object",
|
47
|
+
"properties": {
|
48
|
+
"message": {"type": "string"},
|
49
|
+
"timestamp": {"type": "string"},
|
50
|
+
"echoed": {"type": "boolean"}
|
51
|
+
},
|
52
|
+
"required": ["message", "timestamp", "echoed"]
|
53
|
+
}
|
54
|
+
},
|
55
|
+
"required": ["data"]
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
class EchoCommand(Command):
|
60
|
+
"""
|
61
|
+
Echo command that returns the input message.
|
62
|
+
"""
|
63
|
+
|
64
|
+
name = "echo"
|
65
|
+
result_class = EchoResult
|
66
|
+
|
67
|
+
async def execute(self, message: Optional[str] = None, **kwargs) -> EchoResult:
|
68
|
+
"""
|
69
|
+
Execute echo command.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
message: Message to echo (optional)
|
73
|
+
**kwargs: Additional parameters
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
EchoResult: Echo command result
|
77
|
+
"""
|
78
|
+
# Use provided message or default
|
79
|
+
if message is None:
|
80
|
+
message = kwargs.get("text", "Hello, World!")
|
81
|
+
|
82
|
+
# Check if hook added timestamp
|
83
|
+
hook_timestamp = kwargs.get("hook_timestamp")
|
84
|
+
if hook_timestamp:
|
85
|
+
# Use hook timestamp if available
|
86
|
+
timestamp = hook_timestamp
|
87
|
+
else:
|
88
|
+
# Get current timestamp
|
89
|
+
timestamp = datetime.now().isoformat()
|
90
|
+
|
91
|
+
# Add hook metadata to result
|
92
|
+
result = EchoResult(message=message, timestamp=timestamp)
|
93
|
+
|
94
|
+
# Add hook information if available
|
95
|
+
if kwargs.get("hook_processed"):
|
96
|
+
result.data["hook_processed"] = True
|
97
|
+
result.data["hook_timestamp"] = hook_timestamp
|
98
|
+
|
99
|
+
return result
|
100
|
+
|
101
|
+
@classmethod
|
102
|
+
def get_schema(cls) -> Dict[str, Any]:
|
103
|
+
"""
|
104
|
+
Get JSON schema for command parameters.
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
Dict[str, Any]: JSON schema
|
108
|
+
"""
|
109
|
+
return {
|
110
|
+
"type": "object",
|
111
|
+
"properties": {
|
112
|
+
"message": {
|
113
|
+
"type": "string",
|
114
|
+
"description": "Message to echo",
|
115
|
+
"default": "Hello, World!"
|
116
|
+
},
|
117
|
+
"text": {
|
118
|
+
"type": "string",
|
119
|
+
"description": "Alternative parameter name for message"
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|