mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__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/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +12 -2
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -13,11 +13,15 @@ from mcp_proxy_adapter.core.logging import logger
|
|
13
13
|
|
14
14
|
class TransportManagementResult(SuccessResult):
|
15
15
|
"""Result class for transport management operations."""
|
16
|
-
|
17
|
-
def __init__(
|
16
|
+
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
transport_info: Dict[str, Any],
|
20
|
+
message: str = "Transport management operation completed",
|
21
|
+
):
|
18
22
|
"""
|
19
23
|
Initialize transport management result.
|
20
|
-
|
24
|
+
|
21
25
|
Args:
|
22
26
|
transport_info: Transport information
|
23
27
|
message: Success message
|
@@ -28,18 +32,18 @@ class TransportManagementResult(SuccessResult):
|
|
28
32
|
class TransportManagementCommand(Command):
|
29
33
|
"""
|
30
34
|
Transport management command.
|
31
|
-
|
35
|
+
|
32
36
|
This command provides functionality to manage and query transport configurations.
|
33
37
|
"""
|
34
|
-
|
38
|
+
|
35
39
|
name = "transport_management"
|
36
40
|
descr = "Manage and query transport configurations (HTTP, HTTPS, MTLS)"
|
37
|
-
|
41
|
+
|
38
42
|
@classmethod
|
39
43
|
def get_schema(cls) -> Dict[str, Any]:
|
40
44
|
"""
|
41
45
|
Get command schema.
|
42
|
-
|
46
|
+
|
43
47
|
Returns:
|
44
48
|
Command schema dictionary
|
45
49
|
"""
|
@@ -49,25 +53,25 @@ class TransportManagementCommand(Command):
|
|
49
53
|
"action": {
|
50
54
|
"type": "string",
|
51
55
|
"enum": ["get_info", "validate", "reload"],
|
52
|
-
"description": "Action to perform"
|
56
|
+
"description": "Action to perform",
|
53
57
|
}
|
54
58
|
},
|
55
|
-
"required": ["action"]
|
59
|
+
"required": ["action"],
|
56
60
|
}
|
57
|
-
|
61
|
+
|
58
62
|
async def execute(self, **params) -> TransportManagementResult:
|
59
63
|
"""
|
60
64
|
Execute transport management command.
|
61
|
-
|
65
|
+
|
62
66
|
Args:
|
63
67
|
params: Command parameters
|
64
|
-
|
68
|
+
|
65
69
|
Returns:
|
66
70
|
Transport management result
|
67
71
|
"""
|
68
72
|
try:
|
69
73
|
action = params.get("action", "get_info")
|
70
|
-
|
74
|
+
|
71
75
|
if action == "get_info":
|
72
76
|
return await self._get_transport_info()
|
73
77
|
elif action == "validate":
|
@@ -77,56 +81,57 @@ class TransportManagementCommand(Command):
|
|
77
81
|
else:
|
78
82
|
return TransportManagementResult(
|
79
83
|
transport_info={"error": f"Unknown action: {action}"},
|
80
|
-
message=f"Unknown action: {action}"
|
84
|
+
message=f"Unknown action: {action}",
|
81
85
|
)
|
82
|
-
|
86
|
+
|
83
87
|
except Exception as e:
|
84
88
|
logger.error(f"Transport management command error: {e}")
|
85
89
|
return TransportManagementResult(
|
86
90
|
transport_info={"error": str(e)},
|
87
|
-
message=f"Transport management failed: {e}"
|
91
|
+
message=f"Transport management failed: {e}",
|
88
92
|
)
|
89
|
-
|
93
|
+
|
90
94
|
async def _get_transport_info(self) -> TransportManagementResult:
|
91
95
|
"""
|
92
96
|
Get transport information.
|
93
|
-
|
97
|
+
|
94
98
|
Returns:
|
95
99
|
Transport information result
|
96
100
|
"""
|
97
101
|
transport_info = transport_manager.get_transport_info()
|
98
|
-
|
102
|
+
|
99
103
|
return TransportManagementResult(
|
100
104
|
transport_info=transport_info,
|
101
|
-
message="Transport information retrieved successfully"
|
105
|
+
message="Transport information retrieved successfully",
|
102
106
|
)
|
103
|
-
|
107
|
+
|
104
108
|
async def _validate_transport(self) -> TransportManagementResult:
|
105
109
|
"""
|
106
110
|
Validate transport configuration.
|
107
|
-
|
111
|
+
|
108
112
|
Returns:
|
109
113
|
Validation result
|
110
114
|
"""
|
111
115
|
is_valid = transport_manager.validate_config()
|
112
|
-
|
116
|
+
|
113
117
|
transport_info = transport_manager.get_transport_info()
|
114
118
|
transport_info["validation"] = {
|
115
119
|
"is_valid": is_valid,
|
116
|
-
"timestamp": "2025-08-15T12:00:00Z"
|
120
|
+
"timestamp": "2025-08-15T12:00:00Z",
|
117
121
|
}
|
118
|
-
|
119
|
-
message =
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
message=message
|
122
|
+
|
123
|
+
message = (
|
124
|
+
"Transport configuration validated successfully"
|
125
|
+
if is_valid
|
126
|
+
else "Transport configuration validation failed"
|
124
127
|
)
|
125
|
-
|
128
|
+
|
129
|
+
return TransportManagementResult(transport_info=transport_info, message=message)
|
130
|
+
|
126
131
|
async def _reload_transport(self) -> TransportManagementResult:
|
127
132
|
"""
|
128
133
|
Reload transport configuration.
|
129
|
-
|
134
|
+
|
130
135
|
Returns:
|
131
136
|
Reload result
|
132
137
|
"""
|
@@ -135,10 +140,10 @@ class TransportManagementCommand(Command):
|
|
135
140
|
transport_info = transport_manager.get_transport_info()
|
136
141
|
transport_info["reload"] = {
|
137
142
|
"status": "completed",
|
138
|
-
"timestamp": "2025-08-15T12:00:00Z"
|
143
|
+
"timestamp": "2025-08-15T12:00:00Z",
|
139
144
|
}
|
140
|
-
|
145
|
+
|
141
146
|
return TransportManagementResult(
|
142
147
|
transport_info=transport_info,
|
143
|
-
message="Transport configuration reload completed"
|
144
|
-
)
|
148
|
+
message="Transport configuration reload completed",
|
149
|
+
)
|
@@ -13,31 +13,34 @@ class UnloadResult(SuccessResult):
|
|
13
13
|
"""
|
14
14
|
Result of the unload command execution.
|
15
15
|
"""
|
16
|
-
|
17
|
-
def __init__(
|
16
|
+
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
success: bool,
|
20
|
+
command_name: str,
|
21
|
+
message: str,
|
22
|
+
error: Optional[str] = None,
|
23
|
+
):
|
18
24
|
"""
|
19
25
|
Initialize unload command result.
|
20
|
-
|
26
|
+
|
21
27
|
Args:
|
22
28
|
success: Whether unloading was successful
|
23
29
|
command_name: Name of the command that was unloaded
|
24
30
|
message: Result message
|
25
31
|
error: Error message if unloading failed
|
26
32
|
"""
|
27
|
-
data = {
|
28
|
-
"success": success,
|
29
|
-
"command_name": command_name
|
30
|
-
}
|
33
|
+
data = {"success": success, "command_name": command_name}
|
31
34
|
if error:
|
32
35
|
data["error"] = error
|
33
|
-
|
36
|
+
|
34
37
|
super().__init__(data=data, message=message)
|
35
|
-
|
38
|
+
|
36
39
|
@classmethod
|
37
40
|
def get_schema(cls) -> Dict[str, Any]:
|
38
41
|
"""
|
39
42
|
Get JSON schema for result validation.
|
40
|
-
|
43
|
+
|
41
44
|
Returns:
|
42
45
|
Dict[str, Any]: JSON schema
|
43
46
|
"""
|
@@ -49,69 +52,69 @@ class UnloadResult(SuccessResult):
|
|
49
52
|
"properties": {
|
50
53
|
"success": {"type": "boolean"},
|
51
54
|
"command_name": {"type": "string"},
|
52
|
-
"error": {"type": "string"}
|
55
|
+
"error": {"type": "string"},
|
53
56
|
},
|
54
|
-
"required": ["success", "command_name"]
|
57
|
+
"required": ["success", "command_name"],
|
55
58
|
}
|
56
59
|
},
|
57
|
-
"required": ["data"]
|
60
|
+
"required": ["data"],
|
58
61
|
}
|
59
62
|
|
60
63
|
|
61
64
|
class UnloadCommand(Command):
|
62
65
|
"""
|
63
66
|
Command that unloads loaded commands from registry.
|
64
|
-
|
67
|
+
|
65
68
|
This command allows removal of dynamically loaded commands from the command registry.
|
66
69
|
Only commands that were loaded via the 'load' command or from the commands directory
|
67
70
|
can be unloaded. Built-in commands and custom commands registered with higher priority
|
68
71
|
cannot be unloaded using this command.
|
69
|
-
|
72
|
+
|
70
73
|
When a command is unloaded:
|
71
74
|
- The command class is removed from the loaded commands registry
|
72
75
|
- Any command instances are also removed
|
73
76
|
- The command becomes unavailable for execution
|
74
77
|
- Built-in and custom commands with the same name remain unaffected
|
75
|
-
|
78
|
+
|
76
79
|
This is useful for:
|
77
80
|
- Removing outdated or problematic commands
|
78
81
|
- Managing memory usage by unloading unused commands
|
79
82
|
- Testing different versions of commands
|
80
83
|
- Cleaning up temporary commands loaded for testing
|
81
|
-
|
84
|
+
|
82
85
|
Note: Unloading a command does not affect other commands and does not require
|
83
86
|
a system restart. The command can be reloaded later if needed.
|
84
87
|
"""
|
85
|
-
|
88
|
+
|
86
89
|
name = "unload"
|
87
90
|
result_class = UnloadResult
|
88
|
-
|
91
|
+
|
89
92
|
async def execute(self, command_name: str, **kwargs) -> UnloadResult:
|
90
93
|
"""
|
91
94
|
Execute unload command.
|
92
|
-
|
95
|
+
|
93
96
|
Args:
|
94
97
|
command_name: Name of the command to unload
|
95
98
|
**kwargs: Additional parameters
|
96
|
-
|
99
|
+
|
97
100
|
Returns:
|
98
101
|
UnloadResult: Unload command result
|
99
102
|
"""
|
100
103
|
# Unload command from registry
|
101
104
|
result = registry.unload_command(command_name)
|
102
|
-
|
105
|
+
|
103
106
|
return UnloadResult(
|
104
107
|
success=result.get("success", False),
|
105
108
|
command_name=result.get("command_name", command_name),
|
106
109
|
message=result.get("message", "Unknown result"),
|
107
|
-
error=result.get("error")
|
110
|
+
error=result.get("error"),
|
108
111
|
)
|
109
|
-
|
112
|
+
|
110
113
|
@classmethod
|
111
114
|
def get_schema(cls) -> Dict[str, Any]:
|
112
115
|
"""
|
113
116
|
Get JSON schema for command parameters.
|
114
|
-
|
117
|
+
|
115
118
|
Returns:
|
116
119
|
Dict[str, Any]: JSON schema
|
117
120
|
"""
|
@@ -120,20 +123,22 @@ class UnloadCommand(Command):
|
|
120
123
|
"properties": {
|
121
124
|
"command_name": {
|
122
125
|
"type": "string",
|
123
|
-
"description": "Name of the command to unload (must be a loaded command)"
|
126
|
+
"description": "Name of the command to unload (must be a loaded command)",
|
124
127
|
}
|
125
128
|
},
|
126
|
-
"required": ["command_name"]
|
129
|
+
"required": ["command_name"],
|
127
130
|
}
|
128
|
-
|
131
|
+
|
129
132
|
@classmethod
|
130
|
-
def _generate_examples(
|
133
|
+
def _generate_examples(
|
134
|
+
cls, params: Dict[str, Dict[str, Any]]
|
135
|
+
) -> List[Dict[str, Any]]:
|
131
136
|
"""
|
132
137
|
Generate custom examples for unload command.
|
133
|
-
|
138
|
+
|
134
139
|
Args:
|
135
140
|
params: Information about command parameters
|
136
|
-
|
141
|
+
|
137
142
|
Returns:
|
138
143
|
List of examples
|
139
144
|
"""
|
@@ -141,18 +146,18 @@ class UnloadCommand(Command):
|
|
141
146
|
{
|
142
147
|
"command": cls.name,
|
143
148
|
"params": {"command_name": "test_command"},
|
144
|
-
"description": "Unload a previously loaded test command"
|
149
|
+
"description": "Unload a previously loaded test command",
|
145
150
|
},
|
146
151
|
{
|
147
152
|
"command": cls.name,
|
148
153
|
"params": {"command_name": "remote_command"},
|
149
|
-
"description": "Unload a command that was loaded from URL"
|
154
|
+
"description": "Unload a command that was loaded from URL",
|
150
155
|
},
|
151
156
|
{
|
152
157
|
"command": cls.name,
|
153
158
|
"params": {"command_name": "custom_command"},
|
154
|
-
"description": "Unload a custom command loaded from local file"
|
155
|
-
}
|
159
|
+
"description": "Unload a custom command loaded from local file",
|
160
|
+
},
|
156
161
|
]
|
157
|
-
|
158
|
-
return examples
|
162
|
+
|
163
|
+
return examples
|
mcp_proxy_adapter/config.py
CHANGED
@@ -39,7 +39,7 @@ class Config:
|
|
39
39
|
"host": "0.0.0.0",
|
40
40
|
"port": 8000,
|
41
41
|
"debug": False,
|
42
|
-
"log_level": "INFO"
|
42
|
+
"log_level": "INFO",
|
43
43
|
},
|
44
44
|
"logging": {
|
45
45
|
"level": "INFO",
|
@@ -53,7 +53,7 @@ class Config:
|
|
53
53
|
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
54
54
|
"date_format": "%Y-%m-%d %H:%M:%S",
|
55
55
|
"console_output": True,
|
56
|
-
"file_output": True
|
56
|
+
"file_output": True,
|
57
57
|
},
|
58
58
|
"commands": {
|
59
59
|
"auto_discovery": True,
|
@@ -63,7 +63,7 @@ class Config:
|
|
63
63
|
"auto_install_dependencies": True,
|
64
64
|
"enabled_commands": ["health", "echo", "list", "help"],
|
65
65
|
"disabled_commands": [],
|
66
|
-
"custom_commands_path": "./commands"
|
66
|
+
"custom_commands_path": "./commands",
|
67
67
|
},
|
68
68
|
"ssl": {
|
69
69
|
"enabled": False,
|
@@ -75,7 +75,7 @@ class Config:
|
|
75
75
|
"client_cert_required": False,
|
76
76
|
"cipher_suites": [
|
77
77
|
"TLS_AES_256_GCM_SHA384",
|
78
|
-
"TLS_CHACHA20_POLY1305_SHA256"
|
78
|
+
"TLS_CHACHA20_POLY1305_SHA256",
|
79
79
|
],
|
80
80
|
"min_tls_version": "TLSv1.2",
|
81
81
|
"max_tls_version": "1.3",
|
@@ -86,8 +86,8 @@ class Config:
|
|
86
86
|
"tokens_file": "tokens.json",
|
87
87
|
"token_expiry": 3600,
|
88
88
|
"jwt_secret": "",
|
89
|
-
"jwt_algorithm": "HS256"
|
90
|
-
}
|
89
|
+
"jwt_algorithm": "HS256",
|
90
|
+
},
|
91
91
|
},
|
92
92
|
"roles": {
|
93
93
|
"enabled": False,
|
@@ -96,10 +96,10 @@ class Config:
|
|
96
96
|
"deny_by_default": False,
|
97
97
|
"require_role_match": False,
|
98
98
|
"case_sensitive": False,
|
99
|
-
"allow_wildcard": False
|
99
|
+
"allow_wildcard": False,
|
100
100
|
},
|
101
101
|
"auto_load": False,
|
102
|
-
"validation_enabled": False
|
102
|
+
"validation_enabled": False,
|
103
103
|
},
|
104
104
|
"transport": {
|
105
105
|
"type": "http",
|
@@ -110,8 +110,8 @@ class Config:
|
|
110
110
|
"key_file": None,
|
111
111
|
"ca_cert": None,
|
112
112
|
"verify_client": False,
|
113
|
-
"client_cert_required": False
|
114
|
-
}
|
113
|
+
"client_cert_required": False,
|
114
|
+
},
|
115
115
|
},
|
116
116
|
"proxy_registration": {
|
117
117
|
"enabled": False,
|
@@ -124,12 +124,9 @@ class Config:
|
|
124
124
|
"retry_attempts": 3,
|
125
125
|
"retry_delay": 5,
|
126
126
|
"auto_register_on_startup": True,
|
127
|
-
"auto_unregister_on_shutdown": True
|
128
|
-
},
|
129
|
-
"debug": {
|
130
|
-
"enabled": False,
|
131
|
-
"level": "WARNING"
|
127
|
+
"auto_unregister_on_shutdown": True,
|
132
128
|
},
|
129
|
+
"debug": {"enabled": False, "level": "WARNING"},
|
133
130
|
"security": {
|
134
131
|
"framework": "mcp_security_framework",
|
135
132
|
"enabled": False,
|
@@ -150,7 +147,7 @@ class Config:
|
|
150
147
|
"basic_auth": False,
|
151
148
|
"oauth2_config": None,
|
152
149
|
"public_paths": ["/health", "/docs", "/openapi.json"],
|
153
|
-
"security_headers": None
|
150
|
+
"security_headers": None,
|
154
151
|
},
|
155
152
|
"ssl": {
|
156
153
|
"enabled": False,
|
@@ -165,7 +162,7 @@ class Config:
|
|
165
162
|
"cipher_suite": None,
|
166
163
|
"check_hostname": True,
|
167
164
|
"check_expiry": True,
|
168
|
-
"expiry_warning_days": 30
|
165
|
+
"expiry_warning_days": 30,
|
169
166
|
},
|
170
167
|
"certificates": {
|
171
168
|
"enabled": False,
|
@@ -181,7 +178,7 @@ class Config:
|
|
181
178
|
"crl_url": None,
|
182
179
|
"crl_validity_days": 30,
|
183
180
|
"auto_renewal": False,
|
184
|
-
"renewal_threshold_days": 30
|
181
|
+
"renewal_threshold_days": 30,
|
185
182
|
},
|
186
183
|
"permissions": {
|
187
184
|
"enabled": False,
|
@@ -193,7 +190,7 @@ class Config:
|
|
193
190
|
"permission_cache_ttl": 300,
|
194
191
|
"wildcard_permissions": False,
|
195
192
|
"strict_mode": False,
|
196
|
-
"roles": None
|
193
|
+
"roles": None,
|
197
194
|
},
|
198
195
|
"rate_limit": {
|
199
196
|
"enabled": False,
|
@@ -205,7 +202,7 @@ class Config:
|
|
205
202
|
"redis_config": None,
|
206
203
|
"cleanup_interval": 300,
|
207
204
|
"exempt_paths": ["/health", "/docs", "/openapi.json"],
|
208
|
-
"exempt_roles": ["admin"]
|
205
|
+
"exempt_roles": ["admin"],
|
209
206
|
},
|
210
207
|
"logging": {
|
211
208
|
"enabled": True,
|
@@ -219,21 +216,21 @@ class Config:
|
|
219
216
|
"json_format": False,
|
220
217
|
"include_timestamp": True,
|
221
218
|
"include_level": True,
|
222
|
-
"include_module": True
|
223
|
-
}
|
219
|
+
"include_module": True,
|
220
|
+
},
|
224
221
|
},
|
225
222
|
"protocols": {
|
226
223
|
"enabled": True,
|
227
224
|
"allowed_protocols": ["http", "jsonrpc"],
|
228
225
|
"default_protocol": "http",
|
229
|
-
"auto_discovery": True
|
230
|
-
}
|
226
|
+
"auto_discovery": True,
|
227
|
+
},
|
231
228
|
}
|
232
229
|
|
233
230
|
# Try to load configuration from file
|
234
231
|
if os.path.exists(self.config_path):
|
235
232
|
try:
|
236
|
-
with open(self.config_path,
|
233
|
+
with open(self.config_path, "r", encoding="utf-8") as f:
|
237
234
|
file_config = json.load(f)
|
238
235
|
self._update_nested_dict(self.config_data, file_config)
|
239
236
|
except Exception as e:
|
@@ -261,7 +258,7 @@ class Config:
|
|
261
258
|
prefix = "SERVICE_"
|
262
259
|
for key, value in os.environ.items():
|
263
260
|
if key.startswith(prefix):
|
264
|
-
parts = key[len(prefix):].lower().split("_", 1)
|
261
|
+
parts = key[len(prefix) :].lower().split("_", 1)
|
265
262
|
if len(parts) == 2:
|
266
263
|
section, param = parts
|
267
264
|
if section not in self.config_data:
|
@@ -357,7 +354,7 @@ class Config:
|
|
357
354
|
self.config_path is used.
|
358
355
|
"""
|
359
356
|
save_path = path or self.config_path
|
360
|
-
with open(save_path,
|
357
|
+
with open(save_path, "w", encoding="utf-8") as f:
|
361
358
|
json.dump(self.config_data, f, indent=2)
|
362
359
|
|
363
360
|
def _update_nested_dict(self, d: Dict, u: Dict) -> Dict:
|
@@ -444,13 +441,15 @@ class Config:
|
|
444
441
|
True if feature is enabled, False otherwise
|
445
442
|
"""
|
446
443
|
if feature == "ssl":
|
447
|
-
return
|
448
|
-
|
444
|
+
return self.get("ssl.enabled", False) or self.get(
|
445
|
+
"security.ssl.enabled", False
|
446
|
+
)
|
449
447
|
elif feature == "auth":
|
450
448
|
return self.get("security.auth.enabled", False)
|
451
449
|
elif feature == "roles":
|
452
|
-
return
|
453
|
-
|
450
|
+
return self.get("security.permissions.enabled", False) or self.get(
|
451
|
+
"roles.enabled", False
|
452
|
+
)
|
454
453
|
elif feature == "proxy_registration":
|
455
454
|
return self.get("proxy_registration.enabled", False)
|
456
455
|
elif feature == "security":
|
@@ -535,11 +534,13 @@ class Config:
|
|
535
534
|
elif mode == "certificate":
|
536
535
|
self.set("proxy_registration.auth_method", "certificate")
|
537
536
|
if "cert_file" in kwargs:
|
538
|
-
self.set(
|
539
|
-
|
537
|
+
self.set(
|
538
|
+
"proxy_registration.certificate.cert_file", kwargs["cert_file"]
|
539
|
+
)
|
540
540
|
if "key_file" in kwargs:
|
541
|
-
self.set(
|
542
|
-
|
541
|
+
self.set(
|
542
|
+
"proxy_registration.certificate.key_file", kwargs["key_file"]
|
543
|
+
)
|
543
544
|
elif mode == "api_key":
|
544
545
|
self.set("proxy_registration.auth_method", "api_key")
|
545
546
|
if "key" in kwargs:
|
@@ -12,7 +12,6 @@ __all__ = [
|
|
12
12
|
"InvalidParamsError",
|
13
13
|
"CommandExecutionError",
|
14
14
|
"ConfigurationError",
|
15
|
-
|
16
15
|
# Logging
|
17
16
|
"setup_logging",
|
18
17
|
"get_logger",
|
@@ -20,25 +19,24 @@ __all__ = [
|
|
20
19
|
"RequestLogger",
|
21
20
|
"CustomFormatter",
|
22
21
|
"RequestContextFilter",
|
23
|
-
|
24
22
|
# 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"
|
23
|
+
"Settings",
|
24
|
+
"ServerSettings",
|
25
|
+
"LoggingSettings",
|
26
|
+
"CommandsSettings",
|
27
|
+
"get_server_host",
|
28
|
+
"get_server_port",
|
29
|
+
"get_server_debug",
|
30
|
+
"get_logging_level",
|
31
|
+
"get_logging_dir",
|
32
|
+
"get_auto_discovery",
|
33
|
+
"get_discovery_path",
|
34
|
+
"get_setting",
|
35
|
+
"set_setting",
|
36
|
+
"reload_settings",
|
37
|
+
"add_custom_settings",
|
38
|
+
"get_custom_settings",
|
39
|
+
"get_custom_setting_value",
|
40
|
+
"set_custom_setting_value",
|
41
|
+
"clear_custom_settings",
|
44
42
|
]
|