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.
- aip_agents/__init__.py +65 -0
- aip_agents/__init__.pyi +19 -0
- aip_agents/a2a/__init__.py +19 -0
- aip_agents/a2a/__init__.pyi +3 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/__init__.pyi +4 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/base_executor.pyi +73 -0
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/google_adk_executor.pyi +51 -0
- aip_agents/a2a/server/langflow_executor.py +180 -0
- aip_agents/a2a/server/langflow_executor.pyi +43 -0
- aip_agents/a2a/server/langgraph_executor.py +270 -0
- aip_agents/a2a/server/langgraph_executor.pyi +47 -0
- aip_agents/a2a/types.py +232 -0
- aip_agents/a2a/types.pyi +132 -0
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/__init__.pyi +9 -0
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_agent.pyi +221 -0
- aip_agents/agent/base_langgraph_agent.py +3037 -0
- aip_agents/agent/base_langgraph_agent.pyi +233 -0
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_agent.pyi +141 -0
- aip_agents/agent/google_adk_constants.py +6 -0
- aip_agents/agent/google_adk_constants.pyi +3 -0
- aip_agents/agent/hitl/__init__.py +24 -0
- aip_agents/agent/hitl/__init__.pyi +6 -0
- aip_agents/agent/hitl/config.py +28 -0
- aip_agents/agent/hitl/config.pyi +15 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
- aip_agents/agent/hitl/manager.py +532 -0
- aip_agents/agent/hitl/manager.pyi +200 -0
- aip_agents/agent/hitl/models.py +18 -0
- aip_agents/agent/hitl/models.pyi +3 -0
- aip_agents/agent/hitl/prompt/__init__.py +9 -0
- aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
- aip_agents/agent/hitl/prompt/base.py +42 -0
- aip_agents/agent/hitl/prompt/base.pyi +24 -0
- aip_agents/agent/hitl/prompt/deferred.py +73 -0
- aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
- aip_agents/agent/hitl/registry.py +149 -0
- aip_agents/agent/hitl/registry.pyi +101 -0
- aip_agents/agent/interface.py +138 -0
- aip_agents/agent/interface.pyi +81 -0
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/interfaces.pyi +44 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langflow_agent.pyi +133 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.py +767 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +50 -0
- aip_agents/agent/langgraph_react_agent.py +2856 -0
- aip_agents/agent/langgraph_react_agent.pyi +170 -0
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/agent/system_instruction_context.pyi +13 -0
- aip_agents/clients/__init__.py +10 -0
- aip_agents/clients/__init__.pyi +4 -0
- aip_agents/clients/langflow/__init__.py +10 -0
- aip_agents/clients/langflow/__init__.pyi +4 -0
- aip_agents/clients/langflow/client.py +477 -0
- aip_agents/clients/langflow/client.pyi +140 -0
- aip_agents/clients/langflow/types.py +18 -0
- aip_agents/clients/langflow/types.pyi +7 -0
- aip_agents/constants.py +23 -0
- aip_agents/constants.pyi +7 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/__init__.pyi +0 -0
- aip_agents/examples/compare_streaming_client.py +783 -0
- aip_agents/examples/compare_streaming_client.pyi +48 -0
- aip_agents/examples/compare_streaming_server.py +142 -0
- aip_agents/examples/compare_streaming_server.pyi +18 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
- aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_google_adk.py +41 -0
- aip_agents/examples/hello_world_google_adk.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_stream.py +44 -0
- aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain.py +28 -0
- aip_agents/examples/hello_world_langchain.pyi +5 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream.py +36 -0
- aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_langflow_agent.py +163 -0
- aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
- aip_agents/examples/hello_world_langgraph.py +39 -0
- aip_agents/examples/hello_world_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
- aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream.py +43 -0
- aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_model_switch_cli.py +210 -0
- aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
- aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
- aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
- aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
- aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_pii_logger.pyi +5 -0
- aip_agents/examples/hello_world_ptc.py +49 -0
- aip_agents/examples/hello_world_ptc.pyi +5 -0
- aip_agents/examples/hello_world_sentry.py +133 -0
- aip_agents/examples/hello_world_sentry.pyi +21 -0
- aip_agents/examples/hello_world_step_limits.py +273 -0
- aip_agents/examples/hello_world_step_limits.pyi +17 -0
- aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
- aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
- aip_agents/examples/hello_world_tool_output_client.py +55 -0
- aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
- aip_agents/examples/hitl_demo.py +724 -0
- aip_agents/examples/hitl_demo.pyi +67 -0
- aip_agents/examples/mcp_configs/configs.py +63 -0
- aip_agents/examples/mcp_servers/common.py +76 -0
- aip_agents/examples/mcp_servers/mcp_name.py +29 -0
- aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
- aip_agents/examples/mcp_servers/mcp_time.py +10 -0
- aip_agents/examples/pii_demo_langgraph_client.py +69 -0
- aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
- aip_agents/examples/pii_demo_langgraph_server.py +126 -0
- aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
- aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/__init__.pyi +9 -0
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
- aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_generator_tool.pyi +15 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
- aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
- aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
- aip_agents/examples/tools/pii_demo_tools.py +189 -0
- aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
- aip_agents/examples/tools/random_chart_tool.py +142 -0
- aip_agents/examples/tools/random_chart_tool.pyi +20 -0
- aip_agents/examples/tools/serper_tool.py +202 -0
- aip_agents/examples/tools/serper_tool.pyi +16 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- aip_agents/examples/tools/stock_tools.pyi +36 -0
- aip_agents/examples/tools/table_generator_tool.py +167 -0
- aip_agents/examples/tools/table_generator_tool.pyi +22 -0
- aip_agents/examples/tools/time_tool.py +82 -0
- aip_agents/examples/tools/time_tool.pyi +15 -0
- aip_agents/examples/tools/weather_forecast_tool.py +38 -0
- aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
- aip_agents/executor/agent_executor.py +473 -0
- aip_agents/executor/base.py +48 -0
- aip_agents/guardrails/__init__.py +83 -0
- aip_agents/guardrails/__init__.pyi +6 -0
- aip_agents/guardrails/engines/__init__.py +69 -0
- aip_agents/guardrails/engines/__init__.pyi +4 -0
- aip_agents/guardrails/engines/base.py +90 -0
- aip_agents/guardrails/engines/base.pyi +61 -0
- aip_agents/guardrails/engines/nemo.py +101 -0
- aip_agents/guardrails/engines/nemo.pyi +46 -0
- aip_agents/guardrails/engines/phrase_matcher.py +113 -0
- aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
- aip_agents/guardrails/exceptions.py +39 -0
- aip_agents/guardrails/exceptions.pyi +23 -0
- aip_agents/guardrails/manager.py +163 -0
- aip_agents/guardrails/manager.pyi +42 -0
- aip_agents/guardrails/middleware.py +199 -0
- aip_agents/guardrails/middleware.pyi +87 -0
- aip_agents/guardrails/schemas.py +63 -0
- aip_agents/guardrails/schemas.pyi +43 -0
- aip_agents/guardrails/utils.py +45 -0
- aip_agents/guardrails/utils.pyi +19 -0
- aip_agents/mcp/__init__.py +1 -0
- aip_agents/mcp/__init__.pyi +0 -0
- aip_agents/mcp/client/__init__.py +14 -0
- aip_agents/mcp/client/__init__.pyi +5 -0
- aip_agents/mcp/client/base_mcp_client.py +369 -0
- aip_agents/mcp/client/base_mcp_client.pyi +148 -0
- aip_agents/mcp/client/connection_manager.py +228 -0
- aip_agents/mcp/client/connection_manager.pyi +51 -0
- aip_agents/mcp/client/google_adk/__init__.py +11 -0
- aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/google_adk/client.pyi +75 -0
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/__init__.pyi +3 -0
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/langchain/client.pyi +48 -0
- aip_agents/mcp/client/persistent_session.py +612 -0
- aip_agents/mcp/client/persistent_session.pyi +122 -0
- aip_agents/mcp/client/session_pool.py +351 -0
- aip_agents/mcp/client/session_pool.pyi +101 -0
- aip_agents/mcp/client/transports.py +263 -0
- aip_agents/mcp/client/transports.pyi +132 -0
- aip_agents/mcp/utils/__init__.py +7 -0
- aip_agents/mcp/utils/__init__.pyi +0 -0
- aip_agents/mcp/utils/config_validator.py +139 -0
- aip_agents/mcp/utils/config_validator.pyi +82 -0
- aip_agents/memory/__init__.py +14 -0
- aip_agents/memory/__init__.pyi +5 -0
- aip_agents/memory/adapters/__init__.py +10 -0
- aip_agents/memory/adapters/__init__.pyi +4 -0
- aip_agents/memory/adapters/base_adapter.py +811 -0
- aip_agents/memory/adapters/base_adapter.pyi +176 -0
- aip_agents/memory/adapters/mem0.py +84 -0
- aip_agents/memory/adapters/mem0.pyi +22 -0
- aip_agents/memory/base.py +84 -0
- aip_agents/memory/base.pyi +60 -0
- aip_agents/memory/constants.py +49 -0
- aip_agents/memory/constants.pyi +25 -0
- aip_agents/memory/factory.py +86 -0
- aip_agents/memory/factory.pyi +24 -0
- aip_agents/memory/guidance.py +20 -0
- aip_agents/memory/guidance.pyi +3 -0
- aip_agents/memory/simple_memory.py +47 -0
- aip_agents/memory/simple_memory.pyi +23 -0
- aip_agents/middleware/__init__.py +17 -0
- aip_agents/middleware/__init__.pyi +5 -0
- aip_agents/middleware/base.py +96 -0
- aip_agents/middleware/base.pyi +75 -0
- aip_agents/middleware/manager.py +150 -0
- aip_agents/middleware/manager.pyi +84 -0
- aip_agents/middleware/todolist.py +274 -0
- aip_agents/middleware/todolist.pyi +125 -0
- aip_agents/ptc/__init__.py +48 -0
- aip_agents/ptc/__init__.pyi +10 -0
- aip_agents/ptc/doc_gen.py +122 -0
- aip_agents/ptc/doc_gen.pyi +40 -0
- aip_agents/ptc/exceptions.py +39 -0
- aip_agents/ptc/exceptions.pyi +22 -0
- aip_agents/ptc/executor.py +143 -0
- aip_agents/ptc/executor.pyi +73 -0
- aip_agents/ptc/mcp/__init__.py +45 -0
- aip_agents/ptc/mcp/__init__.pyi +7 -0
- aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
- aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
- aip_agents/ptc/mcp/templates/__init__.py +1 -0
- aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
- aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
- aip_agents/ptc/naming.py +184 -0
- aip_agents/ptc/naming.pyi +76 -0
- aip_agents/ptc/payload.py +26 -0
- aip_agents/ptc/payload.pyi +15 -0
- aip_agents/ptc/prompt_builder.py +571 -0
- aip_agents/ptc/prompt_builder.pyi +55 -0
- aip_agents/ptc/ptc_helper.py +16 -0
- aip_agents/ptc/ptc_helper.pyi +1 -0
- aip_agents/ptc/sandbox_bridge.py +58 -0
- aip_agents/ptc/sandbox_bridge.pyi +25 -0
- aip_agents/ptc/template_utils.py +33 -0
- aip_agents/ptc/template_utils.pyi +13 -0
- aip_agents/ptc/templates/__init__.py +1 -0
- aip_agents/ptc/templates/__init__.pyi +0 -0
- aip_agents/ptc/templates/ptc_helper.py.template +134 -0
- aip_agents/sandbox/__init__.py +43 -0
- aip_agents/sandbox/__init__.pyi +5 -0
- aip_agents/sandbox/defaults.py +9 -0
- aip_agents/sandbox/defaults.pyi +2 -0
- aip_agents/sandbox/e2b_runtime.py +267 -0
- aip_agents/sandbox/e2b_runtime.pyi +51 -0
- aip_agents/sandbox/template_builder.py +131 -0
- aip_agents/sandbox/template_builder.pyi +36 -0
- aip_agents/sandbox/types.py +24 -0
- aip_agents/sandbox/types.pyi +14 -0
- aip_agents/sandbox/validation.py +50 -0
- aip_agents/sandbox/validation.pyi +20 -0
- aip_agents/schema/__init__.py +69 -0
- aip_agents/schema/__init__.pyi +9 -0
- aip_agents/schema/a2a.py +56 -0
- aip_agents/schema/a2a.pyi +40 -0
- aip_agents/schema/agent.py +111 -0
- aip_agents/schema/agent.pyi +65 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/hitl.pyi +89 -0
- aip_agents/schema/langgraph.py +37 -0
- aip_agents/schema/langgraph.pyi +28 -0
- aip_agents/schema/model_id.py +97 -0
- aip_agents/schema/model_id.pyi +54 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/step_limit.pyi +63 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/schema/storage.pyi +21 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/__init__.pyi +3 -0
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/sentry/sentry.pyi +48 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/__init__.pyi +8 -0
- aip_agents/storage/base.py +85 -0
- aip_agents/storage/base.pyi +58 -0
- aip_agents/storage/clients/__init__.py +12 -0
- aip_agents/storage/clients/__init__.pyi +3 -0
- aip_agents/storage/clients/minio_client.py +318 -0
- aip_agents/storage/clients/minio_client.pyi +137 -0
- aip_agents/storage/config.py +62 -0
- aip_agents/storage/config.pyi +29 -0
- aip_agents/storage/providers/__init__.py +15 -0
- aip_agents/storage/providers/__init__.pyi +5 -0
- aip_agents/storage/providers/base.py +106 -0
- aip_agents/storage/providers/base.pyi +88 -0
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/memory.pyi +79 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/storage/providers/object_storage.pyi +98 -0
- aip_agents/tools/__init__.py +64 -0
- aip_agents/tools/__init__.pyi +11 -0
- aip_agents/tools/browser_use/__init__.py +82 -0
- aip_agents/tools/browser_use/__init__.pyi +14 -0
- aip_agents/tools/browser_use/action_parser.py +103 -0
- aip_agents/tools/browser_use/action_parser.pyi +18 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1120 -0
- aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/llm_config.pyi +52 -0
- aip_agents/tools/browser_use/minio_storage.py +198 -0
- aip_agents/tools/browser_use/minio_storage.pyi +109 -0
- aip_agents/tools/browser_use/schemas.py +119 -0
- aip_agents/tools/browser_use/schemas.pyi +32 -0
- aip_agents/tools/browser_use/session.py +76 -0
- aip_agents/tools/browser_use/session.pyi +4 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/session_errors.pyi +53 -0
- aip_agents/tools/browser_use/steel_session_recording.py +317 -0
- aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
- aip_agents/tools/browser_use/streaming.py +815 -0
- aip_agents/tools/browser_use/streaming.pyi +81 -0
- aip_agents/tools/browser_use/structured_data_parser.py +257 -0
- aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
- aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
- aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
- aip_agents/tools/browser_use/types.py +78 -0
- aip_agents/tools/browser_use/types.pyi +45 -0
- aip_agents/tools/code_sandbox/__init__.py +26 -0
- aip_agents/tools/code_sandbox/__init__.pyi +3 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/constant.pyi +4 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
- aip_agents/tools/constants.py +177 -0
- aip_agents/tools/constants.pyi +138 -0
- aip_agents/tools/date_range_tool.py +554 -0
- aip_agents/tools/date_range_tool.pyi +21 -0
- aip_agents/tools/document_loader/__init__.py +44 -0
- aip_agents/tools/document_loader/__init__.pyi +7 -0
- aip_agents/tools/document_loader/base_reader.py +302 -0
- aip_agents/tools/document_loader/base_reader.pyi +75 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
- aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
- aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
- aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
- aip_agents/tools/execute_ptc_code.py +308 -0
- aip_agents/tools/execute_ptc_code.pyi +90 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/__init__.pyi +3 -0
- aip_agents/tools/gl_connector/tool.py +383 -0
- aip_agents/tools/gl_connector/tool.pyi +74 -0
- aip_agents/tools/gl_connector_tools.py +119 -0
- aip_agents/tools/gl_connector_tools.pyi +39 -0
- aip_agents/tools/memory_search/__init__.py +29 -0
- aip_agents/tools/memory_search/__init__.pyi +5 -0
- aip_agents/tools/memory_search/base.py +200 -0
- aip_agents/tools/memory_search/base.pyi +69 -0
- aip_agents/tools/memory_search/mem0.py +365 -0
- aip_agents/tools/memory_search/mem0.pyi +29 -0
- aip_agents/tools/memory_search/schema.py +81 -0
- aip_agents/tools/memory_search/schema.pyi +25 -0
- aip_agents/tools/memory_search_tool.py +34 -0
- aip_agents/tools/memory_search_tool.pyi +3 -0
- aip_agents/tools/time_tool.py +117 -0
- aip_agents/tools/time_tool.pyi +16 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/tool_config_injector.pyi +26 -0
- aip_agents/tools/web_search/__init__.py +15 -0
- aip_agents/tools/web_search/__init__.pyi +3 -0
- aip_agents/tools/web_search/serper_tool.py +187 -0
- aip_agents/tools/web_search/serper_tool.pyi +19 -0
- aip_agents/types/__init__.py +70 -0
- aip_agents/types/__init__.pyi +36 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/types/a2a_events.pyi +3 -0
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/__init__.pyi +11 -0
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/a2a_connector.pyi +146 -0
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/artifact_helpers.pyi +203 -0
- aip_agents/utils/constants.py +22 -0
- aip_agents/utils/constants.pyi +10 -0
- aip_agents/utils/datetime/__init__.py +34 -0
- aip_agents/utils/datetime/__init__.pyi +4 -0
- aip_agents/utils/datetime/normalization.py +231 -0
- aip_agents/utils/datetime/normalization.pyi +95 -0
- aip_agents/utils/datetime/timezone.py +206 -0
- aip_agents/utils/datetime/timezone.pyi +48 -0
- aip_agents/utils/env_loader.py +27 -0
- aip_agents/utils/env_loader.pyi +10 -0
- aip_agents/utils/event_handler_registry.py +58 -0
- aip_agents/utils/event_handler_registry.pyi +23 -0
- aip_agents/utils/file_prompt_utils.py +176 -0
- aip_agents/utils/file_prompt_utils.pyi +21 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/final_response_builder.pyi +34 -0
- aip_agents/utils/formatter_llm_client.py +231 -0
- aip_agents/utils/formatter_llm_client.pyi +71 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/__init__.pyi +3 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- aip_agents/utils/langgraph/converter.pyi +49 -0
- aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
- aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1096 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
- aip_agents/utils/langgraph/tool_output_management.py +1047 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +329 -0
- aip_agents/utils/logger.py +195 -0
- aip_agents/utils/logger.pyi +60 -0
- aip_agents/utils/metadata/__init__.py +27 -0
- aip_agents/utils/metadata/__init__.pyi +5 -0
- aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
- aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
- aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
- aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
- aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
- aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
- aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
- aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
- aip_agents/utils/metadata/activity_narrative/context.py +49 -0
- aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
- aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
- aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
- aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
- aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
- aip_agents/utils/metadata/schemas/__init__.py +16 -0
- aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
- aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
- aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
- aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
- aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
- aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
- aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
- aip_agents/utils/metadata_helper.py +358 -0
- aip_agents/utils/metadata_helper.pyi +117 -0
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
- aip_agents/utils/pii/__init__.py +25 -0
- aip_agents/utils/pii/__init__.pyi +5 -0
- aip_agents/utils/pii/pii_handler.py +397 -0
- aip_agents/utils/pii/pii_handler.pyi +96 -0
- aip_agents/utils/pii/pii_helper.py +207 -0
- aip_agents/utils/pii/pii_helper.pyi +78 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
- aip_agents/utils/reference_helper.py +273 -0
- aip_agents/utils/reference_helper.pyi +81 -0
- aip_agents/utils/sse_chunk_transformer.py +831 -0
- aip_agents/utils/sse_chunk_transformer.pyi +166 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/step_limit_manager.pyi +112 -0
- aip_agents/utils/token_usage_helper.py +156 -0
- aip_agents/utils/token_usage_helper.pyi +60 -0
- aip_agents_binary-0.6.4.dist-info/METADATA +673 -0
- aip_agents_binary-0.6.4.dist-info/RECORD +612 -0
- aip_agents_binary-0.6.4.dist-info/WHEEL +5 -0
- aip_agents_binary-0.6.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"""Base MCP Client for aip-agents with Session Persistence.
|
|
2
|
+
|
|
3
|
+
This base class provides persistent session management for MCP connections and serves
|
|
4
|
+
as the foundation for SDK-specific MCP clients (LangChain, Google ADK, etc.). It handles
|
|
5
|
+
session pooling, initialization, tool discovery, and cleanup while leaving SDK-specific
|
|
6
|
+
tool conversion to subclasses.
|
|
7
|
+
|
|
8
|
+
Authors:
|
|
9
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
from abc import ABC, abstractmethod
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from gllm_tools.mcp.client.client import MCPClient
|
|
17
|
+
from gllm_tools.mcp.client.config import MCPConfiguration
|
|
18
|
+
from gllm_tools.mcp.client.resource import MCPResource
|
|
19
|
+
from mcp.types import CallToolResult, Tool
|
|
20
|
+
|
|
21
|
+
from aip_agents.mcp.client.persistent_session import PersistentMCPSession
|
|
22
|
+
from aip_agents.mcp.client.session_pool import MCPSessionPool
|
|
23
|
+
from aip_agents.utils.logger import get_logger
|
|
24
|
+
|
|
25
|
+
logger = get_logger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class BaseMCPClient(MCPClient, ABC):
|
|
29
|
+
"""Base MCP Client with persistent session management for aip-agents.
|
|
30
|
+
|
|
31
|
+
This class provides:
|
|
32
|
+
- Persistent session management across tool calls
|
|
33
|
+
- One-time tool registration and caching
|
|
34
|
+
- Automatic connection health monitoring and reconnection
|
|
35
|
+
- Centralized cleanup of all MCP resources
|
|
36
|
+
- Generic tool discovery from all configured MCP servers
|
|
37
|
+
|
|
38
|
+
Subclasses should implement SDK-specific tool conversion in _process_tool() method.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, servers: dict[str, MCPConfiguration]):
|
|
42
|
+
"""Initialize the base MCP client with session pool.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
servers (dict[str, MCPConfiguration]): Dictionary of MCP server configurations by server name
|
|
46
|
+
"""
|
|
47
|
+
super().__init__(servers)
|
|
48
|
+
self.session_pool = MCPSessionPool()
|
|
49
|
+
self._tools_cache: list[Tool] = []
|
|
50
|
+
self._initialized = False
|
|
51
|
+
# Guard against concurrent initialization
|
|
52
|
+
self._init_lock: asyncio.Lock = asyncio.Lock()
|
|
53
|
+
|
|
54
|
+
async def initialize(self) -> None:
|
|
55
|
+
"""Initialize all MCP sessions and cache tools once.
|
|
56
|
+
|
|
57
|
+
This method is idempotent and only performs initialization if not already done.
|
|
58
|
+
It establishes persistent connections to all configured MCP servers and caches
|
|
59
|
+
available tools for efficient access.
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
Exception: If any session initialization fails
|
|
63
|
+
"""
|
|
64
|
+
if self._initialized:
|
|
65
|
+
logger.debug("BaseMCPClient already initialized, skipping")
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
# Ensure only one concurrent initializer proceeds
|
|
69
|
+
async with self._init_lock:
|
|
70
|
+
if self._initialized:
|
|
71
|
+
logger.debug("BaseMCPClient already initialized (post-lock), skipping")
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
logger.info(f"Initializing BaseMCPClient with {len(self.servers)} MCP servers")
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
# Initialize all persistent sessions concurrently
|
|
78
|
+
await self.session_pool.initialize_all_sessions(self.servers)
|
|
79
|
+
|
|
80
|
+
# Cache all available tools from all sessions
|
|
81
|
+
self._tools_cache = await self.session_pool.get_all_tools()
|
|
82
|
+
|
|
83
|
+
self._initialized = True
|
|
84
|
+
logger.info(
|
|
85
|
+
f"BaseMCPClient initialization complete: "
|
|
86
|
+
f"{len(self._tools_cache)} tools cached from {self.session_pool.session_count} sessions"
|
|
87
|
+
)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.error(f"Failed to initialize BaseMCPClient: {e}", exc_info=True)
|
|
90
|
+
# Cleanup any partially initialized sessions on failure
|
|
91
|
+
await self.cleanup()
|
|
92
|
+
raise
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
async def get_tools(self, server: str | None = None) -> list[Any]:
|
|
96
|
+
"""Get framework-specific tools from MCP servers.
|
|
97
|
+
|
|
98
|
+
This method must be implemented by subclasses to provide framework-specific
|
|
99
|
+
tool conversion (e.g., StructuredTool for LangChain, FunctionTool for Google ADK).
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
103
|
+
If None, returns tools from all configured servers.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
list[Any]: List of framework-specific tool objects.
|
|
107
|
+
"""
|
|
108
|
+
pass # pragma: no cover # Abstract method - cannot be executed directly
|
|
109
|
+
|
|
110
|
+
async def get_raw_mcp_tools(self, server: str | None = None) -> list[Tool]:
|
|
111
|
+
"""Get raw MCP tools - for subclasses to perform framework-specific conversions.
|
|
112
|
+
|
|
113
|
+
This method provides access to the cached raw MCP Tool objects.
|
|
114
|
+
Subclasses use this to convert to framework-specific tools.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
118
|
+
If None, returns tools from all configured servers.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
list[Tool]: List of raw MCP Tool objects. Empty list if not initialized or no tools available.
|
|
122
|
+
"""
|
|
123
|
+
if not self._initialized:
|
|
124
|
+
await self.initialize()
|
|
125
|
+
|
|
126
|
+
if server:
|
|
127
|
+
if server not in self.servers:
|
|
128
|
+
logger.warning(f"Server '{server}' not found in configuration")
|
|
129
|
+
return []
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
session = self.session_pool.get_session(server)
|
|
133
|
+
return await session.list_tools()
|
|
134
|
+
except KeyError:
|
|
135
|
+
logger.warning(f"No active session found for server '{server}'")
|
|
136
|
+
return []
|
|
137
|
+
except Exception as e:
|
|
138
|
+
logger.error(f"Failed to get tools from server '{server}': {e}")
|
|
139
|
+
return []
|
|
140
|
+
else:
|
|
141
|
+
return self._tools_cache.copy()
|
|
142
|
+
|
|
143
|
+
def get_tools_count(self, server: str | None = None) -> int:
|
|
144
|
+
"""Get count of raw MCP tools without expensive copying.
|
|
145
|
+
|
|
146
|
+
This is an efficient way to get tool counts for logging/metrics
|
|
147
|
+
without the overhead of copying tool lists.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
151
|
+
If None, returns count from all configured servers.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
int: Count of raw MCP tools available.
|
|
155
|
+
"""
|
|
156
|
+
if not self._initialized:
|
|
157
|
+
return 0
|
|
158
|
+
|
|
159
|
+
if server:
|
|
160
|
+
if server not in self.servers:
|
|
161
|
+
return 0
|
|
162
|
+
try:
|
|
163
|
+
session = self.session_pool.get_session(server)
|
|
164
|
+
return session.get_tools_count()
|
|
165
|
+
except KeyError:
|
|
166
|
+
return 0
|
|
167
|
+
except Exception as e:
|
|
168
|
+
logger.error(f"Failed to get tools count from server '{server}': {e}")
|
|
169
|
+
return 0
|
|
170
|
+
else:
|
|
171
|
+
return len(self._tools_cache)
|
|
172
|
+
|
|
173
|
+
async def get_session(self, server_name: str) -> PersistentMCPSession:
|
|
174
|
+
"""Get a persistent session for a specific server.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
server_name (str): The name of the MCP server
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
PersistentMCPSession: Persistent MCP session for the specified server
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
KeyError: If the server is not configured or no active session exists
|
|
184
|
+
"""
|
|
185
|
+
if not self._initialized:
|
|
186
|
+
await self.initialize()
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
return self.session_pool.get_session(server_name)
|
|
190
|
+
except KeyError:
|
|
191
|
+
logger.error(f"Server '{server_name}' not found in configuration")
|
|
192
|
+
raise
|
|
193
|
+
except Exception as e:
|
|
194
|
+
logger.error(f"Failed to get session for server '{server_name}': {e}")
|
|
195
|
+
raise
|
|
196
|
+
|
|
197
|
+
async def call_tool(self, server_name: str, tool_name: str, arguments: dict[str, Any]) -> CallToolResult:
|
|
198
|
+
"""Execute a tool on a specific MCP server using persistent session.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
server_name (str): The MCP server to execute the tool on
|
|
202
|
+
tool_name (str): The name of the tool to execute
|
|
203
|
+
arguments (dict[str, Any]): Arguments for the tool execution
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
CallToolResult: The result of the tool execution
|
|
207
|
+
|
|
208
|
+
Raises:
|
|
209
|
+
KeyError: If the server doesn't exist
|
|
210
|
+
Exception: If tool execution fails
|
|
211
|
+
"""
|
|
212
|
+
if not self._initialized:
|
|
213
|
+
await self.initialize()
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
session = self.session_pool.get_session(server_name)
|
|
217
|
+
return await session.call_tool(tool_name, arguments)
|
|
218
|
+
except KeyError:
|
|
219
|
+
logger.error(f"Server '{server_name}' not found in configuration")
|
|
220
|
+
raise
|
|
221
|
+
except Exception as e:
|
|
222
|
+
logger.error(f"Failed to call tool '{tool_name}' on server '{server_name}': {e}")
|
|
223
|
+
raise
|
|
224
|
+
|
|
225
|
+
async def read_resource(self, server_name: str, resource_uri: str):
|
|
226
|
+
"""Read an MCP resource from a specific server using persistent session.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
server_name (str): The MCP server to read the resource from
|
|
230
|
+
resource_uri (str): The URI of the resource to read
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Any: The resource content
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
KeyError: If the server doesn't exist
|
|
237
|
+
Exception: If resource reading fails
|
|
238
|
+
"""
|
|
239
|
+
if not self._initialized:
|
|
240
|
+
await self.initialize()
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
session = self.session_pool.get_session(server_name)
|
|
244
|
+
return await session.read_resource(resource_uri)
|
|
245
|
+
except KeyError:
|
|
246
|
+
logger.error(f"Server '{server_name}' not found in configuration")
|
|
247
|
+
raise
|
|
248
|
+
except Exception as e:
|
|
249
|
+
logger.error(f"Failed to read resource '{resource_uri}' from server '{server_name}': {e}")
|
|
250
|
+
raise
|
|
251
|
+
|
|
252
|
+
async def cleanup(self) -> None:
|
|
253
|
+
"""Clean up all MCP resources and close sessions.
|
|
254
|
+
|
|
255
|
+
This method properly closes all persistent sessions and cleans up resources.
|
|
256
|
+
It can be called multiple times safely.
|
|
257
|
+
"""
|
|
258
|
+
if self._initialized:
|
|
259
|
+
logger.info("Cleaning up BaseMCPClient resources")
|
|
260
|
+
cleanup_error = None
|
|
261
|
+
try:
|
|
262
|
+
await self.session_pool.close_all_sessions()
|
|
263
|
+
except TimeoutError as e:
|
|
264
|
+
cleanup_error = e
|
|
265
|
+
logger.warning(f"Timeout during BaseMCPClient cleanup: {e}")
|
|
266
|
+
except Exception as e:
|
|
267
|
+
cleanup_error = e
|
|
268
|
+
logger.error(f"Unexpected error during BaseMCPClient cleanup: {e}", exc_info=True)
|
|
269
|
+
# Don't re-raise - cleanup should be best-effort
|
|
270
|
+
finally:
|
|
271
|
+
# Always clear cache and mark as not initialized, even if session cleanup failed
|
|
272
|
+
self._tools_cache.clear()
|
|
273
|
+
self._initialized = False
|
|
274
|
+
if cleanup_error:
|
|
275
|
+
logger.info("BaseMCPClient cleanup completed (session cleanup had errors)")
|
|
276
|
+
else:
|
|
277
|
+
logger.info("BaseMCPClient cleanup completed successfully")
|
|
278
|
+
else:
|
|
279
|
+
logger.debug("BaseMCPClient cleanup called but not initialized, skipping")
|
|
280
|
+
|
|
281
|
+
@property
|
|
282
|
+
def is_initialized(self) -> bool:
|
|
283
|
+
"""Check if the client is fully initialized.
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
bool: True if sessions are initialized and tools are cached, False otherwise
|
|
287
|
+
"""
|
|
288
|
+
return self._initialized
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def active_sessions(self) -> dict[str, PersistentMCPSession]:
|
|
292
|
+
"""Get all active persistent sessions.
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
dict[str, PersistentMCPSession]: Dictionary of active sessions by server name
|
|
296
|
+
"""
|
|
297
|
+
if not self._initialized:
|
|
298
|
+
return {}
|
|
299
|
+
return self.session_pool.get_all_active_sessions()
|
|
300
|
+
|
|
301
|
+
def get_session_count(self) -> int:
|
|
302
|
+
"""Get the number of active MCP sessions.
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Number of active persistent sessions
|
|
306
|
+
"""
|
|
307
|
+
return self.session_pool.session_count
|
|
308
|
+
|
|
309
|
+
def _get_annotated_server(self, resource: MCPResource) -> str | None:
|
|
310
|
+
"""Extract server name from resource annotations if valid.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
resource (MCPResource): The MCP resource.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
str | None: Annotated server name if valid and configured, else None.
|
|
317
|
+
"""
|
|
318
|
+
if not self.servers:
|
|
319
|
+
return None
|
|
320
|
+
|
|
321
|
+
annotations = getattr(resource, "annotations", None)
|
|
322
|
+
if annotations and hasattr(annotations, "server") and annotations.server:
|
|
323
|
+
annotated = annotations.server
|
|
324
|
+
if annotated in self.servers:
|
|
325
|
+
return annotated
|
|
326
|
+
logger.warning(f"Resource annotation requested server '{annotated}' which is not configured; falling back")
|
|
327
|
+
return None
|
|
328
|
+
|
|
329
|
+
def _get_default_server(self) -> str:
|
|
330
|
+
"""Get the default server name (first configured server).
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
str: First server name.
|
|
334
|
+
|
|
335
|
+
Raises:
|
|
336
|
+
ValueError: If no servers configured.
|
|
337
|
+
"""
|
|
338
|
+
if not self.servers:
|
|
339
|
+
raise ValueError("No MCP servers configured; cannot resolve server for resource")
|
|
340
|
+
|
|
341
|
+
server_list = list(self.servers.keys())
|
|
342
|
+
if len(server_list) > 1:
|
|
343
|
+
logger.warning(
|
|
344
|
+
"Multiple MCP servers configured but resource provided no annotation; "
|
|
345
|
+
f"defaulting to first server '{server_list[0]}'"
|
|
346
|
+
)
|
|
347
|
+
return server_list[0]
|
|
348
|
+
|
|
349
|
+
def _determine_server_name_for_resource(self, resource: MCPResource) -> str:
|
|
350
|
+
"""Determine the server name for an MCP resource.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
resource (MCPResource): The MCP resource to determine server for.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
str: Server name string.
|
|
357
|
+
|
|
358
|
+
Raises:
|
|
359
|
+
ValueError: If cannot determine server.
|
|
360
|
+
"""
|
|
361
|
+
try:
|
|
362
|
+
annotated = self._get_annotated_server(resource)
|
|
363
|
+
if annotated:
|
|
364
|
+
return annotated
|
|
365
|
+
return self._get_default_server()
|
|
366
|
+
except Exception as e:
|
|
367
|
+
error_msg = f"Failed to determine server for resource {resource.uri}: {e}"
|
|
368
|
+
logger.error(error_msg)
|
|
369
|
+
raise ValueError(error_msg) from e
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from aip_agents.mcp.client.persistent_session import PersistentMCPSession as PersistentMCPSession
|
|
4
|
+
from aip_agents.mcp.client.session_pool import MCPSessionPool as MCPSessionPool
|
|
5
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
6
|
+
from gllm_tools.mcp.client.client import MCPClient
|
|
7
|
+
from gllm_tools.mcp.client.config import MCPConfiguration as MCPConfiguration
|
|
8
|
+
from mcp.types import CallToolResult, Tool as Tool
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
logger: Incomplete
|
|
12
|
+
|
|
13
|
+
class BaseMCPClient(MCPClient, ABC):
|
|
14
|
+
"""Base MCP Client with persistent session management for aip-agents.
|
|
15
|
+
|
|
16
|
+
This class provides:
|
|
17
|
+
- Persistent session management across tool calls
|
|
18
|
+
- One-time tool registration and caching
|
|
19
|
+
- Automatic connection health monitoring and reconnection
|
|
20
|
+
- Centralized cleanup of all MCP resources
|
|
21
|
+
- Generic tool discovery from all configured MCP servers
|
|
22
|
+
|
|
23
|
+
Subclasses should implement SDK-specific tool conversion in _process_tool() method.
|
|
24
|
+
"""
|
|
25
|
+
session_pool: Incomplete
|
|
26
|
+
def __init__(self, servers: dict[str, MCPConfiguration]) -> None:
|
|
27
|
+
"""Initialize the base MCP client with session pool.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
servers (dict[str, MCPConfiguration]): Dictionary of MCP server configurations by server name
|
|
31
|
+
"""
|
|
32
|
+
async def initialize(self) -> None:
|
|
33
|
+
"""Initialize all MCP sessions and cache tools once.
|
|
34
|
+
|
|
35
|
+
This method is idempotent and only performs initialization if not already done.
|
|
36
|
+
It establishes persistent connections to all configured MCP servers and caches
|
|
37
|
+
available tools for efficient access.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
Exception: If any session initialization fails
|
|
41
|
+
"""
|
|
42
|
+
@abstractmethod
|
|
43
|
+
async def get_tools(self, server: str | None = None) -> list[Any]:
|
|
44
|
+
"""Get framework-specific tools from MCP servers.
|
|
45
|
+
|
|
46
|
+
This method must be implemented by subclasses to provide framework-specific
|
|
47
|
+
tool conversion (e.g., StructuredTool for LangChain, FunctionTool for Google ADK).
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
51
|
+
If None, returns tools from all configured servers.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
list[Any]: List of framework-specific tool objects.
|
|
55
|
+
"""
|
|
56
|
+
async def get_raw_mcp_tools(self, server: str | None = None) -> list[Tool]:
|
|
57
|
+
"""Get raw MCP tools - for subclasses to perform framework-specific conversions.
|
|
58
|
+
|
|
59
|
+
This method provides access to the cached raw MCP Tool objects.
|
|
60
|
+
Subclasses use this to convert to framework-specific tools.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
64
|
+
If None, returns tools from all configured servers.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
list[Tool]: List of raw MCP Tool objects. Empty list if not initialized or no tools available.
|
|
68
|
+
"""
|
|
69
|
+
def get_tools_count(self, server: str | None = None) -> int:
|
|
70
|
+
"""Get count of raw MCP tools without expensive copying.
|
|
71
|
+
|
|
72
|
+
This is an efficient way to get tool counts for logging/metrics
|
|
73
|
+
without the overhead of copying tool lists.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
server (str | None): Optional server name to filter tools from a specific server.
|
|
77
|
+
If None, returns count from all configured servers.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
int: Count of raw MCP tools available.
|
|
81
|
+
"""
|
|
82
|
+
async def get_session(self, server_name: str) -> PersistentMCPSession:
|
|
83
|
+
"""Get a persistent session for a specific server.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
server_name (str): The name of the MCP server
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
PersistentMCPSession: Persistent MCP session for the specified server
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
KeyError: If the server is not configured or no active session exists
|
|
93
|
+
"""
|
|
94
|
+
async def call_tool(self, server_name: str, tool_name: str, arguments: dict[str, Any]) -> CallToolResult:
|
|
95
|
+
"""Execute a tool on a specific MCP server using persistent session.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
server_name (str): The MCP server to execute the tool on
|
|
99
|
+
tool_name (str): The name of the tool to execute
|
|
100
|
+
arguments (dict[str, Any]): Arguments for the tool execution
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
CallToolResult: The result of the tool execution
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
KeyError: If the server doesn't exist
|
|
107
|
+
Exception: If tool execution fails
|
|
108
|
+
"""
|
|
109
|
+
async def read_resource(self, server_name: str, resource_uri: str):
|
|
110
|
+
"""Read an MCP resource from a specific server using persistent session.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
server_name (str): The MCP server to read the resource from
|
|
114
|
+
resource_uri (str): The URI of the resource to read
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Any: The resource content
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
KeyError: If the server doesn't exist
|
|
121
|
+
Exception: If resource reading fails
|
|
122
|
+
"""
|
|
123
|
+
async def cleanup(self) -> None:
|
|
124
|
+
"""Clean up all MCP resources and close sessions.
|
|
125
|
+
|
|
126
|
+
This method properly closes all persistent sessions and cleans up resources.
|
|
127
|
+
It can be called multiple times safely.
|
|
128
|
+
"""
|
|
129
|
+
@property
|
|
130
|
+
def is_initialized(self) -> bool:
|
|
131
|
+
"""Check if the client is fully initialized.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
bool: True if sessions are initialized and tools are cached, False otherwise
|
|
135
|
+
"""
|
|
136
|
+
@property
|
|
137
|
+
def active_sessions(self) -> dict[str, PersistentMCPSession]:
|
|
138
|
+
"""Get all active persistent sessions.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
dict[str, PersistentMCPSession]: Dictionary of active sessions by server name
|
|
142
|
+
"""
|
|
143
|
+
def get_session_count(self) -> int:
|
|
144
|
+
"""Get the number of active MCP sessions.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Number of active persistent sessions
|
|
148
|
+
"""
|