mcp-proxy-adapter 6.3.4__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 +7 -3
- 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.4.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.4.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -20,18 +20,18 @@ from .client import UniversalClient, create_client_from_config
|
|
20
20
|
class ClientManager:
|
21
21
|
"""
|
22
22
|
Manages client connections and proxy registrations.
|
23
|
-
|
23
|
+
|
24
24
|
This class provides functionality for:
|
25
25
|
- Creating and managing client connections
|
26
26
|
- Proxy registration
|
27
27
|
- Connection pooling
|
28
28
|
- Authentication management
|
29
29
|
"""
|
30
|
-
|
30
|
+
|
31
31
|
def __init__(self, config: Dict[str, Any]):
|
32
32
|
"""
|
33
33
|
Initialize client manager.
|
34
|
-
|
34
|
+
|
35
35
|
Args:
|
36
36
|
config: Client manager configuration
|
37
37
|
"""
|
@@ -39,60 +39,62 @@ class ClientManager:
|
|
39
39
|
self.logger = logging.getLogger(__name__)
|
40
40
|
self.clients: Dict[str, UniversalClient] = {}
|
41
41
|
self.connection_pool: Dict[str, UniversalClient] = {}
|
42
|
-
|
42
|
+
|
43
43
|
# Client manager settings
|
44
44
|
self.max_connections = config.get("max_connections", 10)
|
45
45
|
self.connection_timeout = config.get("connection_timeout", 30)
|
46
46
|
self.retry_attempts = config.get("retry_attempts", 3)
|
47
47
|
self.retry_delay = config.get("retry_delay", 1)
|
48
|
-
|
48
|
+
|
49
49
|
self.logger.info("Client manager initialized")
|
50
|
-
|
50
|
+
|
51
51
|
async def create_client(self, client_id: str, config_file: str) -> UniversalClient:
|
52
52
|
"""
|
53
53
|
Create a new client instance.
|
54
|
-
|
54
|
+
|
55
55
|
Args:
|
56
56
|
client_id: Unique identifier for the client
|
57
57
|
config_file: Path to client configuration file
|
58
|
-
|
58
|
+
|
59
59
|
Returns:
|
60
60
|
UniversalClient instance
|
61
61
|
"""
|
62
62
|
try:
|
63
63
|
if client_id in self.clients:
|
64
|
-
self.logger.warning(
|
64
|
+
self.logger.warning(
|
65
|
+
f"Client {client_id} already exists, reusing existing connection"
|
66
|
+
)
|
65
67
|
return self.clients[client_id]
|
66
|
-
|
68
|
+
|
67
69
|
client = create_client_from_config(config_file)
|
68
70
|
self.clients[client_id] = client
|
69
|
-
|
71
|
+
|
70
72
|
self.logger.info(f"Client {client_id} created successfully")
|
71
73
|
return client
|
72
|
-
|
74
|
+
|
73
75
|
except Exception as e:
|
74
76
|
self.logger.error(f"Failed to create client {client_id}: {e}")
|
75
77
|
raise
|
76
|
-
|
78
|
+
|
77
79
|
async def get_client(self, client_id: str) -> Optional[UniversalClient]:
|
78
80
|
"""
|
79
81
|
Get an existing client instance.
|
80
|
-
|
82
|
+
|
81
83
|
Args:
|
82
84
|
client_id: Client identifier
|
83
|
-
|
85
|
+
|
84
86
|
Returns:
|
85
87
|
UniversalClient instance or None if not found
|
86
88
|
"""
|
87
89
|
return self.clients.get(client_id)
|
88
|
-
|
90
|
+
|
89
91
|
async def remove_client(self, client_id: str) -> bool:
|
90
92
|
"""
|
91
93
|
Remove a client instance.
|
92
|
-
|
94
|
+
|
93
95
|
Args:
|
94
96
|
client_id: Client identifier
|
95
|
-
|
97
|
+
|
96
98
|
Returns:
|
97
99
|
True if client was removed, False otherwise
|
98
100
|
"""
|
@@ -103,14 +105,14 @@ class ClientManager:
|
|
103
105
|
self.logger.info(f"Client {client_id} removed")
|
104
106
|
return True
|
105
107
|
return False
|
106
|
-
|
108
|
+
|
107
109
|
async def test_client_connection(self, client_id: str) -> bool:
|
108
110
|
"""
|
109
111
|
Test connection for a specific client.
|
110
|
-
|
112
|
+
|
111
113
|
Args:
|
112
114
|
client_id: Client identifier
|
113
|
-
|
115
|
+
|
114
116
|
Returns:
|
115
117
|
True if connection is successful, False otherwise
|
116
118
|
"""
|
@@ -118,28 +120,30 @@ class ClientManager:
|
|
118
120
|
if not client:
|
119
121
|
self.logger.error(f"Client {client_id} not found")
|
120
122
|
return False
|
121
|
-
|
123
|
+
|
122
124
|
try:
|
123
125
|
return await client.test_connection()
|
124
126
|
except Exception as e:
|
125
127
|
self.logger.error(f"Connection test failed for client {client_id}: {e}")
|
126
128
|
return False
|
127
|
-
|
128
|
-
async def register_proxy(
|
129
|
+
|
130
|
+
async def register_proxy(
|
131
|
+
self, client_id: str, proxy_config: Dict[str, Any]
|
132
|
+
) -> Dict[str, Any]:
|
129
133
|
"""
|
130
134
|
Register with proxy server using a specific client.
|
131
|
-
|
135
|
+
|
132
136
|
Args:
|
133
137
|
client_id: Client identifier
|
134
138
|
proxy_config: Proxy registration configuration
|
135
|
-
|
139
|
+
|
136
140
|
Returns:
|
137
141
|
Registration result
|
138
142
|
"""
|
139
143
|
client = await self.get_client(client_id)
|
140
144
|
if not client:
|
141
145
|
return {"error": f"Client {client_id} not found"}
|
142
|
-
|
146
|
+
|
143
147
|
try:
|
144
148
|
result = await client.register_proxy(proxy_config)
|
145
149
|
self.logger.info(f"Proxy registration completed for client {client_id}")
|
@@ -147,23 +151,25 @@ class ClientManager:
|
|
147
151
|
except Exception as e:
|
148
152
|
self.logger.error(f"Proxy registration failed for client {client_id}: {e}")
|
149
153
|
return {"error": str(e)}
|
150
|
-
|
151
|
-
async def execute_command(
|
154
|
+
|
155
|
+
async def execute_command(
|
156
|
+
self, client_id: str, command: str, params: Dict[str, Any] = None
|
157
|
+
) -> Dict[str, Any]:
|
152
158
|
"""
|
153
159
|
Execute a command using a specific client.
|
154
|
-
|
160
|
+
|
155
161
|
Args:
|
156
162
|
client_id: Client identifier
|
157
163
|
command: Command name
|
158
164
|
params: Command parameters
|
159
|
-
|
165
|
+
|
160
166
|
Returns:
|
161
167
|
Command result
|
162
168
|
"""
|
163
169
|
client = await self.get_client(client_id)
|
164
170
|
if not client:
|
165
171
|
return {"error": f"Client {client_id} not found"}
|
166
|
-
|
172
|
+
|
167
173
|
try:
|
168
174
|
result = await client.execute_command(command, params or {})
|
169
175
|
self.logger.info(f"Command {command} executed for client {client_id}")
|
@@ -171,61 +177,61 @@ class ClientManager:
|
|
171
177
|
except Exception as e:
|
172
178
|
self.logger.error(f"Command execution failed for client {client_id}: {e}")
|
173
179
|
return {"error": str(e)}
|
174
|
-
|
180
|
+
|
175
181
|
async def get_client_status(self, client_id: str) -> Dict[str, Any]:
|
176
182
|
"""
|
177
183
|
Get status information for a specific client.
|
178
|
-
|
184
|
+
|
179
185
|
Args:
|
180
186
|
client_id: Client identifier
|
181
|
-
|
187
|
+
|
182
188
|
Returns:
|
183
189
|
Client status information
|
184
190
|
"""
|
185
191
|
client = await self.get_client(client_id)
|
186
192
|
if not client:
|
187
193
|
return {"error": f"Client {client_id} not found"}
|
188
|
-
|
194
|
+
|
189
195
|
try:
|
190
196
|
# Test connection
|
191
197
|
connection_ok = await client.test_connection()
|
192
|
-
|
198
|
+
|
193
199
|
# Test security features
|
194
200
|
security_features = await client.test_security_features()
|
195
|
-
|
201
|
+
|
196
202
|
status = {
|
197
203
|
"client_id": client_id,
|
198
204
|
"base_url": client.base_url,
|
199
205
|
"auth_method": client.auth_method,
|
200
206
|
"connection_ok": connection_ok,
|
201
207
|
"security_features": security_features,
|
202
|
-
"session_active": client.session is not None
|
208
|
+
"session_active": client.session is not None,
|
203
209
|
}
|
204
|
-
|
210
|
+
|
205
211
|
return status
|
206
212
|
except Exception as e:
|
207
213
|
self.logger.error(f"Failed to get status for client {client_id}: {e}")
|
208
214
|
return {"error": str(e)}
|
209
|
-
|
215
|
+
|
210
216
|
async def list_clients(self) -> List[str]:
|
211
217
|
"""
|
212
218
|
Get list of all client identifiers.
|
213
|
-
|
219
|
+
|
214
220
|
Returns:
|
215
221
|
List of client identifiers
|
216
222
|
"""
|
217
223
|
return list(self.clients.keys())
|
218
|
-
|
224
|
+
|
219
225
|
async def cleanup(self):
|
220
226
|
"""Clean up all client connections."""
|
221
227
|
for client_id in list(self.clients.keys()):
|
222
228
|
await self.remove_client(client_id)
|
223
229
|
self.logger.info("All client connections cleaned up")
|
224
|
-
|
230
|
+
|
225
231
|
async def __aenter__(self):
|
226
232
|
"""Async context manager entry."""
|
227
233
|
return self
|
228
|
-
|
234
|
+
|
229
235
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
230
236
|
"""Async context manager exit."""
|
231
237
|
await self.cleanup()
|
@@ -234,10 +240,10 @@ class ClientManager:
|
|
234
240
|
def create_client_manager(config: Dict[str, Any]) -> ClientManager:
|
235
241
|
"""
|
236
242
|
Create a ClientManager instance.
|
237
|
-
|
243
|
+
|
238
244
|
Args:
|
239
245
|
config: Client manager configuration
|
240
|
-
|
246
|
+
|
241
247
|
Returns:
|
242
248
|
ClientManager instance
|
243
249
|
"""
|
@@ -252,30 +258,30 @@ async def test_client_manager():
|
|
252
258
|
"max_connections": 5,
|
253
259
|
"connection_timeout": 30,
|
254
260
|
"retry_attempts": 3,
|
255
|
-
"retry_delay": 1
|
261
|
+
"retry_delay": 1,
|
256
262
|
}
|
257
|
-
|
263
|
+
|
258
264
|
async with ClientManager(config) as manager:
|
259
265
|
# Create a client
|
260
266
|
client_id = "test_client"
|
261
267
|
config_file = "configs/http_simple.json"
|
262
|
-
|
268
|
+
|
263
269
|
try:
|
264
270
|
client = await manager.create_client(client_id, config_file)
|
265
271
|
print(f"✅ Client {client_id} created successfully")
|
266
|
-
|
272
|
+
|
267
273
|
# Test connection
|
268
274
|
connection_ok = await manager.test_client_connection(client_id)
|
269
275
|
print(f"✅ Connection test: {connection_ok}")
|
270
|
-
|
276
|
+
|
271
277
|
# Get status
|
272
278
|
status = await manager.get_client_status(client_id)
|
273
279
|
print(f"✅ Client status: {json.dumps(status, indent=2)}")
|
274
|
-
|
280
|
+
|
275
281
|
# Execute command
|
276
282
|
result = await manager.execute_command(client_id, "help")
|
277
283
|
print(f"✅ Command result: {json.dumps(result, indent=2)}")
|
278
|
-
|
284
|
+
|
279
285
|
except Exception as e:
|
280
286
|
print(f"❌ Test failed: {e}")
|
281
287
|
|