mcp-mesh 0.7.21__tar.gz → 0.8.0b1__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 (164) hide show
  1. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/.gitignore +10 -0
  2. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/PKG-INFO +2 -1
  3. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/__init__.py +1 -1
  4. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/dependency_injector.py +4 -6
  5. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/http_wrapper.py +69 -10
  6. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/mesh_llm_agent.py +4 -7
  7. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/mesh_llm_agent_injector.py +2 -1
  8. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/provider_handlers/__init__.py +14 -1
  9. mcp_mesh-0.8.0b1/_mcp_mesh/engine/provider_handlers/base_provider_handler.py +228 -0
  10. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/provider_handlers/claude_handler.py +15 -57
  11. mcp_mesh-0.8.0b1/_mcp_mesh/engine/provider_handlers/gemini_handler.py +181 -0
  12. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/provider_handlers/openai_handler.py +8 -63
  13. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/provider_handlers/provider_handler_registry.py +16 -10
  14. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/response_parser.py +61 -15
  15. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/unified_mcp_proxy.py +18 -34
  16. mcp_mesh-0.8.0b1/_mcp_mesh/pipeline/__init__.py +35 -0
  17. mcp_mesh-0.8.0b1/_mcp_mesh/pipeline/api_heartbeat/__init__.py +21 -0
  18. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py +23 -49
  19. mcp_mesh-0.8.0b1/_mcp_mesh/pipeline/api_heartbeat/rust_api_heartbeat.py +425 -0
  20. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/api_pipeline.py +7 -9
  21. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/api_server_setup.py +91 -70
  22. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/fastapi_discovery.py +22 -23
  23. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/middleware_integration.py +32 -24
  24. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/route_collection.py +2 -4
  25. mcp_mesh-0.8.0b1/_mcp_mesh/pipeline/mcp_heartbeat/__init__.py +13 -0
  26. mcp_mesh-0.8.0b1/_mcp_mesh/pipeline/mcp_heartbeat/rust_heartbeat.py +695 -0
  27. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/__init__.py +2 -5
  28. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/configuration.py +1 -1
  29. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py +5 -6
  30. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/heartbeat_loop.py +6 -7
  31. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +21 -9
  32. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/startup_pipeline.py +3 -8
  33. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/shared/mesh_pipeline.py +0 -2
  34. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/reload.py +1 -3
  35. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/__init__.py +2 -8
  36. mcp_mesh-0.8.0b1/_mcp_mesh/shared/config_resolver.py +270 -0
  37. mcp_mesh-0.8.0b1/_mcp_mesh/shared/defaults.py +139 -0
  38. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/fastapi_middleware_manager.py +149 -91
  39. mcp_mesh-0.8.0b1/_mcp_mesh/shared/host_resolver.py +48 -0
  40. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/server_discovery.py +115 -86
  41. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/simple_shutdown.py +44 -86
  42. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/execution_tracer.py +2 -6
  43. mcp_mesh-0.8.0b1/_mcp_mesh/tracing/redis_metadata_publisher.py +84 -0
  44. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/trace_context_helper.py +3 -13
  45. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/utils.py +29 -15
  46. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/utils/fastmcp_schema_extractor.py +2 -1
  47. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/mesh/__init__.py +2 -1
  48. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/mesh/decorators.py +89 -5
  49. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/pyproject.toml +6 -4
  50. mcp_mesh-0.7.21/_mcp_mesh/engine/provider_handlers/base_provider_handler.py +0 -122
  51. mcp_mesh-0.7.21/_mcp_mesh/generated/.openapi-generator/FILES +0 -50
  52. mcp_mesh-0.7.21/_mcp_mesh/generated/.openapi-generator/VERSION +0 -1
  53. mcp_mesh-0.7.21/_mcp_mesh/generated/.openapi-generator-ignore +0 -15
  54. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +0 -90
  55. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api/__init__.py +0 -6
  56. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api/agents_api.py +0 -1088
  57. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api/health_api.py +0 -764
  58. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api/tracing_api.py +0 -303
  59. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api_client.py +0 -798
  60. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/api_response.py +0 -21
  61. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/configuration.py +0 -577
  62. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/exceptions.py +0 -217
  63. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +0 -55
  64. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +0 -158
  65. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata.py +0 -126
  66. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner.py +0 -139
  67. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_metadata_dependencies_inner_one_of.py +0 -92
  68. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration.py +0 -103
  69. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agent_registration_metadata.py +0 -136
  70. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/agents_list_response.py +0 -100
  71. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/capability_info.py +0 -107
  72. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_metadata.py +0 -112
  73. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_agent_request.py +0 -103
  74. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/decorator_info.py +0 -105
  75. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_info.py +0 -103
  76. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_resolution_info.py +0 -106
  77. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/error_response.py +0 -91
  78. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/health_response.py +0 -103
  79. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request.py +0 -101
  80. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_request_metadata.py +0 -111
  81. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/heartbeat_response.py +0 -117
  82. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider.py +0 -93
  83. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider_resolution_info.py +0 -106
  84. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter.py +0 -109
  85. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py +0 -139
  86. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py +0 -91
  87. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_info.py +0 -101
  88. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_resolution_info.py +0 -120
  89. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_register_metadata.py +0 -112
  90. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +0 -129
  91. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py +0 -153
  92. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response_dependencies_resolved_value_inner.py +0 -101
  93. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_dependency_registration.py +0 -93
  94. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_register_metadata.py +0 -107
  95. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_registration.py +0 -117
  96. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/registration_response.py +0 -119
  97. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/resolved_llm_provider.py +0 -110
  98. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/rich_dependency.py +0 -93
  99. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/root_response.py +0 -92
  100. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py +0 -93
  101. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py +0 -106
  102. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/py.typed +0 -0
  103. mcp_mesh-0.7.21/_mcp_mesh/generated/mcp_mesh_registry_client/rest.py +0 -259
  104. mcp_mesh-0.7.21/_mcp_mesh/pipeline/__init__.py +0 -46
  105. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/__init__.py +0 -16
  106. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +0 -418
  107. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +0 -117
  108. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_health_check.py +0 -140
  109. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py +0 -243
  110. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +0 -311
  111. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py +0 -386
  112. mcp_mesh-0.7.21/_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py +0 -104
  113. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/__init__.py +0 -25
  114. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +0 -396
  115. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py +0 -116
  116. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py +0 -311
  117. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py +0 -282
  118. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py +0 -98
  119. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/lifespan_integration.py +0 -84
  120. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +0 -264
  121. mcp_mesh-0.7.21/_mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py +0 -79
  122. mcp_mesh-0.7.21/_mcp_mesh/pipeline/shared/registry_connection.py +0 -80
  123. mcp_mesh-0.7.21/_mcp_mesh/shared/config_resolver.py +0 -226
  124. mcp_mesh-0.7.21/_mcp_mesh/shared/defaults.py +0 -64
  125. mcp_mesh-0.7.21/_mcp_mesh/shared/host_resolver.py +0 -86
  126. mcp_mesh-0.7.21/_mcp_mesh/shared/registry_client_wrapper.py +0 -515
  127. mcp_mesh-0.7.21/_mcp_mesh/tracing/redis_metadata_publisher.py +0 -139
  128. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/LICENSE +0 -0
  129. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/README.md +0 -0
  130. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/__init__.py +0 -0
  131. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/async_mcp_client.py +0 -0
  132. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/base_injector.py +0 -0
  133. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/decorator_registry.py +0 -0
  134. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/llm_config.py +0 -0
  135. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/llm_errors.py +0 -0
  136. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/provider_handlers/generic_handler.py +0 -0
  137. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/self_dependency_proxy.py +0 -0
  138. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/session_aware_client.py +0 -0
  139. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/session_manager.py +0 -0
  140. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/signature_analyzer.py +0 -0
  141. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/tool_executor.py +0 -0
  142. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/engine/tool_schema_builder.py +0 -0
  143. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/__init__.py +0 -0
  144. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/api_startup/route_integration.py +0 -0
  145. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/decorator_collection.py +0 -0
  146. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/fastmcpserver_discovery.py +0 -0
  147. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/heartbeat_preparation.py +0 -0
  148. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/lifespan_factory.py +0 -0
  149. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/mcp_startup/server_discovery.py +0 -0
  150. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/shared/__init__.py +0 -0
  151. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/shared/base_step.py +0 -0
  152. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/pipeline/shared/pipeline_types.py +0 -0
  153. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/reload_runner.py +0 -0
  154. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/content_extractor.py +0 -0
  155. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/fast_heartbeat_status.py +0 -0
  156. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/health_check_manager.py +0 -0
  157. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/logging_config.py +0 -0
  158. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/sse_parser.py +0 -0
  159. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/shared/support_types.py +0 -0
  160. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/agent_context_helper.py +0 -0
  161. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/context.py +0 -0
  162. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/_mcp_mesh/tracing/fastapi_tracing_middleware.py +0 -0
  163. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/mesh/helpers.py +0 -0
  164. {mcp_mesh-0.7.21 → mcp_mesh-0.8.0b1}/mesh/types.py +0 -0
