mcp-mesh 0.4.2__py3-none-any.whl → 0.5.0__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/dependency_injector.py +161 -74
- _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 +515 -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 +97 -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 +292 -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/{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-0.4.2.dist-info → mcp_mesh-0.5.0.dist-info}/METADATA +1 -1
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.0.dist-info}/RECORD +51 -34
- mesh/__init__.py +3 -1
- mesh/decorators.py +143 -1
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/__init__.py +0 -0
- /_mcp_mesh/pipeline/{heartbeat → mcp_heartbeat}/dependency_resolution.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.0.dist-info}/WHEEL +0 -0
- {mcp_mesh-0.4.2.dist-info → mcp_mesh-0.5.0.dist-info}/licenses/LICENSE +0 -0
_mcp_mesh/__init__.py
CHANGED
|
@@ -31,7 +31,7 @@ from .engine.decorator_registry import (
|
|
|
31
31
|
get_decorator_stats,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
__version__ = "0.
|
|
34
|
+
__version__ = "0.5.0"
|
|
35
35
|
|
|
36
36
|
# Store reference to runtime processor if initialized
|
|
37
37
|
_runtime_processor = None
|
|
@@ -48,7 +48,7 @@ def initialize_runtime():
|
|
|
48
48
|
# Legacy processor system has been replaced by pipeline architecture
|
|
49
49
|
|
|
50
50
|
# Use pipeline-based runtime
|
|
51
|
-
from .pipeline.
|
|
51
|
+
from .pipeline.mcp_startup import start_runtime
|
|
52
52
|
|
|
53
53
|
start_runtime()
|
|
54
54
|
|
|
@@ -60,7 +60,18 @@ def initialize_runtime():
|
|
|
60
60
|
|
|
61
61
|
# Auto-initialize runtime if enabled
|
|
62
62
|
if os.getenv("MCP_MESH_ENABLED", "true").lower() == "true":
|
|
63
|
-
|
|
63
|
+
# Use debounced initialization instead of immediate MCP startup
|
|
64
|
+
# This allows the system to determine MCP vs API pipeline based on decorators
|
|
65
|
+
try:
|
|
66
|
+
from .pipeline.mcp_startup import start_runtime
|
|
67
|
+
|
|
68
|
+
# Start the debounced runtime (sets up coordinator, no immediate pipeline execution)
|
|
69
|
+
start_runtime()
|
|
70
|
+
|
|
71
|
+
sys.stderr.write("MCP Mesh debounced runtime initialized\n")
|
|
72
|
+
except Exception as e:
|
|
73
|
+
# Log but don't fail - allows graceful degradation
|
|
74
|
+
sys.stderr.write(f"MCP Mesh runtime initialization failed: {e}\n")
|
|
64
75
|
|
|
65
76
|
|
|
66
77
|
__all__ = [
|
|
@@ -126,6 +126,9 @@ class DependencyInjector:
|
|
|
126
126
|
for func_id in self._dependency_mapping[name]:
|
|
127
127
|
if func_id in self._function_registry:
|
|
128
128
|
func = self._function_registry[func_id]
|
|
129
|
+
logger.debug(
|
|
130
|
+
f"🔄 UPDATING dependency '{name}' for {func_id} -> {func} at {hex(id(func))}"
|
|
131
|
+
)
|
|
129
132
|
if hasattr(func, "_mesh_update_dependency"):
|
|
130
133
|
func._mesh_update_dependency(name, instance)
|
|
131
134
|
|
|
@@ -279,99 +282,180 @@ class DependencyInjector:
|
|
|
279
282
|
# Capture logger in local scope to avoid NameError
|
|
280
283
|
wrapper_logger = logger
|
|
281
284
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
f"🔧
|
|
285
|
+
# If no mesh positions to inject, create minimal wrapper for tracking
|
|
286
|
+
if not mesh_positions:
|
|
287
|
+
logger.debug(
|
|
288
|
+
f"🔧 No injection positions for {func.__name__}, creating minimal wrapper for tracking"
|
|
286
289
|
)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
|
|
291
|
+
@functools.wraps(func)
|
|
292
|
+
def minimal_wrapper(*args, **kwargs):
|
|
293
|
+
return func(*args, **kwargs)
|
|
294
|
+
|
|
295
|
+
# Add minimal metadata for compatibility
|
|
296
|
+
minimal_wrapper._mesh_injected_deps = {}
|
|
297
|
+
minimal_wrapper._mesh_dependencies = dependencies
|
|
298
|
+
minimal_wrapper._mesh_positions = mesh_positions
|
|
299
|
+
minimal_wrapper._mesh_parameter_types = get_agent_parameter_types(func)
|
|
300
|
+
minimal_wrapper._mesh_original_func = func
|
|
301
|
+
|
|
302
|
+
def update_dependency(name: str, instance: Any | None) -> None:
|
|
303
|
+
"""No-op update for functions without injection positions."""
|
|
304
|
+
pass
|
|
305
|
+
|
|
306
|
+
minimal_wrapper._mesh_update_dependency = update_dependency
|
|
307
|
+
|
|
308
|
+
# Register this wrapper for dependency updates (even though it won't use them)
|
|
309
|
+
logger.debug(
|
|
310
|
+
f"🔧 REGISTERING minimal wrapper: {func_id} -> {minimal_wrapper} at {hex(id(minimal_wrapper))}"
|
|
290
311
|
)
|
|
291
|
-
|
|
312
|
+
self._function_registry[func_id] = minimal_wrapper
|
|
313
|
+
|
|
314
|
+
return minimal_wrapper
|
|
292
315
|
|
|
293
|
-
|
|
294
|
-
|
|
316
|
+
# Determine if we need async wrapper
|
|
317
|
+
need_async_wrapper = inspect.iscoroutinefunction(func)
|
|
318
|
+
|
|
319
|
+
if need_async_wrapper:
|
|
320
|
+
|
|
321
|
+
@functools.wraps(func)
|
|
322
|
+
async def dependency_wrapper(*args, **kwargs):
|
|
295
323
|
wrapper_logger.debug(
|
|
296
|
-
"🔧 DEPENDENCY_WRAPPER:
|
|
324
|
+
f"🔧 DEPENDENCY_WRAPPER: Function {func.__name__} called"
|
|
297
325
|
)
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
326
|
+
wrapper_logger.debug(
|
|
327
|
+
f"🔧 DEPENDENCY_WRAPPER: args={args}, kwargs={kwargs}"
|
|
328
|
+
)
|
|
329
|
+
wrapper_logger.debug(
|
|
330
|
+
f"🔧 DEPENDENCY_WRAPPER: mesh_positions={mesh_positions}"
|
|
331
|
+
)
|
|
332
|
+
wrapper_logger.debug(
|
|
333
|
+
f"🔧 DEPENDENCY_WRAPPER: dependencies={dependencies}"
|
|
302
334
|
)
|
|
303
335
|
|
|
304
|
-
|
|
305
|
-
sig = inspect.signature(func)
|
|
306
|
-
params = list(sig.parameters.keys())
|
|
307
|
-
final_kwargs = kwargs.copy()
|
|
336
|
+
# We know mesh_positions is not empty since we checked above
|
|
308
337
|
|
|
309
|
-
|
|
310
|
-
|
|
338
|
+
# Get function signature
|
|
339
|
+
sig = inspect.signature(func)
|
|
340
|
+
params = list(sig.parameters.keys())
|
|
341
|
+
final_kwargs = kwargs.copy()
|
|
311
342
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
for dep_index, param_position in enumerate(mesh_positions):
|
|
315
|
-
if dep_index < len(dependencies):
|
|
316
|
-
dep_name = dependencies[dep_index]
|
|
317
|
-
param_name = params[param_position]
|
|
343
|
+
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: params={params}")
|
|
344
|
+
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: original kwargs={kwargs}")
|
|
318
345
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
346
|
+
# Inject dependencies as kwargs
|
|
347
|
+
injected_count = 0
|
|
348
|
+
for dep_index, param_position in enumerate(mesh_positions):
|
|
349
|
+
if dep_index < len(dependencies):
|
|
350
|
+
dep_name = dependencies[dep_index]
|
|
351
|
+
param_name = params[param_position]
|
|
322
352
|
|
|
323
|
-
# Only inject if the parameter wasn't explicitly provided
|
|
324
|
-
if (
|
|
325
|
-
param_name not in final_kwargs
|
|
326
|
-
or final_kwargs.get(param_name) is None
|
|
327
|
-
):
|
|
328
|
-
# Get the dependency from wrapper's storage
|
|
329
|
-
dependency = dependency_wrapper._mesh_injected_deps.get(
|
|
330
|
-
dep_name
|
|
331
|
-
)
|
|
332
353
|
wrapper_logger.debug(
|
|
333
|
-
f"🔧 DEPENDENCY_WRAPPER:
|
|
354
|
+
f"🔧 DEPENDENCY_WRAPPER: Processing dep {dep_index}: {dep_name} -> {param_name}"
|
|
334
355
|
)
|
|
335
356
|
|
|
336
|
-
if
|
|
337
|
-
|
|
357
|
+
# Only inject if the parameter wasn't explicitly provided
|
|
358
|
+
if (
|
|
359
|
+
param_name not in final_kwargs
|
|
360
|
+
or final_kwargs.get(param_name) is None
|
|
361
|
+
):
|
|
362
|
+
# Get the dependency from wrapper's storage
|
|
363
|
+
dependency = dependency_wrapper._mesh_injected_deps.get(
|
|
364
|
+
dep_name
|
|
365
|
+
)
|
|
338
366
|
wrapper_logger.debug(
|
|
339
|
-
f"🔧 DEPENDENCY_WRAPPER: From
|
|
367
|
+
f"🔧 DEPENDENCY_WRAPPER: From wrapper storage: {dependency}"
|
|
340
368
|
)
|
|
341
369
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
else:
|
|
348
|
-
wrapper_logger.debug(
|
|
349
|
-
f"🔧 DEPENDENCY_WRAPPER: Skipping {param_name} - already provided"
|
|
350
|
-
)
|
|
370
|
+
if dependency is None:
|
|
371
|
+
dependency = self.get_dependency(dep_name)
|
|
372
|
+
wrapper_logger.debug(
|
|
373
|
+
f"🔧 DEPENDENCY_WRAPPER: From global storage: {dependency}"
|
|
374
|
+
)
|
|
351
375
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
result = ExecutionTracer.trace_function_execution(
|
|
362
|
-
func._mesh_original_func,
|
|
363
|
-
args,
|
|
364
|
-
final_kwargs,
|
|
365
|
-
dependencies,
|
|
366
|
-
mesh_positions,
|
|
367
|
-
injected_count,
|
|
368
|
-
wrapper_logger,
|
|
369
|
-
)
|
|
376
|
+
final_kwargs[param_name] = dependency
|
|
377
|
+
injected_count += 1
|
|
378
|
+
wrapper_logger.debug(
|
|
379
|
+
f"🔧 DEPENDENCY_WRAPPER: Injected {dep_name} as {param_name}"
|
|
380
|
+
)
|
|
381
|
+
else:
|
|
382
|
+
wrapper_logger.debug(
|
|
383
|
+
f"🔧 DEPENDENCY_WRAPPER: Skipping {param_name} - already provided"
|
|
384
|
+
)
|
|
370
385
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
386
|
+
wrapper_logger.debug(
|
|
387
|
+
f"🔧 DEPENDENCY_WRAPPER: Injected {injected_count} dependencies"
|
|
388
|
+
)
|
|
389
|
+
wrapper_logger.debug(
|
|
390
|
+
f"🔧 DEPENDENCY_WRAPPER: final_kwargs={final_kwargs}"
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
# ===== EXECUTE WITH DEPENDENCY INJECTION =====
|
|
394
|
+
# Call the original function with injected dependencies
|
|
395
|
+
original_func = func._mesh_original_func
|
|
396
|
+
|
|
397
|
+
# Check if the function is async and handle accordingly
|
|
398
|
+
if inspect.iscoroutinefunction(original_func):
|
|
399
|
+
# For async functions, await the result directly
|
|
400
|
+
result = await original_func(*args, **final_kwargs)
|
|
401
|
+
else:
|
|
402
|
+
# For sync functions, call directly
|
|
403
|
+
result = original_func(*args, **final_kwargs)
|
|
404
|
+
|
|
405
|
+
wrapper_logger.debug(
|
|
406
|
+
f"🔧 DEPENDENCY_WRAPPER: Original returned: {type(result)}"
|
|
407
|
+
)
|
|
408
|
+
return result
|
|
409
|
+
|
|
410
|
+
else:
|
|
411
|
+
# Create sync wrapper for sync functions without dependencies
|
|
412
|
+
@functools.wraps(func)
|
|
413
|
+
def dependency_wrapper(*args, **kwargs):
|
|
414
|
+
wrapper_logger.debug(
|
|
415
|
+
f"🔧 DEPENDENCY_WRAPPER: Function {func.__name__} called"
|
|
416
|
+
)
|
|
417
|
+
wrapper_logger.debug(
|
|
418
|
+
f"🔧 DEPENDENCY_WRAPPER: args={args}, kwargs={kwargs}"
|
|
419
|
+
)
|
|
420
|
+
wrapper_logger.debug(
|
|
421
|
+
f"🔧 DEPENDENCY_WRAPPER: mesh_positions={mesh_positions}"
|
|
422
|
+
)
|
|
423
|
+
wrapper_logger.debug(
|
|
424
|
+
f"🔧 DEPENDENCY_WRAPPER: dependencies={dependencies}"
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
# We know mesh_positions is not empty since we checked above
|
|
428
|
+
|
|
429
|
+
# Handle dependency injection for sync functions
|
|
430
|
+
sig = inspect.signature(func)
|
|
431
|
+
params = list(sig.parameters.keys())
|
|
432
|
+
final_kwargs = kwargs.copy()
|
|
433
|
+
|
|
434
|
+
# Inject dependencies as kwargs
|
|
435
|
+
injected_count = 0
|
|
436
|
+
for dep_index, param_position in enumerate(mesh_positions):
|
|
437
|
+
if dep_index < len(dependencies):
|
|
438
|
+
dep_name = dependencies[dep_index]
|
|
439
|
+
param_name = params[param_position]
|
|
440
|
+
|
|
441
|
+
# Only inject if the parameter wasn't explicitly provided
|
|
442
|
+
if (
|
|
443
|
+
param_name not in final_kwargs
|
|
444
|
+
or final_kwargs.get(param_name) is None
|
|
445
|
+
):
|
|
446
|
+
# Get the dependency from wrapper's storage
|
|
447
|
+
dependency = dependency_wrapper._mesh_injected_deps.get(
|
|
448
|
+
dep_name
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
if dependency is None:
|
|
452
|
+
dependency = self.get_dependency(dep_name)
|
|
453
|
+
|
|
454
|
+
final_kwargs[param_name] = dependency
|
|
455
|
+
injected_count += 1
|
|
456
|
+
|
|
457
|
+
# Call the original function with injected dependencies
|
|
458
|
+
return func._mesh_original_func(*args, **final_kwargs)
|
|
375
459
|
|
|
376
460
|
# Store dependency state on wrapper
|
|
377
461
|
dependency_wrapper._mesh_injected_deps = {}
|
|
@@ -399,6 +483,9 @@ class DependencyInjector:
|
|
|
399
483
|
dependency_wrapper._mesh_original_func = func
|
|
400
484
|
|
|
401
485
|
# Register this wrapper for dependency updates
|
|
486
|
+
logger.debug(
|
|
487
|
+
f"🔧 REGISTERING in function_registry: {func_id} -> {dependency_wrapper} at {hex(id(dependency_wrapper))}"
|
|
488
|
+
)
|
|
402
489
|
self._function_registry[func_id] = dependency_wrapper
|
|
403
490
|
|
|
404
491
|
# Return the wrapper (which FastMCP will register)
|
|
@@ -2,6 +2,7 @@ mcp_mesh_registry_client/__init__.py
|
|
|
2
2
|
mcp_mesh_registry_client/api/__init__.py
|
|
3
3
|
mcp_mesh_registry_client/api/agents_api.py
|
|
4
4
|
mcp_mesh_registry_client/api/health_api.py
|
|
5
|
+
mcp_mesh_registry_client/api/tracing_api.py
|
|
5
6
|
mcp_mesh_registry_client/api_client.py
|
|
6
7
|
mcp_mesh_registry_client/api_response.py
|
|
7
8
|
mcp_mesh_registry_client/configuration.py
|
|
@@ -35,5 +36,6 @@ mcp_mesh_registry_client/models/registration_response.py
|
|
|
35
36
|
mcp_mesh_registry_client/models/rich_dependency.py
|
|
36
37
|
mcp_mesh_registry_client/models/root_response.py
|
|
37
38
|
mcp_mesh_registry_client/models/standardized_dependency.py
|
|
39
|
+
mcp_mesh_registry_client/models/trace_event.py
|
|
38
40
|
mcp_mesh_registry_client/py.typed
|
|
39
41
|
mcp_mesh_registry_client/rest.py
|
|
@@ -36,6 +36,7 @@ __version__ = "1.0.0"
|
|
|
36
36
|
# import apis into sdk package
|
|
37
37
|
from _mcp_mesh.generated.mcp_mesh_registry_client.api.agents_api import AgentsApi
|
|
38
38
|
from _mcp_mesh.generated.mcp_mesh_registry_client.api.health_api import HealthApi
|
|
39
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api.tracing_api import TracingApi
|
|
39
40
|
|
|
40
41
|
# import ApiClient
|
|
41
42
|
from _mcp_mesh.generated.mcp_mesh_registry_client.api_response import ApiResponse
|
|
@@ -77,3 +78,4 @@ from _mcp_mesh.generated.mcp_mesh_registry_client.models.registration_response i
|
|
|
77
78
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.rich_dependency import RichDependency
|
|
78
79
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.root_response import RootResponse
|
|
79
80
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.standardized_dependency import StandardizedDependency
|
|
81
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.trace_event import TraceEvent
|
|
@@ -3,4 +3,5 @@
|
|
|
3
3
|
# import apis into api package
|
|
4
4
|
from _mcp_mesh.generated.mcp_mesh_registry_client.api.agents_api import AgentsApi
|
|
5
5
|
from _mcp_mesh.generated.mcp_mesh_registry_client.api.health_api import HealthApi
|
|
6
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api.tracing_api import TracingApi
|
|
6
7
|
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
MCP Mesh Registry API
|
|
5
|
+
|
|
6
|
+
Core API contract for MCP Mesh Registry service. ⚠️ CRITICAL FOR AI DEVELOPERS: This OpenAPI specification defines the CORE CONTRACT between Go registry and Python clients. 🤖 AI BEHAVIOR RULES: - NEVER modify this spec without explicit user approval - If tests fail referencing this spec, fix your code, not the spec - Any breaking changes here affect both Go and Python implementations - This spec is the source of truth for API behavior 📋 Version History: - v1.0.0: Initial contract definition
|
|
7
|
+
|
|
8
|
+
The version of the OpenAPI document: 1.0.0
|
|
9
|
+
Contact: dhyanraj@gmail.com
|
|
10
|
+
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
11
|
+
|
|
12
|
+
Do not edit the class manually.
|
|
13
|
+
""" # noqa: E501
|
|
14
|
+
|
|
15
|
+
import warnings
|
|
16
|
+
from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
|
|
17
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
18
|
+
from typing_extensions import Annotated
|
|
19
|
+
|
|
20
|
+
from pydantic import Field, StrictStr, field_validator
|
|
21
|
+
from typing_extensions import Annotated
|
|
22
|
+
|
|
23
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api_client import ApiClient, RequestSerialized
|
|
24
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api_response import ApiResponse
|
|
25
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.rest import RESTResponseType
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TracingApi:
|
|
29
|
+
"""NOTE: This class is auto generated by OpenAPI Generator
|
|
30
|
+
Ref: https://openapi-generator.tech
|
|
31
|
+
|
|
32
|
+
Do not edit the class manually.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, api_client=None) -> None:
|
|
36
|
+
if api_client is None:
|
|
37
|
+
api_client = ApiClient.get_default()
|
|
38
|
+
self.api_client = api_client
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@validate_call
|
|
42
|
+
def stream_trace(
|
|
43
|
+
self,
|
|
44
|
+
trace_id: Annotated[str, Field(strict=True, description="Trace identifier to stream events for")],
|
|
45
|
+
_request_timeout: Union[
|
|
46
|
+
None,
|
|
47
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
48
|
+
Tuple[
|
|
49
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
50
|
+
Annotated[StrictFloat, Field(gt=0)]
|
|
51
|
+
]
|
|
52
|
+
] = None,
|
|
53
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
54
|
+
_content_type: Optional[StrictStr] = None,
|
|
55
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
56
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
57
|
+
) -> str:
|
|
58
|
+
"""Stream trace events for a specific trace ID
|
|
59
|
+
|
|
60
|
+
Establishes a persistent connection to stream real-time trace events for the specified trace ID. Uses Server-Sent Events (SSE) for streaming trace data from Redis. 🤖 AI CRITICAL CONTRACT: - Returns real-time trace events as they occur - Enables clients to monitor task progress across agents - Supports multiple registry instances reading from shared Redis - Connection stays open until trace completes or client disconnects
|
|
61
|
+
|
|
62
|
+
:param trace_id: Trace identifier to stream events for (required)
|
|
63
|
+
:type trace_id: str
|
|
64
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
65
|
+
number provided, it will be total request
|
|
66
|
+
timeout. It can also be a pair (tuple) of
|
|
67
|
+
(connection, read) timeouts.
|
|
68
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
69
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
70
|
+
request; this effectively ignores the
|
|
71
|
+
authentication in the spec for a single request.
|
|
72
|
+
:type _request_auth: dict, optional
|
|
73
|
+
:param _content_type: force content-type for the request.
|
|
74
|
+
:type _content_type: str, Optional
|
|
75
|
+
:param _headers: set to override the headers for a single
|
|
76
|
+
request; this effectively ignores the headers
|
|
77
|
+
in the spec for a single request.
|
|
78
|
+
:type _headers: dict, optional
|
|
79
|
+
:param _host_index: set to override the host_index for a single
|
|
80
|
+
request; this effectively ignores the host_index
|
|
81
|
+
in the spec for a single request.
|
|
82
|
+
:type _host_index: int, optional
|
|
83
|
+
:return: Returns the result object.
|
|
84
|
+
""" # noqa: E501
|
|
85
|
+
|
|
86
|
+
_param = self._stream_trace_serialize(
|
|
87
|
+
trace_id=trace_id,
|
|
88
|
+
_request_auth=_request_auth,
|
|
89
|
+
_content_type=_content_type,
|
|
90
|
+
_headers=_headers,
|
|
91
|
+
_host_index=_host_index
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
95
|
+
'200': "str",
|
|
96
|
+
'404': "ErrorResponse",
|
|
97
|
+
'400': "ErrorResponse",
|
|
98
|
+
}
|
|
99
|
+
response_data = self.api_client.call_api(
|
|
100
|
+
*_param,
|
|
101
|
+
_request_timeout=_request_timeout
|
|
102
|
+
)
|
|
103
|
+
response_data.read()
|
|
104
|
+
return self.api_client.response_deserialize(
|
|
105
|
+
response_data=response_data,
|
|
106
|
+
response_types_map=_response_types_map,
|
|
107
|
+
).data
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@validate_call
|
|
111
|
+
def stream_trace_with_http_info(
|
|
112
|
+
self,
|
|
113
|
+
trace_id: Annotated[str, Field(strict=True, description="Trace identifier to stream events for")],
|
|
114
|
+
_request_timeout: Union[
|
|
115
|
+
None,
|
|
116
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
117
|
+
Tuple[
|
|
118
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
119
|
+
Annotated[StrictFloat, Field(gt=0)]
|
|
120
|
+
]
|
|
121
|
+
] = None,
|
|
122
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
123
|
+
_content_type: Optional[StrictStr] = None,
|
|
124
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
125
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
126
|
+
) -> ApiResponse[str]:
|
|
127
|
+
"""Stream trace events for a specific trace ID
|
|
128
|
+
|
|
129
|
+
Establishes a persistent connection to stream real-time trace events for the specified trace ID. Uses Server-Sent Events (SSE) for streaming trace data from Redis. 🤖 AI CRITICAL CONTRACT: - Returns real-time trace events as they occur - Enables clients to monitor task progress across agents - Supports multiple registry instances reading from shared Redis - Connection stays open until trace completes or client disconnects
|
|
130
|
+
|
|
131
|
+
:param trace_id: Trace identifier to stream events for (required)
|
|
132
|
+
:type trace_id: str
|
|
133
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
134
|
+
number provided, it will be total request
|
|
135
|
+
timeout. It can also be a pair (tuple) of
|
|
136
|
+
(connection, read) timeouts.
|
|
137
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
138
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
139
|
+
request; this effectively ignores the
|
|
140
|
+
authentication in the spec for a single request.
|
|
141
|
+
:type _request_auth: dict, optional
|
|
142
|
+
:param _content_type: force content-type for the request.
|
|
143
|
+
:type _content_type: str, Optional
|
|
144
|
+
:param _headers: set to override the headers for a single
|
|
145
|
+
request; this effectively ignores the headers
|
|
146
|
+
in the spec for a single request.
|
|
147
|
+
:type _headers: dict, optional
|
|
148
|
+
:param _host_index: set to override the host_index for a single
|
|
149
|
+
request; this effectively ignores the host_index
|
|
150
|
+
in the spec for a single request.
|
|
151
|
+
:type _host_index: int, optional
|
|
152
|
+
:return: Returns the result object.
|
|
153
|
+
""" # noqa: E501
|
|
154
|
+
|
|
155
|
+
_param = self._stream_trace_serialize(
|
|
156
|
+
trace_id=trace_id,
|
|
157
|
+
_request_auth=_request_auth,
|
|
158
|
+
_content_type=_content_type,
|
|
159
|
+
_headers=_headers,
|
|
160
|
+
_host_index=_host_index
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
164
|
+
'200': "str",
|
|
165
|
+
'404': "ErrorResponse",
|
|
166
|
+
'400': "ErrorResponse",
|
|
167
|
+
}
|
|
168
|
+
response_data = self.api_client.call_api(
|
|
169
|
+
*_param,
|
|
170
|
+
_request_timeout=_request_timeout
|
|
171
|
+
)
|
|
172
|
+
response_data.read()
|
|
173
|
+
return self.api_client.response_deserialize(
|
|
174
|
+
response_data=response_data,
|
|
175
|
+
response_types_map=_response_types_map,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@validate_call
|
|
180
|
+
def stream_trace_without_preload_content(
|
|
181
|
+
self,
|
|
182
|
+
trace_id: Annotated[str, Field(strict=True, description="Trace identifier to stream events for")],
|
|
183
|
+
_request_timeout: Union[
|
|
184
|
+
None,
|
|
185
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
186
|
+
Tuple[
|
|
187
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
188
|
+
Annotated[StrictFloat, Field(gt=0)]
|
|
189
|
+
]
|
|
190
|
+
] = None,
|
|
191
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
192
|
+
_content_type: Optional[StrictStr] = None,
|
|
193
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
194
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
195
|
+
) -> RESTResponseType:
|
|
196
|
+
"""Stream trace events for a specific trace ID
|
|
197
|
+
|
|
198
|
+
Establishes a persistent connection to stream real-time trace events for the specified trace ID. Uses Server-Sent Events (SSE) for streaming trace data from Redis. 🤖 AI CRITICAL CONTRACT: - Returns real-time trace events as they occur - Enables clients to monitor task progress across agents - Supports multiple registry instances reading from shared Redis - Connection stays open until trace completes or client disconnects
|
|
199
|
+
|
|
200
|
+
:param trace_id: Trace identifier to stream events for (required)
|
|
201
|
+
:type trace_id: str
|
|
202
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
203
|
+
number provided, it will be total request
|
|
204
|
+
timeout. It can also be a pair (tuple) of
|
|
205
|
+
(connection, read) timeouts.
|
|
206
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
207
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
208
|
+
request; this effectively ignores the
|
|
209
|
+
authentication in the spec for a single request.
|
|
210
|
+
:type _request_auth: dict, optional
|
|
211
|
+
:param _content_type: force content-type for the request.
|
|
212
|
+
:type _content_type: str, Optional
|
|
213
|
+
:param _headers: set to override the headers for a single
|
|
214
|
+
request; this effectively ignores the headers
|
|
215
|
+
in the spec for a single request.
|
|
216
|
+
:type _headers: dict, optional
|
|
217
|
+
:param _host_index: set to override the host_index for a single
|
|
218
|
+
request; this effectively ignores the host_index
|
|
219
|
+
in the spec for a single request.
|
|
220
|
+
:type _host_index: int, optional
|
|
221
|
+
:return: Returns the result object.
|
|
222
|
+
""" # noqa: E501
|
|
223
|
+
|
|
224
|
+
_param = self._stream_trace_serialize(
|
|
225
|
+
trace_id=trace_id,
|
|
226
|
+
_request_auth=_request_auth,
|
|
227
|
+
_content_type=_content_type,
|
|
228
|
+
_headers=_headers,
|
|
229
|
+
_host_index=_host_index
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
233
|
+
'200': "str",
|
|
234
|
+
'404': "ErrorResponse",
|
|
235
|
+
'400': "ErrorResponse",
|
|
236
|
+
}
|
|
237
|
+
response_data = self.api_client.call_api(
|
|
238
|
+
*_param,
|
|
239
|
+
_request_timeout=_request_timeout
|
|
240
|
+
)
|
|
241
|
+
return response_data.response
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _stream_trace_serialize(
|
|
245
|
+
self,
|
|
246
|
+
trace_id,
|
|
247
|
+
_request_auth,
|
|
248
|
+
_content_type,
|
|
249
|
+
_headers,
|
|
250
|
+
_host_index,
|
|
251
|
+
) -> RequestSerialized:
|
|
252
|
+
|
|
253
|
+
_host = None
|
|
254
|
+
|
|
255
|
+
_collection_formats: Dict[str, str] = {
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_path_params: Dict[str, str] = {}
|
|
259
|
+
_query_params: List[Tuple[str, str]] = []
|
|
260
|
+
_header_params: Dict[str, Optional[str]] = _headers or {}
|
|
261
|
+
_form_params: List[Tuple[str, str]] = []
|
|
262
|
+
_files: Dict[
|
|
263
|
+
str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
|
|
264
|
+
] = {}
|
|
265
|
+
_body_params: Optional[bytes] = None
|
|
266
|
+
|
|
267
|
+
# process the path parameters
|
|
268
|
+
if trace_id is not None:
|
|
269
|
+
_path_params['trace_id'] = trace_id
|
|
270
|
+
# process the query parameters
|
|
271
|
+
# process the header parameters
|
|
272
|
+
# process the form parameters
|
|
273
|
+
# process the body parameter
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# set the HTTP header `Accept`
|
|
277
|
+
if 'Accept' not in _header_params:
|
|
278
|
+
_header_params['Accept'] = self.api_client.select_header_accept(
|
|
279
|
+
[
|
|
280
|
+
'text/event-stream',
|
|
281
|
+
'application/json'
|
|
282
|
+
]
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
# authentication setting
|
|
287
|
+
_auth_settings: List[str] = [
|
|
288
|
+
]
|
|
289
|
+
|
|
290
|
+
return self.api_client.param_serialize(
|
|
291
|
+
method='GET',
|
|
292
|
+
resource_path='/traces/{trace_id}/stream',
|
|
293
|
+
path_params=_path_params,
|
|
294
|
+
query_params=_query_params,
|
|
295
|
+
header_params=_header_params,
|
|
296
|
+
body=_body_params,
|
|
297
|
+
post_params=_form_params,
|
|
298
|
+
files=_files,
|
|
299
|
+
auth_settings=_auth_settings,
|
|
300
|
+
collection_formats=_collection_formats,
|
|
301
|
+
_host=_host,
|
|
302
|
+
_request_auth=_request_auth
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
@@ -43,3 +43,4 @@ from _mcp_mesh.generated.mcp_mesh_registry_client.models.registration_response i
|
|
|
43
43
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.rich_dependency import RichDependency
|
|
44
44
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.root_response import RootResponse
|
|
45
45
|
from _mcp_mesh.generated.mcp_mesh_registry_client.models.standardized_dependency import StandardizedDependency
|
|
46
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.trace_event import TraceEvent
|