mcp-mesh 0.5.5__py3-none-any.whl → 0.5.7__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 +1 -1
- _mcp_mesh/engine/dependency_injector.py +122 -57
- _mcp_mesh/engine/signature_analyzer.py +23 -14
- _mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +107 -58
- _mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +58 -30
- _mcp_mesh/pipeline/mcp_heartbeat/lifespan_integration.py +13 -0
- _mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py +40 -4
- _mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +4 -154
- _mcp_mesh/shared/simple_shutdown.py +217 -0
- {mcp_mesh-0.5.5.dist-info → mcp_mesh-0.5.7.dist-info}/METADATA +1 -1
- {mcp_mesh-0.5.5.dist-info → mcp_mesh-0.5.7.dist-info}/RECORD +14 -14
- mesh/decorators.py +29 -20
- _mcp_mesh/shared/graceful_shutdown_manager.py +0 -236
- {mcp_mesh-0.5.5.dist-info → mcp_mesh-0.5.7.dist-info}/WHEEL +0 -0
- {mcp_mesh-0.5.5.dist-info → mcp_mesh-0.5.7.dist-info}/licenses/LICENSE +0 -0
_mcp_mesh/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Dynamic dependency injection system for MCP Mesh.
|
|
3
3
|
|
|
4
4
|
Handles both initial injection and runtime updates when topology changes.
|
|
5
|
-
Focused purely on dependency injection - telemetry/tracing is handled at
|
|
5
|
+
Focused purely on dependency injection - telemetry/tracing is handled at
|
|
6
6
|
the HTTP middleware layer for unified approach across MCP agents and FastAPI apps.
|
|
7
7
|
"""
|
|
8
8
|
|
|
@@ -57,17 +57,17 @@ def analyze_injection_strategy(func: Callable, dependencies: list[str]) -> list[
|
|
|
57
57
|
logger.warning(
|
|
58
58
|
f"Single parameter '{param_name}' in function '{func_name}' found, "
|
|
59
59
|
f"injecting {dependencies[0] if dependencies else 'dependency'} proxy "
|
|
60
|
-
f"(consider typing as McpMeshAgent for clarity)"
|
|
60
|
+
f"(consider typing as McpMeshAgent or McpAgent for clarity)"
|
|
61
61
|
)
|
|
62
62
|
return [0] # Inject into the single parameter
|
|
63
63
|
|
|
64
|
-
# Multiple parameters rule: only inject into McpMeshAgent typed parameters
|
|
64
|
+
# Multiple parameters rule: only inject into McpMeshAgent or McpAgent typed parameters
|
|
65
65
|
if param_count > 1:
|
|
66
66
|
if not mesh_positions:
|
|
67
67
|
logger.warning(
|
|
68
68
|
f"⚠️ Function '{func_name}' has {param_count} parameters but none are "
|
|
69
|
-
f"typed as McpMeshAgent. Skipping injection of {len(dependencies)} dependencies. "
|
|
70
|
-
f"Consider typing dependency parameters as McpMeshAgent."
|
|
69
|
+
f"typed as McpMeshAgent or McpAgent. Skipping injection of {len(dependencies)} dependencies. "
|
|
70
|
+
f"Consider typing dependency parameters as McpMeshAgent or McpAgent."
|
|
71
71
|
)
|
|
72
72
|
return []
|
|
73
73
|
|
|
@@ -77,7 +77,7 @@ def analyze_injection_strategy(func: Callable, dependencies: list[str]) -> list[
|
|
|
77
77
|
excess_deps = dependencies[len(mesh_positions) :]
|
|
78
78
|
logger.warning(
|
|
79
79
|
f"Function '{func_name}' has {len(dependencies)} dependencies "
|
|
80
|
-
f"but only {len(mesh_positions)} McpMeshAgent parameters. "
|
|
80
|
+
f"but only {len(mesh_positions)} McpMeshAgent/McpAgent parameters. "
|
|
81
81
|
f"Dependencies {excess_deps} will not be injected."
|
|
82
82
|
)
|
|
83
83
|
else:
|
|
@@ -85,7 +85,7 @@ def analyze_injection_strategy(func: Callable, dependencies: list[str]) -> list[
|
|
|
85
85
|
params[pos].name for pos in mesh_positions[len(dependencies) :]
|
|
86
86
|
]
|
|
87
87
|
logger.warning(
|
|
88
|
-
f"Function '{func_name}' has {len(mesh_positions)} McpMeshAgent parameters "
|
|
88
|
+
f"Function '{func_name}' has {len(mesh_positions)} McpMeshAgent/McpAgent parameters "
|
|
89
89
|
f"but only {len(dependencies)} dependencies declared. "
|
|
90
90
|
f"Parameters {excess_params} will remain None."
|
|
91
91
|
)
|
|
@@ -118,12 +118,17 @@ class DependencyInjector:
|
|
|
118
118
|
self._lock = asyncio.Lock()
|
|
119
119
|
|
|
120
120
|
async def register_dependency(self, name: str, instance: Any) -> None:
|
|
121
|
-
"""Register a new dependency or update existing one.
|
|
121
|
+
"""Register a new dependency or update existing one.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
name: Composite key in format "function_id:dep_N" or legacy capability name
|
|
125
|
+
instance: Proxy instance to register
|
|
126
|
+
"""
|
|
122
127
|
async with self._lock:
|
|
123
128
|
logger.info(f"📦 Registering dependency: {name}")
|
|
124
129
|
self._dependencies[name] = instance
|
|
125
130
|
|
|
126
|
-
# Notify all functions that depend on this
|
|
131
|
+
# Notify all functions that depend on this (using composite keys)
|
|
127
132
|
if name in self._dependency_mapping:
|
|
128
133
|
for func_id in self._dependency_mapping[name]:
|
|
129
134
|
if func_id in self._function_registry:
|
|
@@ -132,10 +137,28 @@ class DependencyInjector:
|
|
|
132
137
|
f"🔄 UPDATING dependency '{name}' for {func_id} -> {func} at {hex(id(func))}"
|
|
133
138
|
)
|
|
134
139
|
if hasattr(func, "_mesh_update_dependency"):
|
|
135
|
-
|
|
140
|
+
# Extract dep_index from composite key (format: "function_id:dep_N")
|
|
141
|
+
if ":dep_" in name:
|
|
142
|
+
dep_index_str = name.split(":dep_")[-1]
|
|
143
|
+
try:
|
|
144
|
+
dep_index = int(dep_index_str)
|
|
145
|
+
func._mesh_update_dependency(dep_index, instance)
|
|
146
|
+
except ValueError:
|
|
147
|
+
logger.warning(
|
|
148
|
+
f"⚠️ Invalid dep_index in key '{name}', skipping update"
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
# Legacy format (shouldn't happen with new code)
|
|
152
|
+
logger.warning(
|
|
153
|
+
f"⚠️ Legacy dependency key format '{name}' not supported in array-based injection"
|
|
154
|
+
)
|
|
136
155
|
|
|
137
156
|
async def unregister_dependency(self, name: str) -> None:
|
|
138
|
-
"""Remove a dependency (e.g., service went down).
|
|
157
|
+
"""Remove a dependency (e.g., service went down).
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
name: Composite key in format "function_id:dep_N" or legacy capability name
|
|
161
|
+
"""
|
|
139
162
|
async with self._lock:
|
|
140
163
|
logger.info(f"🗑️ INJECTOR: Unregistering dependency: {name}")
|
|
141
164
|
if name in self._dependencies:
|
|
@@ -156,7 +179,21 @@ class DependencyInjector:
|
|
|
156
179
|
logger.info(
|
|
157
180
|
f"🗑️ INJECTOR: Removing {name} from function {func_id}"
|
|
158
181
|
)
|
|
159
|
-
|
|
182
|
+
# Extract dep_index from composite key
|
|
183
|
+
if ":dep_" in name:
|
|
184
|
+
dep_index_str = name.split(":dep_")[-1]
|
|
185
|
+
try:
|
|
186
|
+
dep_index = int(dep_index_str)
|
|
187
|
+
func._mesh_update_dependency(dep_index, None)
|
|
188
|
+
except ValueError:
|
|
189
|
+
logger.warning(
|
|
190
|
+
f"⚠️ Invalid dep_index in key '{name}', skipping removal"
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
# Legacy format
|
|
194
|
+
logger.warning(
|
|
195
|
+
f"⚠️ Legacy dependency key format '{name}' not supported in array-based injection"
|
|
196
|
+
)
|
|
160
197
|
else:
|
|
161
198
|
logger.warning(
|
|
162
199
|
f"🗑️ INJECTOR: Function {func_id} has no _mesh_update_dependency method"
|
|
@@ -266,15 +303,16 @@ class DependencyInjector:
|
|
|
266
303
|
# Get parameter type information for proxy selection
|
|
267
304
|
parameter_types = get_agent_parameter_types(func)
|
|
268
305
|
|
|
269
|
-
# Track which dependencies this function needs
|
|
270
|
-
for dep in dependencies:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
306
|
+
# Track which dependencies this function needs (using composite keys)
|
|
307
|
+
for dep_index, dep in enumerate(dependencies):
|
|
308
|
+
dep_key = f"{func_id}:dep_{dep_index}"
|
|
309
|
+
if dep_key not in self._dependency_mapping:
|
|
310
|
+
self._dependency_mapping[dep_key] = set()
|
|
311
|
+
self._dependency_mapping[dep_key].add(func_id)
|
|
274
312
|
|
|
275
|
-
# Store current dependency values
|
|
313
|
+
# Store current dependency values as array (indexed by position)
|
|
276
314
|
if not hasattr(func, "_mesh_injected_deps"):
|
|
277
|
-
func._mesh_injected_deps =
|
|
315
|
+
func._mesh_injected_deps = [None] * len(dependencies)
|
|
278
316
|
|
|
279
317
|
# Store original implementation if not already stored
|
|
280
318
|
if not hasattr(func, "_mesh_original_func"):
|
|
@@ -292,34 +330,45 @@ class DependencyInjector:
|
|
|
292
330
|
|
|
293
331
|
# Check if we need async wrapper for minimal case
|
|
294
332
|
if inspect.iscoroutinefunction(func):
|
|
333
|
+
|
|
295
334
|
@functools.wraps(func)
|
|
296
335
|
async def minimal_wrapper(*args, **kwargs):
|
|
297
336
|
# Use ExecutionTracer for functions without dependencies (v0.4.0 style)
|
|
298
337
|
from ..tracing.execution_tracer import ExecutionTracer
|
|
299
|
-
|
|
300
|
-
|
|
338
|
+
|
|
339
|
+
wrapper_logger.debug(
|
|
340
|
+
f"🔧 DI: Executing async function {func.__name__} (no dependencies)"
|
|
341
|
+
)
|
|
342
|
+
|
|
301
343
|
# For async functions without dependencies, use the async tracer
|
|
302
344
|
return await ExecutionTracer.trace_function_execution_async(
|
|
303
345
|
func, args, kwargs, [], [], 0, wrapper_logger
|
|
304
346
|
)
|
|
347
|
+
|
|
305
348
|
else:
|
|
349
|
+
|
|
306
350
|
@functools.wraps(func)
|
|
307
351
|
def minimal_wrapper(*args, **kwargs):
|
|
308
352
|
# Use ExecutionTracer for functions without dependencies (v0.4.0 style)
|
|
309
353
|
from ..tracing.execution_tracer import ExecutionTracer
|
|
310
|
-
|
|
311
|
-
|
|
354
|
+
|
|
355
|
+
wrapper_logger.debug(
|
|
356
|
+
f"🔧 DI: Executing sync function {func.__name__} (no dependencies)"
|
|
357
|
+
)
|
|
358
|
+
|
|
312
359
|
# Use original function tracer for functions without dependencies
|
|
313
|
-
return ExecutionTracer.trace_original_function(
|
|
360
|
+
return ExecutionTracer.trace_original_function(
|
|
361
|
+
func, args, kwargs, wrapper_logger
|
|
362
|
+
)
|
|
314
363
|
|
|
315
|
-
# Add minimal metadata for compatibility
|
|
316
|
-
minimal_wrapper._mesh_injected_deps =
|
|
364
|
+
# Add minimal metadata for compatibility (use array for consistency)
|
|
365
|
+
minimal_wrapper._mesh_injected_deps = [None] * len(dependencies)
|
|
317
366
|
minimal_wrapper._mesh_dependencies = dependencies
|
|
318
367
|
minimal_wrapper._mesh_positions = mesh_positions
|
|
319
368
|
minimal_wrapper._mesh_parameter_types = get_agent_parameter_types(func)
|
|
320
369
|
minimal_wrapper._mesh_original_func = func
|
|
321
370
|
|
|
322
|
-
def update_dependency(
|
|
371
|
+
def update_dependency(dep_index: int, instance: Any | None) -> None:
|
|
323
372
|
"""No-op update for functions without injection positions."""
|
|
324
373
|
pass
|
|
325
374
|
|
|
@@ -363,7 +412,7 @@ class DependencyInjector:
|
|
|
363
412
|
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: params={params}")
|
|
364
413
|
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: original kwargs={kwargs}")
|
|
365
414
|
|
|
366
|
-
# Inject dependencies as kwargs
|
|
415
|
+
# Inject dependencies as kwargs (using array-based lookup)
|
|
367
416
|
injected_count = 0
|
|
368
417
|
for dep_index, param_position in enumerate(mesh_positions):
|
|
369
418
|
if dep_index < len(dependencies):
|
|
@@ -379,24 +428,28 @@ class DependencyInjector:
|
|
|
379
428
|
param_name not in final_kwargs
|
|
380
429
|
or final_kwargs.get(param_name) is None
|
|
381
430
|
):
|
|
382
|
-
# Get the dependency from wrapper's storage
|
|
383
|
-
dependency =
|
|
384
|
-
|
|
385
|
-
|
|
431
|
+
# Get the dependency from wrapper's array storage (by index)
|
|
432
|
+
dependency = None
|
|
433
|
+
if dep_index < len(dependency_wrapper._mesh_injected_deps):
|
|
434
|
+
dependency = dependency_wrapper._mesh_injected_deps[
|
|
435
|
+
dep_index
|
|
436
|
+
]
|
|
386
437
|
wrapper_logger.debug(
|
|
387
|
-
f"🔧 DEPENDENCY_WRAPPER: From wrapper storage: {dependency}"
|
|
438
|
+
f"🔧 DEPENDENCY_WRAPPER: From wrapper storage[{dep_index}]: {dependency}"
|
|
388
439
|
)
|
|
389
440
|
|
|
390
441
|
if dependency is None:
|
|
391
|
-
|
|
442
|
+
# Fallback to global storage with composite key
|
|
443
|
+
dep_key = f"{func.__module__}.{func.__qualname__}:dep_{dep_index}"
|
|
444
|
+
dependency = self.get_dependency(dep_key)
|
|
392
445
|
wrapper_logger.debug(
|
|
393
|
-
f"🔧 DEPENDENCY_WRAPPER: From global storage: {dependency}"
|
|
446
|
+
f"🔧 DEPENDENCY_WRAPPER: From global storage[{dep_key}]: {dependency}"
|
|
394
447
|
)
|
|
395
448
|
|
|
396
449
|
final_kwargs[param_name] = dependency
|
|
397
450
|
injected_count += 1
|
|
398
451
|
wrapper_logger.debug(
|
|
399
|
-
f"🔧 DEPENDENCY_WRAPPER: Injected {dep_name} as {param_name}"
|
|
452
|
+
f"🔧 DEPENDENCY_WRAPPER: Injected {dep_name} from index {dep_index} as {param_name}"
|
|
400
453
|
)
|
|
401
454
|
else:
|
|
402
455
|
wrapper_logger.debug(
|
|
@@ -413,7 +466,7 @@ class DependencyInjector:
|
|
|
413
466
|
# ===== EXECUTE WITH DEPENDENCY INJECTION AND TRACING =====
|
|
414
467
|
# Use ExecutionTracer for comprehensive execution logging (v0.4.0 style)
|
|
415
468
|
from ..tracing.execution_tracer import ExecutionTracer
|
|
416
|
-
|
|
469
|
+
|
|
417
470
|
original_func = func._mesh_original_func
|
|
418
471
|
|
|
419
472
|
wrapper_logger.debug(
|
|
@@ -460,7 +513,7 @@ class DependencyInjector:
|
|
|
460
513
|
params = list(sig.parameters.keys())
|
|
461
514
|
final_kwargs = kwargs.copy()
|
|
462
515
|
|
|
463
|
-
# Inject dependencies as kwargs
|
|
516
|
+
# Inject dependencies as kwargs (using array-based lookup)
|
|
464
517
|
injected_count = 0
|
|
465
518
|
for dep_index, param_position in enumerate(mesh_positions):
|
|
466
519
|
if dep_index < len(dependencies):
|
|
@@ -472,13 +525,17 @@ class DependencyInjector:
|
|
|
472
525
|
param_name not in final_kwargs
|
|
473
526
|
or final_kwargs.get(param_name) is None
|
|
474
527
|
):
|
|
475
|
-
# Get the dependency from wrapper's storage
|
|
476
|
-
dependency =
|
|
477
|
-
|
|
478
|
-
|
|
528
|
+
# Get the dependency from wrapper's array storage (by index)
|
|
529
|
+
dependency = None
|
|
530
|
+
if dep_index < len(dependency_wrapper._mesh_injected_deps):
|
|
531
|
+
dependency = dependency_wrapper._mesh_injected_deps[
|
|
532
|
+
dep_index
|
|
533
|
+
]
|
|
479
534
|
|
|
480
535
|
if dependency is None:
|
|
481
|
-
|
|
536
|
+
# Fallback to global storage with composite key
|
|
537
|
+
dep_key = f"{func.__module__}.{func.__qualname__}:dep_{dep_index}"
|
|
538
|
+
dependency = self.get_dependency(dep_key)
|
|
482
539
|
|
|
483
540
|
final_kwargs[param_name] = dependency
|
|
484
541
|
injected_count += 1
|
|
@@ -486,7 +543,7 @@ class DependencyInjector:
|
|
|
486
543
|
# ===== EXECUTE WITH DEPENDENCY INJECTION AND TRACING =====
|
|
487
544
|
# Use ExecutionTracer for comprehensive execution logging (v0.4.0 style)
|
|
488
545
|
from ..tracing.execution_tracer import ExecutionTracer
|
|
489
|
-
|
|
546
|
+
|
|
490
547
|
wrapper_logger.debug(
|
|
491
548
|
f"🔧 DI: Executing sync function {func._mesh_original_func.__name__} with {injected_count} injected dependencies"
|
|
492
549
|
)
|
|
@@ -502,20 +559,28 @@ class DependencyInjector:
|
|
|
502
559
|
wrapper_logger,
|
|
503
560
|
)
|
|
504
561
|
|
|
505
|
-
# Store dependency state on wrapper
|
|
506
|
-
dependency_wrapper._mesh_injected_deps =
|
|
507
|
-
|
|
508
|
-
# Add update method to wrapper
|
|
509
|
-
def update_dependency(
|
|
510
|
-
"""Called when a dependency changes."""
|
|
511
|
-
if
|
|
512
|
-
dependency_wrapper._mesh_injected_deps
|
|
513
|
-
|
|
562
|
+
# Store dependency state on wrapper as array (indexed by position)
|
|
563
|
+
dependency_wrapper._mesh_injected_deps = [None] * len(dependencies)
|
|
564
|
+
|
|
565
|
+
# Add update method to wrapper (now uses index-based updates)
|
|
566
|
+
def update_dependency(dep_index: int, instance: Any | None) -> None:
|
|
567
|
+
"""Called when a dependency changes (index-based for duplicate capability support)."""
|
|
568
|
+
if dep_index < len(dependency_wrapper._mesh_injected_deps):
|
|
569
|
+
dependency_wrapper._mesh_injected_deps[dep_index] = instance
|
|
570
|
+
if instance is None:
|
|
571
|
+
wrapper_logger.debug(
|
|
572
|
+
f"Removed dependency at index {dep_index} from {func_id}"
|
|
573
|
+
)
|
|
574
|
+
else:
|
|
575
|
+
wrapper_logger.debug(
|
|
576
|
+
f"Updated dependency at index {dep_index} for {func_id}"
|
|
577
|
+
)
|
|
578
|
+
wrapper_logger.debug(
|
|
579
|
+
f"🔗 Wrapper pointer receiving dependency: {dependency_wrapper} at {hex(id(dependency_wrapper))}"
|
|
580
|
+
)
|
|
514
581
|
else:
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
wrapper_logger.debug(
|
|
518
|
-
f"🔗 Wrapper pointer receiving dependency: {dependency_wrapper} at {hex(id(dependency_wrapper))}"
|
|
582
|
+
wrapper_logger.warning(
|
|
583
|
+
f"⚠️ Attempted to update dependency at index {dep_index} but wrapper only has {len(dependency_wrapper._mesh_injected_deps)} dependencies"
|
|
519
584
|
)
|
|
520
585
|
|
|
521
586
|
# Store update method on wrapper
|
|
@@ -151,13 +151,13 @@ def get_mesh_agent_positions(func: Any) -> list[int]:
|
|
|
151
151
|
|
|
152
152
|
def get_mesh_agent_parameter_names(func: Any) -> list[str]:
|
|
153
153
|
"""
|
|
154
|
-
Get names of McpMeshAgent parameters in function signature.
|
|
154
|
+
Get names of McpMeshAgent/McpAgent parameters in function signature.
|
|
155
155
|
|
|
156
156
|
Args:
|
|
157
157
|
func: Function to analyze
|
|
158
158
|
|
|
159
159
|
Returns:
|
|
160
|
-
List of parameter names that are McpMeshAgent types
|
|
160
|
+
List of parameter names that are McpMeshAgent or McpAgent types
|
|
161
161
|
"""
|
|
162
162
|
try:
|
|
163
163
|
type_hints = get_type_hints(func)
|
|
@@ -168,22 +168,31 @@ def get_mesh_agent_parameter_names(func: Any) -> list[str]:
|
|
|
168
168
|
if param_name in type_hints:
|
|
169
169
|
param_type = type_hints[param_name]
|
|
170
170
|
|
|
171
|
-
# Check if it's McpMeshAgent type (handle different import paths and Union types)
|
|
171
|
+
# Check if it's McpAgent or McpMeshAgent type (handle different import paths and Union types)
|
|
172
172
|
is_mesh_agent = False
|
|
173
173
|
|
|
174
|
-
# Direct McpMeshAgent type
|
|
175
|
-
if
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
# Direct McpAgent or McpMeshAgent type
|
|
175
|
+
if (
|
|
176
|
+
param_type in (McpAgent, McpMeshAgent)
|
|
177
|
+
or (
|
|
178
|
+
hasattr(param_type, "__name__")
|
|
179
|
+
and param_type.__name__ in ("McpAgent", "McpMeshAgent")
|
|
180
|
+
)
|
|
181
|
+
or (
|
|
182
|
+
hasattr(param_type, "__origin__")
|
|
183
|
+
and param_type.__origin__
|
|
184
|
+
in (type(McpAgent), type(McpMeshAgent))
|
|
185
|
+
)
|
|
178
186
|
):
|
|
179
187
|
is_mesh_agent = True
|
|
180
188
|
|
|
181
|
-
# Union type (e.g., McpMeshAgent | None)
|
|
189
|
+
# Union type (e.g., McpAgent | None, McpMeshAgent | None)
|
|
182
190
|
elif hasattr(param_type, "__args__"):
|
|
183
|
-
# Check if any arg in the union is McpMeshAgent
|
|
191
|
+
# Check if any arg in the union is McpAgent or McpMeshAgent
|
|
184
192
|
for arg in param_type.__args__:
|
|
185
|
-
if arg
|
|
186
|
-
hasattr(arg, "__name__")
|
|
193
|
+
if arg in (McpAgent, McpMeshAgent) or (
|
|
194
|
+
hasattr(arg, "__name__")
|
|
195
|
+
and arg.__name__ in ("McpAgent", "McpMeshAgent")
|
|
187
196
|
):
|
|
188
197
|
is_mesh_agent = True
|
|
189
198
|
break
|
|
@@ -199,7 +208,7 @@ def get_mesh_agent_parameter_names(func: Any) -> list[str]:
|
|
|
199
208
|
|
|
200
209
|
def validate_mesh_dependencies(func: Any, dependencies: list[dict]) -> tuple[bool, str]:
|
|
201
210
|
"""
|
|
202
|
-
Validate that the number of dependencies matches McpMeshAgent parameters.
|
|
211
|
+
Validate that the number of dependencies matches McpMeshAgent/McpAgent parameters.
|
|
203
212
|
|
|
204
213
|
Args:
|
|
205
214
|
func: Function to validate
|
|
@@ -212,9 +221,9 @@ def validate_mesh_dependencies(func: Any, dependencies: list[dict]) -> tuple[boo
|
|
|
212
221
|
|
|
213
222
|
if len(dependencies) != len(mesh_positions):
|
|
214
223
|
return False, (
|
|
215
|
-
f"Function {func.__name__} has {len(mesh_positions)} McpMeshAgent parameters "
|
|
224
|
+
f"Function {func.__name__} has {len(mesh_positions)} McpMeshAgent/McpAgent parameters "
|
|
216
225
|
f"but {len(dependencies)} dependencies declared. "
|
|
217
|
-
f"Each McpMeshAgent parameter needs a corresponding dependency."
|
|
226
|
+
f"Each McpMeshAgent/McpAgent parameter needs a corresponding dependency."
|
|
218
227
|
)
|
|
219
228
|
|
|
220
229
|
return True, ""
|