mcp-mesh 0.7.11__py3-none-any.whl → 0.7.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _mcp_mesh/__init__.py +1 -1
- _mcp_mesh/engine/__init__.py +1 -22
- _mcp_mesh/engine/async_mcp_client.py +88 -25
- _mcp_mesh/engine/decorator_registry.py +10 -9
- _mcp_mesh/engine/dependency_injector.py +64 -53
- _mcp_mesh/engine/mesh_llm_agent.py +119 -5
- _mcp_mesh/engine/mesh_llm_agent_injector.py +30 -0
- _mcp_mesh/engine/session_aware_client.py +3 -3
- _mcp_mesh/engine/unified_mcp_proxy.py +82 -90
- _mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +0 -89
- _mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py +3 -3
- _mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py +30 -28
- _mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +16 -18
- _mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py +5 -5
- _mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py +3 -3
- _mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py +6 -6
- _mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py +1 -1
- _mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +15 -11
- _mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py +3 -3
- _mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py +37 -268
- _mcp_mesh/pipeline/mcp_startup/lifespan_factory.py +142 -0
- _mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +57 -93
- _mcp_mesh/pipeline/shared/registry_connection.py +1 -1
- _mcp_mesh/shared/health_check_manager.py +313 -0
- _mcp_mesh/shared/logging_config.py +205 -14
- _mcp_mesh/shared/registry_client_wrapper.py +8 -8
- _mcp_mesh/shared/sse_parser.py +19 -17
- _mcp_mesh/tracing/execution_tracer.py +26 -1
- _mcp_mesh/tracing/fastapi_tracing_middleware.py +3 -4
- _mcp_mesh/tracing/trace_context_helper.py +25 -6
- {mcp_mesh-0.7.11.dist-info → mcp_mesh-0.7.13.dist-info}/METADATA +1 -1
- {mcp_mesh-0.7.11.dist-info → mcp_mesh-0.7.13.dist-info}/RECORD +38 -39
- mesh/__init__.py +3 -1
- mesh/decorators.py +81 -43
- mesh/helpers.py +72 -4
- mesh/types.py +48 -4
- _mcp_mesh/engine/full_mcp_proxy.py +0 -641
- _mcp_mesh/engine/mcp_client_proxy.py +0 -457
- _mcp_mesh/shared/health_check_cache.py +0 -246
- {mcp_mesh-0.7.11.dist-info → mcp_mesh-0.7.13.dist-info}/WHEEL +0 -0
- {mcp_mesh-0.7.11.dist-info → mcp_mesh-0.7.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
_mcp_mesh/__init__.py,sha256=
|
|
2
|
-
_mcp_mesh/engine/__init__.py,sha256=
|
|
3
|
-
_mcp_mesh/engine/async_mcp_client.py,sha256=
|
|
1
|
+
_mcp_mesh/__init__.py,sha256=Op8T4rx0MN_ILAC8sr_ueOBgfVL3Au6aENGgMLuLWAY,2720
|
|
2
|
+
_mcp_mesh/engine/__init__.py,sha256=U_6Kw3vA_3RiNK0Oln5c5C7WvA9lSONV22wWzfxYHNw,2975
|
|
3
|
+
_mcp_mesh/engine/async_mcp_client.py,sha256=Sz-rXTkb1Mng_f0SpLqLuOdPJ8vZjv3DFy0i8yYOqYk,8792
|
|
4
4
|
_mcp_mesh/engine/base_injector.py,sha256=qzRLZqFP2VvEFagVovkpdldvDmm3VwPHm6tHwV58a2k,5648
|
|
5
|
-
_mcp_mesh/engine/decorator_registry.py,sha256=
|
|
6
|
-
_mcp_mesh/engine/dependency_injector.py,sha256=
|
|
7
|
-
_mcp_mesh/engine/full_mcp_proxy.py,sha256=PlRv7GSKqn5riOCqeCVulVdtq3z1Ug76mOkwMsOFHXw,25297
|
|
5
|
+
_mcp_mesh/engine/decorator_registry.py,sha256=cch2QdQ6bKjHKEGi1XWp1YcLLO3uI2YlxwWBO7Np65E,28229
|
|
6
|
+
_mcp_mesh/engine/dependency_injector.py,sha256=VLOmYAAvWSOs1wg5nUX8Psy4IL88a_gaMZpEHNZPDEc,31536
|
|
8
7
|
_mcp_mesh/engine/http_wrapper.py,sha256=OHbbxHBLyUGDoamHZ2hpYnFKapW_djQ60Y_vMOL6J70,21173
|
|
9
8
|
_mcp_mesh/engine/llm_config.py,sha256=95bOsGWro5E1JGq7oZtEYhVdrzcIJqjht_r5vEdJVz4,2049
|
|
10
9
|
_mcp_mesh/engine/llm_errors.py,sha256=h7BiI14u-jL8vtvBfFbFDDrN7gIw8PQjXIl5AP1SBuA,3276
|
|
11
|
-
_mcp_mesh/engine/
|
|
12
|
-
_mcp_mesh/engine/
|
|
13
|
-
_mcp_mesh/engine/mesh_llm_agent_injector.py,sha256=isufzCBExli8tdLUZOaPuea3uQs3C_yeVXbOVSF0YIU,27270
|
|
10
|
+
_mcp_mesh/engine/mesh_llm_agent.py,sha256=ChfHL2qXLhvI6M3BYjVe2PDVzGB-8NbdDV_ZNgP6jFk,34205
|
|
11
|
+
_mcp_mesh/engine/mesh_llm_agent_injector.py,sha256=Ji_lmycB-xGVL-J3n50eQWemYB9kpsLd1tqOTNYUZ4Q,28343
|
|
14
12
|
_mcp_mesh/engine/response_parser.py,sha256=NsOuGD7HJ0BFiiDUCp9v9cjLzVaU86HShVKzsrNnulk,8786
|
|
15
13
|
_mcp_mesh/engine/self_dependency_proxy.py,sha256=OkKt0-B_ADnJlWtHiHItoZCBZ7Su0iz2unEPFfXvrs4,3302
|
|
16
|
-
_mcp_mesh/engine/session_aware_client.py,sha256=
|
|
14
|
+
_mcp_mesh/engine/session_aware_client.py,sha256=QejKag5zYNos5BVffQvNXFMECHFMLNOv78By4e_JzQE,10589
|
|
17
15
|
_mcp_mesh/engine/session_manager.py,sha256=MCr0_fXBaUjXM51WU5EhDkiGvBdfzYQFVNb9DCXXL0A,10418
|
|
18
16
|
_mcp_mesh/engine/signature_analyzer.py,sha256=ftn9XsX0ZHWIaACdjgBVtCuIdqVU_4ST8cvcpzu4HTk,12339
|
|
19
17
|
_mcp_mesh/engine/tool_executor.py,sha256=Bf_9d02EEY9_yHm1p1-5YZ4rY6MPxn4SVpI6-3sm1uo,5456
|
|
20
18
|
_mcp_mesh/engine/tool_schema_builder.py,sha256=SQCxQIrSfdLu9-dLqiFurQLK7dhl0dc0xa0ibaxU-iE,3644
|
|
21
|
-
_mcp_mesh/engine/unified_mcp_proxy.py,sha256=
|
|
19
|
+
_mcp_mesh/engine/unified_mcp_proxy.py,sha256=dkhX0jgP_Rcg63WVM3h0KefEHSPh51dwmqgZyoKztGw,36521
|
|
22
20
|
_mcp_mesh/engine/provider_handlers/__init__.py,sha256=LLTCOgnuM3dlogbLmrpiMK3oB5L22eAmDC4BfxJ-L2I,593
|
|
23
21
|
_mcp_mesh/engine/provider_handlers/base_provider_handler.py,sha256=J-SPFFFG1eFSUVvfsv7y4EuNM4REjSxaYWC5E_lC6Pc,4195
|
|
24
22
|
_mcp_mesh/engine/provider_handlers/claude_handler.py,sha256=CCmlsWiCfIcgrLbAZzeSnl0g2pq0uDffT8zOj4F-sPQ,15727
|
|
@@ -80,11 +78,11 @@ _mcp_mesh/generated/mcp_mesh_registry_client/models/standardized_dependency.py,s
|
|
|
80
78
|
_mcp_mesh/generated/mcp_mesh_registry_client/models/trace_event.py,sha256=zceJuFnY-q2B43avqEc1GwkW1UcBpOAgRl__zcb-WDc,4458
|
|
81
79
|
_mcp_mesh/pipeline/__init__.py,sha256=9Aplh4m1z-rYTQys0JQLYlq9wTPdI72eSOhUPqcnvpA,1557
|
|
82
80
|
_mcp_mesh/pipeline/api_heartbeat/__init__.py,sha256=IXTLoQLAPqQEWZ8VMWc5W_cQJkDv95rlVGXyXoQDjHk,473
|
|
83
|
-
_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py,sha256=
|
|
84
|
-
_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py,sha256=
|
|
81
|
+
_mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py,sha256=LDeLvN2U2MgYK3HLEUIhG5FUC2FyrGUs7SueF7gcfAA,20027
|
|
82
|
+
_mcp_mesh/pipeline/api_heartbeat/api_fast_heartbeat_check.py,sha256=vXiGTvBl5mwnVRwzFFNa7GvYWa7B-flCsHSX_ECv_JI,4822
|
|
85
83
|
_mcp_mesh/pipeline/api_heartbeat/api_health_check.py,sha256=kDmFeOG_4tyqyJSBZjPcc7xTzGpP4vq6ObW_WBqXvzM,5130
|
|
86
84
|
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_orchestrator.py,sha256=uBswzWOBzU8p_C0AE2DF8UwIWG4rP2zecHfPqKzNuC0,10367
|
|
87
|
-
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py,sha256=
|
|
85
|
+
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_pipeline.py,sha256=1bvQcO6lwZYTGILLAyWQuTOhyI5IY8mmhfSWAoJzMQU,13480
|
|
88
86
|
_mcp_mesh/pipeline/api_heartbeat/api_heartbeat_send.py,sha256=vszesutlAFXv9B4XXFutEMEBBhN54hF8eztTtDudLaI,15785
|
|
89
87
|
_mcp_mesh/pipeline/api_heartbeat/api_lifespan_integration.py,sha256=WBo2crcaGfxi8Q46TU-i5OMhAv0sQKz7Z9jps-GLkvM,5183
|
|
90
88
|
_mcp_mesh/pipeline/api_heartbeat/api_registry_connection.py,sha256=6N0JdXdnLkaXau4t8syt9DLgv9Y51SPfTXYK3DefBk8,3846
|
|
@@ -96,56 +94,57 @@ _mcp_mesh/pipeline/api_startup/middleware_integration.py,sha256=ybImXZlmIR6yA-wY
|
|
|
96
94
|
_mcp_mesh/pipeline/api_startup/route_collection.py,sha256=UjA-F5_RbGVU5TfDT19Np5_x2PtYkNn2mGFyivDsk24,2031
|
|
97
95
|
_mcp_mesh/pipeline/api_startup/route_integration.py,sha256=qq1AVaWna-CWEXyehyDL3EyeYKgo5aMtei8uBNdvkZ8,12448
|
|
98
96
|
_mcp_mesh/pipeline/mcp_heartbeat/__init__.py,sha256=nRNjZ3VD_9bPLQuJ6Nc02gE7KSLcMP7TMquB0hP6hHs,844
|
|
99
|
-
_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py,sha256=
|
|
100
|
-
_mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py,sha256=
|
|
101
|
-
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py,sha256=
|
|
102
|
-
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py,sha256=
|
|
103
|
-
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py,sha256=
|
|
97
|
+
_mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py,sha256=3f6B5uUUGKj1o5Q5kVR817YpEVI9V173xcVRHAV3k4Q,18784
|
|
98
|
+
_mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py,sha256=XgU3Y5XPThXaPaEfxGZVCmwAgzTG8p0tba95EnMwWeE,4468
|
|
99
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py,sha256=yMl_oE_Bim0F0W39V9pvvTCN_81KoqwSa5rfjJ1mPxo,12560
|
|
100
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py,sha256=I9kohm8lugJDEFT5kMLcLCt5DaRaK3q_wcvN-ed18Bw,11767
|
|
101
|
+
_mcp_mesh/pipeline/mcp_heartbeat/heartbeat_send.py,sha256=_97o_T0odK-oTH-0qQ_r7gUiy-hxj1HSEhCI7djbE3c,3602
|
|
104
102
|
_mcp_mesh/pipeline/mcp_heartbeat/lifespan_integration.py,sha256=4XPPlaJ6rz-FkDO3bxzVxHmVF-aq1CCaTW4vIBXrB0c,3016
|
|
105
|
-
_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py,sha256=
|
|
106
|
-
_mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py,sha256=
|
|
103
|
+
_mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py,sha256=dKYpr8ZKBHthkKxZKYI0WR6e2yEWVRsvf6cDj6XUjUc,10963
|
|
104
|
+
_mcp_mesh/pipeline/mcp_heartbeat/registry_connection.py,sha256=kL7k_yx2zafH3HO4sAxYCTxWdYWCoFsTOwCsRJVqUJk,2876
|
|
107
105
|
_mcp_mesh/pipeline/mcp_startup/__init__.py,sha256=gS0xNmVx66bkLUMw64olMsN40ZLPH3ymwlLixZ4NuTs,1239
|
|
108
106
|
_mcp_mesh/pipeline/mcp_startup/configuration.py,sha256=6LRLIxrqFMU76qrBb6GjGknUlKPZZ9iqOlxE7F9ZhLs,2808
|
|
109
107
|
_mcp_mesh/pipeline/mcp_startup/decorator_collection.py,sha256=RHC6MHtfP9aP0hZ-IJjISZu72e0Pml3LU0qr7dc284w,2294
|
|
110
|
-
_mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py,sha256=
|
|
108
|
+
_mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py,sha256=si_HkHkpBbJDUIciDOA9-tppjnutGVg4K6Qcm6-gCKg,33888
|
|
111
109
|
_mcp_mesh/pipeline/mcp_startup/fastmcpserver_discovery.py,sha256=Pm24wrSuRGsgeUrHvMPDnNh6RhIZoznnMAUwAkllohk,10661
|
|
112
110
|
_mcp_mesh/pipeline/mcp_startup/heartbeat_loop.py,sha256=v85B0ynomvYu87eIvLe-aSZ7-Iwov2VtM4Fg3PkmrZs,3865
|
|
113
111
|
_mcp_mesh/pipeline/mcp_startup/heartbeat_preparation.py,sha256=sOpzxRc0kYiXwSW9lvv8DSjliT85oZCWPODeJRuiqgg,15635
|
|
112
|
+
_mcp_mesh/pipeline/mcp_startup/lifespan_factory.py,sha256=Hu7IvrhVH9sM7-XQDyWAGA3rgOnNIRyWFBtobkUQ5Es,4404
|
|
114
113
|
_mcp_mesh/pipeline/mcp_startup/server_discovery.py,sha256=VuqqaBE00h6AerPjk-Ab-g51x6jODCbMX4nemLRQIIQ,8375
|
|
115
|
-
_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py,sha256=
|
|
114
|
+
_mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py,sha256=dT96P2f6Ci0H8sDe-6_Uro88Y0lZiyjPanN2bPsrTyk,25066
|
|
116
115
|
_mcp_mesh/pipeline/mcp_startup/startup_pipeline.py,sha256=cAAbqioYRswf-P25OpZFX2yL_qN2sl_bVk-kcynFxPw,2347
|
|
117
116
|
_mcp_mesh/pipeline/shared/__init__.py,sha256=s9xmdf6LkoetrVRGd7Zp3NUxcJCW6YZ_yNKzUBcnYys,352
|
|
118
117
|
_mcp_mesh/pipeline/shared/base_step.py,sha256=kyPbNUX79NyGrE_0Q-e-Aek7m1J0TW036njWfv0iZ0I,1080
|
|
119
118
|
_mcp_mesh/pipeline/shared/mesh_pipeline.py,sha256=UlQBrPWqbruFiUdVYgFKgPOpp_sMVsO97nZsWX90k9U,6498
|
|
120
119
|
_mcp_mesh/pipeline/shared/pipeline_types.py,sha256=iKSgzCoYu3bpIwLViw6lE7T7irEzOm7gpie29lyy7SQ,1504
|
|
121
|
-
_mcp_mesh/pipeline/shared/registry_connection.py,sha256=
|
|
120
|
+
_mcp_mesh/pipeline/shared/registry_connection.py,sha256=kB6gL1B7avmsPsOpEZVFh9143p0CAMeRIaLPBy86i-U,2905
|
|
122
121
|
_mcp_mesh/shared/__init__.py,sha256=L0detgEWjnc_XfxA_5vIBcaGTuLcT6AARKkUpUBIaH4,1116
|
|
123
122
|
_mcp_mesh/shared/config_resolver.py,sha256=r8WcO8lrd4XBHhH9IkAM7iy-QeCmTiVLmKhnJ47pFP0,7780
|
|
124
123
|
_mcp_mesh/shared/content_extractor.py,sha256=culjhieFl_J6EMDv1VFKvS38O3IMhWMs8fHhNuR2rVk,3656
|
|
125
124
|
_mcp_mesh/shared/defaults.py,sha256=5qazybkn7QHi418dXCS0b6QlNQl3DMg97ItzNGkc8d4,1851
|
|
126
125
|
_mcp_mesh/shared/fast_heartbeat_status.py,sha256=OquEsX9ZTbxY1lIsll0Mbb2KDzSJD76sLMOlr3Z73Sc,5188
|
|
127
126
|
_mcp_mesh/shared/fastapi_middleware_manager.py,sha256=_h10dSL9mgQstpJW_ZM2cpkU6yTKaYKlZaKXMk2i6IA,14638
|
|
128
|
-
_mcp_mesh/shared/
|
|
127
|
+
_mcp_mesh/shared/health_check_manager.py,sha256=xZjQp-mWdPD64djp06nU5fN-fqi3Q_cIc1PAwMQTRBY,10362
|
|
129
128
|
_mcp_mesh/shared/host_resolver.py,sha256=ycs6gXnI1zJX5KiqiLJPX5GkHX8r4j8NMHQOlG2J2X8,2964
|
|
130
|
-
_mcp_mesh/shared/logging_config.py,sha256=
|
|
131
|
-
_mcp_mesh/shared/registry_client_wrapper.py,sha256=
|
|
129
|
+
_mcp_mesh/shared/logging_config.py,sha256=a0r6EmpuGhNHl3-t6fgw84qSiyGdW7cdiCGfiyEigSg,8872
|
|
130
|
+
_mcp_mesh/shared/registry_client_wrapper.py,sha256=WTHivh4Np740CvqN4d4wEYcimjPy1GCr1XXt-ZhEzO4,21181
|
|
132
131
|
_mcp_mesh/shared/server_discovery.py,sha256=W5nsN-GvEVFD-7XkbMTxh-9FUIEiyWOxP3GYr8GNi3E,13142
|
|
133
132
|
_mcp_mesh/shared/simple_shutdown.py,sha256=jnF1rTR2yR619LZnEjNlu-ZdKlB3PovxKqG0VZ3HDgE,8319
|
|
134
|
-
_mcp_mesh/shared/sse_parser.py,sha256=
|
|
133
|
+
_mcp_mesh/shared/sse_parser.py,sha256=1NgnTMr4LQ-tW_cKJYj2oY0B5KDNskNeGlE23LcTOVk,8128
|
|
135
134
|
_mcp_mesh/shared/support_types.py,sha256=k-ICF_UwDkHxQ1D5LwFZrp-UrNb4E5dzw02CRuLW9iI,7264
|
|
136
135
|
_mcp_mesh/tracing/agent_context_helper.py,sha256=BIJ3Kc4Znd6emMAu97aUhSoxSIza3qYUmObLgc9ONiA,4765
|
|
137
136
|
_mcp_mesh/tracing/context.py,sha256=2ozqKEYfx4Qxj64DnbwoVIbMkhNLbaV8BNWtkzAPA7I,2516
|
|
138
|
-
_mcp_mesh/tracing/execution_tracer.py,sha256=
|
|
139
|
-
_mcp_mesh/tracing/fastapi_tracing_middleware.py,sha256=
|
|
137
|
+
_mcp_mesh/tracing/execution_tracer.py,sha256=nm1bXlomc8B_YYERO-LntwEDAcxJP3vbW8qpbVaXShg,10267
|
|
138
|
+
_mcp_mesh/tracing/fastapi_tracing_middleware.py,sha256=FXjhA1A1Krk-ngyuOZPc1Ic4Llggv4Wide9OuPmkwCY,6959
|
|
140
139
|
_mcp_mesh/tracing/redis_metadata_publisher.py,sha256=F78E34qnI3D0tOmbHUTBsLbDst2G7Su2-0F37Rq0rcM,4652
|
|
141
|
-
_mcp_mesh/tracing/trace_context_helper.py,sha256=
|
|
140
|
+
_mcp_mesh/tracing/trace_context_helper.py,sha256=3XWVU_cnsqrfjgAGRJaRK0Uvkns363scr4hVCGMzBgo,6858
|
|
142
141
|
_mcp_mesh/tracing/utils.py,sha256=t9lJuTH7CeuzAiiAaD0WxsJMFJPdzZFR0w6-vyR9f2E,3849
|
|
143
142
|
_mcp_mesh/utils/fastmcp_schema_extractor.py,sha256=M54ffesC-56zl_fNJHj9dZxElDQaWFf1MXdSLCuFStg,17253
|
|
144
|
-
mesh/__init__.py,sha256=
|
|
145
|
-
mesh/decorators.py,sha256=
|
|
146
|
-
mesh/helpers.py,sha256=
|
|
147
|
-
mesh/types.py,sha256=
|
|
148
|
-
mcp_mesh-0.7.
|
|
149
|
-
mcp_mesh-0.7.
|
|
150
|
-
mcp_mesh-0.7.
|
|
151
|
-
mcp_mesh-0.7.
|
|
143
|
+
mesh/__init__.py,sha256=Va5XRBWgejQurad7Maz3E-zPY7vu431B2_4sAdCu1zk,3868
|
|
144
|
+
mesh/decorators.py,sha256=v0l_0oAS_UZBQLC1WwhJQTil9AvGMCFL9kYS-N7febk,59627
|
|
145
|
+
mesh/helpers.py,sha256=ITua2zdxbXeBLF5qS46A6A1P2GQNbfL_2_BMCKazQ4U,12575
|
|
146
|
+
mesh/types.py,sha256=n0MxrBYZJ84xyQWGf_X2ZbVWSAaIcEBkRV7qaCmX6Ac,17008
|
|
147
|
+
mcp_mesh-0.7.13.dist-info/METADATA,sha256=-8HA6G4aePVlFZYau62AdSjXd2tNjGZW0dEdD6-k36A,4973
|
|
148
|
+
mcp_mesh-0.7.13.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
149
|
+
mcp_mesh-0.7.13.dist-info/licenses/LICENSE,sha256=_EBQHRQThv9FPOLc5eFOUdeeRO0mYwChC7cx60dM1tM,1078
|
|
150
|
+
mcp_mesh-0.7.13.dist-info/RECORD,,
|
mesh/__init__.py
CHANGED
|
@@ -19,7 +19,7 @@ Use 'import mesh' and then '@mesh.tool()' for consistency with MCP patterns.
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from . import decorators
|
|
22
|
-
from .types import McpMeshAgent, MeshContextModel, MeshLlmAgent, MeshLlmRequest
|
|
22
|
+
from .types import LlmMeta, McpMeshAgent, MeshContextModel, MeshLlmAgent, MeshLlmRequest
|
|
23
23
|
|
|
24
24
|
# Note: helpers.llm_provider is imported lazily in __getattr__ to avoid
|
|
25
25
|
# initialization timing issues with @mesh.agent auto_run in tests
|
|
@@ -113,6 +113,8 @@ def __getattr__(name):
|
|
|
113
113
|
return MeshLlmAgent
|
|
114
114
|
elif name == "MeshLlmRequest":
|
|
115
115
|
return MeshLlmRequest
|
|
116
|
+
elif name == "LlmMeta":
|
|
117
|
+
return LlmMeta
|
|
116
118
|
elif name == "create_server":
|
|
117
119
|
return create_server
|
|
118
120
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
mesh/decorators.py
CHANGED
|
@@ -85,30 +85,88 @@ def _start_uvicorn_immediately(http_host: str, http_port: int):
|
|
|
85
85
|
"MCP_MESH_DISTRIBUTED_TRACING_ENABLED", "false"
|
|
86
86
|
).lower() in ("true", "1", "yes")
|
|
87
87
|
if tracing_enabled:
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
# Use pure ASGI middleware for proper SSE header injection (Issue #310)
|
|
89
|
+
class TraceContextMiddleware:
|
|
90
|
+
"""Pure ASGI middleware for trace context and header injection.
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
This middleware:
|
|
93
|
+
1. Extracts trace context from incoming request headers
|
|
94
|
+
2. Sets up trace context for the request lifecycle
|
|
95
|
+
3. Injects trace headers into the response (works with SSE)
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(self, app):
|
|
99
|
+
self.app = app
|
|
100
|
+
|
|
101
|
+
async def __call__(self, scope, receive, send):
|
|
102
|
+
if scope["type"] != "http":
|
|
103
|
+
await self.app(scope, receive, send)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
path = scope.get("path", "")
|
|
107
|
+
logger.debug(f"[TRACE] Processing request {path}")
|
|
108
|
+
|
|
109
|
+
# Extract and set trace context from request headers
|
|
110
|
+
trace_id = None
|
|
111
|
+
span_id = None
|
|
112
|
+
parent_span = None
|
|
93
113
|
|
|
94
|
-
async def dispatch(self, request: Request, call_next):
|
|
95
114
|
try:
|
|
115
|
+
from _mcp_mesh.tracing.context import TraceContext
|
|
96
116
|
from _mcp_mesh.tracing.trace_context_helper import (
|
|
97
117
|
TraceContextHelper,
|
|
118
|
+
get_header_case_insensitive,
|
|
98
119
|
)
|
|
99
120
|
|
|
100
|
-
# Extract
|
|
101
|
-
|
|
102
|
-
|
|
121
|
+
# Extract trace headers from request (case-insensitive)
|
|
122
|
+
headers_list = scope.get("headers", [])
|
|
123
|
+
incoming_trace_id = get_header_case_insensitive(
|
|
124
|
+
headers_list, "x-trace-id"
|
|
103
125
|
)
|
|
126
|
+
incoming_parent_span = get_header_case_insensitive(
|
|
127
|
+
headers_list, "x-parent-span"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Setup trace context
|
|
131
|
+
trace_context = {
|
|
132
|
+
"trace_id": (
|
|
133
|
+
incoming_trace_id if incoming_trace_id else None
|
|
134
|
+
),
|
|
135
|
+
"parent_span": (
|
|
136
|
+
incoming_parent_span
|
|
137
|
+
if incoming_parent_span
|
|
138
|
+
else None
|
|
139
|
+
),
|
|
140
|
+
}
|
|
104
141
|
TraceContextHelper.setup_request_trace_context(
|
|
105
142
|
trace_context, logger
|
|
106
143
|
)
|
|
144
|
+
|
|
145
|
+
# Get trace IDs to inject into response
|
|
146
|
+
current_trace = TraceContext.get_current()
|
|
147
|
+
if current_trace:
|
|
148
|
+
trace_id = current_trace.trace_id
|
|
149
|
+
span_id = current_trace.span_id
|
|
150
|
+
parent_span = current_trace.parent_span
|
|
107
151
|
except Exception as e:
|
|
108
|
-
# Never fail request due to tracing issues
|
|
109
152
|
logger.warning(f"Failed to set trace context: {e}")
|
|
110
153
|
|
|
111
|
-
|
|
154
|
+
# Wrap send to inject headers before response starts
|
|
155
|
+
async def send_with_trace_headers(message):
|
|
156
|
+
if message["type"] == "http.response.start" and trace_id:
|
|
157
|
+
# Add trace headers to the response
|
|
158
|
+
headers = list(message.get("headers", []))
|
|
159
|
+
headers.append((b"x-trace-id", trace_id.encode()))
|
|
160
|
+
if span_id:
|
|
161
|
+
headers.append((b"x-span-id", span_id.encode()))
|
|
162
|
+
if parent_span:
|
|
163
|
+
headers.append(
|
|
164
|
+
(b"x-parent-span-id", parent_span.encode())
|
|
165
|
+
)
|
|
166
|
+
message = {**message, "headers": headers}
|
|
167
|
+
await send(message)
|
|
168
|
+
|
|
169
|
+
await self.app(scope, receive, send_with_trace_headers)
|
|
112
170
|
|
|
113
171
|
app.add_middleware(TraceContextMiddleware)
|
|
114
172
|
logger.debug(
|
|
@@ -119,54 +177,34 @@ def _start_uvicorn_immediately(http_host: str, http_port: int):
|
|
|
119
177
|
f"⚠️ IMMEDIATE UVICORN: Failed to add trace context middleware: {e}"
|
|
120
178
|
)
|
|
121
179
|
|
|
122
|
-
# Add health
|
|
123
|
-
|
|
124
|
-
|
|
180
|
+
# Add K8s health endpoints using health_check_manager
|
|
181
|
+
from _mcp_mesh.shared.health_check_manager import (
|
|
182
|
+
build_health_response,
|
|
183
|
+
build_livez_response,
|
|
184
|
+
build_ready_response,
|
|
185
|
+
)
|
|
125
186
|
|
|
126
187
|
@app.get("/health")
|
|
127
188
|
@app.head("/health")
|
|
128
189
|
async def health(response: Response):
|
|
129
190
|
"""Health check endpoint that supports custom health checks."""
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
health_data = custom_health if custom_health else health_result
|
|
134
|
-
|
|
135
|
-
# Set HTTP status code based on health status
|
|
136
|
-
# K8s expects non-200 status for unhealthy services
|
|
137
|
-
status = health_data.get("status", "starting")
|
|
138
|
-
if status == "healthy":
|
|
139
|
-
response.status_code = 200
|
|
140
|
-
else:
|
|
141
|
-
# Return 503 for unhealthy, degraded, starting, or unknown
|
|
142
|
-
response.status_code = 503
|
|
143
|
-
|
|
144
|
-
return health_data
|
|
191
|
+
data, status_code = build_health_response(agent_name="mcp-mesh-agent")
|
|
192
|
+
response.status_code = status_code
|
|
193
|
+
return data
|
|
145
194
|
|
|
146
195
|
@app.get("/ready")
|
|
147
196
|
@app.head("/ready")
|
|
148
197
|
async def ready(response: Response):
|
|
149
198
|
"""Kubernetes readiness probe - service ready to serve traffic."""
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
status = health_data.get("status", "starting")
|
|
154
|
-
if status == "healthy":
|
|
155
|
-
response.status_code = 200
|
|
156
|
-
return {"ready": True, "status": status}
|
|
157
|
-
else:
|
|
158
|
-
response.status_code = 503
|
|
159
|
-
return {
|
|
160
|
-
"ready": False,
|
|
161
|
-
"status": status,
|
|
162
|
-
"reason": f"Service is {status}",
|
|
163
|
-
}
|
|
199
|
+
data, status_code = build_ready_response(agent_name="mcp-mesh-agent")
|
|
200
|
+
response.status_code = status_code
|
|
201
|
+
return data
|
|
164
202
|
|
|
165
203
|
@app.get("/livez")
|
|
166
204
|
@app.head("/livez")
|
|
167
205
|
async def livez():
|
|
168
206
|
"""Kubernetes liveness probe - always returns 200 if app is running."""
|
|
169
|
-
return
|
|
207
|
+
return build_livez_response(agent_name="mcp-mesh-agent")
|
|
170
208
|
|
|
171
209
|
@app.get("/immediate-status")
|
|
172
210
|
def immediate_status():
|
mesh/helpers.py
CHANGED
|
@@ -11,6 +11,34 @@ from typing import Any, Dict, List, Optional
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
def _extract_vendor_from_model(model: str) -> str | None:
|
|
15
|
+
"""
|
|
16
|
+
Extract vendor name from LiteLLM model string.
|
|
17
|
+
|
|
18
|
+
LiteLLM uses vendor/model format (e.g., "anthropic/claude-sonnet-4-5").
|
|
19
|
+
This extracts the vendor for provider handler selection.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
model: LiteLLM model string
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Vendor name (e.g., "anthropic", "openai") or None if not extractable
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
"anthropic/claude-sonnet-4-5" -> "anthropic"
|
|
29
|
+
"openai/gpt-4o" -> "openai"
|
|
30
|
+
"gpt-4" -> None (no vendor prefix)
|
|
31
|
+
"""
|
|
32
|
+
if not model:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
if "/" in model:
|
|
36
|
+
vendor = model.split("/")[0].lower().strip()
|
|
37
|
+
return vendor
|
|
38
|
+
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
14
42
|
def llm_provider(
|
|
15
43
|
model: str,
|
|
16
44
|
capability: str = "llm",
|
|
@@ -154,9 +182,39 @@ def llm_provider(
|
|
|
154
182
|
"""
|
|
155
183
|
import litellm
|
|
156
184
|
|
|
185
|
+
# Determine effective model (check for consumer override - issue #308)
|
|
186
|
+
effective_model = model # Default to provider's model
|
|
187
|
+
model_params_copy = (
|
|
188
|
+
dict(request.model_params) if request.model_params else {}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if "model" in model_params_copy:
|
|
192
|
+
override_model = model_params_copy.pop(
|
|
193
|
+
"model"
|
|
194
|
+
) # Remove to avoid duplication
|
|
195
|
+
|
|
196
|
+
if override_model:
|
|
197
|
+
# Validate vendor compatibility
|
|
198
|
+
override_vendor = _extract_vendor_from_model(override_model)
|
|
199
|
+
|
|
200
|
+
if override_vendor and override_vendor != vendor:
|
|
201
|
+
# Vendor mismatch - log warning and fall back to provider's model
|
|
202
|
+
logger.warning(
|
|
203
|
+
f"⚠️ Model override '{override_model}' ignored - vendor mismatch "
|
|
204
|
+
f"(override vendor: '{override_vendor}', provider vendor: '{vendor}'). "
|
|
205
|
+
f"Using provider's default model: '{model}'"
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
# Vendor matches or can't be determined - use override
|
|
209
|
+
effective_model = override_model
|
|
210
|
+
logger.info(
|
|
211
|
+
f"🔄 Using model override '{effective_model}' "
|
|
212
|
+
f"(requested by consumer)"
|
|
213
|
+
)
|
|
214
|
+
|
|
157
215
|
# Build litellm.completion arguments
|
|
158
216
|
completion_args: dict[str, Any] = {
|
|
159
|
-
"model":
|
|
217
|
+
"model": effective_model,
|
|
160
218
|
"messages": request.messages,
|
|
161
219
|
**litellm_kwargs,
|
|
162
220
|
}
|
|
@@ -165,8 +223,8 @@ def llm_provider(
|
|
|
165
223
|
if request.tools:
|
|
166
224
|
completion_args["tools"] = request.tools
|
|
167
225
|
|
|
168
|
-
if
|
|
169
|
-
completion_args.update(
|
|
226
|
+
if model_params_copy:
|
|
227
|
+
completion_args.update(model_params_copy)
|
|
170
228
|
|
|
171
229
|
# Call LiteLLM
|
|
172
230
|
try:
|
|
@@ -219,9 +277,19 @@ def llm_provider(
|
|
|
219
277
|
for tc in message.tool_calls
|
|
220
278
|
]
|
|
221
279
|
|
|
280
|
+
# Issue #311: Include usage metadata for cost tracking
|
|
281
|
+
if hasattr(response, "usage") and response.usage:
|
|
282
|
+
usage = response.usage
|
|
283
|
+
message_dict["_mesh_usage"] = {
|
|
284
|
+
"prompt_tokens": getattr(usage, "prompt_tokens", 0) or 0,
|
|
285
|
+
"completion_tokens": getattr(usage, "completion_tokens", 0)
|
|
286
|
+
or 0,
|
|
287
|
+
"model": effective_model,
|
|
288
|
+
}
|
|
289
|
+
|
|
222
290
|
logger.info(
|
|
223
291
|
f"LLM provider {func.__name__} processed request "
|
|
224
|
-
f"(model={
|
|
292
|
+
f"(model={effective_model}, messages={len(request.messages)}, "
|
|
225
293
|
f"tool_calls={len(message_dict.get('tool_calls', []))})"
|
|
226
294
|
)
|
|
227
295
|
|
mesh/types.py
CHANGED
|
@@ -386,6 +386,50 @@ except ImportError:
|
|
|
386
386
|
pass
|
|
387
387
|
|
|
388
388
|
|
|
389
|
+
@dataclass
|
|
390
|
+
class LlmMeta:
|
|
391
|
+
"""
|
|
392
|
+
Metadata from LLM response for cost tracking and debugging.
|
|
393
|
+
|
|
394
|
+
This is attached to results from @mesh.llm calls as `_mesh_meta` attribute,
|
|
395
|
+
providing access to token counts, latency, and model information.
|
|
396
|
+
|
|
397
|
+
Attributes:
|
|
398
|
+
provider: LLM provider name (e.g., "anthropic", "openai")
|
|
399
|
+
model: Full model identifier (e.g., "anthropic/claude-3-5-haiku-20241022")
|
|
400
|
+
input_tokens: Number of tokens in the prompt
|
|
401
|
+
output_tokens: Number of tokens in the response
|
|
402
|
+
total_tokens: Total tokens used (input + output)
|
|
403
|
+
latency_ms: Request latency in milliseconds
|
|
404
|
+
|
|
405
|
+
Usage:
|
|
406
|
+
@mesh.llm(provider="anthropic/claude-3-5-haiku-20241022")
|
|
407
|
+
async def ask(question: str, llm: MeshLlmAgent) -> Answer:
|
|
408
|
+
result = await llm(question)
|
|
409
|
+
|
|
410
|
+
# Access result normally
|
|
411
|
+
print(result.answer)
|
|
412
|
+
|
|
413
|
+
# Access metadata
|
|
414
|
+
print(result._mesh_meta.model) # "anthropic/claude-3-5-haiku-20241022"
|
|
415
|
+
print(result._mesh_meta.output_tokens) # 85
|
|
416
|
+
print(result._mesh_meta.latency_ms) # 125.5
|
|
417
|
+
|
|
418
|
+
return result
|
|
419
|
+
|
|
420
|
+
Note:
|
|
421
|
+
For primitive return types (str, int, etc.) and frozen Pydantic models,
|
|
422
|
+
_mesh_meta cannot be attached. This is a Python limitation.
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
provider: str
|
|
426
|
+
model: str
|
|
427
|
+
input_tokens: int
|
|
428
|
+
output_tokens: int
|
|
429
|
+
total_tokens: int
|
|
430
|
+
latency_ms: float
|
|
431
|
+
|
|
432
|
+
|
|
389
433
|
@dataclass
|
|
390
434
|
class MeshLlmRequest:
|
|
391
435
|
"""
|
|
@@ -414,9 +458,9 @@ class MeshLlmRequest:
|
|
|
414
458
|
caller_agent: Optional agent name that initiated the request
|
|
415
459
|
"""
|
|
416
460
|
|
|
417
|
-
messages:
|
|
418
|
-
tools: Optional[
|
|
419
|
-
model_params: Optional[
|
|
420
|
-
context: Optional[
|
|
461
|
+
messages: list[dict[str, Any]] # Changed from Dict[str, str] to allow tool_calls
|
|
462
|
+
tools: Optional[list[dict]] = None
|
|
463
|
+
model_params: Optional[dict] = None
|
|
464
|
+
context: Optional[dict] = None
|
|
421
465
|
request_id: Optional[str] = None
|
|
422
466
|
caller_agent: Optional[str] = None
|