mcp-proxy-adapter 3.1.6__py3-none-any.whl → 4.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_proxy_adapter/api/app.py +65 -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 +254 -8
- 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/unit/test_base_command.py +391 -85
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.1.0.dist-info}/METADATA +3 -3
- mcp_proxy_adapter-4.1.0.dist-info/RECORD +110 -0
- {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.1.0.dist-info}/WHEEL +1 -1
- {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.1.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.6.dist-info/RECORD +0 -118
- {mcp_proxy_adapter-3.1.6.dist-info → mcp_proxy_adapter-4.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,211 @@
|
|
1
|
+
"""
|
2
|
+
Reload command for configuration and command discovery.
|
3
|
+
|
4
|
+
This command allows reloading configuration and rediscovering commands
|
5
|
+
without restarting the server.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import Any, Dict, Optional
|
9
|
+
|
10
|
+
from mcp_proxy_adapter.commands.base import Command
|
11
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
12
|
+
from mcp_proxy_adapter.core.logging import logger
|
13
|
+
|
14
|
+
|
15
|
+
class ReloadResult:
|
16
|
+
"""
|
17
|
+
Result of reload operation.
|
18
|
+
"""
|
19
|
+
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
config_reloaded: bool,
|
23
|
+
commands_discovered: int,
|
24
|
+
custom_commands_preserved: int,
|
25
|
+
total_commands: int,
|
26
|
+
built_in_commands: int,
|
27
|
+
custom_commands: int,
|
28
|
+
server_restart_required: bool = True,
|
29
|
+
success: bool = True,
|
30
|
+
error_message: Optional[str] = None
|
31
|
+
):
|
32
|
+
"""
|
33
|
+
Initialize reload result.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
config_reloaded: Whether configuration was reloaded successfully
|
37
|
+
commands_discovered: Number of commands discovered
|
38
|
+
custom_commands_preserved: Number of custom commands preserved
|
39
|
+
total_commands: Total number of commands after reload
|
40
|
+
built_in_commands: Number of built-in commands
|
41
|
+
custom_commands: Number of custom commands
|
42
|
+
server_restart_required: Whether server restart is required
|
43
|
+
success: Whether reload was successful
|
44
|
+
error_message: Error message if reload failed
|
45
|
+
"""
|
46
|
+
self.config_reloaded = config_reloaded
|
47
|
+
self.commands_discovered = commands_discovered
|
48
|
+
self.custom_commands_preserved = custom_commands_preserved
|
49
|
+
self.total_commands = total_commands
|
50
|
+
self.built_in_commands = built_in_commands
|
51
|
+
self.custom_commands = custom_commands
|
52
|
+
self.server_restart_required = server_restart_required
|
53
|
+
self.success = success
|
54
|
+
self.error_message = error_message
|
55
|
+
|
56
|
+
def to_dict(self) -> Dict[str, Any]:
|
57
|
+
"""
|
58
|
+
Convert result to dictionary.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
Dictionary representation of the result.
|
62
|
+
"""
|
63
|
+
return {
|
64
|
+
"success": self.success,
|
65
|
+
"config_reloaded": self.config_reloaded,
|
66
|
+
"commands_discovered": self.commands_discovered,
|
67
|
+
"custom_commands_preserved": self.custom_commands_preserved,
|
68
|
+
"total_commands": self.total_commands,
|
69
|
+
"built_in_commands": self.built_in_commands,
|
70
|
+
"custom_commands": self.custom_commands,
|
71
|
+
"server_restart_required": self.server_restart_required,
|
72
|
+
"message": "Server restart required to apply configuration changes",
|
73
|
+
"error_message": self.error_message
|
74
|
+
}
|
75
|
+
|
76
|
+
def get_schema(self) -> Dict[str, Any]:
|
77
|
+
"""
|
78
|
+
Get JSON schema for the result.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
JSON schema dictionary.
|
82
|
+
"""
|
83
|
+
return {
|
84
|
+
"type": "object",
|
85
|
+
"properties": {
|
86
|
+
"success": {
|
87
|
+
"type": "boolean",
|
88
|
+
"description": "Whether reload was successful"
|
89
|
+
},
|
90
|
+
"config_reloaded": {
|
91
|
+
"type": "boolean",
|
92
|
+
"description": "Whether configuration was reloaded successfully"
|
93
|
+
},
|
94
|
+
"commands_discovered": {
|
95
|
+
"type": "integer",
|
96
|
+
"description": "Number of commands discovered"
|
97
|
+
},
|
98
|
+
"custom_commands_preserved": {
|
99
|
+
"type": "integer",
|
100
|
+
"description": "Number of custom commands preserved"
|
101
|
+
},
|
102
|
+
"total_commands": {
|
103
|
+
"type": "integer",
|
104
|
+
"description": "Total number of commands after reload"
|
105
|
+
},
|
106
|
+
"built_in_commands": {
|
107
|
+
"type": "integer",
|
108
|
+
"description": "Number of built-in commands"
|
109
|
+
},
|
110
|
+
"custom_commands": {
|
111
|
+
"type": "integer",
|
112
|
+
"description": "Number of custom commands"
|
113
|
+
},
|
114
|
+
"server_restart_required": {
|
115
|
+
"type": "boolean",
|
116
|
+
"description": "Whether server restart is required to apply changes"
|
117
|
+
},
|
118
|
+
"message": {
|
119
|
+
"type": "string",
|
120
|
+
"description": "Information message about the reload operation"
|
121
|
+
},
|
122
|
+
"error_message": {
|
123
|
+
"type": ["string", "null"],
|
124
|
+
"description": "Error message if reload failed"
|
125
|
+
}
|
126
|
+
},
|
127
|
+
"required": [
|
128
|
+
"success", "config_reloaded", "commands_discovered",
|
129
|
+
"custom_commands_preserved", "total_commands",
|
130
|
+
"built_in_commands", "custom_commands", "server_restart_required"
|
131
|
+
]
|
132
|
+
}
|
133
|
+
|
134
|
+
|
135
|
+
class ReloadCommand(Command):
|
136
|
+
"""
|
137
|
+
Command for reloading configuration and rediscovering commands.
|
138
|
+
Note: This command will trigger a server restart to apply configuration changes.
|
139
|
+
"""
|
140
|
+
|
141
|
+
name = "reload"
|
142
|
+
|
143
|
+
async def execute(self, **params) -> ReloadResult:
|
144
|
+
"""
|
145
|
+
Execute reload command.
|
146
|
+
|
147
|
+
Args:
|
148
|
+
**params: Command parameters (currently unused)
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
ReloadResult with reload information
|
152
|
+
"""
|
153
|
+
try:
|
154
|
+
logger.info("🔄 Starting configuration and commands reload...")
|
155
|
+
|
156
|
+
# Perform reload
|
157
|
+
reload_info = registry.reload_config_and_commands()
|
158
|
+
|
159
|
+
# Create result
|
160
|
+
result = ReloadResult(
|
161
|
+
config_reloaded=reload_info.get("config_reloaded", False),
|
162
|
+
commands_discovered=reload_info.get("commands_discovered", 0),
|
163
|
+
custom_commands_preserved=reload_info.get("custom_commands_preserved", 0),
|
164
|
+
total_commands=reload_info.get("total_commands", 0),
|
165
|
+
built_in_commands=reload_info.get("built_in_commands", 0),
|
166
|
+
custom_commands=reload_info.get("custom_commands", 0),
|
167
|
+
server_restart_required=True,
|
168
|
+
success=True
|
169
|
+
)
|
170
|
+
|
171
|
+
logger.info(f"✅ Reload completed successfully: {result.to_dict()}")
|
172
|
+
return result
|
173
|
+
|
174
|
+
except Exception as e:
|
175
|
+
logger.error(f"❌ Reload failed: {str(e)}")
|
176
|
+
return ReloadResult(
|
177
|
+
config_reloaded=False,
|
178
|
+
commands_discovered=0,
|
179
|
+
custom_commands_preserved=0,
|
180
|
+
total_commands=0,
|
181
|
+
built_in_commands=0,
|
182
|
+
custom_commands=0,
|
183
|
+
server_restart_required=False,
|
184
|
+
success=False,
|
185
|
+
error_message=str(e)
|
186
|
+
)
|
187
|
+
|
188
|
+
@classmethod
|
189
|
+
def get_schema(cls) -> Dict[str, Any]:
|
190
|
+
"""
|
191
|
+
Get JSON schema for command parameters.
|
192
|
+
|
193
|
+
Returns:
|
194
|
+
JSON schema dictionary.
|
195
|
+
"""
|
196
|
+
return {
|
197
|
+
"type": "object",
|
198
|
+
"properties": {
|
199
|
+
"package_path": {
|
200
|
+
"type": "string",
|
201
|
+
"description": "Path to package with commands to discover",
|
202
|
+
"default": "mcp_proxy_adapter.commands"
|
203
|
+
},
|
204
|
+
"force_restart": {
|
205
|
+
"type": "boolean",
|
206
|
+
"description": "Force server restart to apply configuration changes",
|
207
|
+
"default": True
|
208
|
+
}
|
209
|
+
},
|
210
|
+
"additionalProperties": False
|
211
|
+
}
|
@@ -0,0 +1,125 @@
|
|
1
|
+
"""
|
2
|
+
Reload Settings Command
|
3
|
+
|
4
|
+
This command allows reloading configuration settings from files and environment variables.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import Dict, Any
|
8
|
+
from mcp_proxy_adapter.commands.base import Command
|
9
|
+
from mcp_proxy_adapter.core.settings import reload_settings, get_custom_settings
|
10
|
+
from mcp_proxy_adapter.core.logging import get_logger
|
11
|
+
|
12
|
+
|
13
|
+
class ReloadSettingsResult:
|
14
|
+
"""
|
15
|
+
Result class for reload settings command.
|
16
|
+
"""
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
success: bool,
|
21
|
+
message: str,
|
22
|
+
custom_settings: Dict[str, Any] = None,
|
23
|
+
error_message: str = None
|
24
|
+
):
|
25
|
+
self.success = success
|
26
|
+
self.message = message
|
27
|
+
self.custom_settings = custom_settings or {}
|
28
|
+
self.error_message = error_message
|
29
|
+
|
30
|
+
def to_dict(self) -> Dict[str, Any]:
|
31
|
+
"""Convert result to dictionary."""
|
32
|
+
result = {
|
33
|
+
"success": self.success,
|
34
|
+
"message": self.message,
|
35
|
+
"custom_settings": self.custom_settings
|
36
|
+
}
|
37
|
+
if self.error_message:
|
38
|
+
result["error_message"] = self.error_message
|
39
|
+
return result
|
40
|
+
|
41
|
+
def get_schema(self) -> Dict[str, Any]:
|
42
|
+
"""Get JSON schema for the result."""
|
43
|
+
return {
|
44
|
+
"type": "object",
|
45
|
+
"properties": {
|
46
|
+
"success": {
|
47
|
+
"type": "boolean",
|
48
|
+
"description": "Whether the operation was successful"
|
49
|
+
},
|
50
|
+
"message": {
|
51
|
+
"type": "string",
|
52
|
+
"description": "Operation result message"
|
53
|
+
},
|
54
|
+
"custom_settings": {
|
55
|
+
"type": "object",
|
56
|
+
"description": "Current custom settings after reload",
|
57
|
+
"additionalProperties": True
|
58
|
+
},
|
59
|
+
"error_message": {
|
60
|
+
"type": "string",
|
61
|
+
"description": "Error message if operation failed"
|
62
|
+
}
|
63
|
+
},
|
64
|
+
"required": ["success", "message", "custom_settings"]
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
class ReloadSettingsCommand(Command):
|
69
|
+
"""
|
70
|
+
Command to reload configuration settings.
|
71
|
+
"""
|
72
|
+
|
73
|
+
name = "reload_settings"
|
74
|
+
description = "Reload configuration settings from files and environment variables"
|
75
|
+
|
76
|
+
async def execute(self, **params) -> ReloadSettingsResult:
|
77
|
+
"""
|
78
|
+
Execute the reload settings command.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
**params: Command parameters (not used)
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
ReloadSettingsResult with operation status
|
85
|
+
"""
|
86
|
+
logger = get_logger("reload_settings_command")
|
87
|
+
|
88
|
+
try:
|
89
|
+
logger.info("🔄 Starting settings reload...")
|
90
|
+
|
91
|
+
# Reload configuration from files and environment variables
|
92
|
+
reload_settings()
|
93
|
+
|
94
|
+
# Get current custom settings
|
95
|
+
custom_settings = get_custom_settings()
|
96
|
+
|
97
|
+
logger.info("✅ Settings reloaded successfully")
|
98
|
+
logger.info(f"📋 Current custom settings: {custom_settings}")
|
99
|
+
|
100
|
+
return ReloadSettingsResult(
|
101
|
+
success=True,
|
102
|
+
message="Settings reloaded successfully from configuration files and environment variables",
|
103
|
+
custom_settings=custom_settings
|
104
|
+
)
|
105
|
+
|
106
|
+
except Exception as e:
|
107
|
+
error_msg = f"Failed to reload settings: {str(e)}"
|
108
|
+
logger.error(f"❌ {error_msg}")
|
109
|
+
|
110
|
+
return ReloadSettingsResult(
|
111
|
+
success=False,
|
112
|
+
message="Failed to reload settings",
|
113
|
+
custom_settings=get_custom_settings(),
|
114
|
+
error_message=error_msg
|
115
|
+
)
|
116
|
+
|
117
|
+
@classmethod
|
118
|
+
def get_schema(cls) -> Dict[str, Any]:
|
119
|
+
"""Get JSON schema for the command parameters."""
|
120
|
+
return {
|
121
|
+
"type": "object",
|
122
|
+
"description": "Reload configuration settings from files and environment variables",
|
123
|
+
"properties": {},
|
124
|
+
"additionalProperties": False
|
125
|
+
}
|
@@ -0,0 +1,189 @@
|
|
1
|
+
"""
|
2
|
+
Settings command for demonstrating configuration management.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Dict, Any, Optional
|
6
|
+
from mcp_proxy_adapter.commands.base import Command
|
7
|
+
from mcp_proxy_adapter.core.settings import Settings, get_setting, set_setting, reload_settings
|
8
|
+
|
9
|
+
|
10
|
+
class SettingsResult:
|
11
|
+
"""Result class for settings command."""
|
12
|
+
|
13
|
+
def __init__(
|
14
|
+
self,
|
15
|
+
success: bool,
|
16
|
+
operation: str,
|
17
|
+
key: Optional[str] = None,
|
18
|
+
value: Any = None,
|
19
|
+
all_settings: Optional[Dict[str, Any]] = None,
|
20
|
+
error_message: Optional[str] = None
|
21
|
+
):
|
22
|
+
self.success = success
|
23
|
+
self.operation = operation
|
24
|
+
self.key = key
|
25
|
+
self.value = value
|
26
|
+
self.all_settings = all_settings
|
27
|
+
self.error_message = error_message
|
28
|
+
|
29
|
+
def to_dict(self) -> Dict[str, Any]:
|
30
|
+
"""Convert result to dictionary."""
|
31
|
+
result = {
|
32
|
+
"success": self.success,
|
33
|
+
"operation": self.operation
|
34
|
+
}
|
35
|
+
|
36
|
+
if self.key is not None:
|
37
|
+
result["key"] = self.key
|
38
|
+
if self.value is not None:
|
39
|
+
result["value"] = self.value
|
40
|
+
if self.all_settings is not None:
|
41
|
+
result["all_settings"] = self.all_settings
|
42
|
+
if self.error_message is not None:
|
43
|
+
result["error_message"] = self.error_message
|
44
|
+
|
45
|
+
return result
|
46
|
+
|
47
|
+
def get_schema(self) -> Dict[str, Any]:
|
48
|
+
"""Get schema for the result."""
|
49
|
+
return {
|
50
|
+
"type": "object",
|
51
|
+
"properties": {
|
52
|
+
"success": {
|
53
|
+
"type": "boolean",
|
54
|
+
"description": "Whether the operation was successful"
|
55
|
+
},
|
56
|
+
"operation": {
|
57
|
+
"type": "string",
|
58
|
+
"description": "Type of operation performed",
|
59
|
+
"enum": ["get", "set", "get_all", "reload"]
|
60
|
+
},
|
61
|
+
"key": {
|
62
|
+
"type": "string",
|
63
|
+
"description": "Configuration key (for get/set operations)"
|
64
|
+
},
|
65
|
+
"value": {
|
66
|
+
"description": "Configuration value (for get/set operations)"
|
67
|
+
},
|
68
|
+
"all_settings": {
|
69
|
+
"type": "object",
|
70
|
+
"description": "All configuration settings (for get_all operation)"
|
71
|
+
},
|
72
|
+
"error_message": {
|
73
|
+
"type": "string",
|
74
|
+
"description": "Error message if operation failed"
|
75
|
+
}
|
76
|
+
},
|
77
|
+
"required": ["success", "operation"]
|
78
|
+
}
|
79
|
+
|
80
|
+
|
81
|
+
class SettingsCommand(Command):
|
82
|
+
"""Command for managing framework settings."""
|
83
|
+
|
84
|
+
name = "settings"
|
85
|
+
description = "Manage framework settings and configuration"
|
86
|
+
|
87
|
+
async def execute(self, **params) -> SettingsResult:
|
88
|
+
"""
|
89
|
+
Execute settings command.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
operation: Operation to perform (get, set, get_all, reload)
|
93
|
+
key: Configuration key (for get/set operations)
|
94
|
+
value: Configuration value (for set operation)
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
SettingsResult with operation result
|
98
|
+
"""
|
99
|
+
try:
|
100
|
+
operation = params.get("operation", "get_all")
|
101
|
+
|
102
|
+
if operation == "get":
|
103
|
+
key = params.get("key")
|
104
|
+
if not key:
|
105
|
+
return SettingsResult(
|
106
|
+
success=False,
|
107
|
+
operation=operation,
|
108
|
+
error_message="Key is required for 'get' operation"
|
109
|
+
)
|
110
|
+
|
111
|
+
value = get_setting(key)
|
112
|
+
return SettingsResult(
|
113
|
+
success=True,
|
114
|
+
operation=operation,
|
115
|
+
key=key,
|
116
|
+
value=value
|
117
|
+
)
|
118
|
+
|
119
|
+
elif operation == "set":
|
120
|
+
key = params.get("key")
|
121
|
+
value = params.get("value")
|
122
|
+
|
123
|
+
if not key:
|
124
|
+
return SettingsResult(
|
125
|
+
success=False,
|
126
|
+
operation=operation,
|
127
|
+
error_message="Key is required for 'set' operation"
|
128
|
+
)
|
129
|
+
|
130
|
+
set_setting(key, value)
|
131
|
+
return SettingsResult(
|
132
|
+
success=True,
|
133
|
+
operation=operation,
|
134
|
+
key=key,
|
135
|
+
value=value
|
136
|
+
)
|
137
|
+
|
138
|
+
elif operation == "get_all":
|
139
|
+
all_settings = Settings.get_all_settings()
|
140
|
+
return SettingsResult(
|
141
|
+
success=True,
|
142
|
+
operation=operation,
|
143
|
+
all_settings=all_settings
|
144
|
+
)
|
145
|
+
|
146
|
+
elif operation == "reload":
|
147
|
+
reload_settings()
|
148
|
+
return SettingsResult(
|
149
|
+
success=True,
|
150
|
+
operation=operation
|
151
|
+
)
|
152
|
+
|
153
|
+
else:
|
154
|
+
return SettingsResult(
|
155
|
+
success=False,
|
156
|
+
operation=operation,
|
157
|
+
error_message=f"Unknown operation: {operation}. Supported operations: get, set, get_all, reload"
|
158
|
+
)
|
159
|
+
|
160
|
+
except Exception as e:
|
161
|
+
return SettingsResult(
|
162
|
+
success=False,
|
163
|
+
operation=params.get("operation", "unknown"),
|
164
|
+
error_message=str(e)
|
165
|
+
)
|
166
|
+
|
167
|
+
@classmethod
|
168
|
+
def get_schema(cls) -> Dict[str, Any]:
|
169
|
+
"""Get schema for the command."""
|
170
|
+
return {
|
171
|
+
"type": "object",
|
172
|
+
"properties": {
|
173
|
+
"operation": {
|
174
|
+
"type": "string",
|
175
|
+
"description": "Operation to perform",
|
176
|
+
"enum": ["get", "set", "get_all", "reload"],
|
177
|
+
"default": "get_all"
|
178
|
+
},
|
179
|
+
"key": {
|
180
|
+
"type": "string",
|
181
|
+
"description": "Configuration key in dot notation (e.g., 'server.host', 'custom.feature_enabled')"
|
182
|
+
},
|
183
|
+
"value": {
|
184
|
+
"description": "Configuration value to set (for 'set' operation)"
|
185
|
+
}
|
186
|
+
},
|
187
|
+
"required": ["operation"],
|
188
|
+
"additionalProperties": False
|
189
|
+
}
|
mcp_proxy_adapter/config.py
CHANGED
@@ -39,7 +39,22 @@ class Config:
|
|
39
39
|
},
|
40
40
|
"logging": {
|
41
41
|
"level": "INFO",
|
42
|
-
"file": None
|
42
|
+
"file": None,
|
43
|
+
"log_dir": "./logs",
|
44
|
+
"log_file": "mcp_proxy_adapter.log",
|
45
|
+
"error_log_file": "mcp_proxy_adapter_error.log",
|
46
|
+
"access_log_file": "mcp_proxy_adapter_access.log",
|
47
|
+
"max_file_size": "10MB",
|
48
|
+
"backup_count": 5,
|
49
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
50
|
+
"date_format": "%Y-%m-%d %H:%M:%S",
|
51
|
+
"console_output": True,
|
52
|
+
"file_output": True
|
53
|
+
},
|
54
|
+
"commands": {
|
55
|
+
"auto_discovery": True,
|
56
|
+
"discovery_path": "mcp_proxy_adapter.commands",
|
57
|
+
"custom_commands_path": None
|
43
58
|
}
|
44
59
|
}
|
45
60
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""
|
2
|
+
Core functionality for MCP Proxy Adapter.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from .errors import *
|
6
|
+
from .logging import *
|
7
|
+
from .settings import *
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
# Errors
|
11
|
+
"NotFoundError",
|
12
|
+
"InvalidParamsError",
|
13
|
+
"CommandExecutionError",
|
14
|
+
"ConfigurationError",
|
15
|
+
|
16
|
+
# Logging
|
17
|
+
"setup_logging",
|
18
|
+
"get_logger",
|
19
|
+
"logger",
|
20
|
+
"RequestLogger",
|
21
|
+
"CustomFormatter",
|
22
|
+
"RequestContextFilter",
|
23
|
+
|
24
|
+
# Settings
|
25
|
+
"Settings",
|
26
|
+
"ServerSettings",
|
27
|
+
"LoggingSettings",
|
28
|
+
"CommandsSettings",
|
29
|
+
"get_server_host",
|
30
|
+
"get_server_port",
|
31
|
+
"get_server_debug",
|
32
|
+
"get_logging_level",
|
33
|
+
"get_logging_dir",
|
34
|
+
"get_auto_discovery",
|
35
|
+
"get_discovery_path",
|
36
|
+
"get_setting",
|
37
|
+
"set_setting",
|
38
|
+
"reload_settings",
|
39
|
+
"add_custom_settings",
|
40
|
+
"get_custom_settings",
|
41
|
+
"get_custom_setting_value",
|
42
|
+
"set_custom_setting_value",
|
43
|
+
"clear_custom_settings"
|
44
|
+
]
|