mcp-mesh 0.3.0__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.3.0 → mcp_mesh-0.7.15}/.gitignore +19 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/PKG-INFO +4 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/__init__.py +18 -4
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/__init__.py +10 -20
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/async_mcp_client.py +93 -43
- mcp_mesh-0.7.15/_mcp_mesh/engine/base_injector.py +171 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/decorator_registry.py +363 -11
- mcp_mesh-0.7.15/_mcp_mesh/engine/dependency_injector.py +708 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/http_wrapper.py +37 -24
- mcp_mesh-0.7.15/_mcp_mesh/engine/llm_config.py +54 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/llm_errors.py +115 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/mesh_llm_agent.py +850 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/mesh_llm_agent_injector.py +710 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/__init__.py +20 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/base_provider_handler.py +122 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/claude_handler.py +418 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/generic_handler.py +162 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/openai_handler.py +234 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py +167 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/response_parser.py +244 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/self_dependency_proxy.py +16 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_aware_client.py +3 -3
- mcp_mesh-0.7.15/_mcp_mesh/engine/signature_analyzer.py +359 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/tool_executor.py +169 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/tool_schema_builder.py +126 -0
- mcp_mesh-0.7.15/_mcp_mesh/engine/unified_mcp_proxy.py +944 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/FILES +11 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +12 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py +1 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/agents_api.py +13 -15
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/health_api.py +10 -12
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py +303 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_client.py +1 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/configuration.py +1 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/exceptions.py +8 -8
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +11 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +41 -4
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner.py +1 -3
- {mcp_mesh-0.3.0 → 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.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agents_list_response.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/capability_info.py +15 -5
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_request.py +2 -4
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_info.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_info.py +1 -3
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_resolution_info.py +106 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/error_response.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/health_response.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_response.py +1 -3
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider.py +93 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider_resolution_info.py +106 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter.py +109 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py +139 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py +91 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_info.py +101 -0
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_resolution_info.py +120 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_register_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +6 -8
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py +36 -4
- {mcp_mesh-0.3.0 → 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.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_dependency_registration.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_register_metadata.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_registration.py +12 -4
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/registration_response.py +1 -3
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/resolved_llm_provider.py +110 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/rich_dependency.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/root_response.py +1 -3
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py +1 -3
- mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py +106 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/rest.py +1 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/__init__.py +2 -2
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/__init__.py +16 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +418 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +117 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_health_check.py +140 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py +247 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +311 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py +386 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py +147 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py +104 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/__init__.py +20 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/api_pipeline.py +64 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/api_server_setup.py +367 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/fastapi_discovery.py +139 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/middleware_integration.py +153 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/route_collection.py +56 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/route_integration.py +317 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +396 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/fast_heartbeat_check.py +5 -5
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_orchestrator.py +40 -11
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_pipeline.py +12 -9
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_send.py +1 -1
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/lifespan_integration.py +13 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +264 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/registry_connection.py +3 -3
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/__init__.py +2 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/configuration.py +9 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/fastapiserver_setup.py +321 -319
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/fastmcpserver_discovery.py +12 -5
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/heartbeat_loop.py +1 -1
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/heartbeat_preparation.py +111 -5
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/lifespan_factory.py +142 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/server_discovery.py +193 -0
- mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +632 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/startup_pipeline.py +9 -6
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/mesh_pipeline.py +4 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/registry_connection.py +1 -1
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/config_resolver.py +0 -3
- mcp_mesh-0.7.15/_mcp_mesh/shared/fastapi_middleware_manager.py +371 -0
- 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.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/registry_client_wrapper.py +92 -9
- mcp_mesh-0.7.15/_mcp_mesh/shared/server_discovery.py +312 -0
- mcp_mesh-0.7.15/_mcp_mesh/shared/simple_shutdown.py +217 -0
- mcp_mesh-0.7.15/_mcp_mesh/shared/sse_parser.py +219 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/agent_context_helper.py +128 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/context.py +85 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/execution_tracer.py +270 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/fastapi_tracing_middleware.py +203 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/redis_metadata_publisher.py +139 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/trace_context_helper.py +185 -0
- mcp_mesh-0.7.15/_mcp_mesh/tracing/utils.py +137 -0
- mcp_mesh-0.7.15/_mcp_mesh/utils/fastmcp_schema_extractor.py +476 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/mesh/__init__.py +22 -2
- mcp_mesh-0.7.15/mesh/decorators.py +1457 -0
- mcp_mesh-0.7.15/mesh/helpers.py +334 -0
- mcp_mesh-0.7.15/mesh/types.py +466 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/pyproject.toml +8 -5
- mcp_mesh-0.3.0/_mcp_mesh/engine/dependency_injector.py +0 -397
- mcp_mesh-0.3.0/_mcp_mesh/engine/full_mcp_proxy.py +0 -616
- mcp_mesh-0.3.0/_mcp_mesh/engine/mcp_client_proxy.py +0 -451
- mcp_mesh-0.3.0/_mcp_mesh/engine/signature_analyzer.py +0 -220
- mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat/dependency_resolution.py +0 -517
- mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup/startup_orchestrator.py +0 -465
- mcp_mesh-0.3.0/_mcp_mesh/shared/logging_config.py +0 -80
- mcp_mesh-0.3.0/mesh/decorators.py +0 -485
- mcp_mesh-0.3.0/mesh/types.py +0 -261
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/LICENSE +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/README.md +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_manager.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/VERSION +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator-ignore +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_response.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/py.typed +0 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/__init__.py +0 -0
- {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/decorator_collection.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/__init__.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/base_step.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/pipeline_types.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/__init__.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/content_extractor.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/defaults.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/fast_heartbeat_status.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/host_resolver.py +0 -0
- {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/support_types.py +0 -0
|
@@ -163,19 +163,26 @@ cython_debug/
|
|
|
163
163
|
# VS Code
|
|
164
164
|
.vscode/
|
|
165
165
|
|
|
166
|
+
# Other IDEs/Tools
|
|
167
|
+
.emigo_repomap/
|
|
168
|
+
.windsurf/
|
|
169
|
+
.windsurfrules
|
|
170
|
+
|
|
166
171
|
# MCP Mesh specific
|
|
167
172
|
*.mcpconfig
|
|
168
173
|
.mcpconfig/
|
|
169
174
|
logs/
|
|
170
175
|
.logs/
|
|
171
176
|
capability_store/
|
|
177
|
+
prompts/
|
|
172
178
|
*.db
|
|
179
|
+
*.pid
|
|
173
180
|
|
|
174
181
|
# Go binaries
|
|
175
182
|
mcp-mesh-dev
|
|
176
|
-
mcp-mesh-registry
|
|
177
|
-
meshctl
|
|
178
|
-
bin/
|
|
183
|
+
/mcp-mesh-registry
|
|
184
|
+
/meshctl
|
|
185
|
+
bin/
|
|
179
186
|
*.exe
|
|
180
187
|
*.dll
|
|
181
188
|
*.dylib
|
|
@@ -229,3 +236,12 @@ packaging/pypi/src/
|
|
|
229
236
|
packaging/pypi/README.md
|
|
230
237
|
packaging/pypi/LICENSE
|
|
231
238
|
packaging/pypi/dist/
|
|
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
|
|
@@ -23,10 +23,13 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
23
23
|
Classifier: Topic :: System :: Distributed Computing
|
|
24
24
|
Requires-Python: >=3.11
|
|
25
25
|
Requires-Dist: aiohttp<4.0.0,>=3.8.0
|
|
26
|
+
Requires-Dist: cachetools>=5.3.0
|
|
26
27
|
Requires-Dist: click<9.0.0,>=8.1.0
|
|
27
28
|
Requires-Dist: fastapi<1.0.0,>=0.104.0
|
|
28
29
|
Requires-Dist: fastmcp<3.0.0,>=2.8.0
|
|
29
30
|
Requires-Dist: httpx<1.0.0,>=0.25.0
|
|
31
|
+
Requires-Dist: jinja2>=3.1.0
|
|
32
|
+
Requires-Dist: litellm>=1.30.0
|
|
30
33
|
Requires-Dist: mcp<2.0.0,>=1.9.0
|
|
31
34
|
Requires-Dist: prometheus-client<1.0.0,>=0.19.0
|
|
32
35
|
Requires-Dist: pydantic<3.0.0,>=2.4.0
|
|
@@ -31,7 +31,7 @@ from .engine.decorator_registry import (
|
|
|
31
31
|
get_decorator_stats,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
__version__ = "0.
|
|
34
|
+
__version__ = "0.7.15"
|
|
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
|
|
|
@@ -59,8 +59,22 @@ def initialize_runtime():
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
# Auto-initialize runtime if enabled
|
|
62
|
-
if
|
|
63
|
-
|
|
62
|
+
if (
|
|
63
|
+
os.getenv("MCP_MESH_ENABLED", "true").lower() == "true"
|
|
64
|
+
and os.getenv("MCP_MESH_AUTO_RUN", "true").lower() == "true"
|
|
65
|
+
):
|
|
66
|
+
# Use debounced initialization instead of immediate MCP startup
|
|
67
|
+
# This allows the system to determine MCP vs API pipeline based on decorators
|
|
68
|
+
try:
|
|
69
|
+
from .pipeline.mcp_startup import start_runtime
|
|
70
|
+
|
|
71
|
+
# Start the debounced runtime (sets up coordinator, no immediate pipeline execution)
|
|
72
|
+
start_runtime()
|
|
73
|
+
|
|
74
|
+
sys.stderr.write("MCP Mesh debounced runtime initialized\n")
|
|
75
|
+
except Exception as e:
|
|
76
|
+
# Log but don't fail - allows graceful degradation
|
|
77
|
+
sys.stderr.write(f"MCP Mesh runtime initialization failed: {e}\n")
|
|
64
78
|
|
|
65
79
|
|
|
66
80
|
__all__ = [
|
|
@@ -18,11 +18,9 @@ __all__ = [
|
|
|
18
18
|
"DependencyInjector",
|
|
19
19
|
"get_global_injector",
|
|
20
20
|
# MCP client proxies
|
|
21
|
-
"MCPClientProxy",
|
|
22
|
-
"EnhancedMCPClientProxy",
|
|
23
|
-
"FullMCPProxy",
|
|
24
|
-
"EnhancedFullMCPProxy",
|
|
25
21
|
"AsyncMCPClient",
|
|
22
|
+
"UnifiedMCPProxy",
|
|
23
|
+
"EnhancedUnifiedMCPProxy",
|
|
26
24
|
# Self-dependency proxy
|
|
27
25
|
"SelfDependencyProxy",
|
|
28
26
|
# Decorator registry
|
|
@@ -56,26 +54,18 @@ def __getattr__(name):
|
|
|
56
54
|
|
|
57
55
|
return get_global_injector
|
|
58
56
|
# MCP client proxies
|
|
59
|
-
elif name == "MCPClientProxy":
|
|
60
|
-
from .mcp_client_proxy import MCPClientProxy
|
|
61
|
-
|
|
62
|
-
return MCPClientProxy
|
|
63
|
-
elif name == "EnhancedMCPClientProxy":
|
|
64
|
-
from .mcp_client_proxy import EnhancedMCPClientProxy
|
|
65
|
-
|
|
66
|
-
return EnhancedMCPClientProxy
|
|
67
|
-
elif name == "FullMCPProxy":
|
|
68
|
-
from .full_mcp_proxy import FullMCPProxy
|
|
69
|
-
|
|
70
|
-
return FullMCPProxy
|
|
71
|
-
elif name == "EnhancedFullMCPProxy":
|
|
72
|
-
from .full_mcp_proxy import EnhancedFullMCPProxy
|
|
73
|
-
|
|
74
|
-
return EnhancedFullMCPProxy
|
|
75
57
|
elif name == "AsyncMCPClient":
|
|
76
58
|
from .async_mcp_client import AsyncMCPClient
|
|
77
59
|
|
|
78
60
|
return AsyncMCPClient
|
|
61
|
+
elif name == "UnifiedMCPProxy":
|
|
62
|
+
from .unified_mcp_proxy import UnifiedMCPProxy
|
|
63
|
+
|
|
64
|
+
return UnifiedMCPProxy
|
|
65
|
+
elif name == "EnhancedUnifiedMCPProxy":
|
|
66
|
+
from .unified_mcp_proxy import EnhancedUnifiedMCPProxy
|
|
67
|
+
|
|
68
|
+
return EnhancedUnifiedMCPProxy
|
|
79
69
|
# Self-dependency proxy
|
|
80
70
|
elif name == "SelfDependencyProxy":
|
|
81
71
|
from .self_dependency_proxy import SelfDependencyProxy
|
|
@@ -1,22 +1,80 @@
|
|
|
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
|
|
10
|
+
|
|
11
|
+
from ..shared.sse_parser import SSEParser
|
|
8
12
|
|
|
9
13
|
logger = logging.getLogger(__name__)
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
class AsyncMCPClient:
|
|
13
|
-
"""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
|
|
14
30
|
|
|
15
31
|
def __init__(self, endpoint: str, timeout: float = 30.0):
|
|
16
32
|
self.endpoint = endpoint
|
|
17
33
|
self.timeout = timeout
|
|
18
34
|
self.logger = logger.getChild(f"client.{endpoint}")
|
|
19
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
|
+
|
|
20
78
|
async def call_tool(self, tool_name: str, arguments: dict) -> Any:
|
|
21
79
|
"""Call remote tool using MCP JSON-RPC protocol."""
|
|
22
80
|
payload = {
|
|
@@ -36,51 +94,38 @@ class AsyncMCPClient:
|
|
|
36
94
|
raise
|
|
37
95
|
|
|
38
96
|
async def _make_request(self, payload: dict) -> dict:
|
|
39
|
-
"""Make async HTTP request to MCP endpoint."""
|
|
40
|
-
url = f"{self.endpoint}/mcp
|
|
97
|
+
"""Make async HTTP request to MCP endpoint using pooled connections."""
|
|
98
|
+
url = f"{self.endpoint}/mcp"
|
|
41
99
|
|
|
42
100
|
try:
|
|
43
|
-
# Use httpx
|
|
101
|
+
# Use httpx with connection pooling for better resource management
|
|
44
102
|
import httpx
|
|
45
103
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
# Get pooled client (reuses connections across requests)
|
|
105
|
+
client = await self._get_pooled_client(self.endpoint, self.timeout)
|
|
106
|
+
|
|
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
|
+
)
|
|
115
|
+
|
|
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}"
|
|
54
121
|
)
|
|
55
122
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
response_text = response.text
|
|
64
|
-
|
|
65
|
-
# Handle Server-Sent Events format from FastMCP
|
|
66
|
-
if response_text.startswith("event:"):
|
|
67
|
-
# Parse SSE format: extract JSON from "data:" lines
|
|
68
|
-
json_data = None
|
|
69
|
-
for line in response_text.split("\n"):
|
|
70
|
-
if line.startswith("data:"):
|
|
71
|
-
json_str = line[5:].strip() # Remove 'data:' prefix
|
|
72
|
-
try:
|
|
73
|
-
json_data = json.loads(json_str)
|
|
74
|
-
break
|
|
75
|
-
except json.JSONDecodeError:
|
|
76
|
-
continue
|
|
77
|
-
|
|
78
|
-
if json_data is None:
|
|
79
|
-
raise RuntimeError("Could not parse SSE response from FastMCP")
|
|
80
|
-
data = json_data
|
|
81
|
-
else:
|
|
82
|
-
# Plain JSON response
|
|
83
|
-
data = response.json()
|
|
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
|
+
)
|
|
84
129
|
|
|
85
130
|
# Check for JSON-RPC error
|
|
86
131
|
if "error" in data:
|
|
@@ -104,7 +149,7 @@ class AsyncMCPClient:
|
|
|
104
149
|
|
|
105
150
|
async def _make_request_sync(self, payload: dict) -> dict:
|
|
106
151
|
"""Fallback sync HTTP request using urllib."""
|
|
107
|
-
url = f"{self.endpoint}/mcp
|
|
152
|
+
url = f"{self.endpoint}/mcp"
|
|
108
153
|
data = json.dumps(payload).encode("utf-8")
|
|
109
154
|
|
|
110
155
|
# Create request
|
|
@@ -182,5 +227,10 @@ class AsyncMCPClient:
|
|
|
182
227
|
return result
|
|
183
228
|
|
|
184
229
|
async def close(self):
|
|
185
|
-
"""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
|
+
"""
|
|
186
236
|
pass
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base injector class with shared wrapper creation logic.
|
|
3
|
+
|
|
4
|
+
Provides common functionality for DependencyInjector and MeshLlmAgentInjector.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import functools
|
|
8
|
+
import inspect
|
|
9
|
+
import logging
|
|
10
|
+
import weakref
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseInjector:
|
|
18
|
+
"""
|
|
19
|
+
Base class for injection systems.
|
|
20
|
+
|
|
21
|
+
Provides shared functionality for creating and managing function wrappers
|
|
22
|
+
that support dynamic injection with two-phase updates.
|
|
23
|
+
|
|
24
|
+
Two-Phase Injection Pattern:
|
|
25
|
+
1. Phase 1 (decorator time): Create wrapper with initial state (None)
|
|
26
|
+
2. Phase 2 (runtime): Update wrapper with actual instances via update method
|
|
27
|
+
|
|
28
|
+
Subclasses must implement:
|
|
29
|
+
- Wrapper logic (what to inject and how)
|
|
30
|
+
- Update method signature
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self):
|
|
34
|
+
"""Initialize base injector with function registry."""
|
|
35
|
+
self._function_registry: weakref.WeakValueDictionary = (
|
|
36
|
+
weakref.WeakValueDictionary()
|
|
37
|
+
)
|
|
38
|
+
logger.debug(f"🔧 {self.__class__.__name__} initialized")
|
|
39
|
+
|
|
40
|
+
def _register_wrapper(self, function_id: str, wrapper: Callable) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Register a wrapper in the function registry.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
function_id: Unique function identifier
|
|
46
|
+
wrapper: Wrapper function to register
|
|
47
|
+
"""
|
|
48
|
+
self._function_registry[function_id] = wrapper
|
|
49
|
+
logger.debug(f"🔧 Registered wrapper for {function_id} at {hex(id(wrapper))}")
|
|
50
|
+
|
|
51
|
+
def _create_async_wrapper(
|
|
52
|
+
self,
|
|
53
|
+
func: Callable,
|
|
54
|
+
function_id: str,
|
|
55
|
+
injection_logic: Callable[[Callable, tuple, dict], tuple],
|
|
56
|
+
metadata: dict[str, Any],
|
|
57
|
+
) -> Callable:
|
|
58
|
+
"""
|
|
59
|
+
Create async wrapper with injection logic.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
func: Original async function to wrap
|
|
63
|
+
function_id: Unique function identifier
|
|
64
|
+
injection_logic: Callable that takes (func, args, kwargs) and returns (args, kwargs)
|
|
65
|
+
This function should modify kwargs to inject dependencies
|
|
66
|
+
metadata: Additional metadata to store on wrapper
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Async wrapper function
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
@functools.wraps(func)
|
|
73
|
+
async def async_wrapper(*args, **kwargs):
|
|
74
|
+
# Apply injection logic to modify kwargs
|
|
75
|
+
args, kwargs = injection_logic(func, args, kwargs)
|
|
76
|
+
|
|
77
|
+
# Execute original function
|
|
78
|
+
return await func(*args, **kwargs)
|
|
79
|
+
|
|
80
|
+
# Store metadata on wrapper
|
|
81
|
+
async_wrapper._mesh_original_func = func
|
|
82
|
+
async_wrapper._mesh_function_id = function_id
|
|
83
|
+
|
|
84
|
+
# Store additional metadata
|
|
85
|
+
for key, value in metadata.items():
|
|
86
|
+
setattr(async_wrapper, key, value)
|
|
87
|
+
|
|
88
|
+
return async_wrapper
|
|
89
|
+
|
|
90
|
+
def _create_sync_wrapper(
|
|
91
|
+
self,
|
|
92
|
+
func: Callable,
|
|
93
|
+
function_id: str,
|
|
94
|
+
injection_logic: Callable[[Callable, tuple, dict], tuple],
|
|
95
|
+
metadata: dict[str, Any],
|
|
96
|
+
) -> Callable:
|
|
97
|
+
"""
|
|
98
|
+
Create sync wrapper with injection logic.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
func: Original sync function to wrap
|
|
102
|
+
function_id: Unique function identifier
|
|
103
|
+
injection_logic: Callable that takes (func, args, kwargs) and returns (args, kwargs)
|
|
104
|
+
This function should modify kwargs to inject dependencies
|
|
105
|
+
metadata: Additional metadata to store on wrapper
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Sync wrapper function
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
@functools.wraps(func)
|
|
112
|
+
def sync_wrapper(*args, **kwargs):
|
|
113
|
+
# Apply injection logic to modify kwargs
|
|
114
|
+
args, kwargs = injection_logic(func, args, kwargs)
|
|
115
|
+
|
|
116
|
+
# Execute original function
|
|
117
|
+
return func(*args, **kwargs)
|
|
118
|
+
|
|
119
|
+
# Store metadata on wrapper
|
|
120
|
+
sync_wrapper._mesh_original_func = func
|
|
121
|
+
sync_wrapper._mesh_function_id = function_id
|
|
122
|
+
|
|
123
|
+
# Store additional metadata
|
|
124
|
+
for key, value in metadata.items():
|
|
125
|
+
setattr(sync_wrapper, key, value)
|
|
126
|
+
|
|
127
|
+
return sync_wrapper
|
|
128
|
+
|
|
129
|
+
def create_wrapper_with_injection(
|
|
130
|
+
self,
|
|
131
|
+
func: Callable,
|
|
132
|
+
function_id: str,
|
|
133
|
+
injection_logic: Callable[[Callable, tuple, dict], tuple],
|
|
134
|
+
metadata: dict[str, Any],
|
|
135
|
+
register: bool = True,
|
|
136
|
+
) -> Callable:
|
|
137
|
+
"""
|
|
138
|
+
Create wrapper (async or sync) based on function type.
|
|
139
|
+
|
|
140
|
+
This is the main entry point for creating wrappers. It automatically
|
|
141
|
+
detects if the function is async or sync and creates the appropriate wrapper.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
func: Function to wrap
|
|
145
|
+
function_id: Unique function identifier
|
|
146
|
+
injection_logic: Callable that takes (func, args, kwargs) and returns (args, kwargs)
|
|
147
|
+
metadata: Additional metadata to store on wrapper
|
|
148
|
+
register: Whether to register wrapper in function_registry (default: True)
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Wrapped function with injection capability
|
|
152
|
+
"""
|
|
153
|
+
# Detect async vs sync
|
|
154
|
+
is_async = inspect.iscoroutinefunction(func)
|
|
155
|
+
|
|
156
|
+
if is_async:
|
|
157
|
+
wrapper = self._create_async_wrapper(
|
|
158
|
+
func, function_id, injection_logic, metadata
|
|
159
|
+
)
|
|
160
|
+
logger.debug(f"✅ Created async wrapper for {function_id}")
|
|
161
|
+
else:
|
|
162
|
+
wrapper = self._create_sync_wrapper(
|
|
163
|
+
func, function_id, injection_logic, metadata
|
|
164
|
+
)
|
|
165
|
+
logger.debug(f"✅ Created sync wrapper for {function_id}")
|
|
166
|
+
|
|
167
|
+
# Register wrapper if requested
|
|
168
|
+
if register:
|
|
169
|
+
self._register_wrapper(function_id, wrapper)
|
|
170
|
+
|
|
171
|
+
return wrapper
|