mcp-proxy-adapter 6.3.4__py3-none-any.whl ā 6.3.6__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 +120 -91
- 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.6.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.6.dist-info/RECORD +144 -0
- mcp_proxy_adapter-6.3.6.dist-info/top_level.txt +2 -0
- mcp_proxy_adapter_issue_package/demonstrate_issue.py +178 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- mcp_proxy_adapter-6.3.4.dist-info/top_level.txt +0 -1
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/licenses/LICENSE +0 -0
@@ -6,6 +6,7 @@ and connection types supported by the security framework.
|
|
6
6
|
Author: Vasiliy Zdanovskiy
|
7
7
|
email: vasilyvz@gmail.com
|
8
8
|
"""
|
9
|
+
|
9
10
|
import asyncio
|
10
11
|
import json
|
11
12
|
import os
|
@@ -17,16 +18,35 @@ from pathlib import Path
|
|
17
18
|
import aiohttp
|
18
19
|
import requests
|
19
20
|
from requests.exceptions import RequestException
|
21
|
+
|
20
22
|
# Import security framework components
|
21
23
|
try:
|
22
|
-
from mcp_security_framework import
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
from mcp_security_framework import (
|
25
|
+
SecurityManager,
|
26
|
+
AuthManager,
|
27
|
+
CertificateManager,
|
28
|
+
PermissionManager,
|
29
|
+
)
|
30
|
+
from mcp_security_framework.utils import (
|
31
|
+
generate_api_key,
|
32
|
+
create_jwt_token,
|
33
|
+
validate_jwt_token,
|
34
|
+
)
|
35
|
+
from mcp_security_framework.utils import (
|
36
|
+
extract_roles_from_cert,
|
37
|
+
validate_certificate_chain,
|
38
|
+
)
|
39
|
+
from mcp_security_framework.utils import (
|
40
|
+
create_ssl_context,
|
41
|
+
validate_server_certificate,
|
42
|
+
)
|
43
|
+
|
26
44
|
SECURITY_FRAMEWORK_AVAILABLE = True
|
27
45
|
except ImportError:
|
28
46
|
SECURITY_FRAMEWORK_AVAILABLE = False
|
29
47
|
print("Warning: mcp_security_framework not available. Using basic HTTP client.")
|
48
|
+
|
49
|
+
|
30
50
|
class UniversalClient:
|
31
51
|
"""
|
32
52
|
Universal client that demonstrates all possible secure connection methods.
|
@@ -39,6 +59,7 @@ class UniversalClient:
|
|
39
59
|
- Role-based access control
|
40
60
|
- Rate limiting awareness
|
41
61
|
"""
|
62
|
+
|
42
63
|
def __init__(self, config: Dict[str, Any]):
|
43
64
|
"""
|
44
65
|
Initialize universal client with configuration.
|
@@ -64,6 +85,7 @@ class UniversalClient:
|
|
64
85
|
self.current_token: Optional[str] = None
|
65
86
|
self.token_expiry: Optional[float] = None
|
66
87
|
print(f"Universal client initialized with auth method: {self.auth_method}")
|
88
|
+
|
67
89
|
def _initialize_security_managers(self) -> None:
|
68
90
|
"""Initialize security framework managers."""
|
69
91
|
try:
|
@@ -81,16 +103,21 @@ class UniversalClient:
|
|
81
103
|
print("Security framework managers initialized successfully")
|
82
104
|
except Exception as e:
|
83
105
|
print(f"Warning: Failed to initialize security managers: {e}")
|
106
|
+
|
84
107
|
async def __aenter__(self):
|
85
108
|
"""Async context manager entry."""
|
86
109
|
await self.connect()
|
87
110
|
return self
|
111
|
+
|
88
112
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
89
113
|
"""Async context manager exit."""
|
90
114
|
await self.disconnect()
|
115
|
+
|
91
116
|
async def connect(self) -> None:
|
92
117
|
"""Establish connection with authentication."""
|
93
|
-
print(
|
118
|
+
print(
|
119
|
+
f"Connecting to {self.base_url} with {self.auth_method} authentication..."
|
120
|
+
)
|
94
121
|
# Create SSL context
|
95
122
|
ssl_context = self._create_ssl_context()
|
96
123
|
# Create connector with SSL context
|
@@ -111,12 +138,14 @@ class UniversalClient:
|
|
111
138
|
else:
|
112
139
|
print("No authentication required")
|
113
140
|
print("Connection established successfully")
|
141
|
+
|
114
142
|
async def disconnect(self) -> None:
|
115
143
|
"""Close connection and cleanup."""
|
116
144
|
if self.session:
|
117
145
|
await self.session.close()
|
118
146
|
self.session = None
|
119
147
|
print("Connection closed")
|
148
|
+
|
120
149
|
async def _authenticate_api_key(self) -> None:
|
121
150
|
"""Authenticate using API key."""
|
122
151
|
api_key_config = self.security_config.get("api_key", {})
|
@@ -126,6 +155,7 @@ class UniversalClient:
|
|
126
155
|
# Store API key for requests
|
127
156
|
self.current_token = api_key
|
128
157
|
print(f"Authenticated with API key: {api_key[:8]}...")
|
158
|
+
|
129
159
|
async def _authenticate_jwt(self) -> None:
|
130
160
|
"""Authenticate using JWT token."""
|
131
161
|
jwt_config = self.security_config.get("jwt", {})
|
@@ -142,20 +172,20 @@ class UniversalClient:
|
|
142
172
|
# Create JWT token
|
143
173
|
if SECURITY_FRAMEWORK_AVAILABLE:
|
144
174
|
self.current_token = create_jwt_token(
|
145
|
-
username,
|
146
|
-
secret,
|
147
|
-
expiry_hours=jwt_config.get("expiry_hours", 24)
|
175
|
+
username, secret, expiry_hours=jwt_config.get("expiry_hours", 24)
|
148
176
|
)
|
149
177
|
else:
|
150
178
|
# Simple JWT creation (for demonstration)
|
151
179
|
import jwt
|
180
|
+
|
152
181
|
payload = {
|
153
182
|
"username": username,
|
154
|
-
"exp": time.time() + (jwt_config.get("expiry_hours", 24) * 3600)
|
183
|
+
"exp": time.time() + (jwt_config.get("expiry_hours", 24) * 3600),
|
155
184
|
}
|
156
185
|
self.current_token = jwt.encode(payload, secret, algorithm="HS256")
|
157
186
|
self.token_expiry = time.time() + (jwt_config.get("expiry_hours", 24) * 3600)
|
158
187
|
print(f"Authenticated with JWT token: {self.current_token[:20]}...")
|
188
|
+
|
159
189
|
async def _authenticate_certificate(self) -> None:
|
160
190
|
"""Authenticate using client certificate."""
|
161
191
|
cert_config = self.security_config.get("certificate", {})
|
@@ -175,6 +205,7 @@ class UniversalClient:
|
|
175
205
|
except Exception as e:
|
176
206
|
print(f"Warning: Certificate validation failed: {e}")
|
177
207
|
print("Certificate authentication prepared")
|
208
|
+
|
178
209
|
async def _authenticate_basic(self) -> None:
|
179
210
|
"""Authenticate using basic authentication."""
|
180
211
|
basic_config = self.security_config.get("basic", {})
|
@@ -183,9 +214,11 @@ class UniversalClient:
|
|
183
214
|
if not username or not password:
|
184
215
|
raise ValueError("Basic auth credentials not provided in configuration")
|
185
216
|
import base64
|
217
|
+
|
186
218
|
credentials = base64.b64encode(f"{username}:{password}".encode()).decode()
|
187
219
|
self.current_token = f"Basic {credentials}"
|
188
220
|
print(f"Authenticated with basic auth: {username}")
|
221
|
+
|
189
222
|
def _get_auth_headers(self) -> Dict[str, str]:
|
190
223
|
"""Get authentication headers for requests."""
|
191
224
|
headers = {"Content-Type": "application/json"}
|
@@ -200,6 +233,7 @@ class UniversalClient:
|
|
200
233
|
elif self.auth_method == "basic":
|
201
234
|
headers["Authorization"] = self.current_token
|
202
235
|
return headers
|
236
|
+
|
203
237
|
def _create_ssl_context(self) -> Optional[ssl.SSLContext]:
|
204
238
|
"""Create SSL context for secure connections."""
|
205
239
|
ssl_config = self.security_config.get("ssl", {})
|
@@ -236,12 +270,13 @@ class UniversalClient:
|
|
236
270
|
except Exception as e:
|
237
271
|
print(f"Warning: Failed to create SSL context: {e}")
|
238
272
|
return None
|
273
|
+
|
239
274
|
async def request(
|
240
275
|
self,
|
241
276
|
method: str,
|
242
277
|
endpoint: str,
|
243
278
|
data: Optional[Dict[str, Any]] = None,
|
244
|
-
headers: Optional[Dict[str, str]] = None
|
279
|
+
headers: Optional[Dict[str, str]] = None,
|
245
280
|
) -> Dict[str, Any]:
|
246
281
|
"""
|
247
282
|
Make authenticated request to server.
|
@@ -266,14 +301,18 @@ class UniversalClient:
|
|
266
301
|
url,
|
267
302
|
json=data,
|
268
303
|
headers=request_headers,
|
269
|
-
timeout=aiohttp.ClientTimeout(total=self.timeout)
|
304
|
+
timeout=aiohttp.ClientTimeout(total=self.timeout),
|
270
305
|
) as response:
|
271
306
|
result = await response.json()
|
272
307
|
# Validate response if security framework available
|
273
308
|
if SECURITY_FRAMEWORK_AVAILABLE and self.security_manager:
|
274
|
-
self.security_manager.validate_server_response(
|
309
|
+
self.security_manager.validate_server_response(
|
310
|
+
dict(response.headers)
|
311
|
+
)
|
275
312
|
if response.status >= 400:
|
276
|
-
print(
|
313
|
+
print(
|
314
|
+
f"Request failed with status {response.status}: {result}"
|
315
|
+
)
|
277
316
|
return {"error": result, "status": response.status}
|
278
317
|
return result
|
279
318
|
except Exception as e:
|
@@ -285,18 +324,27 @@ class UniversalClient:
|
|
285
324
|
except Exception as e:
|
286
325
|
print(f"Request failed: {e}")
|
287
326
|
raise
|
327
|
+
|
288
328
|
async def get(self, endpoint: str, **kwargs) -> Dict[str, Any]:
|
289
329
|
"""Make GET request."""
|
290
330
|
return await self.request("GET", endpoint, **kwargs)
|
291
|
-
|
331
|
+
|
332
|
+
async def post(
|
333
|
+
self, endpoint: str, data: Dict[str, Any], **kwargs
|
334
|
+
) -> Dict[str, Any]:
|
292
335
|
"""Make POST request."""
|
293
336
|
return await self.request("POST", endpoint, data=data, **kwargs)
|
294
|
-
|
337
|
+
|
338
|
+
async def put(
|
339
|
+
self, endpoint: str, data: Dict[str, Any], **kwargs
|
340
|
+
) -> Dict[str, Any]:
|
295
341
|
"""Make PUT request."""
|
296
342
|
return await self.request("PUT", endpoint, data=data, **kwargs)
|
343
|
+
|
297
344
|
async def delete(self, endpoint: str, **kwargs) -> Dict[str, Any]:
|
298
345
|
"""Make DELETE request."""
|
299
346
|
return await self.request("DELETE", endpoint, **kwargs)
|
347
|
+
|
300
348
|
async def test_connection(self) -> bool:
|
301
349
|
"""Test connection to server."""
|
302
350
|
try:
|
@@ -310,6 +358,7 @@ class UniversalClient:
|
|
310
358
|
except Exception as e:
|
311
359
|
print(f"ā Connection test failed: {e}")
|
312
360
|
return False
|
361
|
+
|
313
362
|
async def test_security_features(self) -> Dict[str, bool]:
|
314
363
|
"""Test various security features."""
|
315
364
|
results = {}
|
@@ -333,10 +382,10 @@ class UniversalClient:
|
|
333
382
|
else:
|
334
383
|
results["certificate_validation"] = False
|
335
384
|
return results
|
385
|
+
|
386
|
+
|
336
387
|
def create_client_config(
|
337
|
-
server_url: str,
|
338
|
-
auth_method: str = "none",
|
339
|
-
**kwargs
|
388
|
+
server_url: str, auth_method: str = "none", **kwargs
|
340
389
|
) -> Dict[str, Any]:
|
341
390
|
"""
|
342
391
|
Create client configuration for different authentication methods.
|
@@ -352,40 +401,40 @@ def create_client_config(
|
|
352
401
|
"timeout": 30,
|
353
402
|
"retry_attempts": 3,
|
354
403
|
"retry_delay": 1,
|
355
|
-
"security": {
|
356
|
-
"auth_method": auth_method
|
357
|
-
}
|
404
|
+
"security": {"auth_method": auth_method},
|
358
405
|
}
|
359
406
|
if auth_method == "api_key":
|
360
407
|
config["security"]["api_key"] = {
|
361
408
|
"key": kwargs.get("api_key", "your_api_key_here"),
|
362
|
-
"header": kwargs.get("header", "X-API-Key")
|
409
|
+
"header": kwargs.get("header", "X-API-Key"),
|
363
410
|
}
|
364
411
|
elif auth_method == "jwt":
|
365
412
|
config["security"]["jwt"] = {
|
366
413
|
"username": kwargs.get("username", "user"),
|
367
414
|
"password": kwargs.get("password", "password"),
|
368
415
|
"secret": kwargs.get("secret", "your_jwt_secret"),
|
369
|
-
"expiry_hours": kwargs.get("expiry_hours", 24)
|
416
|
+
"expiry_hours": kwargs.get("expiry_hours", 24),
|
370
417
|
}
|
371
418
|
elif auth_method == "certificate":
|
372
419
|
config["security"]["certificate"] = {
|
373
420
|
"enabled": True,
|
374
421
|
"cert_file": kwargs.get("cert_file", "./certs/client.crt"),
|
375
422
|
"key_file": kwargs.get("key_file", "./keys/client.key"),
|
376
|
-
"ca_cert_file": kwargs.get("ca_cert_file", "./certs/ca.crt")
|
423
|
+
"ca_cert_file": kwargs.get("ca_cert_file", "./certs/ca.crt"),
|
377
424
|
}
|
378
425
|
config["security"]["ssl"] = {
|
379
426
|
"enabled": True,
|
380
427
|
"check_hostname": kwargs.get("check_hostname", True),
|
381
|
-
"ca_cert_file": kwargs.get("ca_cert_file", "./certs/ca.crt")
|
428
|
+
"ca_cert_file": kwargs.get("ca_cert_file", "./certs/ca.crt"),
|
382
429
|
}
|
383
430
|
elif auth_method == "basic":
|
384
431
|
config["security"]["basic"] = {
|
385
432
|
"username": kwargs.get("username", "user"),
|
386
|
-
"password": kwargs.get("password", "password")
|
433
|
+
"password": kwargs.get("password", "password"),
|
387
434
|
}
|
388
435
|
return config
|
436
|
+
|
437
|
+
|
389
438
|
async def demo_all_connection_methods():
|
390
439
|
"""Demonstrate all possible connection methods."""
|
391
440
|
print("š Universal Client Demo - All Connection Methods")
|
@@ -394,15 +443,13 @@ async def demo_all_connection_methods():
|
|
394
443
|
test_configs = [
|
395
444
|
{
|
396
445
|
"name": "No Authentication",
|
397
|
-
"config": create_client_config("http://localhost:8000", "none")
|
446
|
+
"config": create_client_config("http://localhost:8000", "none"),
|
398
447
|
},
|
399
448
|
{
|
400
449
|
"name": "API Key Authentication",
|
401
450
|
"config": create_client_config(
|
402
|
-
"http://localhost:8000",
|
403
|
-
|
404
|
-
api_key="demo_api_key_123"
|
405
|
-
)
|
451
|
+
"http://localhost:8000", "api_key", api_key="demo_api_key_123"
|
452
|
+
),
|
406
453
|
},
|
407
454
|
{
|
408
455
|
"name": "JWT Authentication",
|
@@ -411,8 +458,8 @@ async def demo_all_connection_methods():
|
|
411
458
|
"jwt",
|
412
459
|
username="demo_user",
|
413
460
|
password="demo_password",
|
414
|
-
secret="demo_jwt_secret"
|
415
|
-
)
|
461
|
+
secret="demo_jwt_secret",
|
462
|
+
),
|
416
463
|
},
|
417
464
|
{
|
418
465
|
"name": "Basic Authentication",
|
@@ -420,8 +467,8 @@ async def demo_all_connection_methods():
|
|
420
467
|
"http://localhost:8000",
|
421
468
|
"basic",
|
422
469
|
username="demo_user",
|
423
|
-
password="demo_password"
|
424
|
-
)
|
470
|
+
password="demo_password",
|
471
|
+
),
|
425
472
|
},
|
426
473
|
{
|
427
474
|
"name": "Certificate Authentication (HTTPS)",
|
@@ -430,9 +477,9 @@ async def demo_all_connection_methods():
|
|
430
477
|
"certificate",
|
431
478
|
cert_file="./certs/client.crt",
|
432
479
|
key_file="./keys/client.key",
|
433
|
-
ca_cert_file="./certs/ca.crt"
|
434
|
-
)
|
435
|
-
}
|
480
|
+
ca_cert_file="./certs/ca.crt",
|
481
|
+
),
|
482
|
+
},
|
436
483
|
]
|
437
484
|
for test_config in test_configs:
|
438
485
|
print(f"\nš Testing: {test_config['name']}")
|
@@ -459,6 +506,8 @@ async def demo_all_connection_methods():
|
|
459
506
|
except Exception as e:
|
460
507
|
print(f"ā Test failed: {e}")
|
461
508
|
print("\nš Demo completed!")
|
509
|
+
|
510
|
+
|
462
511
|
async def demo_specific_connection(auth_method: str, **kwargs):
|
463
512
|
"""
|
464
513
|
Demo specific connection method.
|
@@ -484,7 +533,7 @@ async def demo_specific_connection(auth_method: str, **kwargs):
|
|
484
533
|
"jsonrpc": "2.0",
|
485
534
|
"method": "test_command",
|
486
535
|
"params": {"message": "Hello from universal client!"},
|
487
|
-
"id": 1
|
536
|
+
"id": 1,
|
488
537
|
}
|
489
538
|
result = await client.post("/api/jsonrpc", command_data)
|
490
539
|
print(f"Command Result: {result}")
|
@@ -492,11 +541,16 @@ async def demo_specific_connection(auth_method: str, **kwargs):
|
|
492
541
|
print(f"API calls failed: {e}")
|
493
542
|
else:
|
494
543
|
print("ā Connection failed")
|
544
|
+
|
545
|
+
|
495
546
|
if __name__ == "__main__":
|
496
547
|
import sys
|
497
548
|
import argparse
|
498
549
|
import json
|
499
|
-
|
550
|
+
|
551
|
+
parser = argparse.ArgumentParser(
|
552
|
+
description="Universal Client for MCP Proxy Adapter"
|
553
|
+
)
|
500
554
|
parser.add_argument("--config", help="Path to configuration file")
|
501
555
|
parser.add_argument("--method", help="JSON-RPC method to call")
|
502
556
|
parser.add_argument("--params", help="JSON-RPC parameters (JSON string)")
|
@@ -506,7 +560,7 @@ if __name__ == "__main__":
|
|
506
560
|
if args.config:
|
507
561
|
# Load configuration from file
|
508
562
|
try:
|
509
|
-
with open(args.config,
|
563
|
+
with open(args.config, "r") as f:
|
510
564
|
config_data = json.load(f)
|
511
565
|
# Extract server configuration
|
512
566
|
server_config = config_data.get("server", {})
|
@@ -527,21 +581,20 @@ if __name__ == "__main__":
|
|
527
581
|
"timeout": 30,
|
528
582
|
"retry_attempts": 3,
|
529
583
|
"retry_delay": 1,
|
530
|
-
"security": {
|
531
|
-
"auth_method": "none"
|
532
|
-
}
|
584
|
+
"security": {"auth_method": "none"},
|
533
585
|
}
|
534
586
|
# Add SSL configuration if needed
|
535
587
|
if ssl_enabled:
|
536
588
|
client_config["security"]["ssl"] = {
|
537
589
|
"enabled": True,
|
538
590
|
"check_hostname": False,
|
539
|
-
"verify": False
|
591
|
+
"verify": False,
|
540
592
|
}
|
541
593
|
# Add CA certificate if available
|
542
594
|
ca_cert = ssl_config.get("ca_cert")
|
543
595
|
if ca_cert and os.path.exists(ca_cert):
|
544
596
|
client_config["security"]["ssl"]["ca_cert_file"] = ca_cert
|
597
|
+
|
545
598
|
async def test_config_connection():
|
546
599
|
async with UniversalClient(client_config) as client:
|
547
600
|
# Test connection
|
@@ -562,11 +615,13 @@ if __name__ == "__main__":
|
|
562
615
|
"jsonrpc": "2.0",
|
563
616
|
"method": args.method,
|
564
617
|
"params": params,
|
565
|
-
"id": 1
|
618
|
+
"id": 1,
|
566
619
|
}
|
567
620
|
try:
|
568
621
|
result = await client.post("/api/jsonrpc", command_data)
|
569
|
-
print(
|
622
|
+
print(
|
623
|
+
f"ā
Method '{args.method}' executed successfully:"
|
624
|
+
)
|
570
625
|
print(json.dumps(result, indent=2))
|
571
626
|
except Exception as e:
|
572
627
|
print(f"ā Method execution failed: {e}")
|
@@ -576,7 +631,7 @@ if __name__ == "__main__":
|
|
576
631
|
"jsonrpc": "2.0",
|
577
632
|
"method": "help",
|
578
633
|
"params": {},
|
579
|
-
"id": 1
|
634
|
+
"id": 1,
|
580
635
|
}
|
581
636
|
try:
|
582
637
|
result = await client.post("/api/jsonrpc", command_data)
|
@@ -587,6 +642,7 @@ if __name__ == "__main__":
|
|
587
642
|
else:
|
588
643
|
print("ā Connection failed")
|
589
644
|
print("Connection closed")
|
645
|
+
|
590
646
|
asyncio.run(test_config_connection())
|
591
647
|
except FileNotFoundError:
|
592
648
|
print(f"ā Configuration file not found: {args.config}")
|
@@ -601,22 +657,23 @@ if __name__ == "__main__":
|
|
601
657
|
if auth_method == "api_key":
|
602
658
|
kwargs["api_key"] = "demo_key_123"
|
603
659
|
elif auth_method == "jwt":
|
604
|
-
kwargs.update(
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
660
|
+
kwargs.update(
|
661
|
+
{
|
662
|
+
"username": "demo_user",
|
663
|
+
"password": "demo_password",
|
664
|
+
"secret": "demo_secret",
|
665
|
+
}
|
666
|
+
)
|
609
667
|
elif auth_method == "certificate":
|
610
|
-
kwargs.update(
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
668
|
+
kwargs.update(
|
669
|
+
{
|
670
|
+
"cert_file": "./certs/client.crt",
|
671
|
+
"key_file": "./keys/client.key",
|
672
|
+
"ca_cert_file": "./certs/ca.crt",
|
673
|
+
}
|
674
|
+
)
|
615
675
|
elif auth_method == "basic":
|
616
|
-
kwargs.update({
|
617
|
-
"username": "demo_user",
|
618
|
-
"password": "demo_password"
|
619
|
-
})
|
676
|
+
kwargs.update({"username": "demo_user", "password": "demo_password"})
|
620
677
|
asyncio.run(demo_specific_connection(auth_method, **kwargs))
|
621
678
|
else:
|
622
679
|
# Demo all connection methods
|