mcp-proxy-adapter 6.9.28__py3-none-any.whl ā 6.9.29__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.
Potentially problematic release.
This version of mcp-proxy-adapter might be problematic. Click here for more details.
- mcp_proxy_adapter/__init__.py +10 -0
- mcp_proxy_adapter/__main__.py +8 -21
- mcp_proxy_adapter/api/app.py +10 -913
- mcp_proxy_adapter/api/core/__init__.py +18 -0
- mcp_proxy_adapter/api/core/app_factory.py +243 -0
- mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
- mcp_proxy_adapter/api/core/registration_manager.py +166 -0
- mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
- mcp_proxy_adapter/api/handlers.py +78 -199
- mcp_proxy_adapter/api/middleware/__init__.py +1 -44
- mcp_proxy_adapter/api/middleware/base.py +0 -42
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
- mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
- mcp_proxy_adapter/api/middleware/factory.py +0 -94
- mcp_proxy_adapter/api/middleware/logging.py +0 -112
- mcp_proxy_adapter/api/middleware/performance.py +0 -35
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
- mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
- mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
- mcp_proxy_adapter/api/openapi/__init__.py +21 -0
- mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
- mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
- mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
- mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
- mcp_proxy_adapter/api/schemas.py +0 -61
- mcp_proxy_adapter/api/tool_integration.py +0 -117
- mcp_proxy_adapter/api/tools.py +0 -46
- mcp_proxy_adapter/cli/__init__.py +12 -0
- mcp_proxy_adapter/cli/commands/__init__.py +15 -0
- mcp_proxy_adapter/cli/commands/client.py +100 -0
- mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
- mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
- mcp_proxy_adapter/cli/commands/generate.py +259 -0
- mcp_proxy_adapter/cli/commands/server.py +174 -0
- mcp_proxy_adapter/cli/commands/sets.py +128 -0
- mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
- mcp_proxy_adapter/cli/examples/__init__.py +8 -0
- mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
- mcp_proxy_adapter/cli/examples/https_token.py +96 -0
- mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
- mcp_proxy_adapter/cli/main.py +63 -0
- mcp_proxy_adapter/cli/parser.py +324 -0
- mcp_proxy_adapter/cli/validators.py +231 -0
- mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
- mcp_proxy_adapter/client/proxy.py +45 -0
- mcp_proxy_adapter/commands/__init__.py +44 -28
- mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
- mcp_proxy_adapter/commands/base.py +19 -43
- mcp_proxy_adapter/commands/builtin_commands.py +0 -75
- mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
- mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
- mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
- mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
- mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
- mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
- mcp_proxy_adapter/commands/catalog_manager.py +58 -928
- mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
- mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
- mcp_proxy_adapter/commands/command_registry.py +172 -904
- mcp_proxy_adapter/commands/config_command.py +0 -28
- mcp_proxy_adapter/commands/dependency_container.py +1 -70
- mcp_proxy_adapter/commands/dependency_manager.py +0 -128
- mcp_proxy_adapter/commands/echo_command.py +0 -34
- mcp_proxy_adapter/commands/health_command.py +0 -3
- mcp_proxy_adapter/commands/help_command.py +0 -159
- mcp_proxy_adapter/commands/hooks.py +0 -137
- mcp_proxy_adapter/commands/key_management_command.py +0 -25
- mcp_proxy_adapter/commands/load_command.py +7 -78
- mcp_proxy_adapter/commands/plugins_command.py +0 -16
- mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
- mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
- mcp_proxy_adapter/commands/queue_commands.py +750 -0
- mcp_proxy_adapter/commands/registration_status_command.py +0 -43
- mcp_proxy_adapter/commands/registry/__init__.py +18 -0
- mcp_proxy_adapter/commands/registry/command_info.py +103 -0
- mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
- mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
- mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
- mcp_proxy_adapter/commands/reload_command.py +0 -80
- mcp_proxy_adapter/commands/result.py +25 -77
- mcp_proxy_adapter/commands/role_test_command.py +0 -44
- mcp_proxy_adapter/commands/roles_management_command.py +0 -199
- mcp_proxy_adapter/commands/security_command.py +0 -30
- mcp_proxy_adapter/commands/settings_command.py +0 -68
- mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
- mcp_proxy_adapter/commands/token_management_command.py +0 -1
- mcp_proxy_adapter/commands/transport_management_command.py +0 -20
- mcp_proxy_adapter/commands/unload_command.py +0 -71
- mcp_proxy_adapter/config.py +15 -626
- mcp_proxy_adapter/core/__init__.py +5 -39
- mcp_proxy_adapter/core/app_factory.py +14 -36
- mcp_proxy_adapter/core/app_runner.py +0 -27
- mcp_proxy_adapter/core/auth_validator.py +1 -93
- mcp_proxy_adapter/core/certificate/__init__.py +20 -0
- mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
- mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
- mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
- mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
- mcp_proxy_adapter/core/certificate_utils.py +64 -903
- mcp_proxy_adapter/core/client.py +0 -6
- mcp_proxy_adapter/core/client_manager.py +0 -19
- mcp_proxy_adapter/core/client_security.py +0 -2
- mcp_proxy_adapter/core/config/__init__.py +18 -0
- mcp_proxy_adapter/core/config/config.py +195 -0
- mcp_proxy_adapter/core/config/config_factory.py +22 -0
- mcp_proxy_adapter/core/config/config_loader.py +66 -0
- mcp_proxy_adapter/core/config/feature_manager.py +31 -0
- mcp_proxy_adapter/core/config/simple_config.py +112 -0
- mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
- mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
- mcp_proxy_adapter/core/config_converter.py +0 -186
- mcp_proxy_adapter/core/config_validator.py +96 -1238
- mcp_proxy_adapter/core/errors.py +7 -42
- mcp_proxy_adapter/core/job_manager.py +54 -0
- mcp_proxy_adapter/core/logging.py +2 -22
- mcp_proxy_adapter/core/mtls_asgi.py +0 -20
- mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
- mcp_proxy_adapter/core/mtls_proxy.py +0 -80
- mcp_proxy_adapter/core/mtls_server.py +3 -173
- mcp_proxy_adapter/core/protocol_manager.py +1 -191
- mcp_proxy_adapter/core/proxy/__init__.py +22 -0
- mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
- mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
- mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
- mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
- mcp_proxy_adapter/core/proxy_client.py +0 -1
- mcp_proxy_adapter/core/proxy_registration.py +36 -913
- mcp_proxy_adapter/core/role_utils.py +0 -308
- mcp_proxy_adapter/core/security_adapter.py +1 -36
- mcp_proxy_adapter/core/security_factory.py +1 -150
- mcp_proxy_adapter/core/security_integration.py +0 -33
- mcp_proxy_adapter/core/server_adapter.py +1 -40
- mcp_proxy_adapter/core/server_engine.py +2 -173
- mcp_proxy_adapter/core/settings.py +0 -127
- mcp_proxy_adapter/core/signal_handler.py +0 -65
- mcp_proxy_adapter/core/ssl_utils.py +19 -137
- mcp_proxy_adapter/core/transport_manager.py +0 -151
- mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
- mcp_proxy_adapter/core/utils.py +1 -182
- mcp_proxy_adapter/core/validation/__init__.py +21 -0
- mcp_proxy_adapter/core/validation/config_validator.py +211 -0
- mcp_proxy_adapter/core/validation/file_validator.py +73 -0
- mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
- mcp_proxy_adapter/core/validation/security_validator.py +58 -0
- mcp_proxy_adapter/core/validation/validation_result.py +27 -0
- mcp_proxy_adapter/custom_openapi.py +33 -652
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
- mcp_proxy_adapter/examples/check_config.py +0 -2
- mcp_proxy_adapter/examples/client_usage_example.py +164 -0
- mcp_proxy_adapter/examples/config_builder.py +13 -2
- mcp_proxy_adapter/examples/config_cli.py +0 -1
- mcp_proxy_adapter/examples/create_test_configs.py +0 -46
- mcp_proxy_adapter/examples/debug_request_state.py +0 -1
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
- mcp_proxy_adapter/examples/full_application/main.py +186 -150
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
- mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
- mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
- mcp_proxy_adapter/examples/generate_config.py +65 -11
- mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
- mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
- mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
- mcp_proxy_adapter/examples/queue_server_example.py +85 -0
- mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
- mcp_proxy_adapter/examples/required_certificates.py +0 -2
- mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
- mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
- mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
- mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
- mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
- mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
- mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
- mcp_proxy_adapter/examples/security_test_client.py +24 -1075
- mcp_proxy_adapter/examples/setup/__init__.py +24 -0
- mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
- mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
- mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
- mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
- mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
- mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
- mcp_proxy_adapter/examples/test_config.py +0 -3
- mcp_proxy_adapter/examples/test_config_builder.py +25 -405
- mcp_proxy_adapter/examples/test_examples.py +0 -1
- mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
- mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
- mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
- mcp_proxy_adapter/examples/universal_client.py +0 -6
- mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
- mcp_proxy_adapter/integrations/__init__.py +25 -0
- mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
- mcp_proxy_adapter/main.py +70 -62
- mcp_proxy_adapter/openapi.py +0 -22
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.28.dist-info ā mcp_proxy_adapter-6.9.29.dist-info}/METADATA +2 -1
- mcp_proxy_adapter-6.9.29.dist-info/RECORD +235 -0
- {mcp_proxy_adapter-6.9.28.dist-info ā mcp_proxy_adapter-6.9.29.dist-info}/entry_points.txt +1 -1
- mcp_proxy_adapter-6.9.28.dist-info/RECORD +0 -149
- {mcp_proxy_adapter-6.9.28.dist-info ā mcp_proxy_adapter-6.9.29.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.28.dist-info ā mcp_proxy_adapter-6.9.29.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Queue Server Example for MCP Proxy Adapter.
|
|
3
|
+
|
|
4
|
+
This example demonstrates how to run an MCP server with queue integration
|
|
5
|
+
for managing background jobs.
|
|
6
|
+
|
|
7
|
+
Author: Vasiliy Zdanovskiy
|
|
8
|
+
email: vasilyvz@gmail.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
from hypercorn.asyncio import serve
|
|
13
|
+
from hypercorn.config import Config as HyperConfig
|
|
14
|
+
from mcp_proxy_adapter.api.app import create_app
|
|
15
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
|
16
|
+
from mcp_proxy_adapter.commands.queue_commands import (
|
|
17
|
+
QueueAddJobCommand,
|
|
18
|
+
QueueStartJobCommand,
|
|
19
|
+
QueueStopJobCommand,
|
|
20
|
+
QueueDeleteJobCommand,
|
|
21
|
+
QueueGetJobStatusCommand,
|
|
22
|
+
QueueListJobsCommand,
|
|
23
|
+
QueueHealthCommand,
|
|
24
|
+
)
|
|
25
|
+
from mcp_proxy_adapter.integrations.queuemgr_integration import (
|
|
26
|
+
init_global_queue_manager,
|
|
27
|
+
shutdown_global_queue_manager,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def setup_queue_commands():
|
|
32
|
+
"""Setup queue management commands."""
|
|
33
|
+
print("š§ Setting up queue management commands...")
|
|
34
|
+
|
|
35
|
+
# Register queue commands
|
|
36
|
+
registry.register(QueueAddJobCommand())
|
|
37
|
+
registry.register(QueueStartJobCommand())
|
|
38
|
+
registry.register(QueueStopJobCommand())
|
|
39
|
+
registry.register(QueueDeleteJobCommand())
|
|
40
|
+
registry.register(QueueGetJobStatusCommand())
|
|
41
|
+
registry.register(QueueListJobsCommand())
|
|
42
|
+
registry.register(QueueHealthCommand())
|
|
43
|
+
|
|
44
|
+
print("ā
Queue commands registered")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def create_queue_server_app() -> any:
|
|
48
|
+
"""Create MCP server application with queue integration."""
|
|
49
|
+
app = create_app()
|
|
50
|
+
|
|
51
|
+
@app.on_event("startup")
|
|
52
|
+
async def _on_startup() -> None:
|
|
53
|
+
await init_global_queue_manager()
|
|
54
|
+
await setup_queue_commands()
|
|
55
|
+
|
|
56
|
+
@app.on_event("shutdown")
|
|
57
|
+
async def _on_shutdown() -> None:
|
|
58
|
+
await shutdown_global_queue_manager()
|
|
59
|
+
|
|
60
|
+
return app
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def main():
|
|
64
|
+
"""Main function to run the queue server with Hypercorn."""
|
|
65
|
+
print("š Starting MCP Proxy Adapter Queue Server")
|
|
66
|
+
print("=" * 50)
|
|
67
|
+
|
|
68
|
+
app = create_queue_server_app()
|
|
69
|
+
|
|
70
|
+
hc = HyperConfig()
|
|
71
|
+
hc.bind = ["0.0.0.0:8000"]
|
|
72
|
+
hc.loglevel = "info"
|
|
73
|
+
|
|
74
|
+
print("ā
MCP Queue Server will start at http://localhost:8000")
|
|
75
|
+
print("š Example usage:")
|
|
76
|
+
print(" curl -X POST http://localhost:8000/api/jsonrpc \\")
|
|
77
|
+
print(" -H 'Content-Type: application/json' \\")
|
|
78
|
+
print(" -d '{\"jsonrpc\": \"2.0\", \"method\": \"queue_health\", \"params\": {}, \"id\": 1}'")
|
|
79
|
+
print()
|
|
80
|
+
|
|
81
|
+
await serve(app, hc)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Simple Queue Server for MCP Proxy Adapter.
|
|
4
|
+
|
|
5
|
+
This example demonstrates how to run an MCP server with queue integration
|
|
6
|
+
using a minimal configuration.
|
|
7
|
+
|
|
8
|
+
Author: Vasiliy Zdanovskiy
|
|
9
|
+
email: vasilyvz@gmail.com
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import uvicorn
|
|
14
|
+
from mcp_proxy_adapter.api.app import create_app
|
|
15
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
|
16
|
+
from mcp_proxy_adapter.commands.queue_commands import (
|
|
17
|
+
QueueAddJobCommand,
|
|
18
|
+
QueueStartJobCommand,
|
|
19
|
+
QueueStopJobCommand,
|
|
20
|
+
QueueDeleteJobCommand,
|
|
21
|
+
QueueGetJobStatusCommand,
|
|
22
|
+
QueueListJobsCommand,
|
|
23
|
+
QueueHealthCommand,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def setup_queue_commands():
|
|
28
|
+
"""Setup queue management commands."""
|
|
29
|
+
print("š§ Setting up queue management commands...")
|
|
30
|
+
|
|
31
|
+
# Register queue commands
|
|
32
|
+
registry.register_custom(QueueAddJobCommand())
|
|
33
|
+
registry.register_custom(QueueStartJobCommand())
|
|
34
|
+
registry.register_custom(QueueStopJobCommand())
|
|
35
|
+
registry.register_custom(QueueDeleteJobCommand())
|
|
36
|
+
registry.register_custom(QueueGetJobStatusCommand())
|
|
37
|
+
registry.register_custom(QueueListJobsCommand())
|
|
38
|
+
registry.register_custom(QueueHealthCommand())
|
|
39
|
+
|
|
40
|
+
print("ā
Queue commands registered")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def create_queue_server_app():
|
|
44
|
+
"""Create MCP server application with queue integration."""
|
|
45
|
+
# Create minimal config
|
|
46
|
+
config = {
|
|
47
|
+
"uuid": "123e4567-e89b-42d3-8a56-426614174000",
|
|
48
|
+
"server": {
|
|
49
|
+
"host": "172.28.0.1",
|
|
50
|
+
"port": 8000,
|
|
51
|
+
"protocol": "http",
|
|
52
|
+
"debug": False,
|
|
53
|
+
"log_level": "INFO"
|
|
54
|
+
},
|
|
55
|
+
"logging": {
|
|
56
|
+
"level": "INFO",
|
|
57
|
+
"file": None,
|
|
58
|
+
"log_dir": "./logs",
|
|
59
|
+
"log_file": "mcp_proxy_adapter.log",
|
|
60
|
+
"error_log_file": "mcp_proxy_adapter_error.log",
|
|
61
|
+
"access_log_file": "mcp_proxy_adapter_access.log",
|
|
62
|
+
"max_file_size": "10MB",
|
|
63
|
+
"backup_count": 5,
|
|
64
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
65
|
+
"date_format": "%Y-%m-%d %H:%M:%S",
|
|
66
|
+
"console_output": True,
|
|
67
|
+
"file_output": True
|
|
68
|
+
},
|
|
69
|
+
"commands": {
|
|
70
|
+
"auto_discovery": True,
|
|
71
|
+
"commands_directory": "./commands",
|
|
72
|
+
"catalog_directory": "./catalog",
|
|
73
|
+
"plugin_servers": [],
|
|
74
|
+
"auto_install_dependencies": True,
|
|
75
|
+
"enabled_commands": ["health", "echo", "list", "help"],
|
|
76
|
+
"disabled_commands": [],
|
|
77
|
+
"custom_commands_path": "./commands"
|
|
78
|
+
},
|
|
79
|
+
"transport": {
|
|
80
|
+
"type": "http",
|
|
81
|
+
"port": 8000
|
|
82
|
+
},
|
|
83
|
+
"ssl": {
|
|
84
|
+
"enabled": False
|
|
85
|
+
},
|
|
86
|
+
"proxy_registration": {
|
|
87
|
+
"enabled": True,
|
|
88
|
+
"proxy_url": "https://172.28.0.4:3004",
|
|
89
|
+
"server_id": "mcp_queue_server",
|
|
90
|
+
"server_name": "MCP Queue Server",
|
|
91
|
+
"description": "Queue management server with mTLS",
|
|
92
|
+
"version": "6.9.28",
|
|
93
|
+
"protocol": "mtls",
|
|
94
|
+
"ssl": {
|
|
95
|
+
"enabled": True,
|
|
96
|
+
"verify_ssl": False,
|
|
97
|
+
"verify_hostname": False,
|
|
98
|
+
"verify_mode": "CERT_REQUIRED",
|
|
99
|
+
"ca_cert": "./mtls_certificates/ca/ca.crt",
|
|
100
|
+
"cert_file": "./mtls_certificates/client/test-client.crt",
|
|
101
|
+
"key_file": "./mtls_certificates/client/test-client.key"
|
|
102
|
+
},
|
|
103
|
+
"certificate": {
|
|
104
|
+
"cert_file": "./mtls_certificates/client/test-client.crt",
|
|
105
|
+
"key_file": "./mtls_certificates/client/test-client.key"
|
|
106
|
+
},
|
|
107
|
+
"registration_timeout": 30,
|
|
108
|
+
"retry_attempts": 3,
|
|
109
|
+
"retry_delay": 5,
|
|
110
|
+
"auto_register_on_startup": True,
|
|
111
|
+
"auto_unregister_on_shutdown": True,
|
|
112
|
+
"heartbeat": {
|
|
113
|
+
"enabled": True,
|
|
114
|
+
"interval": 30,
|
|
115
|
+
"timeout": 10,
|
|
116
|
+
"retry_attempts": 3,
|
|
117
|
+
"retry_delay": 5,
|
|
118
|
+
"url": "/heartbeat"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"debug": {
|
|
122
|
+
"enabled": False,
|
|
123
|
+
"level": "WARNING"
|
|
124
|
+
},
|
|
125
|
+
"security": {
|
|
126
|
+
"enabled": False
|
|
127
|
+
},
|
|
128
|
+
"roles": {
|
|
129
|
+
"enabled": False
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# Register commands before creating the app
|
|
134
|
+
setup_queue_commands()
|
|
135
|
+
|
|
136
|
+
app = create_app(app_config=config)
|
|
137
|
+
|
|
138
|
+
@app.on_event("startup")
|
|
139
|
+
|
|
140
|
+
@app.on_event("shutdown")
|
|
141
|
+
|
|
142
|
+
return app
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
async def main():
|
|
146
|
+
"""Main function to run the queue server."""
|
|
147
|
+
print("š Starting MCP Proxy Adapter Queue Server")
|
|
148
|
+
print("=" * 50)
|
|
149
|
+
|
|
150
|
+
# Create the app
|
|
151
|
+
app = create_queue_server_app()
|
|
152
|
+
|
|
153
|
+
# Run the server
|
|
154
|
+
config = uvicorn.Config(
|
|
155
|
+
app=app,
|
|
156
|
+
host="0.0.0.0",
|
|
157
|
+
port=8000,
|
|
158
|
+
log_level="info"
|
|
159
|
+
)
|
|
160
|
+
server = uvicorn.Server(config)
|
|
161
|
+
|
|
162
|
+
print("ā
MCP Queue Server started at http://localhost:8000")
|
|
163
|
+
print("š Example usage:")
|
|
164
|
+
print(" curl -X POST http://localhost:8000/api/jsonrpc \\")
|
|
165
|
+
print(" -H 'Content-Type: application/json' \\")
|
|
166
|
+
print(" -d '{\"jsonrpc\": \"2.0\", \"method\": \"queue_health\", \"params\": {}, \"id\": 1}'")
|
|
167
|
+
print()
|
|
168
|
+
|
|
169
|
+
await server.serve()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
asyncio.run(main())
|
|
@@ -444,35 +444,6 @@ class FullTestSuiteRunner:
|
|
|
444
444
|
# Process cleanup is handled by the test scripts themselves
|
|
445
445
|
print("ā
Cleanup completed")
|
|
446
446
|
|
|
447
|
-
def cleanup_directories(self) -> bool:
|
|
448
|
-
"""Clean up existing test directories before starting."""
|
|
449
|
-
self.print_info("Cleaning up existing test directories...")
|
|
450
|
-
|
|
451
|
-
try:
|
|
452
|
-
import shutil
|
|
453
|
-
|
|
454
|
-
# Directories to clean
|
|
455
|
-
dirs_to_clean = [self.configs_dir, self.certs_dir, self.keys_dir]
|
|
456
|
-
files_to_clean = [self.working_dir / "roles.json"]
|
|
457
|
-
|
|
458
|
-
# Remove directories
|
|
459
|
-
for dir_path in dirs_to_clean:
|
|
460
|
-
if dir_path.exists():
|
|
461
|
-
shutil.rmtree(dir_path)
|
|
462
|
-
print(f"šļø Removed directory: {dir_path}")
|
|
463
|
-
|
|
464
|
-
# Remove files
|
|
465
|
-
for file_path in files_to_clean:
|
|
466
|
-
if file_path.exists():
|
|
467
|
-
file_path.unlink()
|
|
468
|
-
print(f"šļø Removed file: {file_path}")
|
|
469
|
-
|
|
470
|
-
self.print_success("Directory cleanup completed")
|
|
471
|
-
return True
|
|
472
|
-
|
|
473
|
-
except Exception as e:
|
|
474
|
-
self.print_error(f"Failed to cleanup directories: {e}")
|
|
475
|
-
return False
|
|
476
447
|
|
|
477
448
|
def test_all_configurations(self) -> bool:
|
|
478
449
|
"""Test all server configurations including proxy registration."""
|
|
@@ -14,13 +14,9 @@ import asyncio
|
|
|
14
14
|
import signal
|
|
15
15
|
import sys
|
|
16
16
|
from typing import Dict, List, Optional
|
|
17
|
-
import json
|
|
18
|
-
from datetime import datetime, timedelta
|
|
19
17
|
|
|
20
18
|
from fastapi import FastAPI, HTTPException
|
|
21
19
|
from pydantic import BaseModel
|
|
22
|
-
from mcp_proxy_adapter.core.server_adapter import UnifiedServerRunner
|
|
23
|
-
|
|
24
20
|
|
|
25
21
|
# Simple in-memory storage for registered adapters
|
|
26
22
|
registered_adapters: Dict[str, Dict] = {}
|
|
@@ -42,68 +38,33 @@ class ProxyRouter:
|
|
|
42
38
|
|
|
43
39
|
def _setup_routes(self):
|
|
44
40
|
@self.app.post("/register")
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
adapter_id = registration_data["server_id"]
|
|
49
|
-
name = registration_data.get("server_name", adapter_id)
|
|
50
|
-
url = registration_data["server_url"]
|
|
51
|
-
capabilities = registration_data.get("capabilities", [])
|
|
52
|
-
metadata = {
|
|
53
|
-
"description": registration_data.get("description", ""),
|
|
54
|
-
"version": registration_data.get("version", ""),
|
|
55
|
-
"endpoints": registration_data.get("endpoints", {})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
registered_adapters[adapter_id] = {
|
|
59
|
-
"name": name,
|
|
60
|
-
"url": url,
|
|
61
|
-
"capabilities": capabilities,
|
|
62
|
-
"metadata": metadata,
|
|
63
|
-
"registered_at": datetime.now().isoformat(),
|
|
64
|
-
"last_heartbeat": datetime.now().isoformat(),
|
|
65
|
-
"status": "active",
|
|
66
|
-
}
|
|
67
|
-
print(f"ā
Registered adapter: {adapter_id} at {url}")
|
|
68
|
-
return {"status": "registered", "adapter_id": adapter_id, "success": True}
|
|
41
|
+
def register(adapter: AdapterRegistration): # type: ignore[name-defined]
|
|
42
|
+
registered_adapters[adapter.name] = adapter.dict()
|
|
43
|
+
return {"status": "ok", "registered": adapter.name}
|
|
69
44
|
|
|
70
45
|
@self.app.post("/unregister")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
46
|
+
def unregister(adapter: AdapterRegistration): # type: ignore[name-defined]
|
|
47
|
+
registered_adapters.pop(adapter.name, None)
|
|
48
|
+
return {"status": "ok", "unregistered": adapter.name}
|
|
49
|
+
|
|
50
|
+
@self.app.post("/proxy/heartbeat")
|
|
51
|
+
def heartbeat(adapter: AdapterRegistration): # type: ignore[name-defined]
|
|
52
|
+
if adapter.name in registered_adapters:
|
|
53
|
+
return {"status": "ok", "heartbeat": adapter.name}
|
|
54
|
+
raise HTTPException(status_code=404, detail="Adapter not registered")
|
|
79
55
|
|
|
80
56
|
@self.app.get("/proxy/list")
|
|
81
|
-
|
|
82
|
-
""
|
|
83
|
-
return {
|
|
84
|
-
"adapters": list(registered_adapters.values()),
|
|
85
|
-
"count": len(registered_adapters),
|
|
86
|
-
}
|
|
57
|
+
def list_registered():
|
|
58
|
+
return {"servers": list(registered_adapters.values())}
|
|
87
59
|
|
|
88
60
|
@self.app.get("/proxy/health")
|
|
89
|
-
|
|
90
|
-
"""
|
|
91
|
-
return {
|
|
92
|
-
"status": "healthy",
|
|
93
|
-
"timestamp": datetime.now().isoformat(),
|
|
94
|
-
"adapters_count": len(registered_adapters),
|
|
95
|
-
}
|
|
61
|
+
def proxy_health():
|
|
62
|
+
return {"status": "ok", "model": "mcp-local-proxy", "version": "1.0.0"}
|
|
96
63
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
registered_adapters[adapter_id][
|
|
102
|
-
"last_heartbeat"
|
|
103
|
-
] = datetime.now().isoformat()
|
|
104
|
-
return {"status": "ok", "adapter_id": adapter_id}
|
|
105
|
-
else:
|
|
106
|
-
raise HTTPException(status_code=404, detail="Adapter not found")
|
|
64
|
+
# Compatibility endpoint expected by test instructions
|
|
65
|
+
@self.app.get("/servers")
|
|
66
|
+
def servers_plain():
|
|
67
|
+
return list(registered_adapters.values())
|
|
107
68
|
|
|
108
69
|
|
|
109
70
|
def create_proxy_app() -> FastAPI:
|
|
@@ -135,8 +96,8 @@ def main() -> None:
|
|
|
135
96
|
app = create_proxy_app()
|
|
136
97
|
|
|
137
98
|
# Setup graceful shutdown
|
|
138
|
-
def signal_handler(signum, frame):
|
|
139
|
-
print("\nš
|
|
99
|
+
def signal_handler(signum, frame): # type: ignore[no-redef]
|
|
100
|
+
print("\nš Proxy server stopping...")
|
|
140
101
|
sys.exit(0)
|
|
141
102
|
|
|
142
103
|
signal.signal(signal.SIGINT, signal_handler)
|
|
@@ -153,16 +114,15 @@ def main() -> None:
|
|
|
153
114
|
print(" POST /proxy/heartbeat - Heartbeat from adapter")
|
|
154
115
|
print("ā” Press Ctrl+C to stop\n")
|
|
155
116
|
|
|
156
|
-
# Run server
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
)
|
|
117
|
+
# Run server with Hypercorn
|
|
118
|
+
from hypercorn.asyncio import serve
|
|
119
|
+
from hypercorn.config import Config
|
|
120
|
+
|
|
121
|
+
config = Config()
|
|
122
|
+
config.bind = [f"{args.host}:{args.port}"]
|
|
123
|
+
config.loglevel = args.log_level
|
|
124
|
+
|
|
125
|
+
asyncio.run(serve(app, config))
|
|
166
126
|
|
|
167
127
|
|
|
168
128
|
if __name__ == "__main__":
|
|
@@ -9,12 +9,10 @@ email: vasilyvz@gmail.com
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import json
|
|
11
11
|
import os
|
|
12
|
-
import signal
|
|
13
12
|
import subprocess
|
|
14
13
|
import sys
|
|
15
14
|
import time
|
|
16
15
|
from pathlib import Path
|
|
17
|
-
from typing import Dict, List, Optional, Tuple
|
|
18
16
|
|
|
19
17
|
# Add project root to path
|
|
20
18
|
project_root = Path(__file__).parent.parent.parent
|
|
@@ -404,31 +402,6 @@ class SecurityTestRunner:
|
|
|
404
402
|
|
|
405
403
|
return passed_tests == total_tests
|
|
406
404
|
|
|
407
|
-
def print_summary(self):
|
|
408
|
-
"""Print test summary."""
|
|
409
|
-
if not self.test_results:
|
|
410
|
-
print("š No test results to display")
|
|
411
|
-
return
|
|
412
|
-
|
|
413
|
-
total_tests = len(self.test_results)
|
|
414
|
-
passed_tests = sum(1 for result in self.test_results if result.success)
|
|
415
|
-
|
|
416
|
-
print("\n" + "=" * 50)
|
|
417
|
-
print("š TEST SUMMARY")
|
|
418
|
-
print("=" * 50)
|
|
419
|
-
print(f"Total tests: {total_tests}")
|
|
420
|
-
print(f"Passed: {passed_tests}")
|
|
421
|
-
print(f"Failed: {total_tests - passed_tests}")
|
|
422
|
-
print(f"Success rate: {(passed_tests/total_tests)*100:.1f}%")
|
|
423
|
-
|
|
424
|
-
if total_tests - passed_tests > 0:
|
|
425
|
-
print(f"\nš DETAILED RESULTS")
|
|
426
|
-
print("-" * 30)
|
|
427
|
-
for result in self.test_results:
|
|
428
|
-
status = "ā
PASS" if result.success else "ā FAIL"
|
|
429
|
-
print(f"{status} {result.test_name}")
|
|
430
|
-
if not result.success and result.error_message:
|
|
431
|
-
print(f" Error: {result.error_message}")
|
|
432
405
|
|
|
433
406
|
|
|
434
407
|
async def main():
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Vasiliy Zdanovskiy
|
|
3
|
+
email: vasilyvz@gmail.com
|
|
4
|
+
|
|
5
|
+
Security test package for MCP Proxy Adapter.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .test_result import TestResult
|
|
9
|
+
from .ssl_context_manager import SSLContextManager
|
|
10
|
+
from .auth_manager import AuthManager
|
|
11
|
+
from .test_client import SecurityTestClient
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"TestResult",
|
|
15
|
+
"SSLContextManager",
|
|
16
|
+
"AuthManager",
|
|
17
|
+
"SecurityTestClient",
|
|
18
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Vasiliy Zdanovskiy
|
|
3
|
+
email: vasilyvz@gmail.com
|
|
4
|
+
|
|
5
|
+
SSL context manager for security testing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import ssl
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SSLContextManager:
|
|
15
|
+
"""Manager for SSL contexts in security testing."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, project_root: Optional[Path] = None):
|
|
18
|
+
"""
|
|
19
|
+
Initialize SSL context manager.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
project_root: Root directory of the project (optional)
|
|
23
|
+
"""
|
|
24
|
+
if project_root is None:
|
|
25
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
26
|
+
self.project_root = project_root
|
|
27
|
+
|
|
28
|
+
|