mcp-mesh 0.6.4__tar.gz → 0.7.15__tar.gz
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-0.6.4 → mcp_mesh-0.7.15}/.gitignore +11 -2
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/PKG-INFO +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/__init__.py +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/__init__.py +1 -22
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/async_mcp_client.py +88 -25
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/decorator_registry.py +60 -20
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/dependency_injector.py +64 -53
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/http_wrapper.py +10 -2
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/mesh_llm_agent.py +217 -11
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/mesh_llm_agent_injector.py +30 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/generic_handler.py +28 -22
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/openai_handler.py +39 -24
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_aware_client.py +3 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/unified_mcp_proxy.py +157 -105
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/FILES +2 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator-ignore +1 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +19 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py +0 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/agents_api.py +13 -15
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/health_api.py +10 -12
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py +5 -7
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_client.py +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/configuration.py +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/exceptions.py +8 -8
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +3 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +22 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner_one_of.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agents_list_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/capability_info.py +15 -5
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_request.py +2 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_info.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_info.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_resolution_info.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/error_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/health_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider.py +2 -4
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider_resolution_info.py +106 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter.py +2 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_info.py +2 -4
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_resolution_info.py +120 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_register_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +2 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response_dependencies_resolved_value_inner.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_dependency_registration.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_register_metadata.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_registration.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/registration_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/resolved_llm_provider.py +2 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/rich_dependency.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/root_response.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py +1 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/rest.py +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +76 -183
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +3 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +30 -28
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py +150 -96
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/route_integration.py +91 -92
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +16 -18
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py +5 -5
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py +3 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py +6 -6
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py +1 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +15 -11
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py +3 -3
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py +44 -268
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/lifespan_factory.py +142 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +57 -93
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/registry_connection.py +1 -1
- mcp_mesh-0.7.15/_mcp_mesh/shared/health_check_manager.py +313 -0
- mcp_mesh-0.7.15/_mcp_mesh/shared/logging_config.py +277 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/registry_client_wrapper.py +8 -8
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/sse_parser.py +19 -17
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/execution_tracer.py +66 -13
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/fastapi_tracing_middleware.py +3 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/trace_context_helper.py +25 -6
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/mesh/__init__.py +3 -1
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/mesh/decorators.py +114 -33
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/mesh/helpers.py +80 -5
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/mesh/types.py +48 -4
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/pyproject.toml +4 -4
- mcp_mesh-0.6.4/_mcp_mesh/engine/full_mcp_proxy.py +0 -641
- mcp_mesh-0.6.4/_mcp_mesh/engine/mcp_client_proxy.py +0 -457
- mcp_mesh-0.6.4/_mcp_mesh/shared/health_check_cache.py +0 -246
- mcp_mesh-0.6.4/_mcp_mesh/shared/logging_config.py +0 -81
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/LICENSE +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/README.md +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/base_injector.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/llm_config.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/llm_errors.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/base_provider_handler.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/claude_handler.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/response_parser.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/self_dependency_proxy.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_manager.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/signature_analyzer.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/tool_executor.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/engine/tool_schema_builder.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/VERSION +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_response.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/py.typed +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_health_check.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/api_pipeline.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/api_server_setup.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/fastapi_discovery.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/middleware_integration.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/api_startup/route_collection.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_heartbeat/lifespan_integration.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/configuration.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/decorator_collection.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/fastmcpserver_discovery.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/heartbeat_loop.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/heartbeat_preparation.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/server_discovery.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/mcp_startup/startup_pipeline.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/base_step.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/mesh_pipeline.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/pipeline_types.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/__init__.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/config_resolver.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/content_extractor.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/defaults.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/fast_heartbeat_status.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/fastapi_middleware_manager.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/host_resolver.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/server_discovery.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/simple_shutdown.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/shared/support_types.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/agent_context_helper.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/context.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/redis_metadata_publisher.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/tracing/utils.py +0 -0
- {mcp_mesh-0.6.4 → mcp_mesh-0.7.15}/_mcp_mesh/utils/fastmcp_schema_extractor.py +0 -0
|
@@ -174,14 +174,15 @@ cython_debug/
|
|
|
174
174
|
logs/
|
|
175
175
|
.logs/
|
|
176
176
|
capability_store/
|
|
177
|
+
prompts/
|
|
177
178
|
*.db
|
|
178
179
|
*.pid
|
|
179
180
|
|
|
180
181
|
# Go binaries
|
|
181
182
|
mcp-mesh-dev
|
|
182
183
|
/mcp-mesh-registry
|
|
183
|
-
meshctl
|
|
184
|
-
bin/
|
|
184
|
+
/meshctl
|
|
185
|
+
bin/
|
|
185
186
|
*.exe
|
|
186
187
|
*.dll
|
|
187
188
|
*.dylib
|
|
@@ -236,3 +237,11 @@ packaging/pypi/README.md
|
|
|
236
237
|
packaging/pypi/LICENSE
|
|
237
238
|
packaging/pypi/dist/
|
|
238
239
|
MEDIUM-POST-MULTI-AGENT-POC.md
|
|
240
|
+
|
|
241
|
+
# Helm chart dependency packages (regenerate with: helm dependency update)
|
|
242
|
+
helm/*/charts/*.tgz
|
|
243
|
+
|
|
244
|
+
# Helm chart files copied during release (generated from observability/)
|
|
245
|
+
helm/mcp-mesh-grafana/files/
|
|
246
|
+
helm/mcp-mesh-tempo/files/
|
|
247
|
+
*.DS_Store
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-mesh
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.15
|
|
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
|
|
@@ -17,13 +17,8 @@ __all__ = [
|
|
|
17
17
|
# Dependency injection
|
|
18
18
|
"DependencyInjector",
|
|
19
19
|
"get_global_injector",
|
|
20
|
-
# MCP client proxies
|
|
21
|
-
"MCPClientProxy",
|
|
22
|
-
"EnhancedMCPClientProxy",
|
|
23
|
-
"FullMCPProxy",
|
|
24
|
-
"EnhancedFullMCPProxy",
|
|
20
|
+
# MCP client proxies
|
|
25
21
|
"AsyncMCPClient",
|
|
26
|
-
# Unified MCP proxy (recommended)
|
|
27
22
|
"UnifiedMCPProxy",
|
|
28
23
|
"EnhancedUnifiedMCPProxy",
|
|
29
24
|
# Self-dependency proxy
|
|
@@ -59,22 +54,6 @@ def __getattr__(name):
|
|
|
59
54
|
|
|
60
55
|
return get_global_injector
|
|
61
56
|
# MCP client proxies
|
|
62
|
-
elif name == "MCPClientProxy":
|
|
63
|
-
from .mcp_client_proxy import MCPClientProxy
|
|
64
|
-
|
|
65
|
-
return MCPClientProxy
|
|
66
|
-
elif name == "EnhancedMCPClientProxy":
|
|
67
|
-
from .mcp_client_proxy import EnhancedMCPClientProxy
|
|
68
|
-
|
|
69
|
-
return EnhancedMCPClientProxy
|
|
70
|
-
elif name == "FullMCPProxy":
|
|
71
|
-
from .full_mcp_proxy import FullMCPProxy
|
|
72
|
-
|
|
73
|
-
return FullMCPProxy
|
|
74
|
-
elif name == "EnhancedFullMCPProxy":
|
|
75
|
-
from .full_mcp_proxy import EnhancedFullMCPProxy
|
|
76
|
-
|
|
77
|
-
return EnhancedFullMCPProxy
|
|
78
57
|
elif name == "AsyncMCPClient":
|
|
79
58
|
from .async_mcp_client import AsyncMCPClient
|
|
80
59
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"""Async HTTP client for MCP JSON-RPC protocol."""
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
4
|
+
import atexit
|
|
3
5
|
import json
|
|
4
6
|
import logging
|
|
5
7
|
import urllib.error
|
|
6
8
|
import urllib.request
|
|
7
|
-
from typing import Any
|
|
9
|
+
from typing import Any, ClassVar, Optional
|
|
8
10
|
|
|
9
11
|
from ..shared.sse_parser import SSEParser
|
|
10
12
|
|
|
@@ -12,13 +14,67 @@ logger = logging.getLogger(__name__)
|
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class AsyncMCPClient:
|
|
15
|
-
"""Async HTTP client for MCP JSON-RPC protocol.
|
|
17
|
+
"""Async HTTP client for MCP JSON-RPC protocol.
|
|
18
|
+
|
|
19
|
+
Uses connection pooling to reuse HTTP connections across requests,
|
|
20
|
+
reducing TCP/SSL handshake overhead and preventing port exhaustion.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# Class-level connection pool (shared across instances for same endpoint)
|
|
24
|
+
_client_pool: ClassVar[dict[str, "httpx.AsyncClient"]] = {}
|
|
25
|
+
_pool_lock: ClassVar[Optional[asyncio.Lock]] = None
|
|
26
|
+
|
|
27
|
+
# Default connection limits for pooling
|
|
28
|
+
DEFAULT_MAX_CONNECTIONS = 100
|
|
29
|
+
DEFAULT_MAX_KEEPALIVE_CONNECTIONS = 20
|
|
16
30
|
|
|
17
31
|
def __init__(self, endpoint: str, timeout: float = 30.0):
|
|
18
32
|
self.endpoint = endpoint
|
|
19
33
|
self.timeout = timeout
|
|
20
34
|
self.logger = logger.getChild(f"client.{endpoint}")
|
|
21
35
|
|
|
36
|
+
@classmethod
|
|
37
|
+
def _get_lock(cls) -> asyncio.Lock:
|
|
38
|
+
"""Get or create the class-level lock (handles event loop creation)."""
|
|
39
|
+
if cls._pool_lock is None:
|
|
40
|
+
cls._pool_lock = asyncio.Lock()
|
|
41
|
+
return cls._pool_lock
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
async def _get_pooled_client(
|
|
45
|
+
cls, endpoint: str, timeout: float
|
|
46
|
+
) -> "httpx.AsyncClient":
|
|
47
|
+
"""Get or create a pooled httpx client for the endpoint.
|
|
48
|
+
|
|
49
|
+
This enables connection reuse across multiple requests to the same endpoint,
|
|
50
|
+
significantly reducing overhead from TCP connection establishment and SSL handshakes.
|
|
51
|
+
"""
|
|
52
|
+
import httpx
|
|
53
|
+
|
|
54
|
+
async with cls._get_lock():
|
|
55
|
+
if endpoint not in cls._client_pool:
|
|
56
|
+
cls._client_pool[endpoint] = httpx.AsyncClient(
|
|
57
|
+
timeout=timeout,
|
|
58
|
+
limits=httpx.Limits(
|
|
59
|
+
max_connections=cls.DEFAULT_MAX_CONNECTIONS,
|
|
60
|
+
max_keepalive_connections=cls.DEFAULT_MAX_KEEPALIVE_CONNECTIONS,
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
logger.debug(f"Created pooled client for endpoint: {endpoint}")
|
|
64
|
+
return cls._client_pool[endpoint]
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
async def close_all_clients(cls) -> None:
|
|
68
|
+
"""Close all pooled clients. Call during application shutdown."""
|
|
69
|
+
async with cls._get_lock():
|
|
70
|
+
for endpoint, client in list(cls._client_pool.items()):
|
|
71
|
+
try:
|
|
72
|
+
await client.aclose()
|
|
73
|
+
logger.debug(f"Closed pooled client for: {endpoint}")
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.warning(f"Error closing client for {endpoint}: {e}")
|
|
76
|
+
cls._client_pool.clear()
|
|
77
|
+
|
|
22
78
|
async def call_tool(self, tool_name: str, arguments: dict) -> Any:
|
|
23
79
|
"""Call remote tool using MCP JSON-RPC protocol."""
|
|
24
80
|
payload = {
|
|
@@ -38,37 +94,39 @@ class AsyncMCPClient:
|
|
|
38
94
|
raise
|
|
39
95
|
|
|
40
96
|
async def _make_request(self, payload: dict) -> dict:
|
|
41
|
-
"""Make async HTTP request to MCP endpoint."""
|
|
97
|
+
"""Make async HTTP request to MCP endpoint using pooled connections."""
|
|
42
98
|
url = f"{self.endpoint}/mcp"
|
|
43
99
|
|
|
44
100
|
try:
|
|
45
|
-
# Use httpx
|
|
101
|
+
# Use httpx with connection pooling for better resource management
|
|
46
102
|
import httpx
|
|
47
103
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
url,
|
|
51
|
-
json=payload,
|
|
52
|
-
headers={
|
|
53
|
-
"Content-Type": "application/json",
|
|
54
|
-
"Accept": "application/json, text/event-stream",
|
|
55
|
-
},
|
|
56
|
-
)
|
|
104
|
+
# Get pooled client (reuses connections across requests)
|
|
105
|
+
client = await self._get_pooled_client(self.endpoint, self.timeout)
|
|
57
106
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
107
|
+
response = await client.post(
|
|
108
|
+
url,
|
|
109
|
+
json=payload,
|
|
110
|
+
headers={
|
|
111
|
+
"Content-Type": "application/json",
|
|
112
|
+
"Accept": "application/json, text/event-stream",
|
|
113
|
+
},
|
|
114
|
+
)
|
|
64
115
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
116
|
+
if response.status_code == 404:
|
|
117
|
+
raise RuntimeError(f"MCP endpoint not found at {url}")
|
|
118
|
+
elif response.status_code >= 400:
|
|
119
|
+
raise RuntimeError(
|
|
120
|
+
f"HTTP error {response.status_code}: {response.reason_phrase}"
|
|
70
121
|
)
|
|
71
122
|
|
|
123
|
+
response_text = response.text
|
|
124
|
+
|
|
125
|
+
# Use shared SSE parser
|
|
126
|
+
data = SSEParser.parse_sse_response(
|
|
127
|
+
response_text, f"AsyncMCPClient.{self.endpoint}"
|
|
128
|
+
)
|
|
129
|
+
|
|
72
130
|
# Check for JSON-RPC error
|
|
73
131
|
if "error" in data:
|
|
74
132
|
error = data["error"]
|
|
@@ -169,5 +227,10 @@ class AsyncMCPClient:
|
|
|
169
227
|
return result
|
|
170
228
|
|
|
171
229
|
async def close(self):
|
|
172
|
-
"""Close client (no
|
|
230
|
+
"""Close client instance (no-op as connections are pooled at class level).
|
|
231
|
+
|
|
232
|
+
Connection pooling is managed at the class level for efficiency.
|
|
233
|
+
To close all pooled connections during shutdown, use:
|
|
234
|
+
await AsyncMCPClient.close_all_clients()
|
|
235
|
+
"""
|
|
173
236
|
pass
|
|
@@ -38,7 +38,7 @@ class LLMAgentMetadata:
|
|
|
38
38
|
|
|
39
39
|
function: Callable
|
|
40
40
|
config: dict[str, Any] # LLM configuration (provider, model, filter, etc.)
|
|
41
|
-
output_type:
|
|
41
|
+
output_type: type | None # Pydantic model type from return annotation
|
|
42
42
|
param_name: str # Name of MeshLlmAgent parameter
|
|
43
43
|
function_id: str # Unique function ID for registry
|
|
44
44
|
registered_at: datetime
|
|
@@ -70,16 +70,55 @@ class DecoratorRegistry:
|
|
|
70
70
|
_custom_decorators: dict[str, dict[str, DecoratedFunction]] = {}
|
|
71
71
|
|
|
72
72
|
# Immediate uvicorn server storage (for preventing shutdown state)
|
|
73
|
-
_immediate_uvicorn_server:
|
|
73
|
+
_immediate_uvicorn_server: dict[str, Any] | None = None
|
|
74
74
|
|
|
75
75
|
# FastMCP lifespan storage (for proper integration with FastAPI)
|
|
76
|
-
_fastmcp_lifespan:
|
|
76
|
+
_fastmcp_lifespan: Any | None = None
|
|
77
77
|
|
|
78
78
|
# FastMCP HTTP app storage (the same app instance whose lifespan was extracted)
|
|
79
|
-
_fastmcp_http_app:
|
|
79
|
+
_fastmcp_http_app: Any | None = None
|
|
80
80
|
|
|
81
81
|
# FastMCP server info storage (for schema extraction during heartbeat)
|
|
82
|
-
_fastmcp_server_info:
|
|
82
|
+
_fastmcp_server_info: dict[str, Any] | None = None
|
|
83
|
+
|
|
84
|
+
# Route-to-wrapper mapping for @mesh.route dependency injection
|
|
85
|
+
# Key: "METHOD:path" (e.g., "GET:/api/v1/benchmark-services")
|
|
86
|
+
# Value: {"wrapper": Callable, "dependencies": list[str]}
|
|
87
|
+
_route_wrapper_registry: dict[str, dict[str, Any]] = {}
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def register_route_wrapper(
|
|
91
|
+
cls, method: str, path: str, wrapper: Callable, dependencies: list[str]
|
|
92
|
+
) -> None:
|
|
93
|
+
"""
|
|
94
|
+
Register a route's wrapper function for dependency injection.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
method: HTTP method (e.g., "GET", "POST")
|
|
98
|
+
path: Route path (e.g., "/api/v1/benchmark-services")
|
|
99
|
+
wrapper: The injection wrapper function
|
|
100
|
+
dependencies: List of dependency capability names
|
|
101
|
+
"""
|
|
102
|
+
route_id = f"{method}:{path}"
|
|
103
|
+
cls._route_wrapper_registry[route_id] = {
|
|
104
|
+
"wrapper": wrapper,
|
|
105
|
+
"dependencies": dependencies,
|
|
106
|
+
"method": method,
|
|
107
|
+
"path": path,
|
|
108
|
+
}
|
|
109
|
+
logger.debug(
|
|
110
|
+
f"📝 Registered route wrapper: {route_id} with {len(dependencies)} dependencies"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def get_route_wrapper(cls, route_id: str) -> dict[str, Any] | None:
|
|
115
|
+
"""Get route wrapper info by route ID (METHOD:path)."""
|
|
116
|
+
return cls._route_wrapper_registry.get(route_id)
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def get_all_route_wrappers(cls) -> dict[str, dict[str, Any]]:
|
|
120
|
+
"""Get all registered route wrappers."""
|
|
121
|
+
return cls._route_wrapper_registry.copy()
|
|
83
122
|
|
|
84
123
|
@classmethod
|
|
85
124
|
def register_mesh_agent(cls, func: Callable, metadata: dict[str, Any]) -> None:
|
|
@@ -154,7 +193,7 @@ class DecoratorRegistry:
|
|
|
154
193
|
cls,
|
|
155
194
|
func: Callable,
|
|
156
195
|
config: dict[str, Any],
|
|
157
|
-
output_type:
|
|
196
|
+
output_type: type | None,
|
|
158
197
|
param_name: str,
|
|
159
198
|
function_id: str,
|
|
160
199
|
) -> None:
|
|
@@ -355,7 +394,7 @@ class DecoratorRegistry:
|
|
|
355
394
|
return stats
|
|
356
395
|
|
|
357
396
|
# Cache for resolved agent configuration to avoid repeated work
|
|
358
|
-
_cached_agent_config:
|
|
397
|
+
_cached_agent_config: dict[str, Any] | None = None
|
|
359
398
|
|
|
360
399
|
@classmethod
|
|
361
400
|
def update_agent_config(cls, updates: dict[str, Any]) -> None:
|
|
@@ -610,7 +649,7 @@ class DecoratorRegistry:
|
|
|
610
649
|
)
|
|
611
650
|
|
|
612
651
|
@classmethod
|
|
613
|
-
def get_immediate_uvicorn_server(cls) ->
|
|
652
|
+
def get_immediate_uvicorn_server(cls) -> dict[str, Any] | None:
|
|
614
653
|
"""
|
|
615
654
|
Get stored immediate uvicorn server reference.
|
|
616
655
|
|
|
@@ -625,27 +664,28 @@ class DecoratorRegistry:
|
|
|
625
664
|
cls._immediate_uvicorn_server = None
|
|
626
665
|
logger.debug("🔄 REGISTRY: Cleared immediate uvicorn server reference")
|
|
627
666
|
|
|
628
|
-
# Health check result storage
|
|
629
|
-
_health_check_result: dict | None = None
|
|
667
|
+
# Health check result storage (delegated to health_check_manager)
|
|
630
668
|
|
|
631
669
|
@classmethod
|
|
632
670
|
def store_health_check_result(cls, result: dict) -> None:
|
|
633
671
|
"""Store health check result for /health endpoint."""
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
)
|
|
672
|
+
from ..shared.health_check_manager import store_health_check_result
|
|
673
|
+
|
|
674
|
+
store_health_check_result(result)
|
|
638
675
|
|
|
639
676
|
@classmethod
|
|
640
677
|
def get_health_check_result(cls) -> dict | None:
|
|
641
678
|
"""Get stored health check result."""
|
|
642
|
-
|
|
679
|
+
from ..shared.health_check_manager import get_health_check_result
|
|
680
|
+
|
|
681
|
+
return get_health_check_result()
|
|
643
682
|
|
|
644
683
|
@classmethod
|
|
645
684
|
def clear_health_check_result(cls) -> None:
|
|
646
685
|
"""Clear stored health check result."""
|
|
647
|
-
|
|
648
|
-
|
|
686
|
+
from ..shared.health_check_manager import clear_health_check_result
|
|
687
|
+
|
|
688
|
+
clear_health_check_result()
|
|
649
689
|
|
|
650
690
|
@classmethod
|
|
651
691
|
def store_fastmcp_lifespan(cls, lifespan: Any) -> None:
|
|
@@ -659,7 +699,7 @@ class DecoratorRegistry:
|
|
|
659
699
|
logger.debug("🔄 REGISTRY: Stored FastMCP lifespan for FastAPI integration")
|
|
660
700
|
|
|
661
701
|
@classmethod
|
|
662
|
-
def get_fastmcp_lifespan(cls) ->
|
|
702
|
+
def get_fastmcp_lifespan(cls) -> Any | None:
|
|
663
703
|
"""
|
|
664
704
|
Get stored FastMCP lifespan.
|
|
665
705
|
|
|
@@ -686,7 +726,7 @@ class DecoratorRegistry:
|
|
|
686
726
|
logger.debug("🔄 REGISTRY: Stored FastMCP HTTP app for mounting")
|
|
687
727
|
|
|
688
728
|
@classmethod
|
|
689
|
-
def get_fastmcp_http_app(cls) ->
|
|
729
|
+
def get_fastmcp_http_app(cls) -> Any | None:
|
|
690
730
|
"""
|
|
691
731
|
Get stored FastMCP HTTP app.
|
|
692
732
|
|
|
@@ -715,7 +755,7 @@ class DecoratorRegistry:
|
|
|
715
755
|
)
|
|
716
756
|
|
|
717
757
|
@classmethod
|
|
718
|
-
def get_fastmcp_server_info(cls) ->
|
|
758
|
+
def get_fastmcp_server_info(cls) -> dict[str, Any] | None:
|
|
719
759
|
"""
|
|
720
760
|
Get stored FastMCP server info.
|
|
721
761
|
|
|
@@ -14,6 +14,11 @@ import weakref
|
|
|
14
14
|
from collections.abc import Callable
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
+
from ..shared.logging_config import (
|
|
18
|
+
format_log_value,
|
|
19
|
+
format_result_summary,
|
|
20
|
+
get_trace_prefix,
|
|
21
|
+
)
|
|
17
22
|
from .signature_analyzer import get_mesh_agent_positions, has_llm_agent_parameter
|
|
18
23
|
|
|
19
24
|
logger = logging.getLogger(__name__)
|
|
@@ -448,17 +453,17 @@ class DependencyInjector:
|
|
|
448
453
|
|
|
449
454
|
@functools.wraps(func)
|
|
450
455
|
async def dependency_wrapper(*args, **kwargs):
|
|
456
|
+
# Get trace prefix if available
|
|
457
|
+
tp = get_trace_prefix()
|
|
458
|
+
|
|
459
|
+
# Log tool invocation - summary line
|
|
460
|
+
arg_keys = list(kwargs.keys()) if kwargs else []
|
|
451
461
|
wrapper_logger.debug(
|
|
452
|
-
f"🔧
|
|
453
|
-
)
|
|
454
|
-
wrapper_logger.debug(
|
|
455
|
-
f"🔧 DEPENDENCY_WRAPPER: args={args}, kwargs={kwargs}"
|
|
456
|
-
)
|
|
457
|
-
wrapper_logger.debug(
|
|
458
|
-
f"🔧 DEPENDENCY_WRAPPER: mesh_positions={mesh_positions}"
|
|
462
|
+
f"{tp}🔧 Tool '{func.__name__}' called with kwargs={arg_keys}"
|
|
459
463
|
)
|
|
464
|
+
# Log full args (will be TRACE later)
|
|
460
465
|
wrapper_logger.debug(
|
|
461
|
-
f"🔧
|
|
466
|
+
f"{tp}🔧 Tool '{func.__name__}' args: {format_log_value(kwargs)}"
|
|
462
467
|
)
|
|
463
468
|
|
|
464
469
|
# We know mesh_positions is not empty since we checked above
|
|
@@ -468,20 +473,14 @@ class DependencyInjector:
|
|
|
468
473
|
params = list(sig.parameters.keys())
|
|
469
474
|
final_kwargs = kwargs.copy()
|
|
470
475
|
|
|
471
|
-
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: params={params}")
|
|
472
|
-
wrapper_logger.debug(f"🔧 DEPENDENCY_WRAPPER: original kwargs={kwargs}")
|
|
473
|
-
|
|
474
476
|
# Inject dependencies as kwargs (using array-based lookup)
|
|
475
477
|
injected_count = 0
|
|
478
|
+
injected_deps = [] # Track what was injected for logging
|
|
476
479
|
for dep_index, param_position in enumerate(mesh_positions):
|
|
477
480
|
if dep_index < len(dependencies):
|
|
478
481
|
dep_name = dependencies[dep_index]
|
|
479
482
|
param_name = params[param_position]
|
|
480
483
|
|
|
481
|
-
wrapper_logger.debug(
|
|
482
|
-
f"🔧 DEPENDENCY_WRAPPER: Processing dep {dep_index}: {dep_name} -> {param_name}"
|
|
483
|
-
)
|
|
484
|
-
|
|
485
484
|
# Only inject if the parameter wasn't explicitly provided
|
|
486
485
|
if (
|
|
487
486
|
param_name not in final_kwargs
|
|
@@ -493,34 +492,25 @@ class DependencyInjector:
|
|
|
493
492
|
dependency = dependency_wrapper._mesh_injected_deps[
|
|
494
493
|
dep_index
|
|
495
494
|
]
|
|
496
|
-
wrapper_logger.debug(
|
|
497
|
-
f"🔧 DEPENDENCY_WRAPPER: From wrapper storage[{dep_index}]: {dependency}"
|
|
498
|
-
)
|
|
499
495
|
|
|
500
496
|
if dependency is None:
|
|
501
497
|
# Fallback to global storage with composite key
|
|
502
498
|
dep_key = f"{func.__module__}.{func.__qualname__}:dep_{dep_index}"
|
|
503
499
|
dependency = self.get_dependency(dep_key)
|
|
504
|
-
wrapper_logger.debug(
|
|
505
|
-
f"🔧 DEPENDENCY_WRAPPER: From global storage[{dep_key}]: {dependency}"
|
|
506
|
-
)
|
|
507
500
|
|
|
508
501
|
final_kwargs[param_name] = dependency
|
|
509
502
|
injected_count += 1
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
else:
|
|
514
|
-
wrapper_logger.debug(
|
|
515
|
-
f"🔧 DEPENDENCY_WRAPPER: Skipping {param_name} - already provided"
|
|
503
|
+
# Track for consolidated logging
|
|
504
|
+
proxy_type = (
|
|
505
|
+
type(dependency).__name__ if dependency else "None"
|
|
516
506
|
)
|
|
507
|
+
injected_deps.append(f"{dep_name} → {proxy_type}")
|
|
517
508
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
)
|
|
509
|
+
# Log consolidated dependency injection summary
|
|
510
|
+
if injected_count > 0:
|
|
511
|
+
wrapper_logger.debug(
|
|
512
|
+
f"{tp}🔧 Injected {injected_count} dependencies: {', '.join(injected_deps)}"
|
|
513
|
+
)
|
|
524
514
|
|
|
525
515
|
# ===== INJECT LLM AGENT IF PRESENT (Option A) =====
|
|
526
516
|
# Check if this function has @mesh.llm metadata attached (on the original function)
|
|
@@ -534,7 +524,7 @@ class DependencyInjector:
|
|
|
534
524
|
llm_agent = getattr(func, "_mesh_llm_agent", None)
|
|
535
525
|
final_kwargs[llm_param] = llm_agent
|
|
536
526
|
wrapper_logger.debug(
|
|
537
|
-
f"🤖 LLM_INJECTION: Injected {llm_param}={llm_agent}"
|
|
527
|
+
f"{tp}🤖 LLM_INJECTION: Injected {llm_param}={llm_agent}"
|
|
538
528
|
)
|
|
539
529
|
|
|
540
530
|
# ===== EXECUTE WITH DEPENDENCY INJECTION AND TRACING =====
|
|
@@ -543,10 +533,6 @@ class DependencyInjector:
|
|
|
543
533
|
|
|
544
534
|
original_func = func._mesh_original_func
|
|
545
535
|
|
|
546
|
-
wrapper_logger.debug(
|
|
547
|
-
f"🔧 DI: Executing async function {original_func.__name__} with {injected_count} injected dependencies"
|
|
548
|
-
)
|
|
549
|
-
|
|
550
536
|
# Use ExecutionTracer's async method for clean tracing
|
|
551
537
|
result = await ExecutionTracer.trace_function_execution_async(
|
|
552
538
|
original_func,
|
|
@@ -558,26 +544,32 @@ class DependencyInjector:
|
|
|
558
544
|
wrapper_logger,
|
|
559
545
|
)
|
|
560
546
|
|
|
547
|
+
# Log result - summary line
|
|
561
548
|
wrapper_logger.debug(
|
|
562
|
-
f"🔧
|
|
549
|
+
f"{tp}🔧 Tool '{func.__name__}' returned: {format_result_summary(result)}"
|
|
563
550
|
)
|
|
551
|
+
# Log full result (will be TRACE later)
|
|
552
|
+
wrapper_logger.debug(
|
|
553
|
+
f"{tp}🔧 Tool '{func.__name__}' result: {format_log_value(result)}"
|
|
554
|
+
)
|
|
555
|
+
|
|
564
556
|
return result
|
|
565
557
|
|
|
566
558
|
else:
|
|
567
559
|
# Create sync wrapper for sync functions without dependencies
|
|
568
560
|
@functools.wraps(func)
|
|
569
561
|
def dependency_wrapper(*args, **kwargs):
|
|
562
|
+
# Get trace prefix if available
|
|
563
|
+
tp = get_trace_prefix()
|
|
564
|
+
|
|
565
|
+
# Log tool invocation - summary line
|
|
566
|
+
arg_keys = list(kwargs.keys()) if kwargs else []
|
|
570
567
|
wrapper_logger.debug(
|
|
571
|
-
f"🔧
|
|
572
|
-
)
|
|
573
|
-
wrapper_logger.debug(
|
|
574
|
-
f"🔧 DEPENDENCY_WRAPPER: args={args}, kwargs={kwargs}"
|
|
575
|
-
)
|
|
576
|
-
wrapper_logger.debug(
|
|
577
|
-
f"🔧 DEPENDENCY_WRAPPER: mesh_positions={mesh_positions}"
|
|
568
|
+
f"{tp}🔧 Tool '{func.__name__}' called with kwargs={arg_keys}"
|
|
578
569
|
)
|
|
570
|
+
# Log full args (will be TRACE later)
|
|
579
571
|
wrapper_logger.debug(
|
|
580
|
-
f"🔧
|
|
572
|
+
f"{tp}🔧 Tool '{func.__name__}' args: {format_log_value(kwargs)}"
|
|
581
573
|
)
|
|
582
574
|
|
|
583
575
|
# We know mesh_positions is not empty since we checked above
|
|
@@ -589,6 +581,7 @@ class DependencyInjector:
|
|
|
589
581
|
|
|
590
582
|
# Inject dependencies as kwargs (using array-based lookup)
|
|
591
583
|
injected_count = 0
|
|
584
|
+
injected_deps = [] # Track what was injected for logging
|
|
592
585
|
for dep_index, param_position in enumerate(mesh_positions):
|
|
593
586
|
if dep_index < len(dependencies):
|
|
594
587
|
dep_name = dependencies[dep_index]
|
|
@@ -613,6 +606,17 @@ class DependencyInjector:
|
|
|
613
606
|
|
|
614
607
|
final_kwargs[param_name] = dependency
|
|
615
608
|
injected_count += 1
|
|
609
|
+
# Track for consolidated logging
|
|
610
|
+
proxy_type = (
|
|
611
|
+
type(dependency).__name__ if dependency else "None"
|
|
612
|
+
)
|
|
613
|
+
injected_deps.append(f"{dep_name} → {proxy_type}")
|
|
614
|
+
|
|
615
|
+
# Log consolidated dependency injection summary
|
|
616
|
+
if injected_count > 0:
|
|
617
|
+
wrapper_logger.debug(
|
|
618
|
+
f"{tp}🔧 Injected {injected_count} dependencies: {', '.join(injected_deps)}"
|
|
619
|
+
)
|
|
616
620
|
|
|
617
621
|
# ===== INJECT LLM AGENT IF PRESENT (Option A) =====
|
|
618
622
|
# Check if this function has @mesh.llm metadata attached (on the original function)
|
|
@@ -626,19 +630,15 @@ class DependencyInjector:
|
|
|
626
630
|
llm_agent = getattr(func, "_mesh_llm_agent", None)
|
|
627
631
|
final_kwargs[llm_param] = llm_agent
|
|
628
632
|
wrapper_logger.debug(
|
|
629
|
-
f"🤖 LLM_INJECTION: Injected {llm_param}={llm_agent}"
|
|
633
|
+
f"{tp}🤖 LLM_INJECTION: Injected {llm_param}={llm_agent}"
|
|
630
634
|
)
|
|
631
635
|
|
|
632
636
|
# ===== EXECUTE WITH DEPENDENCY INJECTION AND TRACING =====
|
|
633
637
|
# Use ExecutionTracer for comprehensive execution logging (v0.4.0 style)
|
|
634
638
|
from ..tracing.execution_tracer import ExecutionTracer
|
|
635
639
|
|
|
636
|
-
wrapper_logger.debug(
|
|
637
|
-
f"🔧 DI: Executing sync function {func._mesh_original_func.__name__} with {injected_count} injected dependencies"
|
|
638
|
-
)
|
|
639
|
-
|
|
640
640
|
# Use ExecutionTracer for clean execution tracing
|
|
641
|
-
|
|
641
|
+
result = ExecutionTracer.trace_function_execution(
|
|
642
642
|
func._mesh_original_func,
|
|
643
643
|
args,
|
|
644
644
|
final_kwargs,
|
|
@@ -648,6 +648,17 @@ class DependencyInjector:
|
|
|
648
648
|
wrapper_logger,
|
|
649
649
|
)
|
|
650
650
|
|
|
651
|
+
# Log result - summary line
|
|
652
|
+
wrapper_logger.debug(
|
|
653
|
+
f"{tp}🔧 Tool '{func.__name__}' returned: {format_result_summary(result)}"
|
|
654
|
+
)
|
|
655
|
+
# Log full result (will be TRACE later)
|
|
656
|
+
wrapper_logger.debug(
|
|
657
|
+
f"{tp}🔧 Tool '{func.__name__}' result: {format_log_value(result)}"
|
|
658
|
+
)
|
|
659
|
+
|
|
660
|
+
return result
|
|
661
|
+
|
|
651
662
|
# Store dependency state on wrapper as array (indexed by position)
|
|
652
663
|
dependency_wrapper._mesh_injected_deps = [None] * len(dependencies)
|
|
653
664
|
|
|
@@ -132,7 +132,7 @@ class HttpMcpWrapper:
|
|
|
132
132
|
|
|
133
133
|
# Phase 3: Metadata caching
|
|
134
134
|
self._metadata_cache: dict[str, Any] = {}
|
|
135
|
-
self._cache_timestamp:
|
|
135
|
+
self._cache_timestamp: datetime | None = None
|
|
136
136
|
self._cache_ttl: timedelta = timedelta(minutes=5) # Cache for 5 minutes
|
|
137
137
|
|
|
138
138
|
# Phase 5: Session storage and pod info
|
|
@@ -254,7 +254,7 @@ class HttpMcpWrapper:
|
|
|
254
254
|
self._cache_timestamp = datetime.now()
|
|
255
255
|
logger.debug(f"📋 Metadata cache updated with {len(metadata)} entries")
|
|
256
256
|
|
|
257
|
-
def get_cached_metadata(self) ->
|
|
257
|
+
def get_cached_metadata(self) -> dict[str, Any] | None:
|
|
258
258
|
"""Get cached metadata if available and valid."""
|
|
259
259
|
if self._is_cache_valid():
|
|
260
260
|
logger.debug("✅ Returning cached metadata")
|
|
@@ -391,6 +391,14 @@ class HttpMcpWrapper:
|
|
|
391
391
|
try:
|
|
392
392
|
from ..tracing.trace_context_helper import TraceContextHelper
|
|
393
393
|
|
|
394
|
+
# DEBUG: Log incoming headers for trace propagation debugging
|
|
395
|
+
trace_id_header = request.headers.get("X-Trace-ID")
|
|
396
|
+
parent_span_header = request.headers.get("X-Parent-Span")
|
|
397
|
+
self.logger.info(
|
|
398
|
+
f"🔍 INCOMING_HEADERS: X-Trace-ID={trace_id_header}, "
|
|
399
|
+
f"X-Parent-Span={parent_span_header}, path={request.url.path}"
|
|
400
|
+
)
|
|
401
|
+
|
|
394
402
|
# Use helper class for trace context extraction and setup
|
|
395
403
|
trace_context = (
|
|
396
404
|
await TraceContextHelper.extract_trace_context_from_request(
|