@@ -245,3 +245,13 @@ helm/*/charts/*.tgz
245
245
  helm/mcp-mesh-grafana/files/
246
246
  helm/mcp-mesh-tempo/files/
247
247
  *.DS_Store
248
+ rust-core-implementation.org
249
+
250
+ # Claude Code local files
251
+ .claude/memories.json
252
+ *.node
253
+
254
+ # NAPI-RS auto-generated build artifacts
255
+ src/runtime/core/index.js
256
+ src/runtime/core/index.d.ts
257
+ test/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-mesh
3
- Version: 0.7.21
3
+ Version: 0.8.0b1
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
@@ -30,6 +30,7 @@ Requires-Dist: fastmcp<3.0.0,>=2.8.0
30
30
  Requires-Dist: httpx<1.0.0,>=0.25.0
31
31
  Requires-Dist: jinja2>=3.1.0
32
32
  Requires-Dist: litellm>=1.30.0
33
+ Requires-Dist: mcp-mesh-core>=0.8.0b1
33
34
  Requires-Dist: mcp<2.0.0,>=1.9.0
34
35
  Requires-Dist: prometheus-client<1.0.0,>=0.19.0
35
36
  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.7.21"
34
+ __version__ = "0.8.0b1"
35
35
 
36
36
  # Store reference to runtime processor if initialized
37
37
  _runtime_processor = None
@@ -14,12 +14,10 @@ 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
- )
22
- from .signature_analyzer import get_mesh_agent_positions, has_llm_agent_parameter
17
+ from ..shared.logging_config import (format_log_value, format_result_summary,
18
+ get_trace_prefix)
19
+ from .signature_analyzer import (get_mesh_agent_positions,
20
+ has_llm_agent_parameter)
23
21
 
24
22
  logger = logging.getLogger(__name__)
25
23
 
@@ -387,8 +387,13 @@ class HttpMcpWrapper:
387
387
  self.logger = logger
388
388
 
389
389
  async def dispatch(self, request: Request, call_next):
390
- # Extract and set trace context from headers for distributed tracing
390
+ # Read body once for processing
391
+ body = await request.body()
392
+ modified_body = body
393
+
394
+ # Extract and set trace context from headers and arguments
391
395
  try:
396
+ from ..tracing.context import TraceContext
392
397
  from ..tracing.trace_context_helper import TraceContextHelper
393
398
 
394
399
  # DEBUG: Log incoming headers for trace propagation debugging
@@ -399,22 +404,67 @@ class HttpMcpWrapper:
399
404
  f"X-Parent-Span={parent_span_header}, path={request.url.path}"
400
405
  )
401
406
 
402
- # Use helper class for trace context extraction and setup
403
- trace_context = (
404
- await TraceContextHelper.extract_trace_context_from_request(
405
- request
407
+ # Extract trace context from both headers AND arguments
408
+ trace_id = trace_id_header
409
+ parent_span = parent_span_header
410
+
411
+ # Try extracting from JSON-RPC body arguments as fallback
412
+ # Also strip trace fields from arguments to avoid Pydantic validation errors
413
+ if body:
414
+ try:
415
+ payload = json.loads(body.decode("utf-8"))
416
+ if payload.get("method") == "tools/call":
417
+ arguments = payload.get("params", {}).get(
418
+ "arguments", {}
419
+ )
420
+
421
+ # Extract trace context from arguments (TypeScript uses _trace_id/_parent_span)
422
+ if not trace_id and arguments.get("_trace_id"):
423
+ trace_id = arguments.get("_trace_id")
424
+ if not parent_span and arguments.get("_parent_span"):
425
+ parent_span = arguments.get("_parent_span")
426
+
427
+ # Strip trace context fields from arguments before passing to FastMCP
428
+ if (
429
+ "_trace_id" in arguments
430
+ or "_parent_span" in arguments
431
+ ):
432
+ arguments.pop("_trace_id", None)
433
+ arguments.pop("_parent_span", None)
434
+ # Update payload with cleaned arguments
435
+ modified_body = json.dumps(payload).encode("utf-8")
436
+ self.logger.debug(
437
+ f"🔗 Stripped trace fields from arguments, "
438
+ f"trace_id={trace_id[:8] if trace_id else None}..."
439
+ )
440
+ except Exception as e:
441
+ self.logger.debug(
442
+ f"Failed to process body for trace context: {e}"
443
+ )
444
+
445
+ # Setup trace context if we have a trace_id
446
+ if trace_id:
447
+ trace_context = {
448
+ "trace_id": trace_id,
449
+ "parent_span": parent_span,
450
+ }
451
+ TraceContextHelper.setup_request_trace_context(
452
+ trace_context, self.logger
406
453
  )
407
- )
408
- TraceContextHelper.setup_request_trace_context(
409
- trace_context, self.logger
410
- )
411
454
  except Exception as e:
412
455
  # Never fail request due to tracing issues
413
456
  self.logger.warning(f"Failed to set trace context: {e}")
414
457
  pass
415
458
 
459
+ # Create a new request scope with the modified body
460
+ async def receive():
461
+ return {"type": "http.request", "body": modified_body}
462
+
463
+ # Update request with modified receive
464
+ request._receive = receive
465
+
416
466
  # Extract session ID from request
417
- session_id = await self.http_wrapper._extract_session_id(request)
467
+ session_id = await self.http_wrapper._extract_session_id_from_body(body)
418
468
 
419
469
  if session_id:
420
470
  # Check for existing session assignment
@@ -458,6 +508,15 @@ class HttpMcpWrapper:
458
508
  # Try extracting from JSON-RPC body
459
509
  try:
460
510
  body = await request.body()
511
+ return await self._extract_session_id_from_body(body)
512
+ except Exception:
513
+ pass
514
+
515
+ return None
516
+
517
+ async def _extract_session_id_from_body(self, body: bytes) -> str:
518
+ """Extract session ID from already-read request body."""
519
+ try:
461
520
  if body:
462
521
  payload = json.loads(body.decode("utf-8"))
463
522
  if payload.get("method") == "tools/call":
@@ -14,12 +14,8 @@ from typing import Any, Dict, List, Literal, Optional, Union
14
14
  from pydantic import BaseModel
15
15
 
16
16
  from .llm_config import LLMConfig
17
- from .llm_errors import (
18
- LLMAPIError,
19
- MaxIterationsError,
20
- ResponseParseError,
21
- ToolExecutionError,
22
- )
17
+ from .llm_errors import (LLMAPIError, MaxIterationsError, ResponseParseError,
18
+ ToolExecutionError)
23
19
  from .provider_handlers import ProviderHandlerRegistry
24
20
  from .response_parser import ResponseParser
25
21
  from .tool_executor import ToolExecutor
@@ -27,7 +23,8 @@ from .tool_schema_builder import ToolSchemaBuilder
27
23
 
28
24
  # Import Jinja2 for template rendering
29
25
  try:
30
- from jinja2 import Environment, FileSystemLoader, Template, TemplateSyntaxError
26
+ from jinja2 import (Environment, FileSystemLoader, Template,
27
+ TemplateSyntaxError)
31
28
  except ImportError:
32
29
  Environment = None
33
30
  FileSystemLoader = None
@@ -431,7 +431,8 @@ class MeshLlmAgentInjector(BaseInjector):
431
431
  if is_template:
432
432
  # Templates enabled - create per-call agent with context
433
433
  # Import signature analyzer for context detection
434
- from .signature_analyzer import get_context_parameter_name
434
+ from .signature_analyzer import \
435
+ get_context_parameter_name
435
436
 
436
437
  # Detect context parameter
437
438
  context_param_name = config_dict.get("context_param")
@@ -5,15 +5,28 @@ This package provides vendor-specific customization for different LLM providers
5
5
  (Claude, OpenAI, Gemini, etc.) to optimize API calls and response handling.
6
6
  """
7
7
 
8
- from .base_provider_handler import BaseProviderHandler
8
+ from .base_provider_handler import (
9
+ BASE_TOOL_INSTRUCTIONS,
10
+ CLAUDE_ANTI_XML_INSTRUCTION,
11
+ BaseProviderHandler,
12
+ make_schema_strict,
13
+ )
9
14
  from .claude_handler import ClaudeHandler
15
+ from .gemini_handler import GeminiHandler
10
16
  from .generic_handler import GenericHandler
11
17
  from .openai_handler import OpenAIHandler
12
18
  from .provider_handler_registry import ProviderHandlerRegistry
13
19
 
14
20
  __all__ = [
21
+ # Constants
22
+ "BASE_TOOL_INSTRUCTIONS",
23
+ "CLAUDE_ANTI_XML_INSTRUCTION",
24
+ # Utilities
25
+ "make_schema_strict",
26
+ # Handlers
15
27
  "BaseProviderHandler",
16
28
  "ClaudeHandler",
29
+ "GeminiHandler",
17
30
  "OpenAIHandler",
18
31
  "GenericHandler",
19
32
  "ProviderHandlerRegistry",
@@ -0,0 +1,228 @@
1
+ """
2
+ Base provider handler interface for vendor-specific LLM behavior.
3
+
4
+ This module defines the abstract base class for provider-specific handlers
5
+ that customize how different LLM vendors (Claude, OpenAI, Gemini, etc.) are called.
6
+ """
7
+
8
+ import copy
9
+ from abc import ABC, abstractmethod
10
+ from typing import Any, Optional
11
+
12
+ from pydantic import BaseModel
13
+
14
+ # ============================================================================
15
+ # Shared Constants
16
+ # ============================================================================
17
+
18
+ # Base tool calling instructions shared across all providers.
19
+ # Claude handler adds anti-XML instruction on top of this.
20
+ BASE_TOOL_INSTRUCTIONS = """
21
+ IMPORTANT TOOL CALLING RULES:
22
+ - You have access to tools that you can call to gather information
23
+ - Make ONE tool call at a time
24
+ - After receiving tool results, you can make additional calls if needed
25
+ - Once you have all needed information, provide your final response
26
+ """
27
+
28
+ # Anti-XML instruction for Claude (prevents <invoke> style tool calls).
29
+ CLAUDE_ANTI_XML_INSTRUCTION = (
30
+ '- NEVER use XML-style syntax like <invoke name="tool_name"/>'
31
+ )
32
+
33
+
34
+ # ============================================================================
35
+ # Shared Schema Utilities
36
+ # ============================================================================
37
+
38
+
39
+ def make_schema_strict(
40
+ schema: dict[str, Any],
41
+ add_all_required: bool = True,
42
+ ) -> dict[str, Any]:
43
+ """
44
+ Make a JSON schema strict for structured output.
45
+
46
+ This is a shared utility used by OpenAI, Gemini, and Claude handlers.
47
+ Adds additionalProperties: false to all object types and optionally
48
+ ensures 'required' includes all property keys.
49
+
50
+ Args:
51
+ schema: JSON schema to make strict
52
+ add_all_required: If True, set 'required' to include ALL property keys.
53
+ OpenAI and Gemini require this; Claude does not.
54
+ Default: True
55
+
56
+ Returns:
57
+ New schema with strict constraints (original not mutated)
58
+ """
59
+ result = copy.deepcopy(schema)
60
+ _add_strict_constraints_recursive(result, add_all_required)
61
+ return result
62
+
63
+
64
+ def _add_strict_constraints_recursive(obj: Any, add_all_required: bool) -> None:
65
+ """
66
+ Recursively add strict constraints to a schema object.
67
+
68
+ Args:
69
+ obj: Schema object to process (mutated in place)
70
+ add_all_required: Whether to set required to all property keys
71
+ """
72
+ if not isinstance(obj, dict):
73
+ return
74
+
75
+ # If this is an object type, add additionalProperties: false
76
+ if obj.get("type") == "object":
77
+ obj["additionalProperties"] = False
78
+
79
+ # Optionally set required to include all property keys
80
+ if add_all_required and "properties" in obj:
81
+ obj["required"] = list(obj["properties"].keys())
82
+
83
+ # Process $defs (Pydantic uses this for nested models)
84
+ if "$defs" in obj:
85
+ for def_schema in obj["$defs"].values():
86
+ _add_strict_constraints_recursive(def_schema, add_all_required)
87
+
88
+ # Process properties
89
+ if "properties" in obj:
90
+ for prop_schema in obj["properties"].values():
91
+ _add_strict_constraints_recursive(prop_schema, add_all_required)
92
+
93
+ # Process items (for arrays)
94
+ # items can be an object (single schema) or a list (tuple validation in older drafts)
95
+ if "items" in obj:
96
+ items = obj["items"]
97
+ if isinstance(items, dict):
98
+ _add_strict_constraints_recursive(items, add_all_required)
99
+ elif isinstance(items, list):
100
+ for item in items:
101
+ _add_strict_constraints_recursive(item, add_all_required)
102
+
103
+ # Process prefixItems (tuple validation in JSON Schema draft 2020-12)
104
+ if "prefixItems" in obj:
105
+ for item in obj["prefixItems"]:
106
+ _add_strict_constraints_recursive(item, add_all_required)
107
+
108
+ # Process anyOf, oneOf, allOf
109
+ for key in ("anyOf", "oneOf", "allOf"):
110
+ if key in obj:
111
+ for item in obj[key]:
112
+ _add_strict_constraints_recursive(item, add_all_required)
113
+
114
+
115
+ # ============================================================================
116
+ # Base Provider Handler
117
+ # ============================================================================
118
+
119
+
120
+ class BaseProviderHandler(ABC):
121
+ """
122
+ Abstract base class for provider-specific LLM handlers.
123
+
124
+ Each vendor (Claude, OpenAI, Gemini, etc.) can have its own handler
125
+ that customizes request preparation, system prompt formatting, and
126
+ response parsing to work optimally with that vendor's API.
127
+
128
+ Handler Selection:
129
+ The ProviderHandlerRegistry selects handlers based on the 'vendor'
130
+ field from the LLM provider registration (extracted via LiteLLM).
131
+
132
+ Extensibility:
133
+ New handlers can be added by:
134
+ 1. Subclassing BaseProviderHandler
135
+ 2. Implementing required methods
136
+ 3. Registering in ProviderHandlerRegistry
137
+ 4. Optionally: Adding as Python entry point for auto-discovery
138
+ """
139
+
140
+ def __init__(self, vendor: str):
141
+ """
142
+ Initialize provider handler.
143
+
144
+ Args:
145
+ vendor: Vendor name (e.g., "anthropic", "openai", "google")
146
+ """
147
+ self.vendor = vendor
148
+
149
+ @abstractmethod
150
+ def prepare_request(
151
+ self,
152
+ messages: list[dict[str, Any]],
153
+ tools: Optional[list[dict[str, Any]]],
154
+ output_type: type[BaseModel],
155
+ **kwargs: Any,
156
+ ) -> dict[str, Any]:
157
+ """
158
+ Prepare vendor-specific request parameters.
159
+
160
+ This method allows customization of the request sent to the LLM provider.
161
+ For example:
162
+ - OpenAI: Add response_format parameter for structured output
163
+ - Claude: Use native tool calling format
164
+ - Gemini: Add generation config
165
+
166
+ Args:
167
+ messages: List of message dicts (role, content)
168
+ tools: Optional list of tool schemas (OpenAI format)
169
+ output_type: Pydantic model for expected response
170
+ **kwargs: Additional model parameters
171
+
172
+ Returns:
173
+ Dictionary of parameters to pass to litellm.completion()
174
+ Must include at minimum: messages, tools (if provided)
175
+ May include vendor-specific params like response_format, temperature, etc.
176
+ """
177
+ pass
178
+
179
+ @abstractmethod
180
+ def format_system_prompt(
181
+ self,
182
+ base_prompt: str,
183
+ tool_schemas: Optional[list[dict[str, Any]]],
184
+ output_type: type[BaseModel],
185
+ ) -> str:
186
+ """
187
+ Format system prompt for vendor-specific requirements.
188
+
189
+ Different vendors have different best practices for system prompts:
190
+ - Claude: Prefers detailed instructions, handles XML well
191
+ - OpenAI: Structured output mode makes JSON instructions optional
192
+ - Gemini: System instructions separate from messages
193
+
194
+ Args:
195
+ base_prompt: Base system prompt (from template or config)
196
+ tool_schemas: Optional list of tool schemas (if tools available)
197
+ output_type: Pydantic model for response validation
198
+
199
+ Returns:
200
+ Formatted system prompt string optimized for this vendor
201
+ """
202
+ pass
203
+
204
+ def get_vendor_capabilities(self) -> dict[str, bool]:
205
+ """
206
+ Return vendor-specific capability flags.
207
+
208
+ Override this to indicate which features the vendor supports:
209
+ - native_tool_calling: Vendor has native function calling
210
+ - structured_output: Vendor supports structured output (response_format)
211
+ - streaming: Vendor supports streaming responses
212
+ - vision: Vendor supports image inputs
213
+ - json_mode: Vendor has JSON response mode
214
+
215
+ Returns:
216
+ Dictionary of capability flags
217
+ """
218
+ return {
219
+ "native_tool_calling": True,
220
+ "structured_output": False,
221
+ "streaming": False,
222
+ "vision": False,
223
+ "json_mode": False,
224
+ }
225
+
226
+ def __repr__(self) -> str:
227
+ """String representation of handler."""
228
+ return f"{self.__class__.__name__}(vendor='{self.vendor}')"
@@ -17,11 +17,16 @@ Features:
17
17
 
18
18
  import json
19
19
  import logging
20
- from typing import Any, Optional, get_args, get_origin
20
+ from typing import Any, Optional
21
21
 
22
22
  from pydantic import BaseModel
23
23
 
24
- from .base_provider_handler import BaseProviderHandler
24
+ from .base_provider_handler import (
25
+ BASE_TOOL_INSTRUCTIONS,
26
+ BaseProviderHandler,
27
+ CLAUDE_ANTI_XML_INSTRUCTION,
28
+ make_schema_strict,
29
+ )
25
30
 
26
31
  logger = logging.getLogger(__name__)
27
32
 
@@ -141,51 +146,6 @@ class ClaudeHandler(BaseProviderHandler):
141
146
  # Default to strict for unknown types
142
147
  return OUTPUT_MODE_STRICT
143
148
 
144
- def _make_schema_strict(self, schema: dict[str, Any]) -> dict[str, Any]:
145
- """
146
- Make a JSON schema strict for Claude's structured output.
147
-
148
- Claude requires additionalProperties: false on all object types.
149
- This recursively processes the schema to add this constraint.
150
-
151
- Args:
152
- schema: JSON schema dict
153
-
154
- Returns:
155
- Schema with additionalProperties: false on all objects
156
- """
157
- if not isinstance(schema, dict):
158
- return schema
159
-
160
- result = schema.copy()
161
-
162
- # If this is an object type, add additionalProperties: false
163
- if result.get("type") == "object":
164
- result["additionalProperties"] = False
165
-
166
- # Recursively process nested schemas
167
- if "properties" in result:
168
- result["properties"] = {
169
- k: self._make_schema_strict(v) for k, v in result["properties"].items()
170
- }
171
-
172
- # Process $defs (Pydantic uses this for nested models)
173
- if "$defs" in result:
174
- result["$defs"] = {
175
- k: self._make_schema_strict(v) for k, v in result["$defs"].items()
176
- }
177
-
178
- # Process items for arrays
179
- if "items" in result:
180
- result["items"] = self._make_schema_strict(result["items"])
181
-
182
- # Process anyOf, oneOf, allOf
183
- for key in ["anyOf", "oneOf", "allOf"]:
184
- if key in result:
185
- result[key] = [self._make_schema_strict(s) for s in result[key]]
186
-
187
- return result
188
-
189
149
  def _apply_prompt_caching(
190
150
  self, messages: list[dict[str, Any]]
191
151
  ) -> list[dict[str, Any]]:
@@ -302,9 +262,10 @@ class ClaudeHandler(BaseProviderHandler):
302
262
  # Only add response_format in "strict" mode
303
263
  if determined_mode == OUTPUT_MODE_STRICT:
304
264
  # Claude requires additionalProperties: false on all object types
265
+ # Unlike OpenAI/Gemini, Claude doesn't require all properties in 'required'
305
266
  if isinstance(output_type, type) and issubclass(output_type, BaseModel):
306
267
  schema = output_type.model_json_schema()
307
- strict_schema = self._make_schema_strict(schema)
268
+ strict_schema = make_schema_strict(schema, add_all_required=False)
308
269
  request_params["response_format"] = {
309
270
  "type": "json_schema",
310
271
  "json_schema": {
@@ -346,15 +307,12 @@ class ClaudeHandler(BaseProviderHandler):
346
307
  # Add tool calling instructions if tools available
347
308
  # These prevent Claude from using XML-style <invoke> syntax
348
309
  if tool_schemas:
349
- system_content += """
350
-
351
- IMPORTANT TOOL CALLING RULES:
352
- - You have access to tools that you can call to gather information
353
- - Make ONE tool call at a time
354
- - NEVER use XML-style syntax like <invoke name="tool_name"/>
355
- - After receiving tool results, you can make additional calls if needed
356
- - Once you have all needed information, provide your final response
357
- """
310
+ # Use base instructions but insert anti-XML rule for Claude
311
+ instructions = BASE_TOOL_INSTRUCTIONS.replace(
312
+ "- Make ONE tool call at a time",
313
+ f"- Make ONE tool call at a time\n{CLAUDE_ANTI_XML_INSTRUCTION}",
314
+ )
315
+ system_content += instructions
358
316
 
359
317
  # Add output format instructions based on mode
360
318
  if determined_mode == OUTPUT_MODE_TEXT: