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.
Files changed (160) hide show
  1. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/.gitignore +19 -3
  2. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/PKG-INFO +4 -1
  3. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/__init__.py +18 -4
  4. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/__init__.py +10 -20
  5. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/async_mcp_client.py +93 -43
  6. mcp_mesh-0.7.15/_mcp_mesh/engine/base_injector.py +171 -0
  7. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/decorator_registry.py +363 -11
  8. mcp_mesh-0.7.15/_mcp_mesh/engine/dependency_injector.py +708 -0
  9. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/http_wrapper.py +37 -24
  10. mcp_mesh-0.7.15/_mcp_mesh/engine/llm_config.py +54 -0
  11. mcp_mesh-0.7.15/_mcp_mesh/engine/llm_errors.py +115 -0
  12. mcp_mesh-0.7.15/_mcp_mesh/engine/mesh_llm_agent.py +850 -0
  13. mcp_mesh-0.7.15/_mcp_mesh/engine/mesh_llm_agent_injector.py +710 -0
  14. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/__init__.py +20 -0
  15. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/base_provider_handler.py +122 -0
  16. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/claude_handler.py +418 -0
  17. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/generic_handler.py +162 -0
  18. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/openai_handler.py +234 -0
  19. mcp_mesh-0.7.15/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py +167 -0
  20. mcp_mesh-0.7.15/_mcp_mesh/engine/response_parser.py +244 -0
  21. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/self_dependency_proxy.py +16 -0
  22. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_aware_client.py +3 -3
  23. mcp_mesh-0.7.15/_mcp_mesh/engine/signature_analyzer.py +359 -0
  24. mcp_mesh-0.7.15/_mcp_mesh/engine/tool_executor.py +169 -0
  25. mcp_mesh-0.7.15/_mcp_mesh/engine/tool_schema_builder.py +126 -0
  26. mcp_mesh-0.7.15/_mcp_mesh/engine/unified_mcp_proxy.py +944 -0
  27. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/FILES +11 -0
  28. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +12 -1
  29. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py +1 -1
  30. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/agents_api.py +13 -15
  31. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api/health_api.py +10 -12
  32. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py +303 -0
  33. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_client.py +1 -1
  34. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/configuration.py +1 -1
  35. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/exceptions.py +8 -8
  36. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +11 -1
  37. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +41 -4
  38. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata.py +1 -3
  39. {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
  40. {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
  41. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration.py +1 -3
  42. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration_metadata.py +1 -3
  43. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/agents_list_response.py +1 -3
  44. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/capability_info.py +15 -5
  45. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_metadata.py +1 -3
  46. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_request.py +2 -4
  47. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_info.py +1 -3
  48. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_info.py +1 -3
  49. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_resolution_info.py +106 -0
  50. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/error_response.py +1 -3
  51. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/health_response.py +1 -3
  52. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request.py +1 -3
  53. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request_metadata.py +1 -3
  54. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_response.py +1 -3
  55. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider.py +93 -0
  56. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider_resolution_info.py +106 -0
  57. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter.py +109 -0
  58. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py +139 -0
  59. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py +91 -0
  60. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_info.py +101 -0
  61. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_resolution_info.py +120 -0
  62. {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
  63. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +6 -8
  64. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py +36 -4
  65. {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
  66. {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
  67. {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
  68. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_registration.py +12 -4
  69. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/registration_response.py +1 -3
  70. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/resolved_llm_provider.py +110 -0
  71. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/rich_dependency.py +1 -3
  72. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/root_response.py +1 -3
  73. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py +1 -3
  74. mcp_mesh-0.7.15/_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py +106 -0
  75. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/rest.py +1 -1
  76. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/__init__.py +2 -2
  77. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/__init__.py +16 -0
  78. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +418 -0
  79. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +117 -0
  80. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_health_check.py +140 -0
  81. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py +247 -0
  82. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +311 -0
  83. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py +386 -0
  84. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py +147 -0
  85. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py +104 -0
  86. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/__init__.py +20 -0
  87. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/api_pipeline.py +64 -0
  88. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/api_server_setup.py +367 -0
  89. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/fastapi_discovery.py +139 -0
  90. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/middleware_integration.py +153 -0
  91. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/route_collection.py +56 -0
  92. mcp_mesh-0.7.15/_mcp_mesh/pipeline/api_startup/route_integration.py +317 -0
  93. mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +396 -0
  94. {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
  95. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_orchestrator.py +40 -11
  96. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_pipeline.py +12 -9
  97. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/heartbeat_send.py +1 -1
  98. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/lifespan_integration.py +13 -0
  99. mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +264 -0
  100. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/registry_connection.py +3 -3
  101. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/__init__.py +2 -0
  102. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/configuration.py +9 -0
  103. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/fastapiserver_setup.py +321 -319
  104. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/fastmcpserver_discovery.py +12 -5
  105. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/heartbeat_loop.py +1 -1
  106. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/heartbeat_preparation.py +111 -5
  107. mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/lifespan_factory.py +142 -0
  108. mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/server_discovery.py +193 -0
  109. mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +632 -0
  110. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/startup_pipeline.py +9 -6
  111. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/mesh_pipeline.py +4 -0
  112. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/registry_connection.py +1 -1
  113. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/config_resolver.py +0 -3
  114. mcp_mesh-0.7.15/_mcp_mesh/shared/fastapi_middleware_manager.py +371 -0
  115. mcp_mesh-0.7.15/_mcp_mesh/shared/health_check_manager.py +313 -0
  116. mcp_mesh-0.7.15/_mcp_mesh/shared/logging_config.py +277 -0
  117. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/registry_client_wrapper.py +92 -9
  118. mcp_mesh-0.7.15/_mcp_mesh/shared/server_discovery.py +312 -0
  119. mcp_mesh-0.7.15/_mcp_mesh/shared/simple_shutdown.py +217 -0
  120. mcp_mesh-0.7.15/_mcp_mesh/shared/sse_parser.py +219 -0
  121. mcp_mesh-0.7.15/_mcp_mesh/tracing/agent_context_helper.py +128 -0
  122. mcp_mesh-0.7.15/_mcp_mesh/tracing/context.py +85 -0
  123. mcp_mesh-0.7.15/_mcp_mesh/tracing/execution_tracer.py +270 -0
  124. mcp_mesh-0.7.15/_mcp_mesh/tracing/fastapi_tracing_middleware.py +203 -0
  125. mcp_mesh-0.7.15/_mcp_mesh/tracing/redis_metadata_publisher.py +139 -0
  126. mcp_mesh-0.7.15/_mcp_mesh/tracing/trace_context_helper.py +185 -0
  127. mcp_mesh-0.7.15/_mcp_mesh/tracing/utils.py +137 -0
  128. mcp_mesh-0.7.15/_mcp_mesh/utils/fastmcp_schema_extractor.py +476 -0
  129. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/mesh/__init__.py +22 -2
  130. mcp_mesh-0.7.15/mesh/decorators.py +1457 -0
  131. mcp_mesh-0.7.15/mesh/helpers.py +334 -0
  132. mcp_mesh-0.7.15/mesh/types.py +466 -0
  133. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/pyproject.toml +8 -5
  134. mcp_mesh-0.3.0/_mcp_mesh/engine/dependency_injector.py +0 -397
  135. mcp_mesh-0.3.0/_mcp_mesh/engine/full_mcp_proxy.py +0 -616
  136. mcp_mesh-0.3.0/_mcp_mesh/engine/mcp_client_proxy.py +0 -451
  137. mcp_mesh-0.3.0/_mcp_mesh/engine/signature_analyzer.py +0 -220
  138. mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat/dependency_resolution.py +0 -517
  139. mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup/startup_orchestrator.py +0 -465
  140. mcp_mesh-0.3.0/_mcp_mesh/shared/logging_config.py +0 -80
  141. mcp_mesh-0.3.0/mesh/decorators.py +0 -485
  142. mcp_mesh-0.3.0/mesh/types.py +0 -261
  143. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/LICENSE +0 -0
  144. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/README.md +0 -0
  145. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/engine/session_manager.py +0 -0
  146. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator/VERSION +0 -0
  147. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/.openapi-generator-ignore +0 -0
  148. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/api_response.py +0 -0
  149. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/generated/mcp_mesh_registry_client/py.typed +0 -0
  150. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/heartbeat → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_heartbeat}/__init__.py +0 -0
  151. {mcp_mesh-0.3.0/_mcp_mesh/pipeline/startup → mcp_mesh-0.7.15/_mcp_mesh/pipeline/mcp_startup}/decorator_collection.py +0 -0
  152. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/__init__.py +0 -0
  153. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/base_step.py +0 -0
  154. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/pipeline/shared/pipeline_types.py +0 -0
  155. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/__init__.py +0 -0
  156. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/content_extractor.py +0 -0
  157. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/defaults.py +0 -0
  158. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/fast_heartbeat_status.py +0 -0
  159. {mcp_mesh-0.3.0 → mcp_mesh-0.7.15}/_mcp_mesh/shared/host_resolver.py +0 -0
  160. {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/meshctl
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.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.3.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.startup import start_runtime
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 os.getenv("MCP_MESH_ENABLED", "true").lower() == "true":
63
- initialize_runtime()
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 for proper async HTTP requests (better threading support than aiohttp)
101
+ # Use httpx with connection pooling for better resource management
44
102
  import httpx
45
103
 
46
- async with httpx.AsyncClient(timeout=self.timeout) as client:
47
- response = await client.post(
48
- url,
49
- json=payload,
50
- headers={
51
- "Content-Type": "application/json",
52
- "Accept": "application/json, text/event-stream",
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
- if response.status_code == 404:
57
- raise RuntimeError(f"MCP endpoint not found at {url}")
58
- elif response.status_code >= 400:
59
- raise RuntimeError(
60
- f"HTTP error {response.status_code}: {response.reason_phrase}"
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 persistent connection to close)."""
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