mcp-proxy-adapter 6.9.27__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.

Files changed (212) hide show
  1. mcp_proxy_adapter/__init__.py +10 -0
  2. mcp_proxy_adapter/__main__.py +8 -21
  3. mcp_proxy_adapter/api/app.py +10 -913
  4. mcp_proxy_adapter/api/core/__init__.py +18 -0
  5. mcp_proxy_adapter/api/core/app_factory.py +243 -0
  6. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  7. mcp_proxy_adapter/api/core/registration_manager.py +166 -0
  8. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  9. mcp_proxy_adapter/api/handlers.py +78 -199
  10. mcp_proxy_adapter/api/middleware/__init__.py +1 -44
  11. mcp_proxy_adapter/api/middleware/base.py +0 -42
  12. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +0 -85
  13. mcp_proxy_adapter/api/middleware/error_handling.py +1 -127
  14. mcp_proxy_adapter/api/middleware/factory.py +0 -94
  15. mcp_proxy_adapter/api/middleware/logging.py +0 -112
  16. mcp_proxy_adapter/api/middleware/performance.py +0 -35
  17. mcp_proxy_adapter/api/middleware/protocol_middleware.py +2 -98
  18. mcp_proxy_adapter/api/middleware/transport_middleware.py +0 -37
  19. mcp_proxy_adapter/api/middleware/unified_security.py +10 -10
  20. mcp_proxy_adapter/api/middleware/user_info_middleware.py +0 -118
  21. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  22. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  23. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  24. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  25. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  26. mcp_proxy_adapter/api/schemas.py +0 -61
  27. mcp_proxy_adapter/api/tool_integration.py +0 -117
  28. mcp_proxy_adapter/api/tools.py +0 -46
  29. mcp_proxy_adapter/cli/__init__.py +12 -0
  30. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  31. mcp_proxy_adapter/cli/commands/client.py +100 -0
  32. mcp_proxy_adapter/cli/commands/config_generate.py +21 -0
  33. mcp_proxy_adapter/cli/commands/config_validate.py +36 -0
  34. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  35. mcp_proxy_adapter/cli/commands/server.py +174 -0
  36. mcp_proxy_adapter/cli/commands/sets.py +128 -0
  37. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  38. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  39. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  40. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  41. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  42. mcp_proxy_adapter/cli/main.py +63 -0
  43. mcp_proxy_adapter/cli/parser.py +324 -0
  44. mcp_proxy_adapter/cli/validators.py +231 -0
  45. mcp_proxy_adapter/client/jsonrpc_client.py +406 -0
  46. mcp_proxy_adapter/client/proxy.py +45 -0
  47. mcp_proxy_adapter/commands/__init__.py +44 -28
  48. mcp_proxy_adapter/commands/auth_validation_command.py +7 -344
  49. mcp_proxy_adapter/commands/base.py +19 -43
  50. mcp_proxy_adapter/commands/builtin_commands.py +0 -75
  51. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  52. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  53. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  54. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  55. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  56. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  57. mcp_proxy_adapter/commands/catalog_manager.py +58 -928
  58. mcp_proxy_adapter/commands/cert_monitor_command.py +0 -88
  59. mcp_proxy_adapter/commands/certificate_management_command.py +0 -45
  60. mcp_proxy_adapter/commands/command_registry.py +172 -904
  61. mcp_proxy_adapter/commands/config_command.py +0 -28
  62. mcp_proxy_adapter/commands/dependency_container.py +1 -70
  63. mcp_proxy_adapter/commands/dependency_manager.py +0 -128
  64. mcp_proxy_adapter/commands/echo_command.py +0 -34
  65. mcp_proxy_adapter/commands/health_command.py +0 -3
  66. mcp_proxy_adapter/commands/help_command.py +0 -159
  67. mcp_proxy_adapter/commands/hooks.py +0 -137
  68. mcp_proxy_adapter/commands/key_management_command.py +0 -25
  69. mcp_proxy_adapter/commands/load_command.py +7 -78
  70. mcp_proxy_adapter/commands/plugins_command.py +0 -16
  71. mcp_proxy_adapter/commands/protocol_management_command.py +0 -28
  72. mcp_proxy_adapter/commands/proxy_registration_command.py +0 -88
  73. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  74. mcp_proxy_adapter/commands/registration_status_command.py +0 -43
  75. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  76. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  77. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  78. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  79. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  80. mcp_proxy_adapter/commands/reload_command.py +0 -80
  81. mcp_proxy_adapter/commands/result.py +25 -77
  82. mcp_proxy_adapter/commands/role_test_command.py +0 -44
  83. mcp_proxy_adapter/commands/roles_management_command.py +0 -199
  84. mcp_proxy_adapter/commands/security_command.py +0 -30
  85. mcp_proxy_adapter/commands/settings_command.py +0 -68
  86. mcp_proxy_adapter/commands/ssl_setup_command.py +0 -42
  87. mcp_proxy_adapter/commands/token_management_command.py +0 -1
  88. mcp_proxy_adapter/commands/transport_management_command.py +0 -20
  89. mcp_proxy_adapter/commands/unload_command.py +0 -71
  90. mcp_proxy_adapter/config.py +15 -626
  91. mcp_proxy_adapter/core/__init__.py +5 -39
  92. mcp_proxy_adapter/core/app_factory.py +14 -36
  93. mcp_proxy_adapter/core/app_runner.py +0 -27
  94. mcp_proxy_adapter/core/auth_validator.py +1 -93
  95. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  96. mcp_proxy_adapter/core/certificate/certificate_creator.py +371 -0
  97. mcp_proxy_adapter/core/certificate/certificate_extractor.py +183 -0
  98. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  99. mcp_proxy_adapter/core/certificate/certificate_validator.py +110 -0
  100. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +70 -0
  101. mcp_proxy_adapter/core/certificate_utils.py +64 -903
  102. mcp_proxy_adapter/core/client.py +0 -6
  103. mcp_proxy_adapter/core/client_manager.py +0 -19
  104. mcp_proxy_adapter/core/client_security.py +0 -2
  105. mcp_proxy_adapter/core/config/__init__.py +18 -0
  106. mcp_proxy_adapter/core/config/config.py +195 -0
  107. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  108. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  109. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  110. mcp_proxy_adapter/core/config/simple_config.py +112 -0
  111. mcp_proxy_adapter/core/config/simple_config_generator.py +50 -0
  112. mcp_proxy_adapter/core/config/simple_config_validator.py +96 -0
  113. mcp_proxy_adapter/core/config_converter.py +0 -186
  114. mcp_proxy_adapter/core/config_validator.py +96 -1238
  115. mcp_proxy_adapter/core/errors.py +7 -42
  116. mcp_proxy_adapter/core/job_manager.py +54 -0
  117. mcp_proxy_adapter/core/logging.py +2 -22
  118. mcp_proxy_adapter/core/mtls_asgi.py +0 -20
  119. mcp_proxy_adapter/core/mtls_asgi_app.py +0 -12
  120. mcp_proxy_adapter/core/mtls_proxy.py +0 -80
  121. mcp_proxy_adapter/core/mtls_server.py +3 -173
  122. mcp_proxy_adapter/core/protocol_manager.py +1 -191
  123. mcp_proxy_adapter/core/proxy/__init__.py +22 -0
  124. mcp_proxy_adapter/core/proxy/auth_manager.py +27 -0
  125. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +137 -0
  126. mcp_proxy_adapter/core/proxy/registration_client.py +60 -0
  127. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  128. mcp_proxy_adapter/core/proxy_client.py +0 -1
  129. mcp_proxy_adapter/core/proxy_registration.py +36 -912
  130. mcp_proxy_adapter/core/role_utils.py +0 -308
  131. mcp_proxy_adapter/core/security_adapter.py +1 -36
  132. mcp_proxy_adapter/core/security_factory.py +1 -150
  133. mcp_proxy_adapter/core/security_integration.py +0 -33
  134. mcp_proxy_adapter/core/server_adapter.py +1 -40
  135. mcp_proxy_adapter/core/server_engine.py +2 -173
  136. mcp_proxy_adapter/core/settings.py +0 -127
  137. mcp_proxy_adapter/core/signal_handler.py +0 -65
  138. mcp_proxy_adapter/core/ssl_utils.py +19 -137
  139. mcp_proxy_adapter/core/transport_manager.py +0 -151
  140. mcp_proxy_adapter/core/unified_config_adapter.py +1 -193
  141. mcp_proxy_adapter/core/utils.py +1 -182
  142. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  143. mcp_proxy_adapter/core/validation/config_validator.py +211 -0
  144. mcp_proxy_adapter/core/validation/file_validator.py +73 -0
  145. mcp_proxy_adapter/core/validation/protocol_validator.py +191 -0
  146. mcp_proxy_adapter/core/validation/security_validator.py +58 -0
  147. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  148. mcp_proxy_adapter/custom_openapi.py +33 -652
  149. mcp_proxy_adapter/examples/bugfix_certificate_config.py +0 -23
  150. mcp_proxy_adapter/examples/check_config.py +0 -2
  151. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  152. mcp_proxy_adapter/examples/config_builder.py +13 -2
  153. mcp_proxy_adapter/examples/config_cli.py +0 -1
  154. mcp_proxy_adapter/examples/create_test_configs.py +0 -46
  155. mcp_proxy_adapter/examples/debug_request_state.py +0 -1
  156. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -47
  157. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -45
  158. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +0 -12
  159. mcp_proxy_adapter/examples/full_application/commands/help_command.py +0 -12
  160. mcp_proxy_adapter/examples/full_application/commands/list_command.py +0 -7
  161. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +0 -2
  162. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -59
  163. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -54
  164. mcp_proxy_adapter/examples/full_application/main.py +186 -150
  165. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +0 -107
  166. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +0 -24
  167. mcp_proxy_adapter/examples/full_application/test_server.py +0 -58
  168. mcp_proxy_adapter/examples/generate_config.py +65 -11
  169. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  170. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  171. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  172. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  173. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  174. mcp_proxy_adapter/examples/required_certificates.py +0 -2
  175. mcp_proxy_adapter/examples/run_full_test_suite.py +0 -29
  176. mcp_proxy_adapter/examples/run_proxy_server.py +31 -71
  177. mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -27
  178. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  179. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  180. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  181. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  182. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  183. mcp_proxy_adapter/examples/security_test_client.py +24 -1075
  184. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  185. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  186. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  187. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  188. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  189. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  190. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  191. mcp_proxy_adapter/examples/setup_test_environment.py +133 -1425
  192. mcp_proxy_adapter/examples/test_config.py +0 -3
  193. mcp_proxy_adapter/examples/test_config_builder.py +25 -405
  194. mcp_proxy_adapter/examples/test_examples.py +0 -1
  195. mcp_proxy_adapter/examples/test_framework_complete.py +0 -2
  196. mcp_proxy_adapter/examples/test_mcp_server.py +0 -1
  197. mcp_proxy_adapter/examples/test_protocol_examples.py +0 -1
  198. mcp_proxy_adapter/examples/universal_client.py +0 -6
  199. mcp_proxy_adapter/examples/update_config_certificates.py +0 -1
  200. mcp_proxy_adapter/examples/validate_generator_compatibility.py +0 -1
  201. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +0 -187
  202. mcp_proxy_adapter/integrations/__init__.py +25 -0
  203. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  204. mcp_proxy_adapter/main.py +70 -62
  205. mcp_proxy_adapter/openapi.py +0 -22
  206. mcp_proxy_adapter/version.py +1 -1
  207. {mcp_proxy_adapter-6.9.27.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/METADATA +2 -1
  208. mcp_proxy_adapter-6.9.29.dist-info/RECORD +235 -0
  209. {mcp_proxy_adapter-6.9.27.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/entry_points.txt +1 -1
  210. mcp_proxy_adapter-6.9.27.dist-info/RECORD +0 -149
  211. {mcp_proxy_adapter-6.9.27.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.9.27.dist-info → mcp_proxy_adapter-6.9.29.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,632 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple Queue Demo for MCP Proxy Adapter.
4
+
5
+ This example demonstrates the queue integration concepts
6
+ without requiring the queuemgr dependency.
7
+
8
+ Author: Vasiliy Zdanovskiy
9
+ email: vasilyvz@gmail.com
10
+ """
11
+
12
+ import asyncio
13
+ import json
14
+ import time
15
+ from typing import Dict, Any, List
16
+
17
+ from mcp_proxy_adapter.commands.command_registry import registry
18
+ QueueAddJobCommand,
19
+ QueueStartJobCommand,
20
+ QueueStopJobCommand,
21
+ QueueDeleteJobCommand,
22
+ QueueGetJobStatusCommand,
23
+ QueueListJobsCommand,
24
+ QueueHealthCommand,
25
+ )
26
+ from mcp_proxy_adapter.integrations.queuemgr_integration import (
27
+ QueueJobStatus,
28
+ QueueJobResult,
29
+ QueueJobError,
30
+ )
31
+
32
+
33
+ class MockQueueManager:
34
+ """Mock queue manager for demonstration purposes."""
35
+
36
+ def __init__(self):
37
+ self.jobs: Dict[str, Dict[str, Any]] = {}
38
+ self.running = True
39
+
40
+ async def add_job(self, job_class, job_id: str, params: Dict[str, Any]) -> QueueJobResult:
41
+ """Add a job to the mock queue."""
42
+ self.jobs[job_id] = {
43
+ "job_id": job_id,
44
+ "status": QueueJobStatus.PENDING,
45
+ "params": params,
46
+ "result": None,
47
+ "error": None,
48
+ "progress": 0,
49
+ "description": "Job added to queue"
50
+ }
51
+ return QueueJobResult(
52
+ job_id=job_id,
53
+ status=QueueJobStatus.PENDING,
54
+ description="Job added to queue"
55
+ )
56
+
57
+ async def start_job(self, job_id: str) -> QueueJobResult:
58
+ """Start a job in the mock queue."""
59
+ if job_id not in self.jobs:
60
+ raise QueueJobError(job_id, "Job not found")
61
+
62
+ self.jobs[job_id]["status"] = QueueJobStatus.RUNNING
63
+ self.jobs[job_id]["description"] = "Job started"
64
+
65
+ # Simulate job execution in background
66
+ asyncio.create_task(self._simulate_job_execution(job_id))
67
+
68
+ return QueueJobResult(
69
+ job_id=job_id,
70
+ status=QueueJobStatus.RUNNING,
71
+ description="Job started"
72
+ )
73
+
74
+ async def stop_job(self, job_id: str) -> QueueJobResult:
75
+ """Stop a job in the mock queue."""
76
+ if job_id not in self.jobs:
77
+ raise QueueJobError(job_id, "Job not found")
78
+
79
+ self.jobs[job_id]["status"] = QueueJobStatus.STOPPED
80
+ self.jobs[job_id]["description"] = "Job stopped"
81
+
82
+ return QueueJobResult(
83
+ job_id=job_id,
84
+ status=QueueJobStatus.STOPPED,
85
+ description="Job stopped"
86
+ )
87
+
88
+ async def delete_job(self, job_id: str) -> QueueJobResult:
89
+ """Delete a job from the mock queue."""
90
+ if job_id not in self.jobs:
91
+ raise QueueJobError(job_id, "Job not found")
92
+
93
+ del self.jobs[job_id]
94
+
95
+ return QueueJobResult(
96
+ job_id=job_id,
97
+ status=QueueJobStatus.DELETED,
98
+ description="Job deleted"
99
+ )
100
+
101
+ async def get_job_status(self, job_id: str) -> QueueJobResult:
102
+ """Get job status from the mock queue."""
103
+ if job_id not in self.jobs:
104
+ raise QueueJobError(job_id, "Job not found")
105
+
106
+ job = self.jobs[job_id]
107
+ return QueueJobResult(
108
+ job_id=job_id,
109
+ status=job["status"],
110
+ result=job["result"],
111
+ error=job["error"],
112
+ progress=job["progress"],
113
+ description=job["description"]
114
+ )
115
+
116
+ async def list_jobs(self) -> List[QueueJobResult]:
117
+ """List all jobs in the mock queue."""
118
+ results = []
119
+ for job_id, job in self.jobs.items():
120
+ results.append(QueueJobResult(
121
+ job_id=job_id,
122
+ status=job["status"],
123
+ result=job["result"],
124
+ error=job["error"],
125
+ progress=job["progress"],
126
+ description=job["description"]
127
+ ))
128
+ return results
129
+
130
+ async def get_queue_health(self) -> Dict[str, Any]:
131
+ """Get queue health information."""
132
+ running_jobs = sum(1 for job in self.jobs.values() if job["status"] == QueueJobStatus.RUNNING)
133
+ completed_jobs = sum(1 for job in self.jobs.values() if job["status"] == QueueJobStatus.COMPLETED)
134
+ failed_jobs = sum(1 for job in self.jobs.values() if job["status"] == QueueJobStatus.FAILED)
135
+
136
+ return {
137
+ "status": "healthy" if self.running else "unhealthy",
138
+ "running": self.running,
139
+ "total_jobs": len(self.jobs),
140
+ "running_jobs": running_jobs,
141
+ "completed_jobs": completed_jobs,
142
+ "failed_jobs": failed_jobs,
143
+ "registry_path": "mock_registry.jsonl",
144
+ "max_concurrent_jobs": 10,
145
+ }
146
+
147
+ async def _simulate_job_execution(self, job_id: str):
148
+ """Simulate job execution with progress updates."""
149
+ job = self.jobs[job_id]
150
+ params = job["params"]
151
+ job_type = params.get("job_type", "custom")
152
+
153
+ try:
154
+ # Simulate different job types
155
+ if job_type == "long_running":
156
+ duration = params.get("duration", 10)
157
+ await self._simulate_long_running_job(job_id, duration)
158
+ elif job_type == "batch_processing":
159
+ items = params.get("items", [])
160
+ await self._simulate_batch_processing_job(job_id, items)
161
+ elif job_type == "file_download":
162
+ file_size = params.get("file_size", 1024 * 1024)
163
+ await self._simulate_file_download_job(job_id, file_size)
164
+ else:
165
+ await self._simulate_simple_job(job_id)
166
+
167
+ except Exception as e:
168
+ self.jobs[job_id]["status"] = QueueJobStatus.FAILED
169
+ self.jobs[job_id]["error"] = str(e)
170
+ self.jobs[job_id]["description"] = f"Job failed: {str(e)}"
171
+
172
+ async def _simulate_simple_job(self, job_id: str):
173
+ """Simulate a simple job."""
174
+ job = self.jobs[job_id]
175
+
176
+ # Update progress
177
+ for i in range(5):
178
+ progress = (i + 1) * 20
179
+ job["progress"] = progress
180
+ job["description"] = f"Processing... {progress}% complete"
181
+ await asyncio.sleep(0.5)
182
+
183
+ # Complete job
184
+ job["status"] = QueueJobStatus.COMPLETED
185
+ job["progress"] = 100
186
+ job["description"] = "Job completed successfully"
187
+ job["result"] = {
188
+ "job_id": job_id,
189
+ "completed_at": time.time(),
190
+ "status": "completed"
191
+ }
192
+
193
+ async def _simulate_long_running_job(self, job_id: str, duration: int):
194
+ """Simulate a long-running job."""
195
+ job = self.jobs[job_id]
196
+ task_type = job["params"].get("task_type", "data_processing")
197
+
198
+ for i in range(duration):
199
+ progress = int((i + 1) / duration * 100)
200
+ job["progress"] = progress
201
+ job["description"] = f"Processing {task_type} task... {progress}% complete"
202
+ await asyncio.sleep(1)
203
+
204
+ # Complete job
205
+ job["status"] = QueueJobStatus.COMPLETED
206
+ job["progress"] = 100
207
+ job["description"] = f"{task_type} task completed"
208
+ job["result"] = {
209
+ "job_id": job_id,
210
+ "task_type": task_type,
211
+ "duration": duration,
212
+ "completed_at": time.time(),
213
+ "status": "completed"
214
+ }
215
+
216
+ async def _simulate_batch_processing_job(self, job_id: str, items: List[str]):
217
+ """Simulate a batch processing job."""
218
+ job = self.jobs[job_id]
219
+ processed_items = []
220
+
221
+ for i, item in enumerate(items):
222
+ progress = int((i + 1) / len(items) * 100)
223
+ job["progress"] = progress
224
+ job["description"] = f"Processing item {i+1}/{len(items)}... {progress}% complete"
225
+
226
+ # Simulate processing
227
+ await asyncio.sleep(0.1)
228
+
229
+ processed_items.append({
230
+ "original": item,
231
+ "processed": f"processed_{item}",
232
+ "timestamp": time.time()
233
+ })
234
+
235
+ # Complete job
236
+ job["status"] = QueueJobStatus.COMPLETED
237
+ job["progress"] = 100
238
+ job["description"] = f"Batch processing completed ({len(processed_items)} items)"
239
+ job["result"] = {
240
+ "job_id": job_id,
241
+ "processed_count": len(processed_items),
242
+ "processed_items": processed_items,
243
+ "completed_at": time.time(),
244
+ "status": "completed"
245
+ }
246
+
247
+ async def _simulate_file_download_job(self, job_id: str, file_size: int):
248
+ """Simulate a file download job."""
249
+ job = self.jobs[job_id]
250
+ url = job["params"].get("url", "https://example.com/file.zip")
251
+
252
+ downloaded = 0
253
+ chunk_size = 64 * 1024 # 64KB chunks
254
+
255
+ while downloaded < file_size:
256
+ chunk = min(chunk_size, file_size - downloaded)
257
+ await asyncio.sleep(0.1) # Simulate network delay
258
+
259
+ downloaded += chunk
260
+ progress = int(downloaded / file_size * 100)
261
+
262
+ job["progress"] = progress
263
+ job["description"] = f"Downloading {url}... {progress}% complete ({downloaded}/{file_size} bytes)"
264
+
265
+ # Complete job
266
+ job["status"] = QueueJobStatus.COMPLETED
267
+ job["progress"] = 100
268
+ job["description"] = f"Download completed ({file_size} bytes)"
269
+ job["result"] = {
270
+ "job_id": job_id,
271
+ "url": url,
272
+ "file_size": file_size,
273
+ "downloaded_bytes": downloaded,
274
+ "completed_at": time.time(),
275
+ "status": "completed"
276
+ }
277
+
278
+
279
+ # Global mock queue manager
280
+ mock_queue_manager = MockQueueManager()
281
+
282
+
283
+ class MockQueueCommands:
284
+ """Mock queue commands that use the mock queue manager."""
285
+
286
+ @staticmethod
287
+ async def add_job(params: Dict[str, Any]) -> Dict[str, Any]:
288
+ """Add a job to the mock queue."""
289
+ job_type = params.get("job_type")
290
+ job_id = params.get("job_id")
291
+ job_params = params.get("params", {})
292
+
293
+ if not job_type or not job_id:
294
+ return {
295
+ "success": False,
296
+ "error": "job_type and job_id are required"
297
+ }
298
+
299
+ # Add job_type to params for simulation
300
+ job_params["job_type"] = job_type
301
+
302
+ result = await mock_queue_manager.add_job(None, job_id, job_params)
303
+
304
+ return {
305
+ "success": True,
306
+ "data": {
307
+ "message": f"Job {job_id} added successfully",
308
+ "job_id": job_id,
309
+ "job_type": job_type,
310
+ "status": result.status,
311
+ "description": result.description
312
+ }
313
+ }
314
+
315
+ @staticmethod
316
+ async def start_job(params: Dict[str, Any]) -> Dict[str, Any]:
317
+ """Start a job in the mock queue."""
318
+ job_id = params.get("job_id")
319
+
320
+ if not job_id:
321
+ return {
322
+ "success": False,
323
+ "error": "job_id is required"
324
+ }
325
+
326
+ result = await mock_queue_manager.start_job(job_id)
327
+
328
+ return {
329
+ "success": True,
330
+ "data": {
331
+ "message": f"Job {job_id} started successfully",
332
+ "job_id": job_id,
333
+ "status": result.status,
334
+ "description": result.description
335
+ }
336
+ }
337
+
338
+ @staticmethod
339
+ async def stop_job(params: Dict[str, Any]) -> Dict[str, Any]:
340
+ """Stop a job in the mock queue."""
341
+ job_id = params.get("job_id")
342
+
343
+ if not job_id:
344
+ return {
345
+ "success": False,
346
+ "error": "job_id is required"
347
+ }
348
+
349
+ result = await mock_queue_manager.stop_job(job_id)
350
+
351
+ return {
352
+ "success": True,
353
+ "data": {
354
+ "message": f"Job {job_id} stopped successfully",
355
+ "job_id": job_id,
356
+ "status": result.status,
357
+ "description": result.description
358
+ }
359
+ }
360
+
361
+ @staticmethod
362
+ async def delete_job(params: Dict[str, Any]) -> Dict[str, Any]:
363
+ """Delete a job from the mock queue."""
364
+ job_id = params.get("job_id")
365
+
366
+ if not job_id:
367
+ return {
368
+ "success": False,
369
+ "error": "job_id is required"
370
+ }
371
+
372
+ result = await mock_queue_manager.delete_job(job_id)
373
+
374
+ return {
375
+ "success": True,
376
+ "data": {
377
+ "message": f"Job {job_id} deleted successfully",
378
+ "job_id": job_id,
379
+ "status": result.status,
380
+ "description": result.description
381
+ }
382
+ }
383
+
384
+ @staticmethod
385
+ async def get_job_status(params: Dict[str, Any]) -> Dict[str, Any]:
386
+ """Get job status from the mock queue."""
387
+ job_id = params.get("job_id")
388
+
389
+ if not job_id:
390
+ return {
391
+ "success": False,
392
+ "error": "job_id is required"
393
+ }
394
+
395
+ result = await mock_queue_manager.get_job_status(job_id)
396
+
397
+ return {
398
+ "success": True,
399
+ "data": {
400
+ "job_id": result.job_id,
401
+ "status": result.status,
402
+ "progress": result.progress,
403
+ "description": result.description,
404
+ "result": result.result,
405
+ "error": result.error
406
+ }
407
+ }
408
+
409
+ @staticmethod
410
+ async def list_jobs(params: Dict[str, Any]) -> Dict[str, Any]:
411
+ """List all jobs in the mock queue."""
412
+ jobs = await mock_queue_manager.list_jobs()
413
+
414
+ jobs_data = []
415
+ for job in jobs:
416
+ jobs_data.append({
417
+ "job_id": job.job_id,
418
+ "status": job.status,
419
+ "progress": job.progress,
420
+ "description": job.description,
421
+ "has_result": bool(job.result),
422
+ "has_error": bool(job.error)
423
+ })
424
+
425
+ return {
426
+ "success": True,
427
+ "data": {
428
+ "jobs": jobs_data,
429
+ "total_count": len(jobs_data)
430
+ }
431
+ }
432
+
433
+ @staticmethod
434
+ async def health(params: Dict[str, Any]) -> Dict[str, Any]:
435
+ """Get queue health information."""
436
+ health = await mock_queue_manager.get_queue_health()
437
+
438
+ return {
439
+ "success": True,
440
+ "data": health
441
+ }
442
+
443
+
444
+ async def demo_queue_operations():
445
+ """Demonstrate queue operations with mock queue manager."""
446
+ print("\n🚀 Demonstrating queue operations with mock queue manager...")
447
+
448
+ try:
449
+ # 1. Add various types of jobs
450
+ print("\n1️⃣ Adding jobs to queue...")
451
+
452
+ # Long-running job (10 seconds)
453
+ result1 = await MockQueueCommands.add_job({
454
+ "job_type": "long_running",
455
+ "job_id": "long_job_1",
456
+ "params": {
457
+ "duration": 10,
458
+ "task_type": "data_analysis"
459
+ }
460
+ })
461
+ print(f"✅ Added long-running job: {result1['data']['job_id']}")
462
+
463
+ # Batch processing job
464
+ result2 = await MockQueueCommands.add_job({
465
+ "job_type": "batch_processing",
466
+ "job_id": "batch_job_1",
467
+ "params": {
468
+ "items": [f"item_{i}" for i in range(20)]
469
+ }
470
+ })
471
+ print(f"✅ Added batch processing job: {result2['data']['job_id']}")
472
+
473
+ # File download job
474
+ result3 = await MockQueueCommands.add_job({
475
+ "job_type": "file_download",
476
+ "job_id": "download_job_1",
477
+ "params": {
478
+ "url": "https://example.com/large_file.zip",
479
+ "file_size": 2 * 1024 * 1024 # 2MB
480
+ }
481
+ })
482
+ print(f"✅ Added file download job: {result3['data']['job_id']}")
483
+
484
+ # 2. Start jobs
485
+ print("\n2️⃣ Starting jobs...")
486
+
487
+ await MockQueueCommands.start_job({"job_id": "long_job_1"})
488
+ print("✅ Started long-running job")
489
+
490
+ await MockQueueCommands.start_job({"job_id": "batch_job_1"})
491
+ print("✅ Started batch processing job")
492
+
493
+ await MockQueueCommands.start_job({"job_id": "download_job_1"})
494
+ print("✅ Started file download job")
495
+
496
+ # 3. Monitor job status with detailed progress
497
+ print("\n3️⃣ Monitoring job status with progress...")
498
+
499
+ for i in range(15): # Monitor for 15 iterations
500
+ print(f"\n--- Status check {i+1} ---")
501
+
502
+ # Check individual job status
503
+ jobs_to_check = ["long_job_1", "batch_job_1", "download_job_1"]
504
+
505
+ for job_id in jobs_to_check:
506
+ try:
507
+ status_result = await MockQueueCommands.get_job_status({"job_id": job_id})
508
+ if status_result["success"]:
509
+ data = status_result["data"]
510
+ print(f"{job_id}: {data['status']} (progress: {data['progress']}%) - {data['description']}")
511
+
512
+ if data["error"]:
513
+ print(f" ❌ Error: {data['error']}")
514
+ else:
515
+ print(f"{job_id}: Error - {status_result['error']}")
516
+ except Exception as e:
517
+ print(f"{job_id}: Exception - {e}")
518
+
519
+ # List all jobs summary
520
+ list_result = await MockQueueCommands.list_jobs({})
521
+ if list_result["success"]:
522
+ jobs = list_result["data"]["jobs"]
523
+ running_jobs = [job for job in jobs if job["status"] == "running"]
524
+ completed_jobs = [job for job in jobs if job["status"] == "completed"]
525
+ failed_jobs = [job for job in jobs if job["status"] == "failed"]
526
+
527
+ print(f"📊 Summary: {len(running_jobs)} running, {len(completed_jobs)} completed, {len(failed_jobs)} failed")
528
+
529
+ # Check if all jobs are done
530
+ if len(running_jobs) == 0:
531
+ print("✅ All jobs completed!")
532
+ break
533
+
534
+ await asyncio.sleep(1) # Check every second
535
+
536
+ # 4. Get detailed job results
537
+ print("\n4️⃣ Getting detailed job results...")
538
+
539
+ for job_id in ["long_job_1", "batch_job_1", "download_job_1"]:
540
+ try:
541
+ status_result = await MockQueueCommands.get_job_status({"job_id": job_id})
542
+ if status_result["success"]:
543
+ data = status_result["data"]
544
+ print(f"\n📋 {job_id} Results:")
545
+ print(f" Status: {data['status']}")
546
+ print(f" Progress: {data['progress']}%")
547
+ print(f" Description: {data['description']}")
548
+
549
+ if data["result"]:
550
+ print(f" Result: {json.dumps(data['result'], indent=4)}")
551
+
552
+ if data["error"]:
553
+ print(f" Error: {data['error']}")
554
+ else:
555
+ print(f"❌ Error getting results for {job_id}: {status_result['error']}")
556
+
557
+ except Exception as e:
558
+ print(f"❌ Exception getting results for {job_id}: {e}")
559
+
560
+ # 5. Check queue health
561
+ print("\n5️⃣ Checking queue health...")
562
+
563
+ health_result = await MockQueueCommands.health({})
564
+ if health_result["success"]:
565
+ health = health_result["data"]
566
+ print(f"Queue health: {json.dumps(health, indent=2)}")
567
+ else:
568
+ print(f"❌ Error getting health: {health_result['error']}")
569
+
570
+ except Exception as e:
571
+ print(f"❌ Demo failed: {e}")
572
+ import traceback
573
+ traceback.print_exc()
574
+
575
+
576
+ async def main():
577
+ """Main function to run the queue demo."""
578
+ print("🚀 MCP Proxy Adapter Queue Integration Demo")
579
+ print("=" * 50)
580
+
581
+ # Demo queue operations
582
+ await demo_queue_operations()
583
+
584
+ print("\n🎉 Queue integration demo completed!")
585
+ print("\n📋 Available queue commands:")
586
+ print(" - queue_add_job: Add a job to the queue")
587
+ print(" - queue_start_job: Start a job")
588
+ print(" - queue_stop_job: Stop a job")
589
+ print(" - queue_delete_job: Delete a job")
590
+ print(" - queue_get_job_status: Get job status")
591
+ print(" - queue_list_jobs: List all jobs")
592
+ print(" - queue_health: Check queue health")
593
+
594
+ print("\n📝 Example JSON-RPC calls:")
595
+ print("1. Add a long-running job:")
596
+ print(json.dumps({
597
+ "jsonrpc": "2.0",
598
+ "method": "queue_add_job",
599
+ "params": {
600
+ "job_type": "long_running",
601
+ "job_id": "my_long_job",
602
+ "params": {
603
+ "duration": 15,
604
+ "task_type": "data_analysis"
605
+ }
606
+ },
607
+ "id": 1
608
+ }, indent=2))
609
+
610
+ print("\n2. Start the job:")
611
+ print(json.dumps({
612
+ "jsonrpc": "2.0",
613
+ "method": "queue_start_job",
614
+ "params": {
615
+ "job_id": "my_long_job"
616
+ },
617
+ "id": 2
618
+ }, indent=2))
619
+
620
+ print("\n3. Check job status:")
621
+ print(json.dumps({
622
+ "jsonrpc": "2.0",
623
+ "method": "queue_get_job_status",
624
+ "params": {
625
+ "job_id": "my_long_job"
626
+ },
627
+ "id": 3
628
+ }, indent=2))
629
+
630
+
631
+ if __name__ == "__main__":
632
+ asyncio.run(main())