aip-agents-binary 0.6.4__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.

Potentially problematic release.


This version of aip-agents-binary might be problematic. Click here for more details.

Files changed (612) hide show
  1. aip_agents/__init__.py +65 -0
  2. aip_agents/__init__.pyi +19 -0
  3. aip_agents/a2a/__init__.py +19 -0
  4. aip_agents/a2a/__init__.pyi +3 -0
  5. aip_agents/a2a/server/__init__.py +10 -0
  6. aip_agents/a2a/server/__init__.pyi +4 -0
  7. aip_agents/a2a/server/base_executor.py +1086 -0
  8. aip_agents/a2a/server/base_executor.pyi +73 -0
  9. aip_agents/a2a/server/google_adk_executor.py +198 -0
  10. aip_agents/a2a/server/google_adk_executor.pyi +51 -0
  11. aip_agents/a2a/server/langflow_executor.py +180 -0
  12. aip_agents/a2a/server/langflow_executor.pyi +43 -0
  13. aip_agents/a2a/server/langgraph_executor.py +270 -0
  14. aip_agents/a2a/server/langgraph_executor.pyi +47 -0
  15. aip_agents/a2a/types.py +232 -0
  16. aip_agents/a2a/types.pyi +132 -0
  17. aip_agents/agent/__init__.py +27 -0
  18. aip_agents/agent/__init__.pyi +9 -0
  19. aip_agents/agent/base_agent.py +970 -0
  20. aip_agents/agent/base_agent.pyi +221 -0
  21. aip_agents/agent/base_langgraph_agent.py +3037 -0
  22. aip_agents/agent/base_langgraph_agent.pyi +233 -0
  23. aip_agents/agent/google_adk_agent.py +926 -0
  24. aip_agents/agent/google_adk_agent.pyi +141 -0
  25. aip_agents/agent/google_adk_constants.py +6 -0
  26. aip_agents/agent/google_adk_constants.pyi +3 -0
  27. aip_agents/agent/hitl/__init__.py +24 -0
  28. aip_agents/agent/hitl/__init__.pyi +6 -0
  29. aip_agents/agent/hitl/config.py +28 -0
  30. aip_agents/agent/hitl/config.pyi +15 -0
  31. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  32. aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
  33. aip_agents/agent/hitl/manager.py +532 -0
  34. aip_agents/agent/hitl/manager.pyi +200 -0
  35. aip_agents/agent/hitl/models.py +18 -0
  36. aip_agents/agent/hitl/models.pyi +3 -0
  37. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  38. aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
  39. aip_agents/agent/hitl/prompt/base.py +42 -0
  40. aip_agents/agent/hitl/prompt/base.pyi +24 -0
  41. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  42. aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
  43. aip_agents/agent/hitl/registry.py +149 -0
  44. aip_agents/agent/hitl/registry.pyi +101 -0
  45. aip_agents/agent/interface.py +138 -0
  46. aip_agents/agent/interface.pyi +81 -0
  47. aip_agents/agent/interfaces.py +65 -0
  48. aip_agents/agent/interfaces.pyi +44 -0
  49. aip_agents/agent/langflow_agent.py +464 -0
  50. aip_agents/agent/langflow_agent.pyi +133 -0
  51. aip_agents/agent/langgraph_memory_enhancer_agent.py +767 -0
  52. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +50 -0
  53. aip_agents/agent/langgraph_react_agent.py +2856 -0
  54. aip_agents/agent/langgraph_react_agent.pyi +170 -0
  55. aip_agents/agent/system_instruction_context.py +34 -0
  56. aip_agents/agent/system_instruction_context.pyi +13 -0
  57. aip_agents/clients/__init__.py +10 -0
  58. aip_agents/clients/__init__.pyi +4 -0
  59. aip_agents/clients/langflow/__init__.py +10 -0
  60. aip_agents/clients/langflow/__init__.pyi +4 -0
  61. aip_agents/clients/langflow/client.py +477 -0
  62. aip_agents/clients/langflow/client.pyi +140 -0
  63. aip_agents/clients/langflow/types.py +18 -0
  64. aip_agents/clients/langflow/types.pyi +7 -0
  65. aip_agents/constants.py +23 -0
  66. aip_agents/constants.pyi +7 -0
  67. aip_agents/credentials/manager.py +132 -0
  68. aip_agents/examples/__init__.py +5 -0
  69. aip_agents/examples/__init__.pyi +0 -0
  70. aip_agents/examples/compare_streaming_client.py +783 -0
  71. aip_agents/examples/compare_streaming_client.pyi +48 -0
  72. aip_agents/examples/compare_streaming_server.py +142 -0
  73. aip_agents/examples/compare_streaming_server.pyi +18 -0
  74. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  75. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
  78. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
  80. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  81. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
  82. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  83. aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
  84. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
  86. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
  88. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  89. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
  90. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  91. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
  92. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  93. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
  94. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  95. aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
  96. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  97. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
  98. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  99. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  100. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  101. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  102. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  103. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
  106. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
  108. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
  110. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
  112. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
  114. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
  118. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
  120. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
  122. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
  124. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  125. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
  126. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  127. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
  128. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  129. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
  130. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  131. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
  132. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  133. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
  134. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  135. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
  136. aip_agents/examples/hello_world_google_adk.py +41 -0
  137. aip_agents/examples/hello_world_google_adk.pyi +5 -0
  138. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  139. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  141. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
  142. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  143. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
  144. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  145. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
  146. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  147. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
  148. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  149. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
  150. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  151. aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
  152. aip_agents/examples/hello_world_langchain.py +28 -0
  153. aip_agents/examples/hello_world_langchain.pyi +5 -0
  154. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  155. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
  156. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  157. aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
  158. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  159. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  160. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  161. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
  162. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  163. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  164. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  165. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
  166. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  167. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
  168. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  169. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
  170. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  171. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
  172. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  173. aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
  174. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  175. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
  176. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  177. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  178. aip_agents/examples/hello_world_langgraph.py +39 -0
  179. aip_agents/examples/hello_world_langgraph.pyi +5 -0
  180. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  181. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  182. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  183. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
  184. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  185. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
  186. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  187. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
  188. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  189. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
  190. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  191. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
  192. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  193. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
  194. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  195. aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
  196. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  197. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
  198. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  199. aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
  200. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  201. aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
  202. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  203. aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
  204. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  205. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
  206. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  207. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
  208. aip_agents/examples/hello_world_pii_logger.py +21 -0
  209. aip_agents/examples/hello_world_pii_logger.pyi +5 -0
  210. aip_agents/examples/hello_world_ptc.py +49 -0
  211. aip_agents/examples/hello_world_ptc.pyi +5 -0
  212. aip_agents/examples/hello_world_sentry.py +133 -0
  213. aip_agents/examples/hello_world_sentry.pyi +21 -0
  214. aip_agents/examples/hello_world_step_limits.py +273 -0
  215. aip_agents/examples/hello_world_step_limits.pyi +17 -0
  216. aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
  217. aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
  218. aip_agents/examples/hello_world_tool_output_client.py +55 -0
  219. aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
  220. aip_agents/examples/hello_world_tool_output_server.py +114 -0
  221. aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
  222. aip_agents/examples/hitl_demo.py +724 -0
  223. aip_agents/examples/hitl_demo.pyi +67 -0
  224. aip_agents/examples/mcp_configs/configs.py +63 -0
  225. aip_agents/examples/mcp_servers/common.py +76 -0
  226. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  227. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  228. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  229. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  230. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  231. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  232. aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
  233. aip_agents/examples/pii_demo_langgraph_server.py +126 -0
  234. aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
  235. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  236. aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
  237. aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
  238. aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
  239. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  240. aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
  241. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
  242. aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
  243. aip_agents/examples/tools/__init__.py +27 -0
  244. aip_agents/examples/tools/__init__.pyi +9 -0
  245. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  246. aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
  247. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  248. aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
  249. aip_agents/examples/tools/data_generator_tool.py +103 -0
  250. aip_agents/examples/tools/data_generator_tool.pyi +15 -0
  251. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  252. aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
  253. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  254. aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
  255. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  256. aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
  257. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  258. aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
  259. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  260. aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
  261. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  262. aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
  263. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  264. aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
  265. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  266. aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
  267. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  268. aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
  269. aip_agents/examples/tools/random_chart_tool.py +142 -0
  270. aip_agents/examples/tools/random_chart_tool.pyi +20 -0
  271. aip_agents/examples/tools/serper_tool.py +202 -0
  272. aip_agents/examples/tools/serper_tool.pyi +16 -0
  273. aip_agents/examples/tools/stock_tools.py +82 -0
  274. aip_agents/examples/tools/stock_tools.pyi +36 -0
  275. aip_agents/examples/tools/table_generator_tool.py +167 -0
  276. aip_agents/examples/tools/table_generator_tool.pyi +22 -0
  277. aip_agents/examples/tools/time_tool.py +82 -0
  278. aip_agents/examples/tools/time_tool.pyi +15 -0
  279. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  280. aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
  281. aip_agents/executor/agent_executor.py +473 -0
  282. aip_agents/executor/base.py +48 -0
  283. aip_agents/guardrails/__init__.py +83 -0
  284. aip_agents/guardrails/__init__.pyi +6 -0
  285. aip_agents/guardrails/engines/__init__.py +69 -0
  286. aip_agents/guardrails/engines/__init__.pyi +4 -0
  287. aip_agents/guardrails/engines/base.py +90 -0
  288. aip_agents/guardrails/engines/base.pyi +61 -0
  289. aip_agents/guardrails/engines/nemo.py +101 -0
  290. aip_agents/guardrails/engines/nemo.pyi +46 -0
  291. aip_agents/guardrails/engines/phrase_matcher.py +113 -0
  292. aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
  293. aip_agents/guardrails/exceptions.py +39 -0
  294. aip_agents/guardrails/exceptions.pyi +23 -0
  295. aip_agents/guardrails/manager.py +163 -0
  296. aip_agents/guardrails/manager.pyi +42 -0
  297. aip_agents/guardrails/middleware.py +199 -0
  298. aip_agents/guardrails/middleware.pyi +87 -0
  299. aip_agents/guardrails/schemas.py +63 -0
  300. aip_agents/guardrails/schemas.pyi +43 -0
  301. aip_agents/guardrails/utils.py +45 -0
  302. aip_agents/guardrails/utils.pyi +19 -0
  303. aip_agents/mcp/__init__.py +1 -0
  304. aip_agents/mcp/__init__.pyi +0 -0
  305. aip_agents/mcp/client/__init__.py +14 -0
  306. aip_agents/mcp/client/__init__.pyi +5 -0
  307. aip_agents/mcp/client/base_mcp_client.py +369 -0
  308. aip_agents/mcp/client/base_mcp_client.pyi +148 -0
  309. aip_agents/mcp/client/connection_manager.py +228 -0
  310. aip_agents/mcp/client/connection_manager.pyi +51 -0
  311. aip_agents/mcp/client/google_adk/__init__.py +11 -0
  312. aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
  313. aip_agents/mcp/client/google_adk/client.py +381 -0
  314. aip_agents/mcp/client/google_adk/client.pyi +75 -0
  315. aip_agents/mcp/client/langchain/__init__.py +11 -0
  316. aip_agents/mcp/client/langchain/__init__.pyi +3 -0
  317. aip_agents/mcp/client/langchain/client.py +265 -0
  318. aip_agents/mcp/client/langchain/client.pyi +48 -0
  319. aip_agents/mcp/client/persistent_session.py +612 -0
  320. aip_agents/mcp/client/persistent_session.pyi +122 -0
  321. aip_agents/mcp/client/session_pool.py +351 -0
  322. aip_agents/mcp/client/session_pool.pyi +101 -0
  323. aip_agents/mcp/client/transports.py +263 -0
  324. aip_agents/mcp/client/transports.pyi +132 -0
  325. aip_agents/mcp/utils/__init__.py +7 -0
  326. aip_agents/mcp/utils/__init__.pyi +0 -0
  327. aip_agents/mcp/utils/config_validator.py +139 -0
  328. aip_agents/mcp/utils/config_validator.pyi +82 -0
  329. aip_agents/memory/__init__.py +14 -0
  330. aip_agents/memory/__init__.pyi +5 -0
  331. aip_agents/memory/adapters/__init__.py +10 -0
  332. aip_agents/memory/adapters/__init__.pyi +4 -0
  333. aip_agents/memory/adapters/base_adapter.py +811 -0
  334. aip_agents/memory/adapters/base_adapter.pyi +176 -0
  335. aip_agents/memory/adapters/mem0.py +84 -0
  336. aip_agents/memory/adapters/mem0.pyi +22 -0
  337. aip_agents/memory/base.py +84 -0
  338. aip_agents/memory/base.pyi +60 -0
  339. aip_agents/memory/constants.py +49 -0
  340. aip_agents/memory/constants.pyi +25 -0
  341. aip_agents/memory/factory.py +86 -0
  342. aip_agents/memory/factory.pyi +24 -0
  343. aip_agents/memory/guidance.py +20 -0
  344. aip_agents/memory/guidance.pyi +3 -0
  345. aip_agents/memory/simple_memory.py +47 -0
  346. aip_agents/memory/simple_memory.pyi +23 -0
  347. aip_agents/middleware/__init__.py +17 -0
  348. aip_agents/middleware/__init__.pyi +5 -0
  349. aip_agents/middleware/base.py +96 -0
  350. aip_agents/middleware/base.pyi +75 -0
  351. aip_agents/middleware/manager.py +150 -0
  352. aip_agents/middleware/manager.pyi +84 -0
  353. aip_agents/middleware/todolist.py +274 -0
  354. aip_agents/middleware/todolist.pyi +125 -0
  355. aip_agents/ptc/__init__.py +48 -0
  356. aip_agents/ptc/__init__.pyi +10 -0
  357. aip_agents/ptc/doc_gen.py +122 -0
  358. aip_agents/ptc/doc_gen.pyi +40 -0
  359. aip_agents/ptc/exceptions.py +39 -0
  360. aip_agents/ptc/exceptions.pyi +22 -0
  361. aip_agents/ptc/executor.py +143 -0
  362. aip_agents/ptc/executor.pyi +73 -0
  363. aip_agents/ptc/mcp/__init__.py +45 -0
  364. aip_agents/ptc/mcp/__init__.pyi +7 -0
  365. aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
  366. aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
  367. aip_agents/ptc/mcp/templates/__init__.py +1 -0
  368. aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
  369. aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
  370. aip_agents/ptc/naming.py +184 -0
  371. aip_agents/ptc/naming.pyi +76 -0
  372. aip_agents/ptc/payload.py +26 -0
  373. aip_agents/ptc/payload.pyi +15 -0
  374. aip_agents/ptc/prompt_builder.py +571 -0
  375. aip_agents/ptc/prompt_builder.pyi +55 -0
  376. aip_agents/ptc/ptc_helper.py +16 -0
  377. aip_agents/ptc/ptc_helper.pyi +1 -0
  378. aip_agents/ptc/sandbox_bridge.py +58 -0
  379. aip_agents/ptc/sandbox_bridge.pyi +25 -0
  380. aip_agents/ptc/template_utils.py +33 -0
  381. aip_agents/ptc/template_utils.pyi +13 -0
  382. aip_agents/ptc/templates/__init__.py +1 -0
  383. aip_agents/ptc/templates/__init__.pyi +0 -0
  384. aip_agents/ptc/templates/ptc_helper.py.template +134 -0
  385. aip_agents/sandbox/__init__.py +43 -0
  386. aip_agents/sandbox/__init__.pyi +5 -0
  387. aip_agents/sandbox/defaults.py +9 -0
  388. aip_agents/sandbox/defaults.pyi +2 -0
  389. aip_agents/sandbox/e2b_runtime.py +267 -0
  390. aip_agents/sandbox/e2b_runtime.pyi +51 -0
  391. aip_agents/sandbox/template_builder.py +131 -0
  392. aip_agents/sandbox/template_builder.pyi +36 -0
  393. aip_agents/sandbox/types.py +24 -0
  394. aip_agents/sandbox/types.pyi +14 -0
  395. aip_agents/sandbox/validation.py +50 -0
  396. aip_agents/sandbox/validation.pyi +20 -0
  397. aip_agents/schema/__init__.py +69 -0
  398. aip_agents/schema/__init__.pyi +9 -0
  399. aip_agents/schema/a2a.py +56 -0
  400. aip_agents/schema/a2a.pyi +40 -0
  401. aip_agents/schema/agent.py +111 -0
  402. aip_agents/schema/agent.pyi +65 -0
  403. aip_agents/schema/hitl.py +157 -0
  404. aip_agents/schema/hitl.pyi +89 -0
  405. aip_agents/schema/langgraph.py +37 -0
  406. aip_agents/schema/langgraph.pyi +28 -0
  407. aip_agents/schema/model_id.py +97 -0
  408. aip_agents/schema/model_id.pyi +54 -0
  409. aip_agents/schema/step_limit.py +108 -0
  410. aip_agents/schema/step_limit.pyi +63 -0
  411. aip_agents/schema/storage.py +40 -0
  412. aip_agents/schema/storage.pyi +21 -0
  413. aip_agents/sentry/__init__.py +11 -0
  414. aip_agents/sentry/__init__.pyi +3 -0
  415. aip_agents/sentry/sentry.py +151 -0
  416. aip_agents/sentry/sentry.pyi +48 -0
  417. aip_agents/storage/__init__.py +41 -0
  418. aip_agents/storage/__init__.pyi +8 -0
  419. aip_agents/storage/base.py +85 -0
  420. aip_agents/storage/base.pyi +58 -0
  421. aip_agents/storage/clients/__init__.py +12 -0
  422. aip_agents/storage/clients/__init__.pyi +3 -0
  423. aip_agents/storage/clients/minio_client.py +318 -0
  424. aip_agents/storage/clients/minio_client.pyi +137 -0
  425. aip_agents/storage/config.py +62 -0
  426. aip_agents/storage/config.pyi +29 -0
  427. aip_agents/storage/providers/__init__.py +15 -0
  428. aip_agents/storage/providers/__init__.pyi +5 -0
  429. aip_agents/storage/providers/base.py +106 -0
  430. aip_agents/storage/providers/base.pyi +88 -0
  431. aip_agents/storage/providers/memory.py +114 -0
  432. aip_agents/storage/providers/memory.pyi +79 -0
  433. aip_agents/storage/providers/object_storage.py +214 -0
  434. aip_agents/storage/providers/object_storage.pyi +98 -0
  435. aip_agents/tools/__init__.py +64 -0
  436. aip_agents/tools/__init__.pyi +11 -0
  437. aip_agents/tools/browser_use/__init__.py +82 -0
  438. aip_agents/tools/browser_use/__init__.pyi +14 -0
  439. aip_agents/tools/browser_use/action_parser.py +103 -0
  440. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  441. aip_agents/tools/browser_use/browser_use_tool.py +1120 -0
  442. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  443. aip_agents/tools/browser_use/llm_config.py +120 -0
  444. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  445. aip_agents/tools/browser_use/minio_storage.py +198 -0
  446. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  447. aip_agents/tools/browser_use/schemas.py +119 -0
  448. aip_agents/tools/browser_use/schemas.pyi +32 -0
  449. aip_agents/tools/browser_use/session.py +76 -0
  450. aip_agents/tools/browser_use/session.pyi +4 -0
  451. aip_agents/tools/browser_use/session_errors.py +132 -0
  452. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  453. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  454. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  455. aip_agents/tools/browser_use/streaming.py +815 -0
  456. aip_agents/tools/browser_use/streaming.pyi +81 -0
  457. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  458. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  459. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  460. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  461. aip_agents/tools/browser_use/types.py +78 -0
  462. aip_agents/tools/browser_use/types.pyi +45 -0
  463. aip_agents/tools/code_sandbox/__init__.py +26 -0
  464. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  465. aip_agents/tools/code_sandbox/constant.py +13 -0
  466. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  467. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
  468. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
  469. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  470. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  471. aip_agents/tools/constants.py +177 -0
  472. aip_agents/tools/constants.pyi +138 -0
  473. aip_agents/tools/date_range_tool.py +554 -0
  474. aip_agents/tools/date_range_tool.pyi +21 -0
  475. aip_agents/tools/document_loader/__init__.py +44 -0
  476. aip_agents/tools/document_loader/__init__.pyi +7 -0
  477. aip_agents/tools/document_loader/base_reader.py +302 -0
  478. aip_agents/tools/document_loader/base_reader.pyi +75 -0
  479. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  480. aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
  481. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  482. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  483. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  484. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  485. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  486. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  487. aip_agents/tools/execute_ptc_code.py +308 -0
  488. aip_agents/tools/execute_ptc_code.pyi +90 -0
  489. aip_agents/tools/gl_connector/__init__.py +5 -0
  490. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  491. aip_agents/tools/gl_connector/tool.py +383 -0
  492. aip_agents/tools/gl_connector/tool.pyi +74 -0
  493. aip_agents/tools/gl_connector_tools.py +119 -0
  494. aip_agents/tools/gl_connector_tools.pyi +39 -0
  495. aip_agents/tools/memory_search/__init__.py +29 -0
  496. aip_agents/tools/memory_search/__init__.pyi +5 -0
  497. aip_agents/tools/memory_search/base.py +200 -0
  498. aip_agents/tools/memory_search/base.pyi +69 -0
  499. aip_agents/tools/memory_search/mem0.py +365 -0
  500. aip_agents/tools/memory_search/mem0.pyi +29 -0
  501. aip_agents/tools/memory_search/schema.py +81 -0
  502. aip_agents/tools/memory_search/schema.pyi +25 -0
  503. aip_agents/tools/memory_search_tool.py +34 -0
  504. aip_agents/tools/memory_search_tool.pyi +3 -0
  505. aip_agents/tools/time_tool.py +117 -0
  506. aip_agents/tools/time_tool.pyi +16 -0
  507. aip_agents/tools/tool_config_injector.py +300 -0
  508. aip_agents/tools/tool_config_injector.pyi +26 -0
  509. aip_agents/tools/web_search/__init__.py +15 -0
  510. aip_agents/tools/web_search/__init__.pyi +3 -0
  511. aip_agents/tools/web_search/serper_tool.py +187 -0
  512. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  513. aip_agents/types/__init__.py +70 -0
  514. aip_agents/types/__init__.pyi +36 -0
  515. aip_agents/types/a2a_events.py +13 -0
  516. aip_agents/types/a2a_events.pyi +3 -0
  517. aip_agents/utils/__init__.py +79 -0
  518. aip_agents/utils/__init__.pyi +11 -0
  519. aip_agents/utils/a2a_connector.py +1757 -0
  520. aip_agents/utils/a2a_connector.pyi +146 -0
  521. aip_agents/utils/artifact_helpers.py +502 -0
  522. aip_agents/utils/artifact_helpers.pyi +203 -0
  523. aip_agents/utils/constants.py +22 -0
  524. aip_agents/utils/constants.pyi +10 -0
  525. aip_agents/utils/datetime/__init__.py +34 -0
  526. aip_agents/utils/datetime/__init__.pyi +4 -0
  527. aip_agents/utils/datetime/normalization.py +231 -0
  528. aip_agents/utils/datetime/normalization.pyi +95 -0
  529. aip_agents/utils/datetime/timezone.py +206 -0
  530. aip_agents/utils/datetime/timezone.pyi +48 -0
  531. aip_agents/utils/env_loader.py +27 -0
  532. aip_agents/utils/env_loader.pyi +10 -0
  533. aip_agents/utils/event_handler_registry.py +58 -0
  534. aip_agents/utils/event_handler_registry.pyi +23 -0
  535. aip_agents/utils/file_prompt_utils.py +176 -0
  536. aip_agents/utils/file_prompt_utils.pyi +21 -0
  537. aip_agents/utils/final_response_builder.py +211 -0
  538. aip_agents/utils/final_response_builder.pyi +34 -0
  539. aip_agents/utils/formatter_llm_client.py +231 -0
  540. aip_agents/utils/formatter_llm_client.pyi +71 -0
  541. aip_agents/utils/langgraph/__init__.py +19 -0
  542. aip_agents/utils/langgraph/__init__.pyi +3 -0
  543. aip_agents/utils/langgraph/converter.py +128 -0
  544. aip_agents/utils/langgraph/converter.pyi +49 -0
  545. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  546. aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
  547. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  548. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
  549. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  550. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
  551. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1096 -0
  552. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
  553. aip_agents/utils/langgraph/tool_output_management.py +1047 -0
  554. aip_agents/utils/langgraph/tool_output_management.pyi +329 -0
  555. aip_agents/utils/logger.py +195 -0
  556. aip_agents/utils/logger.pyi +60 -0
  557. aip_agents/utils/metadata/__init__.py +27 -0
  558. aip_agents/utils/metadata/__init__.pyi +5 -0
  559. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  560. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  561. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  562. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  563. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  564. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  565. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  566. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  567. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  568. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  569. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  570. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  571. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  572. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  573. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  574. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  575. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  576. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  577. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  578. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  579. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  580. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  581. aip_agents/utils/metadata_helper.py +358 -0
  582. aip_agents/utils/metadata_helper.pyi +117 -0
  583. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  584. aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
  585. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  586. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
  587. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  588. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
  589. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  590. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
  591. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  592. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
  593. aip_agents/utils/pii/__init__.py +25 -0
  594. aip_agents/utils/pii/__init__.pyi +5 -0
  595. aip_agents/utils/pii/pii_handler.py +397 -0
  596. aip_agents/utils/pii/pii_handler.pyi +96 -0
  597. aip_agents/utils/pii/pii_helper.py +207 -0
  598. aip_agents/utils/pii/pii_helper.pyi +78 -0
  599. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  600. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  601. aip_agents/utils/reference_helper.py +273 -0
  602. aip_agents/utils/reference_helper.pyi +81 -0
  603. aip_agents/utils/sse_chunk_transformer.py +831 -0
  604. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  605. aip_agents/utils/step_limit_manager.py +265 -0
  606. aip_agents/utils/step_limit_manager.pyi +112 -0
  607. aip_agents/utils/token_usage_helper.py +156 -0
  608. aip_agents/utils/token_usage_helper.pyi +60 -0
  609. aip_agents_binary-0.6.4.dist-info/METADATA +673 -0
  610. aip_agents_binary-0.6.4.dist-info/RECORD +612 -0
  611. aip_agents_binary-0.6.4.dist-info/WHEEL +5 -0
  612. aip_agents_binary-0.6.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,228 @@
1
+ """MCP Connection Manager for persistent connection lifecycle management.
2
+
3
+ This module implements the connection manager pattern inspired by mcp-use library
4
+ to avoid cancel scope issues and provide persistent connections.
5
+
6
+ Authors:
7
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
8
+ """
9
+
10
+ import asyncio
11
+ import inspect
12
+ from typing import Any
13
+
14
+ from gllm_tools.mcp.client.config import MCPConfiguration
15
+
16
+ from aip_agents.mcp.client.transports import TransportType, create_transport
17
+ from aip_agents.utils.logger import get_logger
18
+
19
+ logger = get_logger(__name__)
20
+
21
+
22
+ class MCPConnectionManager:
23
+ """Manages MCP connection lifecycle following mcp-use patterns.
24
+
25
+ This connection manager handles the transport connection lifecycle in a background
26
+ task to avoid cancel scope issues during cleanup. It supports automatic transport
27
+ negotiation (HTTP -> SSE fallback) and graceful shutdown. Invalid explicit transports
28
+ are normalized via aliases (e.g., 'streamable_http' -> 'http') or fall back to
29
+ auto-detection with a warning.
30
+ """
31
+
32
+ TRANSPORT_ALIASES = {
33
+ "http": TransportType.HTTP,
34
+ "streamable-http": TransportType.HTTP,
35
+ "sse": TransportType.SSE,
36
+ "stdio": TransportType.STDIO,
37
+ }
38
+
39
+ def __init__(self, server_name: str, config: MCPConfiguration):
40
+ """Initialize connection manager.
41
+
42
+ Args:
43
+ server_name (str): Name of the MCP server
44
+ config (MCPConfiguration): MCP server configuration
45
+ """
46
+ self.server_name = server_name
47
+ self.config = config
48
+ self._task = None
49
+ self._connection = None
50
+ self._transport = None
51
+ self._stop_event = asyncio.Event()
52
+ self._ready_event = asyncio.Event()
53
+ self._done_event = asyncio.Event()
54
+ self._exception = None
55
+ self.transport_type = None
56
+ # Configurable retry settings (MCP-specific, defaults to reasonable values)
57
+ self.max_retries = config.get("max_retries", 3)
58
+ self.initial_retry_delay = config.get("initial_retry_delay", 1.0)
59
+
60
+ async def start(self) -> tuple[Any, Any]:
61
+ """Start connection in background task.
62
+
63
+ For HTTP/SSE transports, establishes connection directly to avoid anyio context issues.
64
+ For stdio transport, uses background task to manage subprocess lifecycle.
65
+
66
+ Returns:
67
+ tuple[Any, Any]: Tuple of (read_stream, write_stream) for ClientSession
68
+
69
+ Raises:
70
+ Exception: If connection establishment fails
71
+ """
72
+ logger.debug(f"Starting connection manager for {self.server_name}")
73
+
74
+ # Determine transport type first
75
+ self.transport_type = self._get_transport_type()
76
+
77
+ # For HTTP/SSE: connect directly (no background task needed)
78
+ # This avoids anyio.BrokenResourceError when streams cross task boundaries
79
+ if self.transport_type in (TransportType.HTTP, TransportType.SSE):
80
+ await self._establish_connection()
81
+ return self._connection
82
+
83
+ # For stdio: use background task to manage subprocess
84
+ self._task = asyncio.create_task(self._connection_task())
85
+ await self._ready_event.wait()
86
+
87
+ if self._exception:
88
+ raise self._exception
89
+
90
+ return self._connection
91
+
92
+ async def stop(self) -> None:
93
+ """Stop connection gracefully."""
94
+ logger.debug(f"Stopping connection manager for {self.server_name}")
95
+
96
+ # For HTTP/SSE (no background task), just close transport
97
+ if self.transport_type in (TransportType.HTTP, TransportType.SSE):
98
+ if self._transport:
99
+ try:
100
+ close_result = self._transport.close()
101
+ if inspect.isawaitable(close_result):
102
+ await close_result
103
+ except Exception as exc:
104
+ logger.warning(f"Failed to close transport cleanly for {self.server_name}: {exc}")
105
+ self._connection = None
106
+ return
107
+
108
+ # For stdio (with background task), wait for task to finish
109
+ if self._task and not self._task.done():
110
+ self._stop_event.set()
111
+ try:
112
+ await asyncio.wait_for(self._task, timeout=5.0)
113
+ except TimeoutError:
114
+ logger.warning(f"Connection manager for {self.server_name} did not stop gracefully")
115
+ self._task.cancel()
116
+ await self._done_event.wait()
117
+
118
+ @property
119
+ def is_connected(self) -> bool:
120
+ """Check if connection is active.
121
+
122
+ Returns:
123
+ bool: True if connected, False otherwise
124
+ """
125
+ # For HTTP/SSE (no background task), just check if connection exists
126
+ if self.transport_type in (TransportType.HTTP, TransportType.SSE):
127
+ return self._connection is not None
128
+
129
+ # For stdio (with background task), check task status too
130
+ return (
131
+ self._connection is not None
132
+ and self._task is not None
133
+ and not self._task.done()
134
+ and not self._stop_event.is_set()
135
+ )
136
+
137
+ def _auto_detect_transport_type(self) -> TransportType:
138
+ """Auto-detect transport type based on configuration.
139
+
140
+ Returns:
141
+ TransportType: Detected transport type
142
+ """
143
+ if "command" in self.config:
144
+ return TransportType.STDIO
145
+ elif "url" in self.config:
146
+ url = self.config["url"]
147
+ if url.endswith("/sse"):
148
+ return TransportType.SSE
149
+ else:
150
+ return TransportType.HTTP
151
+ else:
152
+ return TransportType.STDIO
153
+
154
+ def _get_transport_type(self) -> TransportType:
155
+ """Determine the transport type to use, prioritizing explicit config with aliases.
156
+
157
+ Returns:
158
+ TransportType: Transport type enum
159
+
160
+ Notes:
161
+ Invalid explicit transports trigger a warning and fallback to auto-detection; no exception raised.
162
+ """
163
+ explicit_transport = self.config.get("transport", "").lower().replace("_", "-")
164
+ if explicit_transport in self.TRANSPORT_ALIASES:
165
+ return self.TRANSPORT_ALIASES[explicit_transport]
166
+
167
+ if explicit_transport:
168
+ logger.warning(f"Unknown explicit transport '{explicit_transport}'. Falling back to auto-detection.")
169
+
170
+ return self._auto_detect_transport_type()
171
+
172
+ async def _establish_connection(self) -> None:
173
+ """Establish connection based on transport preference with fallback.
174
+
175
+ Uses configurable retries with exponential backoff for transient failures.
176
+
177
+ Raises:
178
+ ConnectionError: If all connection attempts fail
179
+ """
180
+ # transport_type may already be set by start() for HTTP/SSE
181
+ if not self.transport_type:
182
+ self.transport_type = self._get_transport_type()
183
+ details = f"URL: {self.config.get('url', 'N/A')}, Command: {self.config.get('command', 'N/A')}"
184
+ logger.info(f"Establishing connection to {self.server_name} via {self.transport_type} ({details})")
185
+
186
+ retry_delay = self.initial_retry_delay
187
+ for attempt in range(self.max_retries):
188
+ self._transport = create_transport(self.server_name, self.config, self.transport_type)
189
+ try:
190
+ read_stream, write_stream, _ = await self._transport.connect()
191
+ self._connection = (read_stream, write_stream)
192
+ logger.info(f"Connection established on attempt {attempt + 1}")
193
+ return
194
+ except ValueError:
195
+ # Config validation errors should not be retried
196
+ raise
197
+ except Exception as e:
198
+ logger.warning(f"Connection attempt {attempt + 1} failed: {e}")
199
+ if attempt < self.max_retries - 1:
200
+ await asyncio.sleep(retry_delay)
201
+ retry_delay *= 2 # Exponential backoff
202
+ else:
203
+ raise ConnectionError(
204
+ f"Failed to establish connection to {self.server_name} "
205
+ f"after {self.max_retries} attempts: {str(e)}"
206
+ ) from e
207
+
208
+ async def _connection_task(self) -> None:
209
+ """Background task that manages the connection lifecycle."""
210
+ try:
211
+ await self._establish_connection()
212
+ self._ready_event.set()
213
+ await self._stop_event.wait()
214
+ except Exception as e:
215
+ logger.error(f"Connection failed for {self.server_name}: {e}", exc_info=True)
216
+ self._exception = e
217
+ self._ready_event.set()
218
+ finally:
219
+ if self._transport:
220
+ try:
221
+ close_result = self._transport.close()
222
+ if inspect.isawaitable(close_result):
223
+ await close_result
224
+ except Exception as exc: # pragma: no cover - defensive
225
+ logger.warning("Failed to close transport cleanly for %s: %s", self.server_name, exc)
226
+ self._connection = None
227
+ self._done_event.set()
228
+ logger.debug(f"Connection manager cleanup complete for {self.server_name}")
@@ -0,0 +1,51 @@
1
+ from _typeshed import Incomplete
2
+ from aip_agents.mcp.client.transports import TransportType as TransportType, create_transport as create_transport
3
+ from aip_agents.utils.logger import get_logger as get_logger
4
+ from gllm_tools.mcp.client.config import MCPConfiguration
5
+ from typing import Any
6
+
7
+ logger: Incomplete
8
+
9
+ class MCPConnectionManager:
10
+ """Manages MCP connection lifecycle following mcp-use patterns.
11
+
12
+ This connection manager handles the transport connection lifecycle in a background
13
+ task to avoid cancel scope issues during cleanup. It supports automatic transport
14
+ negotiation (HTTP -> SSE fallback) and graceful shutdown. Invalid explicit transports
15
+ are normalized via aliases (e.g., 'streamable_http' -> 'http') or fall back to
16
+ auto-detection with a warning.
17
+ """
18
+ TRANSPORT_ALIASES: Incomplete
19
+ server_name: Incomplete
20
+ config: Incomplete
21
+ transport_type: Incomplete
22
+ max_retries: Incomplete
23
+ initial_retry_delay: Incomplete
24
+ def __init__(self, server_name: str, config: MCPConfiguration) -> None:
25
+ """Initialize connection manager.
26
+
27
+ Args:
28
+ server_name (str): Name of the MCP server
29
+ config (MCPConfiguration): MCP server configuration
30
+ """
31
+ async def start(self) -> tuple[Any, Any]:
32
+ """Start connection in background task.
33
+
34
+ For HTTP/SSE transports, establishes connection directly to avoid anyio context issues.
35
+ For stdio transport, uses background task to manage subprocess lifecycle.
36
+
37
+ Returns:
38
+ tuple[Any, Any]: Tuple of (read_stream, write_stream) for ClientSession
39
+
40
+ Raises:
41
+ Exception: If connection establishment fails
42
+ """
43
+ async def stop(self) -> None:
44
+ """Stop connection gracefully."""
45
+ @property
46
+ def is_connected(self) -> bool:
47
+ """Check if connection is active.
48
+
49
+ Returns:
50
+ bool: True if connected, False otherwise
51
+ """
@@ -0,0 +1,11 @@
1
+ """Google ADK MCP Client.
2
+
3
+ This module provides a client for interacting with MCP servers using Google ADK.
4
+
5
+ Authors:
6
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
7
+ """
8
+
9
+ from aip_agents.mcp.client.google_adk.client import GoogleADKMCPClient
10
+
11
+ __all__ = ["GoogleADKMCPClient"]
@@ -0,0 +1,3 @@
1
+ from aip_agents.mcp.client.google_adk.client import GoogleADKMCPClient as GoogleADKMCPClient
2
+
3
+ __all__ = ['GoogleADKMCPClient']
@@ -0,0 +1,381 @@
1
+ """Google ADK MCP Adapter for MCP Client with Session Persistence.
2
+
3
+ This module contains the GoogleADKMCPClient class, which extends the BaseMCPClient
4
+ to integrate persistent MCP tools with Google's Agent Development Kit (ADK).
5
+
6
+ The GoogleADKMCPClient adapts MCP tools into ADK FunctionTool instances that can
7
+ be used seamlessly with ADK agents while maintaining session persistence across
8
+ multiple tool calls.
9
+
10
+ Authors:
11
+ Fachriza Dian Adhiatma (fachriza.d.adhiatma@gdplabs.id)
12
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
13
+ """
14
+
15
+ import base64
16
+ from typing import Any
17
+
18
+ from gllm_tools.mcp.client.config import MCPConfiguration
19
+ from gllm_tools.mcp.client.resource import MCPResource
20
+ from gllm_tools.mcp.client.tool import MCPTool
21
+ from mcp.types import (
22
+ BlobResourceContents,
23
+ CallToolResult,
24
+ EmbeddedResource,
25
+ ImageContent,
26
+ TextContent,
27
+ TextResourceContents,
28
+ )
29
+
30
+ from aip_agents.utils.logger import get_logger
31
+
32
+ try:
33
+ from google.adk.tools import FunctionTool
34
+ from google.genai.types import Part
35
+ except ImportError as e:
36
+ raise ImportError("Google ADK is required to use GoogleADKMCPClient. Install with: pip install google-adk") from e
37
+
38
+ from aip_agents.mcp.client.base_mcp_client import BaseMCPClient
39
+
40
+ NonTextContent = ImageContent | EmbeddedResource
41
+
42
+ logger = get_logger(__name__)
43
+
44
+
45
+ class GoogleADKMCPClient(BaseMCPClient):
46
+ """Google ADK MCP Client with Persistent Sessions.
47
+
48
+ This client extends BaseMCPClient to provide Google ADK-specific tool conversion
49
+ while maintaining persistent MCP sessions and connection reuse across tool calls.
50
+ It converts MCP tools into ADK FunctionTool instances for seamless integration.
51
+
52
+ The client handles:
53
+ - Converting MCP tools to ADK FunctionTool instances using persistent sessions
54
+ - Managing MCP server connections with automatic reconnection
55
+ - Converting MCP resources to ADK-compatible formats
56
+ - Handling tool execution with proper error formatting for ADK agents
57
+
58
+ Example:
59
+ ```python
60
+ from aip_agents.mcp.client.google_adk.client import GoogleADKMCPClient
61
+ from gllm_tools.mcp.client.config import MCPConfiguration
62
+
63
+ servers = {
64
+ "filesystem": MCPConfiguration(
65
+ command="npx",
66
+ args=["-y", "@modelcontextprotocol/server-filesystem", "/path/to/folder"]
67
+ )
68
+ }
69
+
70
+ client = GoogleADKMCPClient(servers)
71
+ await client.initialize() # Initialize persistent sessions
72
+ tools = await client.get_tools() # Returns list of ADK FunctionTool instances
73
+ ```
74
+ """
75
+
76
+ RESOURCE_FETCH_TIMEOUT = 10
77
+
78
+ def __init__(self, servers: dict[str, MCPConfiguration]):
79
+ """Initialize Google ADK MCP client.
80
+
81
+ Args:
82
+ servers (dict[str, MCPConfiguration]): Dictionary of MCP server configurations
83
+ """
84
+ super().__init__(servers)
85
+ # Cache converted ADK tools for consistent pattern with LangChain client
86
+ self._adk_tools_cache: dict[str | None, list[FunctionTool]] = {}
87
+
88
+ async def initialize(self) -> None:
89
+ """Initialize persistent MCP sessions for Google ADK integration.
90
+
91
+ This method ensures all MCP servers are connected with persistent sessions
92
+ and prepares the client for ADK tool conversion.
93
+
94
+ Raises:
95
+ Exception: If session initialization fails
96
+ """
97
+ await super().initialize()
98
+ logger.info(f"GoogleADKMCPClient initialized with {self.get_tools_count()} MCP tools ready for ADK conversion")
99
+
100
+ async def get_tools(self, server: str | None = None) -> list[FunctionTool]:
101
+ """Get ADK-compatible FunctionTool instances with smart caching.
102
+
103
+ Converts MCP tools to ADK format and caches them for better performance
104
+ on repeated access. Cache is keyed by server parameter.
105
+
106
+ Args:
107
+ server (str | None): Optional server name to filter tools from a specific server.
108
+ If None, returns tools from all configured servers.
109
+
110
+ Returns:
111
+ list[FunctionTool]: List of cached ADK FunctionTool instances.
112
+ """
113
+ if not self.is_initialized:
114
+ await self.initialize()
115
+
116
+ if server:
117
+ # Get tools from specific server with caching
118
+ server_tools = await self._get_server_tools_cached(server)
119
+ return server_tools.copy()
120
+ else:
121
+ # Get tools from all servers with efficient caching
122
+ all_tools = []
123
+ for server_name in self.servers.keys():
124
+ try:
125
+ server_tools = await self._get_server_tools_cached(server_name)
126
+ all_tools.extend(server_tools)
127
+ except Exception as e:
128
+ logger.warning(f"Failed to get tools from server '{server_name}': {e}")
129
+
130
+ logger.debug(f"Retrieved {len(all_tools)} total ADK FunctionTools from {len(self.servers)} servers")
131
+ return all_tools
132
+
133
+ async def _get_server_tools_cached(self, server_name: str) -> list[FunctionTool]:
134
+ """Get tools for a specific server with caching.
135
+
136
+ This method centralizes caching logic and ensures tools are only converted once per server.
137
+
138
+ Args:
139
+ server_name (str): Name of the MCP server
140
+
141
+ Returns:
142
+ list[FunctionTool]: List of cached FunctionTool instances for the server
143
+ """
144
+ # Check cache first
145
+ if server_name in self._adk_tools_cache:
146
+ logger.debug(f"Using cached ADK tools for server '{server_name}'")
147
+ return self._adk_tools_cache[server_name]
148
+
149
+ # Convert and cache tools for this server
150
+ logger.info(f"Converting and caching tools for server '{server_name}'")
151
+ mcp_tools = await self.get_raw_mcp_tools(server_name)
152
+ adk_tools = []
153
+
154
+ for mcp_tool in mcp_tools:
155
+ adk_tool = self._process_tool(mcp_tool, server_name)
156
+ adk_tools.append(adk_tool)
157
+ logger.info(f"Converted MCP tool '{mcp_tool.name}' to ADK FunctionTool for server '{server_name}'")
158
+
159
+ # Cache the converted tools
160
+ self._adk_tools_cache[server_name] = adk_tools
161
+ logger.debug(f"Cached {len(adk_tools)} ADK FunctionTools for server '{server_name}'")
162
+
163
+ return adk_tools
164
+
165
+ def _process_tool(self, tool: MCPTool, server_name: str | None = None) -> FunctionTool:
166
+ """Converts an MCP tool into an ADK FunctionTool using persistent session.
167
+
168
+ This method creates a dynamic function that wraps the MCP tool execution
169
+ using the base class's persistent session management, and converts the
170
+ response format to be compatible with ADK's expectations.
171
+
172
+ Args:
173
+ tool (MCPTool): The MCP tool to convert.
174
+ server_name (str | None): The server name for routing tool calls.
175
+
176
+ Returns:
177
+ FunctionTool: An ADK FunctionTool instance that wraps the MCP tool
178
+ with persistent session support.
179
+ """
180
+ # Store the original MCP tool name for the actual server call
181
+ original_tool_name = tool.name
182
+
183
+ # Create the dynamic function that will be wrapped by FunctionTool
184
+ async def mcp_tool_function(**arguments: dict[str, Any]) -> dict[str, Any]:
185
+ """Dynamic function that executes the MCP tool with persistent session.
186
+
187
+ This function uses the base class's call_tool method which handles
188
+ server routing and persistent session management automatically.
189
+
190
+ Args:
191
+ **arguments (dict[str, Any]): Keyword arguments for the MCP tool execution.
192
+
193
+ Returns:
194
+ dict[str, Any]: The tool execution result.
195
+ """
196
+ try:
197
+ # Determine server to route the call to
198
+ resolved_server = server_name or next(iter(self.servers.keys()), None)
199
+ if not resolved_server:
200
+ raise RuntimeError("No MCP servers configured for executing tool")
201
+
202
+ # Use the original MCP tool name for the server call, not the sanitized name
203
+ call_tool_result = await self.call_tool(resolved_server, original_tool_name, arguments)
204
+ return self._convert_call_tool_result(call_tool_result)
205
+ except Exception as e:
206
+ logger.error(f"MCP tool '{original_tool_name}' execution failed: {e}")
207
+ return {"status": "error", "message": str(e)}
208
+
209
+ # Set function metadata for ADK introspection (will be sanitized later by agent)
210
+ mcp_tool_function.__name__ = tool.name
211
+ mcp_tool_function.__doc__ = tool.description or f"MCP tool: {tool.name} (from server: {server_name})"
212
+
213
+ # Create and return the ADK FunctionTool
214
+ return FunctionTool(func=mcp_tool_function)
215
+
216
+ async def _process_resource(self, resource: MCPResource) -> dict[str, Any]:
217
+ """Converts an MCP resource into an ADK-compatible format using persistent session.
218
+
219
+ Args:
220
+ resource (MCPResource): The MCP resource to convert.
221
+
222
+ Returns:
223
+ dict[str, Any]: A dictionary containing resource metadata and accessor function.
224
+ """
225
+ # Determine server name from resource URI or use first available server
226
+ server_name = self._determine_server_name_for_resource(resource)
227
+
228
+ async def read_resource_content() -> Part:
229
+ """Reads the actual content of the MCP resource using persistent session."""
230
+ try:
231
+ # Use base class method for persistent session resource access
232
+ resource_result = await self.read_resource(server_name, str(resource.uri))
233
+
234
+ contents = resource_result.contents[0]
235
+ if isinstance(contents, TextResourceContents):
236
+ return Part.from_text(contents.text)
237
+ elif isinstance(contents, BlobResourceContents):
238
+ data = base64.b64decode(contents.blob)
239
+ return Part.from_bytes(data=data, mime_type=resource.mime_type)
240
+ else:
241
+ raise ValueError(f"Unsupported content type for URI {resource.uri}")
242
+ except Exception as e:
243
+ # Do not break callers; return a safe textual Part describing the error
244
+ logger.error(f"Failed to read MCP resource {resource.uri}: {e}")
245
+ try:
246
+ return Part.from_text(f"Error reading resource {resource.uri}: {e}")
247
+ except Exception as part_error:
248
+ logger.error(f"Failed to create error Part for resource {resource.uri}: {part_error}")
249
+ raise ValueError(f"Cannot create ADK Part for error response: {part_error}") from part_error
250
+
251
+ return {
252
+ "uri": str(resource.uri),
253
+ "name": resource.name,
254
+ "description": resource.description,
255
+ "mime_type": resource.mime_type,
256
+ "read_content": read_resource_content,
257
+ "metadata": {
258
+ "uri": resource.uri,
259
+ "annotations": resource.annotations.model_dump() if resource.annotations else None,
260
+ },
261
+ }
262
+
263
+ async def cleanup(self) -> None:
264
+ """Clean up Google ADK MCP client resources.
265
+
266
+ This method ensures all persistent sessions are properly closed and
267
+ ADK-specific resources are cleaned up.
268
+ """
269
+ logger.info("Cleaning up GoogleADKMCPClient resources")
270
+ try:
271
+ await super().cleanup()
272
+ except Exception as e:
273
+ logger.error(f"Error during base GoogleADKMCPClient cleanup: {e}", exc_info=True)
274
+ finally:
275
+ # Always clear the ADK tools cache
276
+ self._adk_tools_cache.clear()
277
+ logger.info("GoogleADKMCPClient cleanup completed")
278
+
279
+ def _convert_call_tool_result(self, call_tool_result: CallToolResult) -> dict[str, Any]:
280
+ """Converts an MCP call tool result into an ADK-compatible format.
281
+
282
+ ADK tools should return dictionaries with meaningful keys. This method
283
+ extracts text content and formats it appropriately for ADK agents.
284
+
285
+ Args:
286
+ call_tool_result (CallToolResult): The MCP tool execution result.
287
+
288
+ Returns:
289
+ dict[str, Any]: ADK-compatible result dictionary.
290
+
291
+ Raises:
292
+ Exception: If the tool execution resulted in an error.
293
+ """
294
+ text_contents, non_text_contents = self._separate_contents(call_tool_result.content)
295
+
296
+ if call_tool_result.isError:
297
+ error_message = self._format_error_message(text_contents)
298
+ raise RuntimeError(f"MCP tool execution failed: {error_message}")
299
+
300
+ result = {"status": "success"}
301
+ if text_contents:
302
+ result["result"] = (
303
+ text_contents[0].text if len(text_contents) == 1 else [content.text for content in text_contents]
304
+ )
305
+ else:
306
+ result["result"] = "Tool executed successfully"
307
+
308
+ artifacts = [a for a in (self._format_artifact(c) for c in non_text_contents) if a]
309
+ if artifacts:
310
+ result["artifacts"] = artifacts
311
+
312
+ return result
313
+
314
+ @staticmethod
315
+ def _separate_contents(contents) -> tuple[list[TextContent], list[NonTextContent]]:
316
+ """Separates a list of content objects into text and non-text content.
317
+
318
+ This helper method processes a list of content objects and categorizes them
319
+ into text content (TextContent) and other content types for further processing.
320
+
321
+ Args:
322
+ contents (list[Any]): List of content objects to be separated.
323
+
324
+ Returns:
325
+ tuple[list[TextContent], list[NonTextContent]]: A tuple containing two lists:
326
+ - First: TextContent objects
327
+ - Second: All other content types.
328
+ """
329
+ text_contents = []
330
+ non_text_contents = []
331
+ for content in contents:
332
+ if isinstance(content, TextContent):
333
+ text_contents.append(content)
334
+ else:
335
+ non_text_contents.append(content)
336
+ return text_contents, non_text_contents
337
+
338
+ @staticmethod
339
+ def _format_artifact(content: NonTextContent) -> dict[str, Any] | None:
340
+ """Formats non-text content into ADK-compatible artifact dictionaries.
341
+
342
+ Converts different types of content objects (images, embedded resources) into
343
+ a standardized dictionary format expected by ADK agents.
344
+
345
+ Args:
346
+ content (NonTextContent): The content object to be formatted. Can be either ImageContent
347
+ or EmbeddedResource.
348
+
349
+ Returns:
350
+ dict[str, Any] | None: A dictionary containing the formatted content with appropriate type-specific
351
+ fields, or None if the content type is not supported.
352
+ """
353
+ if isinstance(content, ImageContent):
354
+ return {
355
+ "type": "image",
356
+ "data": content.data,
357
+ "mime_type": content.mimeType,
358
+ }
359
+ if isinstance(content, EmbeddedResource):
360
+ return {
361
+ "type": "resource",
362
+ "uri": str(content.resource.uri),
363
+ "text": getattr(content.resource, "text", None),
364
+ }
365
+ return None
366
+
367
+ @staticmethod
368
+ def _format_error_message(text_contents: list[TextContent]) -> str:
369
+ """Formats a list of text contents into a single error message string.
370
+
371
+ Combines multiple text content objects into a single string, typically
372
+ used for creating human-readable error messages from tool execution results.
373
+
374
+ Args:
375
+ text_contents (list[TextContent]): List of TextContent objects containing error message parts.
376
+
377
+ Returns:
378
+ str: A single string containing all text contents joined by spaces,
379
+ or an empty string if the input list is empty.
380
+ """
381
+ return " ".join(content.text for content in text_contents) if text_contents else ""