mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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 +47 -0
- mcp_proxy_adapter/__main__.py +13 -0
- mcp_proxy_adapter/api/__init__.py +0 -0
- mcp_proxy_adapter/api/app.py +66 -0
- mcp_proxy_adapter/api/core/__init__.py +18 -0
- mcp_proxy_adapter/api/core/app_factory.py +400 -0
- mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
- mcp_proxy_adapter/api/core/registration_context.py +356 -0
- mcp_proxy_adapter/api/core/registration_manager.py +307 -0
- mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
- mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
- mcp_proxy_adapter/api/handlers.py +181 -0
- mcp_proxy_adapter/api/middleware/__init__.py +21 -0
- mcp_proxy_adapter/api/middleware/base.py +54 -0
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
- mcp_proxy_adapter/api/middleware/factory.py +147 -0
- mcp_proxy_adapter/api/middleware/logging.py +31 -0
- mcp_proxy_adapter/api/middleware/performance.py +51 -0
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
- 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 +270 -0
- mcp_proxy_adapter/api/tool_integration.py +131 -0
- mcp_proxy_adapter/api/tools.py +163 -0
- 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 +105 -0
- mcp_proxy_adapter/cli/commands/config_validate.py +94 -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 +132 -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 +338 -0
- mcp_proxy_adapter/cli/validators.py +231 -0
- mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
- mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
- mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
- mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
- mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
- mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
- mcp_proxy_adapter/client/proxy.py +123 -0
- mcp_proxy_adapter/commands/__init__.py +66 -0
- mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
- mcp_proxy_adapter/commands/base.py +389 -0
- mcp_proxy_adapter/commands/builtin_commands.py +30 -0
- 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 +97 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
- mcp_proxy_adapter/commands/command_registry.py +298 -0
- mcp_proxy_adapter/commands/config_command.py +102 -0
- mcp_proxy_adapter/commands/dependency_container.py +40 -0
- mcp_proxy_adapter/commands/dependency_manager.py +143 -0
- mcp_proxy_adapter/commands/echo_command.py +48 -0
- mcp_proxy_adapter/commands/health_command.py +142 -0
- mcp_proxy_adapter/commands/help_command.py +175 -0
- mcp_proxy_adapter/commands/hooks.py +172 -0
- mcp_proxy_adapter/commands/key_management_command.py +484 -0
- mcp_proxy_adapter/commands/load_command.py +123 -0
- mcp_proxy_adapter/commands/plugins_command.py +246 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
- mcp_proxy_adapter/commands/queue_commands.py +750 -0
- mcp_proxy_adapter/commands/registration_status_command.py +76 -0
- 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 +136 -0
- mcp_proxy_adapter/commands/result.py +157 -0
- mcp_proxy_adapter/commands/role_test_command.py +99 -0
- mcp_proxy_adapter/commands/roles_management_command.py +502 -0
- mcp_proxy_adapter/commands/security_command.py +472 -0
- mcp_proxy_adapter/commands/settings_command.py +113 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
- mcp_proxy_adapter/commands/token_management_command.py +500 -0
- mcp_proxy_adapter/commands/transport_management_command.py +129 -0
- mcp_proxy_adapter/commands/unload_command.py +92 -0
- mcp_proxy_adapter/config.py +32 -0
- mcp_proxy_adapter/core/__init__.py +8 -0
- mcp_proxy_adapter/core/app_factory.py +560 -0
- mcp_proxy_adapter/core/app_runner.py +318 -0
- mcp_proxy_adapter/core/auth_validator.py +508 -0
- mcp_proxy_adapter/core/certificate/__init__.py +20 -0
- mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
- mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
- mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
- mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
- mcp_proxy_adapter/core/certificate_utils.py +249 -0
- mcp_proxy_adapter/core/client.py +608 -0
- mcp_proxy_adapter/core/client_manager.py +271 -0
- mcp_proxy_adapter/core/client_security.py +411 -0
- mcp_proxy_adapter/core/config/__init__.py +18 -0
- mcp_proxy_adapter/core/config/config.py +237 -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 +204 -0
- mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
- mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
- mcp_proxy_adapter/core/config_converter.py +252 -0
- mcp_proxy_adapter/core/config_validator.py +211 -0
- mcp_proxy_adapter/core/crl_utils.py +362 -0
- mcp_proxy_adapter/core/errors.py +276 -0
- mcp_proxy_adapter/core/job_manager.py +54 -0
- mcp_proxy_adapter/core/logging.py +250 -0
- mcp_proxy_adapter/core/mtls_asgi.py +140 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/mtls_proxy.py +229 -0
- mcp_proxy_adapter/core/mtls_server.py +154 -0
- mcp_proxy_adapter/core/protocol_manager.py +232 -0
- mcp_proxy_adapter/core/proxy/__init__.py +19 -0
- mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
- mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
- mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
- mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
- mcp_proxy_adapter/core/proxy_client.py +184 -0
- mcp_proxy_adapter/core/proxy_registration.py +80 -0
- mcp_proxy_adapter/core/role_utils.py +103 -0
- mcp_proxy_adapter/core/security_adapter.py +343 -0
- mcp_proxy_adapter/core/security_factory.py +96 -0
- mcp_proxy_adapter/core/security_integration.py +342 -0
- mcp_proxy_adapter/core/server_adapter.py +251 -0
- mcp_proxy_adapter/core/server_engine.py +217 -0
- mcp_proxy_adapter/core/settings.py +260 -0
- mcp_proxy_adapter/core/signal_handler.py +107 -0
- mcp_proxy_adapter/core/ssl_utils.py +161 -0
- mcp_proxy_adapter/core/transport_manager.py +153 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
- mcp_proxy_adapter/core/utils.py +101 -0
- mcp_proxy_adapter/core/validation/__init__.py +21 -0
- mcp_proxy_adapter/core/validation/config_validator.py +219 -0
- mcp_proxy_adapter/core/validation/file_validator.py +131 -0
- mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
- mcp_proxy_adapter/core/validation/security_validator.py +140 -0
- mcp_proxy_adapter/core/validation/validation_result.py +27 -0
- mcp_proxy_adapter/custom_openapi.py +58 -0
- mcp_proxy_adapter/examples/__init__.py +16 -0
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
- mcp_proxy_adapter/examples/check_config.py +413 -0
- mcp_proxy_adapter/examples/client_usage_example.py +164 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/config_builder.py +234 -0
- mcp_proxy_adapter/examples/config_cli.py +282 -0
- mcp_proxy_adapter/examples/create_test_configs.py +174 -0
- mcp_proxy_adapter/examples/debug_request_state.py +130 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
- mcp_proxy_adapter/examples/demo_client.py +287 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
- mcp_proxy_adapter/examples/full_application/main.py +311 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
- mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
- mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
- mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
- mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
- mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
- mcp_proxy_adapter/examples/generate_config.py +502 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
- 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 +208 -0
- mcp_proxy_adapter/examples/run_example.py +77 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
- 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 +72 -0
- 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 +235 -0
- mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
- mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
- mcp_proxy_adapter/examples/test_config.py +205 -0
- mcp_proxy_adapter/examples/test_config_builder.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +308 -0
- mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
- mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
- mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
- mcp_proxy_adapter/examples/universal_client.py +674 -0
- mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
- mcp_proxy_adapter/integrations/__init__.py +25 -0
- mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
- mcp_proxy_adapter/main.py +311 -0
- mcp_proxy_adapter/openapi.py +375 -0
- mcp_proxy_adapter/schemas/base_schema.json +114 -0
- mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
- mcp_proxy_adapter/schemas/roles.json +37 -0
- mcp_proxy_adapter/schemas/roles_schema.json +162 -0
- mcp_proxy_adapter/version.py +5 -0
- mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
- mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
- {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
- mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
- mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
- adapters/__init__.py +0 -16
- analyzers/__init__.py +0 -14
- analyzers/docstring_analyzer.py +0 -199
- analyzers/type_analyzer.py +0 -151
- cli/__init__.py +0 -12
- cli/__main__.py +0 -79
- cli/command_runner.py +0 -233
- dispatchers/__init__.py +0 -14
- dispatchers/base_dispatcher.py +0 -85
- dispatchers/json_rpc_dispatcher.py +0 -198
- generators/__init__.py +0 -14
- generators/endpoint_generator.py +0 -172
- generators/openapi_generator.py +0 -254
- generators/rest_api_generator.py +0 -207
- mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
- mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
- mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
- mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
- openapi_schema/__init__.py +0 -38
- openapi_schema/command_registry.py +0 -312
- openapi_schema/rest_schema.py +0 -510
- openapi_schema/rpc_generator.py +0 -307
- openapi_schema/rpc_schema.py +0 -416
- validators/__init__.py +0 -14
- validators/base_validator.py +0 -23
- validators/docstring_validator.py +0 -75
- validators/metadata_validator.py +0 -76
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Queue Manager Integration for MCP Proxy Adapter.
|
|
3
|
+
|
|
4
|
+
This module provides integration between mcp_proxy_adapter and queuemgr
|
|
5
|
+
for managing background jobs and task queues.
|
|
6
|
+
|
|
7
|
+
Author: Vasiliy Zdanovskiy
|
|
8
|
+
email: vasilyvz@gmail.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from contextlib import asynccontextmanager
|
|
14
|
+
from typing import Optional, Dict, Any, Type, List
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
from queuemgr.jobs.base import QueueJobBase as QueuemgrJobBase
|
|
18
|
+
from queuemgr.core.types import JobStatus as QueuemgrJobStatus
|
|
19
|
+
from queuemgr.exceptions import (
|
|
20
|
+
QueueManagerError,
|
|
21
|
+
JobNotFoundError,
|
|
22
|
+
JobAlreadyExistsError,
|
|
23
|
+
InvalidJobStateError,
|
|
24
|
+
JobExecutionError,
|
|
25
|
+
ProcessControlError,
|
|
26
|
+
ValidationError as QueuemgrValidationError,
|
|
27
|
+
TimeoutError as QueuemgrTimeoutError,
|
|
28
|
+
)
|
|
29
|
+
QUEUEMGR_AVAILABLE = True
|
|
30
|
+
except ImportError as e:
|
|
31
|
+
# Fallback for when queuemgr is not available
|
|
32
|
+
QUEUEMGR_AVAILABLE = False
|
|
33
|
+
QueuemgrJobBase = object
|
|
34
|
+
QueuemgrJobStatus = str
|
|
35
|
+
QueueManagerError = Exception
|
|
36
|
+
JobNotFoundError = Exception
|
|
37
|
+
JobAlreadyExistsError = Exception
|
|
38
|
+
InvalidJobStateError = Exception
|
|
39
|
+
JobExecutionError = Exception
|
|
40
|
+
ProcessControlError = Exception
|
|
41
|
+
QueuemgrValidationError = Exception
|
|
42
|
+
QueuemgrTimeoutError = Exception
|
|
43
|
+
|
|
44
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
|
45
|
+
from mcp_proxy_adapter.core.errors import MicroserviceError, ValidationError
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class QueueJobStatus:
|
|
49
|
+
"""Job status constants for queue integration."""
|
|
50
|
+
|
|
51
|
+
PENDING = "pending"
|
|
52
|
+
RUNNING = "running"
|
|
53
|
+
COMPLETED = "completed"
|
|
54
|
+
FAILED = "failed"
|
|
55
|
+
STOPPED = "stopped"
|
|
56
|
+
DELETED = "deleted"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class QueueJobResult:
|
|
60
|
+
"""Result of a queue job execution."""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
job_id: str,
|
|
65
|
+
status: str,
|
|
66
|
+
result: Optional[Dict[str, Any]] = None,
|
|
67
|
+
error: Optional[str] = None,
|
|
68
|
+
progress: int = 0,
|
|
69
|
+
description: str = "",
|
|
70
|
+
):
|
|
71
|
+
"""
|
|
72
|
+
Initialize queue job result.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
job_id: Unique job identifier
|
|
76
|
+
status: Job status
|
|
77
|
+
result: Job result data
|
|
78
|
+
error: Error message if failed
|
|
79
|
+
progress: Progress percentage (0-100)
|
|
80
|
+
description: Job description
|
|
81
|
+
"""
|
|
82
|
+
self.job_id = job_id
|
|
83
|
+
self.status = status
|
|
84
|
+
self.result = result or {}
|
|
85
|
+
self.error = error
|
|
86
|
+
self.progress = max(0, min(100, progress))
|
|
87
|
+
self.description = description
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class QueueJobError(Exception):
|
|
91
|
+
"""Exception raised for queue job errors."""
|
|
92
|
+
|
|
93
|
+
def __init__(self, job_id: str, message: str, original_error: Optional[Exception] = None):
|
|
94
|
+
"""
|
|
95
|
+
Initialize queue job error.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
job_id: Job identifier that failed
|
|
99
|
+
message: Error message
|
|
100
|
+
original_error: Original exception that caused the error
|
|
101
|
+
"""
|
|
102
|
+
super().__init__(f"Job {job_id}: {message}")
|
|
103
|
+
self.job_id = job_id
|
|
104
|
+
self.original_error = original_error
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class QueueJobBase(QueuemgrJobBase):
|
|
108
|
+
"""
|
|
109
|
+
Base class for MCP Proxy Adapter queue jobs.
|
|
110
|
+
|
|
111
|
+
This class extends the queuemgr QueueJobBase to provide
|
|
112
|
+
MCP-specific functionality and error handling.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(self, job_id: str, params: Dict[str, Any]):
|
|
116
|
+
"""
|
|
117
|
+
Initialize MCP queue job.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
job_id: Unique job identifier
|
|
121
|
+
params: Job parameters
|
|
122
|
+
"""
|
|
123
|
+
if not QUEUEMGR_AVAILABLE:
|
|
124
|
+
raise MicroserviceError(
|
|
125
|
+
"queuemgr is not available. Install it with: pip install queuemgr>=1.0.5"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
super().__init__(job_id, params)
|
|
129
|
+
self.logger = get_global_logger()
|
|
130
|
+
self.mcp_params = params
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class QueueManagerIntegration:
|
|
136
|
+
"""
|
|
137
|
+
Queue Manager Integration for MCP Proxy Adapter.
|
|
138
|
+
|
|
139
|
+
This class provides a high-level interface for managing
|
|
140
|
+
background jobs using the queuemgr system.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
def __init__(
|
|
144
|
+
self,
|
|
145
|
+
registry_path: str = "mcp_queue_registry.jsonl",
|
|
146
|
+
shutdown_timeout: float = 30.0,
|
|
147
|
+
max_concurrent_jobs: int = 10,
|
|
148
|
+
):
|
|
149
|
+
"""
|
|
150
|
+
Initialize queue manager integration.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
registry_path: Path to the queue registry file
|
|
154
|
+
shutdown_timeout: Timeout for graceful shutdown
|
|
155
|
+
max_concurrent_jobs: Maximum number of concurrent jobs
|
|
156
|
+
"""
|
|
157
|
+
if not QUEUEMGR_AVAILABLE:
|
|
158
|
+
raise MicroserviceError(
|
|
159
|
+
"queuemgr is not available. Install it with: pip install queuemgr>=1.0.5"
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
self.registry_path = registry_path
|
|
163
|
+
self.shutdown_timeout = shutdown_timeout
|
|
164
|
+
self.max_concurrent_jobs = max_concurrent_jobs
|
|
165
|
+
self.logger = get_global_logger()
|
|
166
|
+
self._queue_system: Optional[AsyncQueueSystem] = None
|
|
167
|
+
self._is_running = False
|
|
168
|
+
|
|
169
|
+
async def start(self) -> None:
|
|
170
|
+
"""Start the queue manager integration."""
|
|
171
|
+
if self._is_running:
|
|
172
|
+
self.logger.warning("Queue manager integration is already running")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
self._queue_system = AsyncQueueSystem(
|
|
177
|
+
registry_path=self.registry_path,
|
|
178
|
+
shutdown_timeout=self.shutdown_timeout,
|
|
179
|
+
)
|
|
180
|
+
await self._queue_system.start()
|
|
181
|
+
self._is_running = True
|
|
182
|
+
self.logger.info("✅ Queue manager integration started")
|
|
183
|
+
|
|
184
|
+
except Exception as e:
|
|
185
|
+
self.logger.error(f"❌ Failed to start queue manager integration: {e}")
|
|
186
|
+
raise MicroserviceError(f"Failed to start queue manager: {str(e)}")
|
|
187
|
+
|
|
188
|
+
async def stop(self) -> None:
|
|
189
|
+
"""Stop the queue manager integration."""
|
|
190
|
+
if not self._is_running:
|
|
191
|
+
self.logger.warning("Queue manager integration is not running")
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
if self._queue_system:
|
|
196
|
+
await self._queue_system.stop()
|
|
197
|
+
self._is_running = False
|
|
198
|
+
self.logger.info("✅ Queue manager integration stopped")
|
|
199
|
+
|
|
200
|
+
except Exception as e:
|
|
201
|
+
self.logger.error(f"❌ Failed to stop queue manager integration: {e}")
|
|
202
|
+
raise MicroserviceError(f"Failed to stop queue manager: {str(e)}")
|
|
203
|
+
|
|
204
|
+
def is_running(self) -> bool:
|
|
205
|
+
"""Check if the queue manager integration is running."""
|
|
206
|
+
return self._is_running and self._queue_system is not None
|
|
207
|
+
|
|
208
|
+
async def add_job(
|
|
209
|
+
self,
|
|
210
|
+
job_class: Type[QueueJobBase],
|
|
211
|
+
job_id: str,
|
|
212
|
+
params: Dict[str, Any],
|
|
213
|
+
) -> QueueJobResult:
|
|
214
|
+
"""
|
|
215
|
+
Add a job to the queue.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
job_class: Job class to instantiate
|
|
219
|
+
job_id: Unique job identifier
|
|
220
|
+
params: Job parameters
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
QueueJobResult with job information
|
|
224
|
+
|
|
225
|
+
Raises:
|
|
226
|
+
QueueJobError: If job cannot be added
|
|
227
|
+
"""
|
|
228
|
+
if not self.is_running():
|
|
229
|
+
raise QueueJobError(job_id, "Queue manager is not running")
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
await self._queue_system.add_job(job_class, job_id, params)
|
|
233
|
+
return QueueJobResult(
|
|
234
|
+
job_id=job_id,
|
|
235
|
+
status=QueueJobStatus.PENDING,
|
|
236
|
+
description="Job added to queue"
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
except JobAlreadyExistsError as e:
|
|
240
|
+
raise QueueJobError(job_id, f"Job already exists: {str(e)}", e)
|
|
241
|
+
except QueuemgrValidationError as e:
|
|
242
|
+
raise QueueJobError(job_id, f"Invalid job parameters: {str(e)}", e)
|
|
243
|
+
except Exception as e:
|
|
244
|
+
raise QueueJobError(job_id, f"Failed to add job: {str(e)}", e)
|
|
245
|
+
|
|
246
|
+
async def start_job(self, job_id: str) -> QueueJobResult:
|
|
247
|
+
"""
|
|
248
|
+
Start a job in the queue.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
job_id: Job identifier to start
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
QueueJobResult with job status
|
|
255
|
+
|
|
256
|
+
Raises:
|
|
257
|
+
QueueJobError: If job cannot be started
|
|
258
|
+
"""
|
|
259
|
+
if not self.is_running():
|
|
260
|
+
raise QueueJobError(job_id, "Queue manager is not running")
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
await self._queue_system.start_job(job_id)
|
|
264
|
+
return QueueJobResult(
|
|
265
|
+
job_id=job_id,
|
|
266
|
+
status=QueueJobStatus.RUNNING,
|
|
267
|
+
description="Job started"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
except JobNotFoundError as e:
|
|
271
|
+
raise QueueJobError(job_id, f"Job not found: {str(e)}", e)
|
|
272
|
+
except InvalidJobStateError as e:
|
|
273
|
+
raise QueueJobError(job_id, f"Invalid job state: {str(e)}", e)
|
|
274
|
+
except Exception as e:
|
|
275
|
+
raise QueueJobError(job_id, f"Failed to start job: {str(e)}", e)
|
|
276
|
+
|
|
277
|
+
async def stop_job(self, job_id: str) -> QueueJobResult:
|
|
278
|
+
"""
|
|
279
|
+
Stop a job in the queue.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
job_id: Job identifier to stop
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
QueueJobResult with job status
|
|
286
|
+
|
|
287
|
+
Raises:
|
|
288
|
+
QueueJobError: If job cannot be stopped
|
|
289
|
+
"""
|
|
290
|
+
if not self.is_running():
|
|
291
|
+
raise QueueJobError(job_id, "Queue manager is not running")
|
|
292
|
+
|
|
293
|
+
try:
|
|
294
|
+
await self._queue_system.stop_job(job_id)
|
|
295
|
+
return QueueJobResult(
|
|
296
|
+
job_id=job_id,
|
|
297
|
+
status=QueueJobStatus.STOPPED,
|
|
298
|
+
description="Job stopped"
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
except JobNotFoundError as e:
|
|
302
|
+
raise QueueJobError(job_id, f"Job not found: {str(e)}", e)
|
|
303
|
+
except ProcessControlError as e:
|
|
304
|
+
raise QueueJobError(job_id, f"Process control error: {str(e)}", e)
|
|
305
|
+
except Exception as e:
|
|
306
|
+
raise QueueJobError(job_id, f"Failed to stop job: {str(e)}", e)
|
|
307
|
+
|
|
308
|
+
async def delete_job(self, job_id: str) -> QueueJobResult:
|
|
309
|
+
"""
|
|
310
|
+
Delete a job from the queue.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
job_id: Job identifier to delete
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
QueueJobResult with job status
|
|
317
|
+
|
|
318
|
+
Raises:
|
|
319
|
+
QueueJobError: If job cannot be deleted
|
|
320
|
+
"""
|
|
321
|
+
if not self.is_running():
|
|
322
|
+
raise QueueJobError(job_id, "Queue manager is not running")
|
|
323
|
+
|
|
324
|
+
try:
|
|
325
|
+
await self._queue_system.delete_job(job_id)
|
|
326
|
+
return QueueJobResult(
|
|
327
|
+
job_id=job_id,
|
|
328
|
+
status=QueueJobStatus.DELETED,
|
|
329
|
+
description="Job deleted"
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
except JobNotFoundError as e:
|
|
333
|
+
raise QueueJobError(job_id, f"Job not found: {str(e)}", e)
|
|
334
|
+
except Exception as e:
|
|
335
|
+
raise QueueJobError(job_id, f"Failed to delete job: {str(e)}", e)
|
|
336
|
+
|
|
337
|
+
async def get_job_status(self, job_id: str) -> QueueJobResult:
|
|
338
|
+
"""
|
|
339
|
+
Get the status of a job.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
job_id: Job identifier to get status for
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
QueueJobResult with job status and information
|
|
346
|
+
|
|
347
|
+
Raises:
|
|
348
|
+
QueueJobError: If job status cannot be retrieved
|
|
349
|
+
"""
|
|
350
|
+
if not self.is_running():
|
|
351
|
+
raise QueueJobError(job_id, "Queue manager is not running")
|
|
352
|
+
|
|
353
|
+
try:
|
|
354
|
+
status_data = await self._queue_system.get_job_status(job_id)
|
|
355
|
+
|
|
356
|
+
# Convert queuemgr status to MCP status
|
|
357
|
+
mcp_status = self._convert_status(status_data.get("status", "unknown"))
|
|
358
|
+
|
|
359
|
+
return QueueJobResult(
|
|
360
|
+
job_id=job_id,
|
|
361
|
+
status=mcp_status,
|
|
362
|
+
result=status_data.get("result", {}),
|
|
363
|
+
error=status_data.get("error"),
|
|
364
|
+
progress=status_data.get("progress", 0),
|
|
365
|
+
description=status_data.get("description", ""),
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
except JobNotFoundError as e:
|
|
369
|
+
raise QueueJobError(job_id, f"Job not found: {str(e)}", e)
|
|
370
|
+
except Exception as e:
|
|
371
|
+
raise QueueJobError(job_id, f"Failed to get job status: {str(e)}", e)
|
|
372
|
+
|
|
373
|
+
async def list_jobs(self) -> List[QueueJobResult]:
|
|
374
|
+
"""
|
|
375
|
+
List all jobs in the queue.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
List of QueueJobResult objects
|
|
379
|
+
|
|
380
|
+
Raises:
|
|
381
|
+
QueueJobError: If jobs cannot be listed
|
|
382
|
+
"""
|
|
383
|
+
if not self.is_running():
|
|
384
|
+
raise QueueJobError("", "Queue manager is not running")
|
|
385
|
+
|
|
386
|
+
try:
|
|
387
|
+
jobs_data = await self._queue_system.list_jobs()
|
|
388
|
+
|
|
389
|
+
results = []
|
|
390
|
+
for job_data in jobs_data:
|
|
391
|
+
mcp_status = self._convert_status(job_data.get("status", "unknown"))
|
|
392
|
+
results.append(QueueJobResult(
|
|
393
|
+
job_id=job_data.get("job_id", "unknown"),
|
|
394
|
+
status=mcp_status,
|
|
395
|
+
result=job_data.get("result", {}),
|
|
396
|
+
error=job_data.get("error"),
|
|
397
|
+
progress=job_data.get("progress", 0),
|
|
398
|
+
description=job_data.get("description", ""),
|
|
399
|
+
))
|
|
400
|
+
|
|
401
|
+
return results
|
|
402
|
+
|
|
403
|
+
except Exception as e:
|
|
404
|
+
raise QueueJobError("", f"Failed to list jobs: {str(e)}", e)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def _convert_status(self, queuemgr_status: str) -> str:
|
|
408
|
+
"""
|
|
409
|
+
Convert queuemgr status to MCP status.
|
|
410
|
+
|
|
411
|
+
Args:
|
|
412
|
+
queuemgr_status: Status from queuemgr
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
MCP-compatible status
|
|
416
|
+
"""
|
|
417
|
+
status_mapping = {
|
|
418
|
+
"pending": QueueJobStatus.PENDING,
|
|
419
|
+
"running": QueueJobStatus.RUNNING,
|
|
420
|
+
"completed": QueueJobStatus.COMPLETED,
|
|
421
|
+
"failed": QueueJobStatus.FAILED,
|
|
422
|
+
"stopped": QueueJobStatus.STOPPED,
|
|
423
|
+
"deleted": QueueJobStatus.DELETED,
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return status_mapping.get(queuemgr_status.lower(), QueueJobStatus.PENDING)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
# Global queue manager instance
|
|
430
|
+
_global_queue_manager: Optional[QueueManagerIntegration] = None
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
async def get_global_queue_manager() -> QueueManagerIntegration:
|
|
434
|
+
"""
|
|
435
|
+
Get global queue manager instance, initializing it if necessary.
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
QueueManagerIntegration instance
|
|
439
|
+
|
|
440
|
+
Raises:
|
|
441
|
+
QueueJobError: If queue manager cannot be initialized
|
|
442
|
+
"""
|
|
443
|
+
global _global_queue_manager
|
|
444
|
+
|
|
445
|
+
if _global_queue_manager is None:
|
|
446
|
+
# Initialize with default configuration
|
|
447
|
+
config = {
|
|
448
|
+
"queue_manager": {
|
|
449
|
+
"backend": "memory", # Default to in-memory for simplicity
|
|
450
|
+
"max_workers": 4,
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
_global_queue_manager = QueueManagerIntegration(config)
|
|
454
|
+
await _global_queue_manager.initialize()
|
|
455
|
+
|
|
456
|
+
return _global_queue_manager
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|