mcp-mesh 0.4.2__py3-none-any.whl → 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _mcp_mesh/__init__.py +14 -3
- _mcp_mesh/engine/__init__.py +12 -1
- _mcp_mesh/engine/async_mcp_client.py +2 -2
- _mcp_mesh/engine/decorator_registry.py +98 -8
- _mcp_mesh/engine/dependency_injector.py +249 -71
- _mcp_mesh/engine/full_mcp_proxy.py +4 -4
- _mcp_mesh/engine/http_wrapper.py +9 -20
- _mcp_mesh/engine/mcp_client_proxy.py +1 -1
- _mcp_mesh/engine/unified_mcp_proxy.py +813 -0
- _mcp_mesh/generated/.openapi-generator/FILES +2 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +2 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py +1 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py +305 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +1 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +10 -1
- _mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +4 -4
- _mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py +108 -0
- _mcp_mesh/pipeline/__init__.py +2 -2
- _mcp_mesh/pipeline/api_heartbeat/__init__.py +16 -0
- _mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +506 -0
- _mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +117 -0
- _mcp_mesh/pipeline/api_heartbeat/api_health_check.py +140 -0
- _mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py +247 -0
- _mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +309 -0
- _mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py +332 -0
- _mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py +147 -0
- _mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py +104 -0
- _mcp_mesh/pipeline/api_startup/__init__.py +20 -0
- _mcp_mesh/pipeline/api_startup/api_pipeline.py +61 -0
- _mcp_mesh/pipeline/api_startup/api_server_setup.py +367 -0
- _mcp_mesh/pipeline/api_startup/fastapi_discovery.py +302 -0
- _mcp_mesh/pipeline/api_startup/route_collection.py +56 -0
- _mcp_mesh/pipeline/api_startup/route_integration.py +318 -0
- _mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/dependency_resolution.py +19 -183
- _mcp_mesh/pipeline/{startup → mcp_startup}/heartbeat_loop.py +1 -1
- _mcp_mesh/pipeline/{startup → mcp_startup}/startup_orchestrator.py +170 -5
- _mcp_mesh/shared/config_resolver.py +0 -3
- _mcp_mesh/shared/logging_config.py +2 -1
- _mcp_mesh/tracing/agent_context_helper.py +1 -1
- _mcp_mesh/tracing/execution_tracer.py +41 -0
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.1.dist-info}/METADATA +1 -1
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.1.dist-info}/RECORD +61 -43
- mesh/__init__.py +3 -1
- mesh/decorators.py +143 -1
- mesh/types.py +109 -48
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/__init__.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/fast_heartbeat_check.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/heartbeat_orchestrator.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/heartbeat_pipeline.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/heartbeat_send.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/lifespan_integration.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/registry_connection.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/__init__.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/configuration.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/decorator_collection.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/fastapiserver_setup.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/fastmcpserver_discovery.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/heartbeat_preparation.py +0 -0
- /_mcp_mesh/pipeline/{startup → mcp_startup}/startup_pipeline.py +0 -0
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.1.dist-info}/WHEEL +0 -0
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -72,6 +72,36 @@ class DebounceCoordinator:
|
|
|
72
72
|
f"⏰ Scheduled processing in {self.delay_seconds} seconds"
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
+
def _determine_pipeline_type(self) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Determine which pipeline to execute based on registered decorators.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
"mcp": Only MCP agents/tools found
|
|
81
|
+
"api": Only API routes found
|
|
82
|
+
"mixed": Both MCP and API decorators found (throws exception)
|
|
83
|
+
"none": No decorators found
|
|
84
|
+
"""
|
|
85
|
+
from ...engine.decorator_registry import DecoratorRegistry
|
|
86
|
+
|
|
87
|
+
agents = DecoratorRegistry.get_mesh_agents()
|
|
88
|
+
tools = DecoratorRegistry.get_mesh_tools()
|
|
89
|
+
routes = DecoratorRegistry.get_all_by_type("mesh_route")
|
|
90
|
+
|
|
91
|
+
has_mcp = len(agents) > 0 or len(tools) > 0
|
|
92
|
+
has_api = len(routes) > 0
|
|
93
|
+
|
|
94
|
+
self.logger.debug(f"🔍 Pipeline type detection: MCP={has_mcp} ({len(agents)} agents, {len(tools)} tools), API={has_api} ({len(routes)} routes)")
|
|
95
|
+
|
|
96
|
+
if has_api and has_mcp:
|
|
97
|
+
return "mixed"
|
|
98
|
+
elif has_api:
|
|
99
|
+
return "api"
|
|
100
|
+
elif has_mcp:
|
|
101
|
+
return "mcp"
|
|
102
|
+
else:
|
|
103
|
+
return "none"
|
|
104
|
+
|
|
75
105
|
def _execute_processing(self) -> None:
|
|
76
106
|
"""Execute the processing (called by timer)."""
|
|
77
107
|
try:
|
|
@@ -83,6 +113,21 @@ class DebounceCoordinator:
|
|
|
83
113
|
f"🚀 Debounce delay ({self.delay_seconds}s) complete, processing all decorators"
|
|
84
114
|
)
|
|
85
115
|
|
|
116
|
+
# Determine which pipeline to execute
|
|
117
|
+
pipeline_type = self._determine_pipeline_type()
|
|
118
|
+
|
|
119
|
+
if pipeline_type == "mixed":
|
|
120
|
+
error_msg = (
|
|
121
|
+
"❌ Mixed mode not supported: Cannot use @mesh.route decorators "
|
|
122
|
+
"together with @mesh.tool/@mesh.agent decorators in the same process. "
|
|
123
|
+
"Please use either MCP agent decorators OR API route decorators, not both."
|
|
124
|
+
)
|
|
125
|
+
self.logger.error(error_msg)
|
|
126
|
+
raise RuntimeError(error_msg)
|
|
127
|
+
elif pipeline_type == "none":
|
|
128
|
+
self.logger.warning("⚠️ No decorators found - nothing to process")
|
|
129
|
+
return
|
|
130
|
+
|
|
86
131
|
# Execute the pipeline using asyncio.run
|
|
87
132
|
import asyncio
|
|
88
133
|
|
|
@@ -90,18 +135,36 @@ class DebounceCoordinator:
|
|
|
90
135
|
auto_run_enabled = self._check_auto_run_enabled()
|
|
91
136
|
|
|
92
137
|
self.logger.debug(f"🔍 Auto-run enabled: {auto_run_enabled}")
|
|
138
|
+
self.logger.info(f"🎯 Pipeline type: {pipeline_type}")
|
|
93
139
|
|
|
94
140
|
if auto_run_enabled:
|
|
95
141
|
self.logger.info("🔄 Auto-run enabled - using FastAPI natural blocking")
|
|
96
|
-
|
|
97
|
-
|
|
142
|
+
|
|
143
|
+
# Execute appropriate pipeline based on type
|
|
144
|
+
if pipeline_type == "mcp":
|
|
145
|
+
# Phase 1: Run async MCP pipeline setup
|
|
146
|
+
result = asyncio.run(self._orchestrator.process_once())
|
|
147
|
+
elif pipeline_type == "api":
|
|
148
|
+
# Phase 1: Run async API pipeline setup
|
|
149
|
+
result = asyncio.run(self._orchestrator.process_api_once())
|
|
150
|
+
else:
|
|
151
|
+
raise RuntimeError(f"Unsupported pipeline type: {pipeline_type}")
|
|
98
152
|
|
|
99
153
|
# Phase 2: Extract FastAPI app and start synchronous server
|
|
100
154
|
pipeline_context = result.get("context", {}).get("pipeline_context", {})
|
|
101
155
|
fastapi_app = pipeline_context.get("fastapi_app")
|
|
102
156
|
binding_config = pipeline_context.get("fastapi_binding_config", {})
|
|
103
|
-
|
|
104
|
-
|
|
157
|
+
heartbeat_config = pipeline_context.get("heartbeat_config", {})
|
|
158
|
+
|
|
159
|
+
if pipeline_type == "api":
|
|
160
|
+
# For API services, ONLY do dependency injection - user controls their FastAPI server
|
|
161
|
+
# Dependency injection is already complete from pipeline execution
|
|
162
|
+
# Optionally start heartbeat in background (non-blocking)
|
|
163
|
+
self._setup_api_heartbeat_background(heartbeat_config, pipeline_context)
|
|
164
|
+
self.logger.info("✅ API dependency injection complete - user's FastAPI server can now start")
|
|
165
|
+
return # Don't block - let user's uvicorn run
|
|
166
|
+
elif fastapi_app and binding_config:
|
|
167
|
+
# For MCP agents with FastAPI server
|
|
105
168
|
self._start_blocking_fastapi_server(fastapi_app, binding_config)
|
|
106
169
|
else:
|
|
107
170
|
self.logger.warning(
|
|
@@ -110,11 +173,20 @@ class DebounceCoordinator:
|
|
|
110
173
|
else:
|
|
111
174
|
# Single execution mode (for testing/debugging)
|
|
112
175
|
self.logger.info("🏁 Auto-run disabled - single execution mode")
|
|
113
|
-
|
|
176
|
+
|
|
177
|
+
if pipeline_type == "mcp":
|
|
178
|
+
result = asyncio.run(self._orchestrator.process_once())
|
|
179
|
+
elif pipeline_type == "api":
|
|
180
|
+
result = asyncio.run(self._orchestrator.process_api_once())
|
|
181
|
+
else:
|
|
182
|
+
raise RuntimeError(f"Unsupported pipeline type: {pipeline_type}")
|
|
183
|
+
|
|
114
184
|
self.logger.info("✅ Pipeline execution completed, exiting")
|
|
115
185
|
|
|
116
186
|
except Exception as e:
|
|
117
187
|
self.logger.error(f"❌ Error in debounced processing: {e}")
|
|
188
|
+
# Re-raise to ensure the system exits on mixed mode or other critical errors
|
|
189
|
+
raise
|
|
118
190
|
|
|
119
191
|
def _start_blocking_fastapi_server(
|
|
120
192
|
self, app: Any, binding_config: dict[str, Any]
|
|
@@ -148,6 +220,58 @@ class DebounceCoordinator:
|
|
|
148
220
|
self.logger.error(f"❌ FastAPI server error: {e}")
|
|
149
221
|
raise
|
|
150
222
|
|
|
223
|
+
def _setup_api_heartbeat_background(
|
|
224
|
+
self, heartbeat_config: dict[str, Any], pipeline_context: dict[str, Any]
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Setup API heartbeat to run in background - non-blocking."""
|
|
227
|
+
try:
|
|
228
|
+
# Populate heartbeat context with current pipeline context
|
|
229
|
+
heartbeat_config["context"] = pipeline_context
|
|
230
|
+
service_id = heartbeat_config.get("service_id", "unknown")
|
|
231
|
+
standalone_mode = heartbeat_config.get("standalone_mode", False)
|
|
232
|
+
|
|
233
|
+
if standalone_mode:
|
|
234
|
+
self.logger.info(
|
|
235
|
+
f"📝 API service '{service_id}' configured in standalone mode - no heartbeat"
|
|
236
|
+
)
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
self.logger.info(
|
|
240
|
+
f"🔗 Setting up background API heartbeat for service '{service_id}'"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Import heartbeat functionality
|
|
244
|
+
from ..api_heartbeat.api_lifespan_integration import api_heartbeat_lifespan_task
|
|
245
|
+
import threading
|
|
246
|
+
import asyncio
|
|
247
|
+
|
|
248
|
+
def run_heartbeat():
|
|
249
|
+
"""Run heartbeat in separate thread with its own event loop."""
|
|
250
|
+
self.logger.debug(f"Starting background heartbeat thread for {service_id}")
|
|
251
|
+
try:
|
|
252
|
+
# Create new event loop for this thread
|
|
253
|
+
loop = asyncio.new_event_loop()
|
|
254
|
+
asyncio.set_event_loop(loop)
|
|
255
|
+
|
|
256
|
+
# Run heartbeat task
|
|
257
|
+
loop.run_until_complete(api_heartbeat_lifespan_task(heartbeat_config))
|
|
258
|
+
except Exception as e:
|
|
259
|
+
self.logger.error(f"❌ Background heartbeat error: {e}")
|
|
260
|
+
finally:
|
|
261
|
+
loop.close()
|
|
262
|
+
|
|
263
|
+
# Start heartbeat in daemon thread (won't prevent process exit)
|
|
264
|
+
heartbeat_thread = threading.Thread(target=run_heartbeat, daemon=True)
|
|
265
|
+
heartbeat_thread.start()
|
|
266
|
+
|
|
267
|
+
self.logger.info(
|
|
268
|
+
f"💓 Background API heartbeat thread started for service '{service_id}'"
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
except Exception as e:
|
|
272
|
+
self.logger.warning(f"⚠️ Could not setup API heartbeat: {e}")
|
|
273
|
+
# Don't fail - heartbeat is optional for API services
|
|
274
|
+
|
|
151
275
|
def _perform_graceful_shutdown(self) -> None:
|
|
152
276
|
"""Perform graceful shutdown by unregistering from registry."""
|
|
153
277
|
try:
|
|
@@ -272,6 +396,43 @@ class MeshOrchestrator:
|
|
|
272
396
|
"timestamp": result.timestamp.isoformat(),
|
|
273
397
|
}
|
|
274
398
|
|
|
399
|
+
async def process_api_once(self) -> dict:
|
|
400
|
+
"""
|
|
401
|
+
Execute the API pipeline once for @mesh.route decorators.
|
|
402
|
+
|
|
403
|
+
This handles FastAPI route integration and dependency injection setup.
|
|
404
|
+
"""
|
|
405
|
+
self.logger.info(f"🚀 Starting API pipeline execution: {self.name}")
|
|
406
|
+
|
|
407
|
+
try:
|
|
408
|
+
# Import API pipeline here to avoid circular imports
|
|
409
|
+
from ..api_startup import APIPipeline
|
|
410
|
+
|
|
411
|
+
# Create and execute API pipeline
|
|
412
|
+
api_pipeline = APIPipeline(name=f"{self.name}-api")
|
|
413
|
+
result = await api_pipeline.execute()
|
|
414
|
+
|
|
415
|
+
# Convert result to dict for return type (same format as MCP pipeline)
|
|
416
|
+
return {
|
|
417
|
+
"status": result.status.value,
|
|
418
|
+
"message": result.message,
|
|
419
|
+
"errors": result.errors,
|
|
420
|
+
"context": result.context,
|
|
421
|
+
"timestamp": result.timestamp.isoformat(),
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
except Exception as e:
|
|
425
|
+
error_msg = f"API pipeline execution failed: {e}"
|
|
426
|
+
self.logger.error(f"❌ {error_msg}")
|
|
427
|
+
|
|
428
|
+
return {
|
|
429
|
+
"status": "failed",
|
|
430
|
+
"message": error_msg,
|
|
431
|
+
"errors": [str(e)],
|
|
432
|
+
"context": {},
|
|
433
|
+
"timestamp": "unknown",
|
|
434
|
+
}
|
|
435
|
+
|
|
275
436
|
async def start_service(self, auto_run_config: Optional[dict] = None) -> None:
|
|
276
437
|
"""
|
|
277
438
|
Start the service with optional auto-run behavior.
|
|
@@ -366,6 +527,10 @@ def start_runtime() -> None:
|
|
|
366
527
|
Actual pipeline execution will be triggered by decorator registration
|
|
367
528
|
with a configurable delay to ensure all decorators are captured.
|
|
368
529
|
"""
|
|
530
|
+
# Configure logging FIRST before any log messages
|
|
531
|
+
from ...shared.logging_config import configure_logging
|
|
532
|
+
configure_logging()
|
|
533
|
+
|
|
369
534
|
logger.info("🔧 Starting MCP Mesh runtime with debouncing")
|
|
370
535
|
|
|
371
536
|
# Install signal handlers in main thread FIRST (before any threading)
|
|
@@ -71,12 +71,9 @@ def get_config_value(
|
|
|
71
71
|
raw_value = default
|
|
72
72
|
source = "default"
|
|
73
73
|
|
|
74
|
-
logger.debug(f"Config {env_var}: raw_value={raw_value} (from {source})")
|
|
75
|
-
|
|
76
74
|
# Step 2: Validate and convert the value
|
|
77
75
|
try:
|
|
78
76
|
validated_value = _validate_value(raw_value, rule, env_var)
|
|
79
|
-
logger.debug(f"Config {env_var}: validated_value={validated_value}")
|
|
80
77
|
return validated_value
|
|
81
78
|
|
|
82
79
|
except ConfigResolutionError as e:
|
|
@@ -69,8 +69,9 @@ def configure_logging():
|
|
|
69
69
|
root_logger.addHandler(handler)
|
|
70
70
|
root_logger.setLevel(log_level)
|
|
71
71
|
|
|
72
|
-
# Set level for all mcp_mesh loggers
|
|
72
|
+
# Set level for all mcp_mesh loggers (both mcp_mesh and _mcp_mesh namespaces)
|
|
73
73
|
logging.getLogger("mcp_mesh").setLevel(log_level)
|
|
74
|
+
logging.getLogger("_mcp_mesh").setLevel(log_level)
|
|
74
75
|
|
|
75
76
|
# Return the configured level for reference
|
|
76
77
|
return log_level
|
|
@@ -41,7 +41,7 @@ class AgentContextHelper:
|
|
|
41
41
|
from ..engine.decorator_registry import DecoratorRegistry
|
|
42
42
|
|
|
43
43
|
agent_config = DecoratorRegistry.get_resolved_agent_config()
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
# Extract core configuration fields using proper resolution
|
|
46
46
|
context["agent_id"] = agent_config.get("agent_id", "unknown")
|
|
47
47
|
context["agent_name"] = agent_config.get("name") or os.getenv(
|
|
@@ -191,3 +191,44 @@ class ExecutionTracer:
|
|
|
191
191
|
except Exception as e:
|
|
192
192
|
tracer.end_execution(error=str(e), success=False)
|
|
193
193
|
raise # Re-raise the exception
|
|
194
|
+
|
|
195
|
+
@staticmethod
|
|
196
|
+
async def trace_function_execution_async(
|
|
197
|
+
func: Callable,
|
|
198
|
+
args: tuple,
|
|
199
|
+
kwargs: dict,
|
|
200
|
+
dependencies: list[str],
|
|
201
|
+
mesh_positions: list[int],
|
|
202
|
+
injected_count: int,
|
|
203
|
+
logger_instance: logging.Logger,
|
|
204
|
+
) -> Any:
|
|
205
|
+
"""
|
|
206
|
+
Trace async function execution with comprehensive logging.
|
|
207
|
+
|
|
208
|
+
This is a static method that handles the complete execution flow with proper
|
|
209
|
+
exception handling and cleanup. If tracing is disabled, calls function directly.
|
|
210
|
+
"""
|
|
211
|
+
import inspect
|
|
212
|
+
|
|
213
|
+
# If tracing is disabled, call function directly without any overhead
|
|
214
|
+
if not _is_tracing_enabled():
|
|
215
|
+
if inspect.iscoroutinefunction(func):
|
|
216
|
+
return await func(*args, **kwargs)
|
|
217
|
+
else:
|
|
218
|
+
return func(*args, **kwargs)
|
|
219
|
+
|
|
220
|
+
tracer = ExecutionTracer(func.__name__, logger_instance)
|
|
221
|
+
tracer.start_execution(
|
|
222
|
+
args, kwargs, dependencies, mesh_positions, injected_count
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
if inspect.iscoroutinefunction(func):
|
|
227
|
+
result = await func(*args, **kwargs)
|
|
228
|
+
else:
|
|
229
|
+
result = func(*args, **kwargs)
|
|
230
|
+
tracer.end_execution(result, success=True)
|
|
231
|
+
return result
|
|
232
|
+
except Exception as e:
|
|
233
|
+
tracer.end_execution(error=str(e), success=False)
|
|
234
|
+
raise # Re-raise the exception
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-mesh
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Kubernetes-native platform for distributed MCP applications
|
|
5
5
|
Project-URL: Homepage, https://github.com/dhyansraj/mcp-mesh
|
|
6
6
|
Project-URL: Documentation, https://github.com/dhyansraj/mcp-mesh/tree/main/docs
|
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
_mcp_mesh/__init__.py,sha256=
|
|
2
|
-
_mcp_mesh/engine/__init__.py,sha256=
|
|
3
|
-
_mcp_mesh/engine/async_mcp_client.py,sha256=
|
|
4
|
-
_mcp_mesh/engine/decorator_registry.py,sha256=
|
|
5
|
-
_mcp_mesh/engine/dependency_injector.py,sha256=
|
|
6
|
-
_mcp_mesh/engine/full_mcp_proxy.py,sha256=
|
|
7
|
-
_mcp_mesh/engine/http_wrapper.py,sha256=
|
|
8
|
-
_mcp_mesh/engine/mcp_client_proxy.py,sha256=
|
|
1
|
+
_mcp_mesh/__init__.py,sha256=BAOIf5sCRsdTxO-EgvzGKGN24_NRdv21wYj6uKjSHYM,2646
|
|
2
|
+
_mcp_mesh/engine/__init__.py,sha256=2ennzbo7yJcpkXO9BqN69TruLjJfmJY4Y5VEsG644K4,3630
|
|
3
|
+
_mcp_mesh/engine/async_mcp_client.py,sha256=UcbQjxtgVfeRw6DHTZhAzN1gkcKlTg-lUPEePRPQWAU,6306
|
|
4
|
+
_mcp_mesh/engine/decorator_registry.py,sha256=Dy3de-CQa3T4-BRV5Xx6Ks3s6gvgL-lcxCYLsfrTdX0,19085
|
|
5
|
+
_mcp_mesh/engine/dependency_injector.py,sha256=tzsv10U_EG8GjhTvlF2fsoXkKQ2x52_WYQCOaLlgWfs,26568
|
|
6
|
+
_mcp_mesh/engine/full_mcp_proxy.py,sha256=PlRv7GSKqn5riOCqeCVulVdtq3z1Ug76mOkwMsOFHXw,25297
|
|
7
|
+
_mcp_mesh/engine/http_wrapper.py,sha256=7Djx5zreai4c644sDpwpV_Kn35Ie6_ulUhqFOWoU_kU,21110
|
|
8
|
+
_mcp_mesh/engine/mcp_client_proxy.py,sha256=eJStwy_VQJexYYD8bOh_m4Ld3Bb8Ae_dt8N1CC41qBc,17625
|
|
9
9
|
_mcp_mesh/engine/self_dependency_proxy.py,sha256=OkKt0-B_ADnJlWtHiHItoZCBZ7Su0iz2unEPFfXvrs4,3302
|
|
10
10
|
_mcp_mesh/engine/session_aware_client.py,sha256=mc9eh-aCvUvfllORiXTf_X8_jPqV-32QdWKlr8tHLkU,10600
|
|
11
11
|
_mcp_mesh/engine/session_manager.py,sha256=MCr0_fXBaUjXM51WU5EhDkiGvBdfzYQFVNb9DCXXL0A,10418
|
|
12
12
|
_mcp_mesh/engine/signature_analyzer.py,sha256=AxBuFq8_TCT2afw_XDF4AjWPqdG6ST5jfbw2BDdp9Mo,7482
|
|
13
|
+
_mcp_mesh/engine/unified_mcp_proxy.py,sha256=pKKwfe5qEKa_JwKelHw6t0hJyYpBMHGYdZ3mFuo3QxY,32748
|
|
13
14
|
_mcp_mesh/generated/.openapi-generator-ignore,sha256=-d-Y-RVAZRrHw36jO0b79oDXpfA8rZdBGPCG4Vs_rUs,227
|
|
14
|
-
_mcp_mesh/generated/.openapi-generator/FILES,sha256=
|
|
15
|
+
_mcp_mesh/generated/.openapi-generator/FILES,sha256=BXFXHe4FTV5GFUTNjMhmvOrVcYVlHJc5O-3UXyp8OCY,2169
|
|
15
16
|
_mcp_mesh/generated/.openapi-generator/VERSION,sha256=nMm490YXJUW3_vAdeAsg7E3yRgUqVwk5-50PuaFonM8,7
|
|
16
|
-
_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py,sha256=
|
|
17
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py,sha256=C_J51kNjdAQ2ikcXQzaIC0x9HQgbibT02x1rmWpeKGw,5604
|
|
17
18
|
_mcp_mesh/generated/mcp_mesh_registry_client/api_client.py,sha256=SLzm-p1vhbhufVDn7sNKjq9aSBkZUXTdwRIf7Ne57l8,28104
|
|
18
19
|
_mcp_mesh/generated/mcp_mesh_registry_client/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
|
|
19
20
|
_mcp_mesh/generated/mcp_mesh_registry_client/configuration.py,sha256=PCZ03PQGCEG0lfIn4s1tk8WrB9HpQ-LCXIUK110F1gY,18544
|
|
20
21
|
_mcp_mesh/generated/mcp_mesh_registry_client/exceptions.py,sha256=wMmZWaCPfoAloDVS4u9MkRKG0oUjXl_B-3KAOrFQbUM,6921
|
|
21
22
|
_mcp_mesh/generated/mcp_mesh_registry_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
23
|
_mcp_mesh/generated/mcp_mesh_registry_client/rest.py,sha256=myEMrqhlSTaYUu52NlhUqFFTTMkhBI4V5cXaxjciWSI,9948
|
|
23
|
-
_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py,sha256=
|
|
24
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py,sha256=CP4BRsWFhioEIcU_fXbONaCa222wnWB8fTwADfqGUsc,296
|
|
24
25
|
_mcp_mesh/generated/mcp_mesh_registry_client/api/agents_api.py,sha256=rHY0h_wcv9eLRzOitkRZ7PDKtgWr5xism3azkZpuI6I,46445
|
|
25
26
|
_mcp_mesh/generated/mcp_mesh_registry_client/api/health_api.py,sha256=BJsqdNHz-dZXJsvQmYdZLLM_vf1Lf6DKRH9xzpyfkuU,30552
|
|
26
|
-
_mcp_mesh/generated/mcp_mesh_registry_client/
|
|
27
|
-
_mcp_mesh/generated/mcp_mesh_registry_client/models/
|
|
27
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py,sha256=2FmSDoWiAfx404kB5mkWvYviE37QVY-Cb-kA90o1rn8,13179
|
|
28
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py,sha256=s54kd3wYhgltJgOFD0RLQX7prcuI4uDibwVXXo5SrTs,3968
|
|
29
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py,sha256=ZD3qwc7GlKYV3Jlxbc79gEJWf-2_H0m07GVyHL4cCVw,5293
|
|
28
30
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata.py,sha256=_ixbM8wlhL5C7jx-NXoA0zdJSK88-TX8URuCIOv7_E8,6520
|
|
29
31
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner.py,sha256=LiO2JfFwasidNJ859LKmDHa6kV1boGIlTdhFwmpgoxw,6303
|
|
30
32
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner_one_of.py,sha256=aQ7h5TloM-FvBrQ0uzH0m9iba4EbX--djxh8etcXids,3615
|
|
@@ -42,7 +44,7 @@ _mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request.py,sha256=
|
|
|
42
44
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request_metadata.py,sha256=A-L6mFz19Pa-QExvCihCHrJDHIlIV18w290usgD6_Yo,4317
|
|
43
45
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_response.py,sha256=dPJxz5XQukw4QejkeP7F3FAm8m0wW-5gm9xpajlkGqQ,4907
|
|
44
46
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_register_metadata.py,sha256=HGABUatJp_mu2uFWzC7HBEZACHXIKFmIeegFYfHEcN4,4820
|
|
45
|
-
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py,sha256=
|
|
47
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py,sha256=qZiljiQH877iBN35poelxDPPnHwpjbu9J2yCwKmZgg8,6182
|
|
46
48
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py,sha256=tKG2maoADs_cXc2IdU-Pycsf0jyfOLnqeGZJtLXwf3E,5075
|
|
47
49
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response_dependencies_resolved_value_inner.py,sha256=tmcFBO8rbB_F-TfpU2lsG29CKTpQPfiuJqE62r81p0k,4071
|
|
48
50
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_dependency_registration.py,sha256=PkY1rWdS3y5TTxRRFpATWmm3dhw_Qw2_4QBzCv_7ZuU,3658
|
|
@@ -52,48 +54,64 @@ _mcp_mesh/generated/mcp_mesh_registry_client/models/registration_response.py,sha
|
|
|
52
54
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/rich_dependency.py,sha256=Y6TB1Zvfkq2U8YMSmWUmIcOZMU6ZZxRFmifUGwdRwa0,3591
|
|
53
55
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/root_response.py,sha256=Das3mRHvgqDJVuWsoWLtwUTv_I5nFejhV10U0JZ_CZM,3221
|
|
54
56
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py,sha256=fm1tmP0f07ziGMz0zYvpIvMGeIcfff2wrS6jlWgvm9A,3650
|
|
55
|
-
_mcp_mesh/
|
|
56
|
-
_mcp_mesh/pipeline/
|
|
57
|
-
_mcp_mesh/pipeline/
|
|
58
|
-
_mcp_mesh/pipeline/
|
|
59
|
-
_mcp_mesh/pipeline/
|
|
60
|
-
_mcp_mesh/pipeline/
|
|
61
|
-
_mcp_mesh/pipeline/
|
|
62
|
-
_mcp_mesh/pipeline/
|
|
63
|
-
_mcp_mesh/pipeline/
|
|
57
|
+
_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py,sha256=9Q_8WaVl0MxswRnHpkqq9GKnvOW54HW4tkrTM9oda14,4461
|
|
58
|
+
_mcp_mesh/pipeline/__init__.py,sha256=9Aplh4m1z-rYTQys0JQLYlq9wTPdI72eSOhUPqcnvpA,1557
|
|
59
|
+
_mcp_mesh/pipeline/api_heartbeat/__init__.py,sha256=IXTLoQLAPqQEWZ8VMWc5W_cQJkDv95rlVGXyXoQDjHk,473
|
|
60
|
+
_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py,sha256=EcWfqZ2IWcagt0pGkVa944uW7KePABVXn6CPAAspjYo,23582
|
|
61
|
+
_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py,sha256=PY4bbuZgxy3r0ccuBl-OuJvcPSMhyGz4FomxwYFhuvM,4821
|
|
62
|
+
_mcp_mesh/pipeline/api_heartbeat/api_health_check.py,sha256=kDmFeOG_4tyqyJSBZjPcc7xTzGpP4vq6ObW_WBqXvzM,5130
|
|
63
|
+
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py,sha256=uBswzWOBzU8p_C0AE2DF8UwIWG4rP2zecHfPqKzNuC0,10367
|
|
64
|
+
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py,sha256=so8IyKT-Wg7lQk3ULdox9CAOrowzxpUs76e93PQnCik,13520
|
|
65
|
+
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py,sha256=0Qy6zau_3a2qtQdd2wzjXv-QhhzR6bwAaEun8Re9hXo,14546
|
|
66
|
+
_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py,sha256=WBo2crcaGfxi8Q46TU-i5OMhAv0sQKz7Z9jps-GLkvM,5183
|
|
67
|
+
_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py,sha256=6N0JdXdnLkaXau4t8syt9DLgv9Y51SPfTXYK3DefBk8,3846
|
|
68
|
+
_mcp_mesh/pipeline/api_startup/__init__.py,sha256=eivolkSKot2bJTWP2BV8-RKRT1Zm7SGQYuEUiTxusOQ,577
|
|
69
|
+
_mcp_mesh/pipeline/api_startup/api_pipeline.py,sha256=9KMyryefhaPBkGJylNoFcFr5Ezh6NJWKBOJfVJaVJ5A,2302
|
|
70
|
+
_mcp_mesh/pipeline/api_startup/api_server_setup.py,sha256=Qy0wbXyIWIQYA7CjiGVZwn0nWCKK85ZzFTRI2JDA9Aw,15099
|
|
71
|
+
_mcp_mesh/pipeline/api_startup/fastapi_discovery.py,sha256=BOo7_cBwABNpk_3Y-Lh_3ygwAOQ_254dwblPyO_vLIw,11991
|
|
72
|
+
_mcp_mesh/pipeline/api_startup/route_collection.py,sha256=UjA-F5_RbGVU5TfDT19Np5_x2PtYkNn2mGFyivDsk24,2031
|
|
73
|
+
_mcp_mesh/pipeline/api_startup/route_integration.py,sha256=aMT7p7cwK8N3tZBRqeGQF8upc7tU-Exj6Dz0a4cSBhU,13441
|
|
74
|
+
_mcp_mesh/pipeline/mcp_heartbeat/__init__.py,sha256=nRNjZ3VD_9bPLQuJ6Nc02gE7KSLcMP7TMquB0hP6hHs,844
|
|
75
|
+
_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py,sha256=nHjKSM4Yyn05wnfw1dI4VGroHZy8lRkDihnZfFHeF8U,16217
|
|
76
|
+
_mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py,sha256=QTzYdL81WERkOaBVOgNbFQh1ddTn70urNtyIgtFTudA,4465
|
|
77
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py,sha256=56IK5p8xlppJ5i6oMMh12fin3XwrOTcppTuVO2CnlV8,11292
|
|
78
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py,sha256=Jb7EVJO13trUVO3aCSgzGqAtoc4vie5kDrYLZtOkiXg,11601
|
|
79
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py,sha256=ydVx-Vb_RgW1WPCboHVdZfEwNbgDngFV6Y9elZIBrAw,3602
|
|
80
|
+
_mcp_mesh/pipeline/mcp_heartbeat/lifespan_integration.py,sha256=yCt731vgniSfxuClIcMvlMtDrubTu_9crgwiOwOYoBQ,2510
|
|
81
|
+
_mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py,sha256=4abbOKN3echwX82PV0RvxF6cJZUu0pMgisOpILZ_ZzY,2875
|
|
82
|
+
_mcp_mesh/pipeline/mcp_startup/__init__.py,sha256=_Y25DgT9eYJ_7Qe7x1Z7y4VFUIaFEmCBS9YD9QIlo7k,1142
|
|
83
|
+
_mcp_mesh/pipeline/mcp_startup/configuration.py,sha256=6LRLIxrqFMU76qrBb6GjGknUlKPZZ9iqOlxE7F9ZhLs,2808
|
|
84
|
+
_mcp_mesh/pipeline/mcp_startup/decorator_collection.py,sha256=RHC6MHtfP9aP0hZ-IJjISZu72e0Pml3LU0qr7dc284w,2294
|
|
85
|
+
_mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py,sha256=pQIrEc70qeWP732S9LF5A2qWq0CZ5wK-bxls7AjX_2o,33346
|
|
86
|
+
_mcp_mesh/pipeline/mcp_startup/fastmcpserver_discovery.py,sha256=ktsE9EZYdyZbCtCKB6HVdzGFMQ0E9n0-7I55LRO99sE,10270
|
|
87
|
+
_mcp_mesh/pipeline/mcp_startup/heartbeat_loop.py,sha256=v85B0ynomvYu87eIvLe-aSZ7-Iwov2VtM4Fg3PkmrZs,3865
|
|
88
|
+
_mcp_mesh/pipeline/mcp_startup/heartbeat_preparation.py,sha256=v3Fl0PvW5s7Ib_Cy7WtXA7gDvsFGiz54a-IlQRTcLPg,10410
|
|
89
|
+
_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py,sha256=W9o_d0xTOAqK5i8Xd7BJgiUJou1uPZwsygslM3I9HYo,25149
|
|
90
|
+
_mcp_mesh/pipeline/mcp_startup/startup_pipeline.py,sha256=E-kmmfkdtRMhpEAF-_qFLAdaY3sLo165SUHjlRXwqC4,2069
|
|
64
91
|
_mcp_mesh/pipeline/shared/__init__.py,sha256=s9xmdf6LkoetrVRGd7Zp3NUxcJCW6YZ_yNKzUBcnYys,352
|
|
65
92
|
_mcp_mesh/pipeline/shared/base_step.py,sha256=kyPbNUX79NyGrE_0Q-e-Aek7m1J0TW036njWfv0iZ0I,1080
|
|
66
93
|
_mcp_mesh/pipeline/shared/mesh_pipeline.py,sha256=wTODlMb7ByhzsT3DnM0lzY3gS9fKLDUxL0yDEozCVeo,6494
|
|
67
94
|
_mcp_mesh/pipeline/shared/pipeline_types.py,sha256=iKSgzCoYu3bpIwLViw6lE7T7irEzOm7gpie29lyy7SQ,1504
|
|
68
95
|
_mcp_mesh/pipeline/shared/registry_connection.py,sha256=jmlgULixRM1NMNyMc-8SJN3RpCtV9hUf76vn9nciAN4,2904
|
|
69
|
-
_mcp_mesh/pipeline/startup/__init__.py,sha256=_Y25DgT9eYJ_7Qe7x1Z7y4VFUIaFEmCBS9YD9QIlo7k,1142
|
|
70
|
-
_mcp_mesh/pipeline/startup/configuration.py,sha256=6LRLIxrqFMU76qrBb6GjGknUlKPZZ9iqOlxE7F9ZhLs,2808
|
|
71
|
-
_mcp_mesh/pipeline/startup/decorator_collection.py,sha256=RHC6MHtfP9aP0hZ-IJjISZu72e0Pml3LU0qr7dc284w,2294
|
|
72
|
-
_mcp_mesh/pipeline/startup/fastapiserver_setup.py,sha256=pQIrEc70qeWP732S9LF5A2qWq0CZ5wK-bxls7AjX_2o,33346
|
|
73
|
-
_mcp_mesh/pipeline/startup/fastmcpserver_discovery.py,sha256=ktsE9EZYdyZbCtCKB6HVdzGFMQ0E9n0-7I55LRO99sE,10270
|
|
74
|
-
_mcp_mesh/pipeline/startup/heartbeat_loop.py,sha256=0IX2Q-OJvTVsNILUKxl7v3-BM8DdAW3UB-W-Z2gAWrc,3861
|
|
75
|
-
_mcp_mesh/pipeline/startup/heartbeat_preparation.py,sha256=v3Fl0PvW5s7Ib_Cy7WtXA7gDvsFGiz54a-IlQRTcLPg,10410
|
|
76
|
-
_mcp_mesh/pipeline/startup/startup_orchestrator.py,sha256=r0po5cQKe9F5nO6ey5PmYGjYKHe5u8pNEFy7Da0Lh5w,17835
|
|
77
|
-
_mcp_mesh/pipeline/startup/startup_pipeline.py,sha256=E-kmmfkdtRMhpEAF-_qFLAdaY3sLo165SUHjlRXwqC4,2069
|
|
78
96
|
_mcp_mesh/shared/__init__.py,sha256=L0detgEWjnc_XfxA_5vIBcaGTuLcT6AARKkUpUBIaH4,1116
|
|
79
|
-
_mcp_mesh/shared/config_resolver.py,sha256=
|
|
97
|
+
_mcp_mesh/shared/config_resolver.py,sha256=r8WcO8lrd4XBHhH9IkAM7iy-QeCmTiVLmKhnJ47pFP0,7780
|
|
80
98
|
_mcp_mesh/shared/content_extractor.py,sha256=culjhieFl_J6EMDv1VFKvS38O3IMhWMs8fHhNuR2rVk,3656
|
|
81
99
|
_mcp_mesh/shared/defaults.py,sha256=5qazybkn7QHi418dXCS0b6QlNQl3DMg97ItzNGkc8d4,1851
|
|
82
100
|
_mcp_mesh/shared/fast_heartbeat_status.py,sha256=OquEsX9ZTbxY1lIsll0Mbb2KDzSJD76sLMOlr3Z73Sc,5188
|
|
83
101
|
_mcp_mesh/shared/host_resolver.py,sha256=ycs6gXnI1zJX5KiqiLJPX5GkHX8r4j8NMHQOlG2J2X8,2964
|
|
84
|
-
_mcp_mesh/shared/logging_config.py,sha256=
|
|
102
|
+
_mcp_mesh/shared/logging_config.py,sha256=n9AqShZ5BZgyrkoTlvux6ECRVpM9dUYvmGB0NPMl-Ak,2477
|
|
85
103
|
_mcp_mesh/shared/registry_client_wrapper.py,sha256=d8yL-MiCrQr_WYdRFStOd531qaLv9kZjh0zJAmCJ-Cc,16976
|
|
86
104
|
_mcp_mesh/shared/sse_parser.py,sha256=OEPnfL9xL3rsjQrbyvfUO82WljPSDeO6Z61uUwN1NAo,8035
|
|
87
105
|
_mcp_mesh/shared/support_types.py,sha256=k-ICF_UwDkHxQ1D5LwFZrp-UrNb4E5dzw02CRuLW9iI,7264
|
|
88
|
-
_mcp_mesh/tracing/agent_context_helper.py,sha256=
|
|
106
|
+
_mcp_mesh/tracing/agent_context_helper.py,sha256=gODirjGf80vTLoHaVZgOOLlf068Tfxg-3GBn2GOBUaY,4607
|
|
89
107
|
_mcp_mesh/tracing/context.py,sha256=yZtTZXVKltX2BUBrWeeNfQ8Y4n6L_2ywFVlFP-wU9og,2353
|
|
90
|
-
_mcp_mesh/tracing/execution_tracer.py,sha256=
|
|
108
|
+
_mcp_mesh/tracing/execution_tracer.py,sha256=Wx6cE7CskZqBPsrn4Fmkyd3DLR9R_E4j_BCLVx1cOWE,8293
|
|
91
109
|
_mcp_mesh/tracing/redis_metadata_publisher.py,sha256=5U5GojBFYZdxJJ1RvmdxXHC-VuPQz4kMla6n0xdZxKc,5371
|
|
92
110
|
_mcp_mesh/tracing/trace_context_helper.py,sha256=xPDygKrXcoJbrr7013Av_I0ajammWEq68ihdP7DZ-Zo,6072
|
|
93
|
-
mesh/__init__.py,sha256=
|
|
94
|
-
mesh/decorators.py,sha256=
|
|
95
|
-
mesh/types.py,sha256=
|
|
96
|
-
mcp_mesh-0.
|
|
97
|
-
mcp_mesh-0.
|
|
98
|
-
mcp_mesh-0.
|
|
99
|
-
mcp_mesh-0.
|
|
111
|
+
mesh/__init__.py,sha256=l5RSMV8Kx0h7cvku8YkZPbTHjEPWciGT0bcEB2O_eNU,3242
|
|
112
|
+
mesh/decorators.py,sha256=UWNfykDBCChpIqqljcjAAzlJphv5TMZLEBCNzwfl478,24264
|
|
113
|
+
mesh/types.py,sha256=g37DXAzya-xGPa1_WKlW3T3_VqyTn8ZVepIDSrhBTkc,10815
|
|
114
|
+
mcp_mesh-0.5.1.dist-info/METADATA,sha256=8R-o_N6olx0pnUwDUij1I2PN2IYFkd9Mmrg-ocBL3ls,4879
|
|
115
|
+
mcp_mesh-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
116
|
+
mcp_mesh-0.5.1.dist-info/licenses/LICENSE,sha256=_EBQHRQThv9FPOLc5eFOUdeeRO0mYwChC7cx60dM1tM,1078
|
|
117
|
+
mcp_mesh-0.5.1.dist-info/RECORD,,
|
mesh/__init__.py
CHANGED
|
@@ -87,12 +87,14 @@ def create_server(name: str | None = None) -> "FastMCP":
|
|
|
87
87
|
return FastMCP(name=name)
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
# Make decorators available as mesh.tool and mesh.
|
|
90
|
+
# Make decorators available as mesh.tool, mesh.agent, and mesh.route
|
|
91
91
|
def __getattr__(name):
|
|
92
92
|
if name == "tool":
|
|
93
93
|
return decorators.tool
|
|
94
94
|
elif name == "agent":
|
|
95
95
|
return decorators.agent
|
|
96
|
+
elif name == "route":
|
|
97
|
+
return decorators.route
|
|
96
98
|
elif name == "McpMeshAgent":
|
|
97
99
|
return McpMeshAgent
|
|
98
100
|
elif name == "McpAgent":
|
mesh/decorators.py
CHANGED
|
@@ -32,7 +32,7 @@ def _trigger_debounced_processing():
|
|
|
32
32
|
all decorators are captured before processing begins.
|
|
33
33
|
"""
|
|
34
34
|
try:
|
|
35
|
-
from _mcp_mesh.pipeline.
|
|
35
|
+
from _mcp_mesh.pipeline.mcp_startup import get_debounce_coordinator
|
|
36
36
|
|
|
37
37
|
coordinator = get_debounce_coordinator()
|
|
38
38
|
coordinator.trigger_processing()
|
|
@@ -485,3 +485,145 @@ def agent(
|
|
|
485
485
|
return target
|
|
486
486
|
|
|
487
487
|
return decorator
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def route(
|
|
491
|
+
*,
|
|
492
|
+
dependencies: list[dict[str, Any]] | list[str] | None = None,
|
|
493
|
+
**kwargs: Any,
|
|
494
|
+
) -> Callable[[T], T]:
|
|
495
|
+
"""
|
|
496
|
+
FastAPI route handler decorator for dependency injection.
|
|
497
|
+
|
|
498
|
+
Enables automatic dependency injection of MCP agents into FastAPI route handlers,
|
|
499
|
+
eliminating the need for manual MCP client management in backend services.
|
|
500
|
+
|
|
501
|
+
Args:
|
|
502
|
+
dependencies: Optional list of agent capabilities to inject (default: [])
|
|
503
|
+
**kwargs: Additional metadata for the route
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
The original route handler function with dependency injection enabled
|
|
507
|
+
|
|
508
|
+
Example:
|
|
509
|
+
@app.post("/upload")
|
|
510
|
+
@mesh.route(dependencies=["pdf-extractor", "user-service"])
|
|
511
|
+
async def upload_resume(
|
|
512
|
+
request: Request,
|
|
513
|
+
file: UploadFile = File(...),
|
|
514
|
+
pdf_agent: McpAgent = None, # Injected by MCP Mesh
|
|
515
|
+
user_service: McpAgent = None # Injected by MCP Mesh
|
|
516
|
+
):
|
|
517
|
+
result = await pdf_agent.extract_text_from_pdf(file)
|
|
518
|
+
await user_service.update_profile(user_data, result)
|
|
519
|
+
return {"success": True}
|
|
520
|
+
"""
|
|
521
|
+
|
|
522
|
+
def decorator(target: T) -> T:
|
|
523
|
+
# Validate and process dependencies (reuse logic from tool decorator)
|
|
524
|
+
if dependencies is not None:
|
|
525
|
+
if not isinstance(dependencies, list):
|
|
526
|
+
raise ValueError("dependencies must be a list")
|
|
527
|
+
|
|
528
|
+
validated_dependencies = []
|
|
529
|
+
for dep in dependencies:
|
|
530
|
+
if isinstance(dep, str):
|
|
531
|
+
# Simple string dependency
|
|
532
|
+
validated_dependencies.append({
|
|
533
|
+
"capability": dep,
|
|
534
|
+
"tags": [],
|
|
535
|
+
})
|
|
536
|
+
elif isinstance(dep, dict):
|
|
537
|
+
# Complex dependency with metadata
|
|
538
|
+
if "capability" not in dep:
|
|
539
|
+
raise ValueError("dependency must have 'capability' field")
|
|
540
|
+
if not isinstance(dep["capability"], str):
|
|
541
|
+
raise ValueError("dependency capability must be a string")
|
|
542
|
+
|
|
543
|
+
# Validate optional dependency fields
|
|
544
|
+
dep_tags = dep.get("tags", [])
|
|
545
|
+
if not isinstance(dep_tags, list):
|
|
546
|
+
raise ValueError("dependency tags must be a list")
|
|
547
|
+
for tag in dep_tags:
|
|
548
|
+
if not isinstance(tag, str):
|
|
549
|
+
raise ValueError("all dependency tags must be strings")
|
|
550
|
+
|
|
551
|
+
dep_version = dep.get("version")
|
|
552
|
+
if dep_version is not None and not isinstance(dep_version, str):
|
|
553
|
+
raise ValueError("dependency version must be a string")
|
|
554
|
+
|
|
555
|
+
dependency_dict = {
|
|
556
|
+
"capability": dep["capability"],
|
|
557
|
+
"tags": dep_tags,
|
|
558
|
+
}
|
|
559
|
+
if dep_version is not None:
|
|
560
|
+
dependency_dict["version"] = dep_version
|
|
561
|
+
validated_dependencies.append(dependency_dict)
|
|
562
|
+
else:
|
|
563
|
+
raise ValueError("dependencies must be strings or dictionaries")
|
|
564
|
+
else:
|
|
565
|
+
validated_dependencies = []
|
|
566
|
+
|
|
567
|
+
# Build route metadata
|
|
568
|
+
metadata = {
|
|
569
|
+
"dependencies": validated_dependencies,
|
|
570
|
+
"description": getattr(target, "__doc__", None),
|
|
571
|
+
**kwargs,
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
# Store metadata on function
|
|
575
|
+
target._mesh_route_metadata = metadata
|
|
576
|
+
|
|
577
|
+
# Register with DecoratorRegistry using custom decorator type
|
|
578
|
+
DecoratorRegistry.register_custom_decorator("mesh_route", target, metadata)
|
|
579
|
+
|
|
580
|
+
logger.debug(
|
|
581
|
+
f"🔍 Route '{target.__name__}' registered with {len(validated_dependencies)} dependencies"
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
try:
|
|
585
|
+
# Import here to avoid circular imports
|
|
586
|
+
from _mcp_mesh.engine.dependency_injector import get_global_injector
|
|
587
|
+
|
|
588
|
+
# Extract dependency names for injector
|
|
589
|
+
dependency_names = [dep["capability"] for dep in validated_dependencies]
|
|
590
|
+
|
|
591
|
+
# Log the original function pointer
|
|
592
|
+
logger.debug(f"🔸 ORIGINAL route function pointer: {target} at {hex(id(target))}")
|
|
593
|
+
|
|
594
|
+
injector = get_global_injector()
|
|
595
|
+
wrapped = injector.create_injection_wrapper(target, dependency_names)
|
|
596
|
+
|
|
597
|
+
# Log the wrapper function pointer
|
|
598
|
+
logger.debug(
|
|
599
|
+
f"🔹 WRAPPER route function pointer: {wrapped} at {hex(id(wrapped))}"
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
# Preserve metadata on wrapper
|
|
603
|
+
wrapped._mesh_route_metadata = metadata
|
|
604
|
+
|
|
605
|
+
# Store the wrapper on the original function for reference
|
|
606
|
+
target._mesh_injection_wrapper = wrapped
|
|
607
|
+
|
|
608
|
+
# Also store a flag on the wrapper itself so route integration can detect it
|
|
609
|
+
wrapped._mesh_is_injection_wrapper = True
|
|
610
|
+
|
|
611
|
+
# Return the wrapped function - FastAPI will register this wrapper when it runs
|
|
612
|
+
logger.debug(f"✅ Returning injection wrapper for route '{target.__name__}'")
|
|
613
|
+
logger.debug(f"🔹 Returning WRAPPER: {wrapped} at {hex(id(wrapped))}")
|
|
614
|
+
|
|
615
|
+
# Trigger debounced processing before returning
|
|
616
|
+
_trigger_debounced_processing()
|
|
617
|
+
return wrapped
|
|
618
|
+
|
|
619
|
+
except Exception as e:
|
|
620
|
+
# Log but don't fail - graceful degradation
|
|
621
|
+
logger.error(
|
|
622
|
+
f"Route dependency injection setup failed for {target.__name__}: {e}"
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Fallback: return original function and trigger processing
|
|
626
|
+
_trigger_debounced_processing()
|
|
627
|
+
return target
|
|
628
|
+
|
|
629
|
+
return decorator
|