mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.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/__main__.py +12 -0
- mcp_proxy_adapter/api/app.py +254 -33
- mcp_proxy_adapter/api/handlers.py +32 -6
- mcp_proxy_adapter/api/middleware/__init__.py +36 -30
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
- mcp_proxy_adapter/api/middleware/factory.py +243 -0
- mcp_proxy_adapter/api/middleware/logging.py +32 -6
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +152 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
- mcp_proxy_adapter/commands/__init__.py +19 -4
- mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
- mcp_proxy_adapter/commands/base.py +66 -32
- mcp_proxy_adapter/commands/builtin_commands.py +95 -0
- mcp_proxy_adapter/commands/catalog_manager.py +838 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
- mcp_proxy_adapter/commands/command_registry.py +711 -354
- mcp_proxy_adapter/commands/dependency_manager.py +245 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +7 -0
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/hooks.py +200 -167
- mcp_proxy_adapter/commands/key_management_command.py +506 -0
- mcp_proxy_adapter/commands/load_command.py +176 -0
- mcp_proxy_adapter/commands/plugins_command.py +235 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
- mcp_proxy_adapter/commands/reload_command.py +48 -50
- mcp_proxy_adapter/commands/result.py +1 -0
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/roles_management_command.py +697 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
- mcp_proxy_adapter/commands/token_management_command.py +529 -0
- mcp_proxy_adapter/commands/transport_management_command.py +144 -0
- mcp_proxy_adapter/commands/unload_command.py +158 -0
- mcp_proxy_adapter/config.py +159 -2
- mcp_proxy_adapter/core/app_factory.py +326 -0
- mcp_proxy_adapter/core/auth_validator.py +606 -0
- mcp_proxy_adapter/core/certificate_utils.py +827 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/config_converter.py +405 -0
- mcp_proxy_adapter/core/config_validator.py +218 -0
- mcp_proxy_adapter/core/logging.py +19 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +235 -0
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +522 -0
- mcp_proxy_adapter/core/role_utils.py +426 -0
- mcp_proxy_adapter/core/security_adapter.py +370 -0
- mcp_proxy_adapter/core/security_factory.py +239 -0
- mcp_proxy_adapter/core/security_integration.py +277 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/settings.py +1 -0
- mcp_proxy_adapter/core/ssl_utils.py +233 -0
- mcp_proxy_adapter/core/transport_manager.py +292 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/custom_openapi.py +22 -11
- mcp_proxy_adapter/examples/README.md +230 -97
- mcp_proxy_adapter/examples/README_EN.md +258 -0
- mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
- mcp_proxy_adapter/examples/__pycache__/security_configurations.cpython-312.pyc +0 -0
- mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
- mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
- mcp_proxy_adapter/examples/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/admin.key +52 -0
- mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
- mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
- mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/client.crt +32 -0
- mcp_proxy_adapter/examples/certs/client.key +52 -0
- mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
- mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_user.key +52 -0
- mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
- mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
- mcp_proxy_adapter/examples/certs/readonly.key +52 -0
- mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/server.crt +32 -0
- mcp_proxy_adapter/examples/certs/server.key +52 -0
- mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
- mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
- mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
- mcp_proxy_adapter/examples/certs/user.crt +32 -0
- mcp_proxy_adapter/examples/certs/user.key +52 -0
- mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
- mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
- mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
- mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
- mcp_proxy_adapter/examples/commands/__init__.py +1 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
- mcp_proxy_adapter/examples/debug_request_state.py +144 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
- mcp_proxy_adapter/examples/demo_client.py +341 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
- mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
- mcp_proxy_adapter/examples/full_application/main.py +138 -0
- mcp_proxy_adapter/examples/full_application/roles.json +21 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
- mcp_proxy_adapter/examples/generate_certificates.py +121 -0
- mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
- mcp_proxy_adapter/examples/roles.json +38 -0
- mcp_proxy_adapter/examples/run_example.py +81 -0
- mcp_proxy_adapter/examples/run_security_tests.py +326 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
- mcp_proxy_adapter/examples/security_test_client.py +743 -0
- mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
- mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
- mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
- mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
- mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
- mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
- mcp_proxy_adapter/examples/test_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +186 -0
- mcp_proxy_adapter/utils/config_generator.py +639 -0
- mcp_proxy_adapter/version.py +2 -1
- mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
- mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
- mcp_proxy_adapter/examples/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -35
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -217
- mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
- mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,401 @@
|
|
1
|
+
"""
|
2
|
+
Proxy Registration Example
|
3
|
+
|
4
|
+
This example demonstrates how to use the MCP Proxy Adapter framework
|
5
|
+
for proxy registration with different authentication methods.
|
6
|
+
|
7
|
+
Author: Vasiliy Zdanovskiy
|
8
|
+
email: vasilyvz@gmail.com
|
9
|
+
"""
|
10
|
+
|
11
|
+
import asyncio
|
12
|
+
import json
|
13
|
+
import sys
|
14
|
+
import os
|
15
|
+
from pathlib import Path
|
16
|
+
from typing import Dict, Any, Optional
|
17
|
+
|
18
|
+
# Add project root to path
|
19
|
+
project_root = Path(__file__).parent.parent.parent
|
20
|
+
sys.path.insert(0, str(project_root))
|
21
|
+
|
22
|
+
import aiohttp
|
23
|
+
from aiohttp import ClientTimeout, TCPConnector
|
24
|
+
import ssl
|
25
|
+
|
26
|
+
from mcp_proxy_adapter.core.logging import logger
|
27
|
+
|
28
|
+
|
29
|
+
class ProxyRegistrationExample:
|
30
|
+
"""Example client for testing proxy registration functionality."""
|
31
|
+
|
32
|
+
def __init__(self, server_url: str, auth_token: Optional[str] = None):
|
33
|
+
"""
|
34
|
+
Initialize example client.
|
35
|
+
|
36
|
+
Args:
|
37
|
+
server_url: Server URL
|
38
|
+
auth_token: Authentication token
|
39
|
+
"""
|
40
|
+
self.server_url = server_url
|
41
|
+
self.auth_token = auth_token
|
42
|
+
self.session: Optional[aiohttp.ClientSession] = None
|
43
|
+
|
44
|
+
# Test data
|
45
|
+
self.test_servers = [
|
46
|
+
{
|
47
|
+
"server_id": "example-server-1",
|
48
|
+
"server_url": "http://localhost:8001",
|
49
|
+
"server_name": "Example Server 1",
|
50
|
+
"description": "Example server for registration testing",
|
51
|
+
"version": "1.0.0",
|
52
|
+
"capabilities": ["jsonrpc", "rest"],
|
53
|
+
"endpoints": {
|
54
|
+
"jsonrpc": "/api/jsonrpc",
|
55
|
+
"rest": "/cmd",
|
56
|
+
"health": "/health"
|
57
|
+
},
|
58
|
+
"auth_method": "api_key",
|
59
|
+
"security_enabled": True
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"server_id": "example-server-2",
|
63
|
+
"server_url": "http://localhost:8002",
|
64
|
+
"server_name": "Example Server 2",
|
65
|
+
"description": "Another example server",
|
66
|
+
"version": "1.0.0",
|
67
|
+
"capabilities": ["jsonrpc", "rest", "security"],
|
68
|
+
"endpoints": {
|
69
|
+
"jsonrpc": "/api/jsonrpc",
|
70
|
+
"rest": "/cmd",
|
71
|
+
"health": "/health"
|
72
|
+
},
|
73
|
+
"auth_method": "certificate",
|
74
|
+
"security_enabled": True
|
75
|
+
}
|
76
|
+
]
|
77
|
+
|
78
|
+
async def __aenter__(self):
|
79
|
+
"""Async context manager entry."""
|
80
|
+
# Create SSL context for HTTPS
|
81
|
+
ssl_context = None
|
82
|
+
if self.server_url.startswith("https"):
|
83
|
+
ssl_context = ssl.create_default_context()
|
84
|
+
ssl_context.check_hostname = False
|
85
|
+
ssl_context.verify_mode = ssl.CERT_NONE
|
86
|
+
|
87
|
+
# Create connector
|
88
|
+
connector = TCPConnector(ssl=ssl_context) if ssl_context else None
|
89
|
+
|
90
|
+
# Create session
|
91
|
+
timeout = ClientTimeout(total=30)
|
92
|
+
self.session = aiohttp.ClientSession(
|
93
|
+
connector=connector,
|
94
|
+
timeout=timeout
|
95
|
+
)
|
96
|
+
|
97
|
+
return self
|
98
|
+
|
99
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
100
|
+
"""Async context manager exit."""
|
101
|
+
if self.session:
|
102
|
+
await self.session.close()
|
103
|
+
|
104
|
+
def _get_headers(self) -> Dict[str, str]:
|
105
|
+
"""Get request headers with authentication."""
|
106
|
+
headers = {
|
107
|
+
"Content-Type": "application/json"
|
108
|
+
}
|
109
|
+
|
110
|
+
if self.auth_token:
|
111
|
+
headers["X-API-Key"] = self.auth_token
|
112
|
+
|
113
|
+
return headers
|
114
|
+
|
115
|
+
async def test_registration(self, server_data: Dict[str, Any]) -> Dict[str, Any]:
|
116
|
+
"""
|
117
|
+
Test registration with authentication.
|
118
|
+
|
119
|
+
Args:
|
120
|
+
server_data: Server registration data
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
Test result
|
124
|
+
"""
|
125
|
+
try:
|
126
|
+
# Prepare JSON-RPC request
|
127
|
+
request_data = {
|
128
|
+
"jsonrpc": "2.0",
|
129
|
+
"id": 1,
|
130
|
+
"method": "proxy_registration",
|
131
|
+
"params": {
|
132
|
+
"operation": "register",
|
133
|
+
**server_data
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
logger.info(f"Testing registration for server: {server_data['server_id']}")
|
138
|
+
logger.debug(f"Request data: {json.dumps(request_data, indent=2)}")
|
139
|
+
|
140
|
+
# Make request
|
141
|
+
async with self.session.post(
|
142
|
+
f"{self.server_url}/cmd",
|
143
|
+
json=request_data,
|
144
|
+
headers=self._get_headers()
|
145
|
+
) as response:
|
146
|
+
result = await response.json()
|
147
|
+
|
148
|
+
logger.info(f"Response status: {response.status}")
|
149
|
+
logger.debug(f"Response: {json.dumps(result, indent=2)}")
|
150
|
+
|
151
|
+
return {
|
152
|
+
"success": response.status == 200,
|
153
|
+
"status_code": response.status,
|
154
|
+
"result": result,
|
155
|
+
"server_id": server_data["server_id"]
|
156
|
+
}
|
157
|
+
|
158
|
+
except Exception as e:
|
159
|
+
logger.error(f"Registration test failed: {e}")
|
160
|
+
return {
|
161
|
+
"success": False,
|
162
|
+
"error": str(e),
|
163
|
+
"server_id": server_data["server_id"]
|
164
|
+
}
|
165
|
+
|
166
|
+
async def test_discovery(self) -> Dict[str, Any]:
|
167
|
+
"""
|
168
|
+
Test discovery operation.
|
169
|
+
|
170
|
+
Returns:
|
171
|
+
Test result
|
172
|
+
"""
|
173
|
+
try:
|
174
|
+
# Prepare JSON-RPC request
|
175
|
+
request_data = {
|
176
|
+
"jsonrpc": "2.0",
|
177
|
+
"id": 1,
|
178
|
+
"method": "proxy_registration",
|
179
|
+
"params": {
|
180
|
+
"operation": "discover"
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
logger.info("Testing discovery operation")
|
185
|
+
|
186
|
+
# Make request
|
187
|
+
async with self.session.post(
|
188
|
+
f"{self.server_url}/cmd",
|
189
|
+
json=request_data,
|
190
|
+
headers=self._get_headers()
|
191
|
+
) as response:
|
192
|
+
result = await response.json()
|
193
|
+
|
194
|
+
logger.info(f"Response status: {response.status}")
|
195
|
+
logger.debug(f"Response: {json.dumps(result, indent=2)}")
|
196
|
+
|
197
|
+
return {
|
198
|
+
"success": response.status == 200,
|
199
|
+
"status_code": response.status,
|
200
|
+
"result": result
|
201
|
+
}
|
202
|
+
|
203
|
+
except Exception as e:
|
204
|
+
logger.error(f"Discovery test failed: {e}")
|
205
|
+
return {
|
206
|
+
"success": False,
|
207
|
+
"error": str(e)
|
208
|
+
}
|
209
|
+
|
210
|
+
async def test_heartbeat(self, server_key: str) -> Dict[str, Any]:
|
211
|
+
"""
|
212
|
+
Test heartbeat operation.
|
213
|
+
|
214
|
+
Args:
|
215
|
+
server_key: Server key for heartbeat
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
Test result
|
219
|
+
"""
|
220
|
+
try:
|
221
|
+
# Prepare JSON-RPC request
|
222
|
+
request_data = {
|
223
|
+
"jsonrpc": "2.0",
|
224
|
+
"id": 1,
|
225
|
+
"method": "proxy_registration",
|
226
|
+
"params": {
|
227
|
+
"operation": "heartbeat",
|
228
|
+
"server_key": server_key,
|
229
|
+
"timestamp": 1234567890,
|
230
|
+
"status": "healthy"
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
logger.info(f"Testing heartbeat for server: {server_key}")
|
235
|
+
|
236
|
+
# Make request
|
237
|
+
async with self.session.post(
|
238
|
+
f"{self.server_url}/cmd",
|
239
|
+
json=request_data,
|
240
|
+
headers=self._get_headers()
|
241
|
+
) as response:
|
242
|
+
result = await response.json()
|
243
|
+
|
244
|
+
logger.info(f"Response status: {response.status}")
|
245
|
+
logger.debug(f"Response: {json.dumps(result, indent=2)}")
|
246
|
+
|
247
|
+
return {
|
248
|
+
"success": response.status == 200,
|
249
|
+
"status_code": response.status,
|
250
|
+
"result": result,
|
251
|
+
"server_key": server_key
|
252
|
+
}
|
253
|
+
|
254
|
+
except Exception as e:
|
255
|
+
logger.error(f"Heartbeat test failed: {e}")
|
256
|
+
return {
|
257
|
+
"success": False,
|
258
|
+
"error": str(e),
|
259
|
+
"server_key": server_key
|
260
|
+
}
|
261
|
+
|
262
|
+
|
263
|
+
async def run_proxy_registration_example():
|
264
|
+
"""Run proxy registration example."""
|
265
|
+
logger.info("🚀 Starting proxy registration example")
|
266
|
+
|
267
|
+
# Test configurations
|
268
|
+
test_configs = [
|
269
|
+
{
|
270
|
+
"name": "Admin Token",
|
271
|
+
"server_url": "http://localhost:8002",
|
272
|
+
"auth_token": "test-token-123"
|
273
|
+
},
|
274
|
+
{
|
275
|
+
"name": "User Token",
|
276
|
+
"server_url": "http://localhost:8002",
|
277
|
+
"auth_token": "user-token-456"
|
278
|
+
},
|
279
|
+
{
|
280
|
+
"name": "Readonly Token",
|
281
|
+
"server_url": "http://localhost:8002",
|
282
|
+
"auth_token": "readonly-token-123"
|
283
|
+
}
|
284
|
+
]
|
285
|
+
|
286
|
+
results = []
|
287
|
+
|
288
|
+
for config in test_configs:
|
289
|
+
logger.info(f"\n📋 Testing: {config['name']}")
|
290
|
+
logger.info(f"Server URL: {config['server_url']}")
|
291
|
+
logger.info(f"Auth Token: {config['auth_token']}")
|
292
|
+
|
293
|
+
async with ProxyRegistrationExample(
|
294
|
+
config['server_url'],
|
295
|
+
config['auth_token']
|
296
|
+
) as client:
|
297
|
+
# Test registration
|
298
|
+
for server_data in client.test_servers:
|
299
|
+
result = await client.test_registration(server_data)
|
300
|
+
results.append({
|
301
|
+
"test": f"{config['name']} - Registration",
|
302
|
+
"server_id": server_data["server_id"],
|
303
|
+
**result
|
304
|
+
})
|
305
|
+
|
306
|
+
# If registration successful, test heartbeat
|
307
|
+
if result["success"] and "result" in result:
|
308
|
+
server_key = result["result"].get("result", {}).get("server_key")
|
309
|
+
if server_key:
|
310
|
+
heartbeat_result = await client.test_heartbeat(server_key)
|
311
|
+
results.append({
|
312
|
+
"test": f"{config['name']} - Heartbeat",
|
313
|
+
"server_key": server_key,
|
314
|
+
**heartbeat_result
|
315
|
+
})
|
316
|
+
|
317
|
+
# Test discovery
|
318
|
+
discovery_result = await client.test_discovery()
|
319
|
+
results.append({
|
320
|
+
"test": f"{config['name']} - Discovery",
|
321
|
+
**discovery_result
|
322
|
+
})
|
323
|
+
|
324
|
+
# Test without authentication
|
325
|
+
logger.info(f"\n📋 Testing: No Authentication")
|
326
|
+
async with ProxyRegistrationExample("http://localhost:8002") as client:
|
327
|
+
for server_data in client.test_servers:
|
328
|
+
result = await client.test_registration(server_data)
|
329
|
+
results.append({
|
330
|
+
"test": "No Auth - Registration",
|
331
|
+
"server_id": server_data["server_id"],
|
332
|
+
**result
|
333
|
+
})
|
334
|
+
|
335
|
+
# Print results
|
336
|
+
logger.info("\n" + "="*80)
|
337
|
+
logger.info("📊 EXAMPLE RESULTS")
|
338
|
+
logger.info("="*80)
|
339
|
+
|
340
|
+
passed = 0
|
341
|
+
failed = 0
|
342
|
+
|
343
|
+
for result in results:
|
344
|
+
status = "✅ PASS" if result["success"] else "❌ FAIL"
|
345
|
+
logger.info(f"{status} {result['test']}")
|
346
|
+
|
347
|
+
if result["success"]:
|
348
|
+
passed += 1
|
349
|
+
else:
|
350
|
+
failed += 1
|
351
|
+
|
352
|
+
if "error" in result:
|
353
|
+
logger.error(f" Error: {result['error']}")
|
354
|
+
elif "result" in result:
|
355
|
+
result_data = result["result"]
|
356
|
+
if "error" in result_data:
|
357
|
+
logger.error(f" API Error: {result_data['error']}")
|
358
|
+
elif "result" in result_data:
|
359
|
+
api_result = result_data["result"]
|
360
|
+
if "server_key" in api_result:
|
361
|
+
logger.info(f" Server Key: {api_result['server_key']}")
|
362
|
+
if "message" in api_result:
|
363
|
+
logger.info(f" Message: {api_result['message']}")
|
364
|
+
|
365
|
+
logger.info("\n" + "="*80)
|
366
|
+
logger.info(f"📈 SUMMARY: {passed} passed, {failed} failed")
|
367
|
+
logger.info("="*80)
|
368
|
+
|
369
|
+
return passed, failed
|
370
|
+
|
371
|
+
|
372
|
+
def main():
|
373
|
+
"""Main function for the example."""
|
374
|
+
logger.info("🔧 MCP Proxy Adapter - Proxy Registration Example")
|
375
|
+
logger.info("="*60)
|
376
|
+
|
377
|
+
# Check if server is running
|
378
|
+
import socket
|
379
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
380
|
+
result = sock.connect_ex(('localhost', 8002))
|
381
|
+
sock.close()
|
382
|
+
|
383
|
+
if result != 0:
|
384
|
+
logger.error("❌ Server is not running on localhost:8002")
|
385
|
+
logger.info("💡 Please start the server first:")
|
386
|
+
logger.info(" cd mcp_proxy_adapter/examples")
|
387
|
+
logger.info(" python -m mcp_proxy_adapter.main --config server_configs/config_proxy_registration.json")
|
388
|
+
sys.exit(1)
|
389
|
+
|
390
|
+
logger.info("✅ Server is running on localhost:8002")
|
391
|
+
logger.info("🚀 Starting proxy registration example...")
|
392
|
+
|
393
|
+
# Run example
|
394
|
+
passed, failed = asyncio.run(run_proxy_registration_example())
|
395
|
+
|
396
|
+
# Exit with appropriate code
|
397
|
+
sys.exit(0 if failed == 0 else 1)
|
398
|
+
|
399
|
+
|
400
|
+
if __name__ == "__main__":
|
401
|
+
main()
|
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"roles": {
|
3
|
+
"admin": {
|
4
|
+
"description": "Administrator with full access",
|
5
|
+
"permissions": ["*"],
|
6
|
+
"inherits": []
|
7
|
+
},
|
8
|
+
"user": {
|
9
|
+
"description": "Standard user with read/write access",
|
10
|
+
"permissions": ["read", "write"],
|
11
|
+
"inherits": ["readonly"]
|
12
|
+
},
|
13
|
+
"readonly": {
|
14
|
+
"description": "Read-only user",
|
15
|
+
"permissions": ["read"],
|
16
|
+
"inherits": []
|
17
|
+
},
|
18
|
+
"guest": {
|
19
|
+
"description": "Guest user with minimal access",
|
20
|
+
"permissions": ["read"],
|
21
|
+
"inherits": []
|
22
|
+
},
|
23
|
+
"proxy": {
|
24
|
+
"description": "Proxy registration and discovery",
|
25
|
+
"permissions": ["register", "heartbeat", "discover"],
|
26
|
+
"inherits": []
|
27
|
+
}
|
28
|
+
},
|
29
|
+
"permissions": {
|
30
|
+
"read": "Read access to resources",
|
31
|
+
"write": "Write access to resources",
|
32
|
+
"delete": "Delete access to resources",
|
33
|
+
"manage": "Manage system settings",
|
34
|
+
"register": "Register proxy with registry",
|
35
|
+
"heartbeat": "Send heartbeat to registry",
|
36
|
+
"discover": "Discover other proxies"
|
37
|
+
}
|
38
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Example Runner Script
|
4
|
+
|
5
|
+
This script provides a simple way to run the examples.
|
6
|
+
|
7
|
+
Author: Vasiliy Zdanovskiy
|
8
|
+
email: vasilyvz@gmail.com
|
9
|
+
"""
|
10
|
+
|
11
|
+
import sys
|
12
|
+
import subprocess
|
13
|
+
import argparse
|
14
|
+
from pathlib import Path
|
15
|
+
|
16
|
+
|
17
|
+
def run_basic_example(config_name: str, port: int = None):
|
18
|
+
"""Run basic framework example."""
|
19
|
+
config_path = Path(__file__).parent / "basic_framework" / "configs" / f"{config_name}.json"
|
20
|
+
main_script = Path(__file__).parent / "basic_framework" / "main.py"
|
21
|
+
|
22
|
+
if not config_path.exists():
|
23
|
+
print(f"❌ Configuration file not found: {config_path}")
|
24
|
+
return False
|
25
|
+
|
26
|
+
cmd = [sys.executable, str(main_script), "--config", str(config_path)]
|
27
|
+
if port:
|
28
|
+
cmd.extend(["--port", str(port)])
|
29
|
+
|
30
|
+
print(f"🚀 Running basic framework example with {config_name} configuration...")
|
31
|
+
return subprocess.run(cmd).returncode == 0
|
32
|
+
|
33
|
+
|
34
|
+
def run_full_example(config_name: str, port: int = None):
|
35
|
+
"""Run full application example."""
|
36
|
+
config_path = Path(__file__).parent / "full_application" / "configs" / f"{config_name}.json"
|
37
|
+
main_script = Path(__file__).parent / "full_application" / "main.py"
|
38
|
+
|
39
|
+
if not config_path.exists():
|
40
|
+
print(f"❌ Configuration file not found: {config_path}")
|
41
|
+
return False
|
42
|
+
|
43
|
+
cmd = [sys.executable, str(main_script), "--config", str(config_path)]
|
44
|
+
if port:
|
45
|
+
cmd.extend(["--port", str(port)])
|
46
|
+
|
47
|
+
print(f"🚀 Running full application example with {config_name} configuration...")
|
48
|
+
return subprocess.run(cmd).returncode == 0
|
49
|
+
|
50
|
+
|
51
|
+
def main():
|
52
|
+
"""Main function."""
|
53
|
+
parser = argparse.ArgumentParser(description="Run MCP Proxy Adapter Examples")
|
54
|
+
parser.add_argument("example", choices=["basic", "full"], help="Example type")
|
55
|
+
parser.add_argument("config", help="Configuration name (e.g., http_simple, https_auth)")
|
56
|
+
parser.add_argument("--port", type=int, help="Override port")
|
57
|
+
|
58
|
+
args = parser.parse_args()
|
59
|
+
|
60
|
+
# Available configurations
|
61
|
+
configs = [
|
62
|
+
"http_simple", "https_simple", "http_auth",
|
63
|
+
"https_auth", "mtls_no_roles", "mtls_with_roles"
|
64
|
+
]
|
65
|
+
|
66
|
+
if args.config not in configs:
|
67
|
+
print(f"❌ Unknown configuration: {args.config}")
|
68
|
+
print(f"Available configurations: {', '.join(configs)}")
|
69
|
+
return 1
|
70
|
+
|
71
|
+
# Run the appropriate example
|
72
|
+
if args.example == "basic":
|
73
|
+
success = run_basic_example(args.config, args.port)
|
74
|
+
else:
|
75
|
+
success = run_full_example(args.config, args.port)
|
76
|
+
|
77
|
+
return 0 if success else 1
|
78
|
+
|
79
|
+
|
80
|
+
if __name__ == "__main__":
|
81
|
+
sys.exit(main())
|