fast-agent-mcp 0.2.27__tar.gz → 0.2.28__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fast-agent-mcp might be problematic. Click here for more details.

Files changed (197) hide show
  1. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/.gitignore +1 -1
  2. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/PKG-INFO +3 -1
  3. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/pyproject.toml +6 -2
  4. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/agent.py +1 -17
  5. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/base_agent.py +2 -0
  6. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/config.py +3 -0
  7. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/context.py +2 -0
  8. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/agent_app.py +7 -2
  9. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/interactive_prompt.py +58 -51
  10. fast_agent_mcp-0.2.28/src/mcp_agent/llm/augmented_llm_slow.py +42 -0
  11. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/model_factory.py +74 -37
  12. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/provider_types.py +4 -3
  13. fast_agent_mcp-0.2.28/src/mcp_agent/llm/providers/augmented_llm_google_native.py +459 -0
  14. fast_agent_mcp-0.2.27/src/mcp_agent/llm/providers/augmented_llm_google.py → fast_agent_mcp-0.2.28/src/mcp_agent/llm/providers/augmented_llm_google_oai.py +2 -2
  15. fast_agent_mcp-0.2.28/src/mcp_agent/llm/providers/google_converter.py +361 -0
  16. fast_agent_mcp-0.2.28/src/mcp_agent/mcp/helpers/server_config_helpers.py +23 -0
  17. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/mcp_agent_client_session.py +51 -24
  18. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/mcp_aggregator.py +18 -3
  19. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/mcp_connection_manager.py +6 -5
  20. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/sampling.py +40 -10
  21. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp_server_registry.py +15 -4
  22. fast_agent_mcp-0.2.28/src/mcp_agent/tools/tool_definition.py +14 -0
  23. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/LICENSE +0 -0
  24. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/README.md +0 -0
  25. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/azure-openai/fastagent.config.yaml +0 -0
  26. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/data-analysis/analysis-campaign.py +0 -0
  27. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/data-analysis/analysis.py +0 -0
  28. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/data-analysis/fastagent.config.yaml +0 -0
  29. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  30. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/state-transfer/agent_one.py +0 -0
  31. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/state-transfer/agent_two.py +0 -0
  32. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
  33. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/vision-examples/example1.py +0 -0
  34. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/vision-examples/example2.py +0 -0
  35. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/vision-examples/example3.py +0 -0
  36. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/mcp/vision-examples/fastagent.config.yaml +0 -0
  37. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/otel/agent.py +0 -0
  38. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/otel/agent2.py +0 -0
  39. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/otel/docker-compose.yaml +0 -0
  40. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/otel/fastagent.config.yaml +0 -0
  41. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/researcher/fastagent.config.yaml +0 -0
  42. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/researcher/researcher-eval.py +0 -0
  43. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/researcher/researcher-imp.py +0 -0
  44. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/researcher/researcher.py +0 -0
  45. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/README.md +0 -0
  46. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/agent.py +0 -0
  47. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/docker-compose.yml +0 -0
  48. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/fastagent.config.yaml +0 -0
  49. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/image_demo.py +0 -0
  50. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/mcp_server/mcp_server.py +0 -0
  51. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/tensorzero/simple_agent.py +0 -0
  52. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/chaining.py +0 -0
  53. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/evaluator.py +0 -0
  54. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/fastagent.config.yaml +0 -0
  55. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/graded_report.md +0 -0
  56. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/human_input.py +0 -0
  57. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/orchestrator.py +0 -0
  58. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/parallel.py +0 -0
  59. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/router.py +0 -0
  60. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/short_story.md +0 -0
  61. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/examples/workflows/short_story.txt +0 -0
  62. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/__init__.py +0 -0
  63. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/__init__.py +0 -0
  64. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/__init__.py +0 -0
  65. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/chain_agent.py +0 -0
  66. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/evaluator_optimizer.py +0 -0
  67. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/orchestrator_agent.py +0 -0
  68. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/orchestrator_models.py +0 -0
  69. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/orchestrator_prompts.py +0 -0
  70. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/parallel_agent.py +0 -0
  71. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/agents/workflow/router_agent.py +0 -0
  72. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/app.py +0 -0
  73. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/__init__.py +0 -0
  74. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/__main__.py +0 -0
  75. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/commands/check_config.py +0 -0
  76. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/commands/go.py +0 -0
  77. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/commands/quickstart.py +0 -0
  78. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/commands/setup.py +0 -0
  79. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/commands/url_parser.py +0 -0
  80. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/main.py +0 -0
  81. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/cli/terminal.py +0 -0
  82. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/console.py +0 -0
  83. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/context_dependent.py +0 -0
  84. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/__init__.py +0 -0
  85. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/agent_types.py +0 -0
  86. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/direct_decorators.py +0 -0
  87. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/direct_factory.py +0 -0
  88. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/enhanced_prompt.py +0 -0
  89. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/error_handling.py +0 -0
  90. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/exceptions.py +0 -0
  91. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/fastagent.py +0 -0
  92. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/mcp_content.py +0 -0
  93. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/prompt.py +0 -0
  94. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/request_params.py +0 -0
  95. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/core/validation.py +0 -0
  96. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/event_progress.py +0 -0
  97. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/executor/__init__.py +0 -0
  98. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/executor/executor.py +0 -0
  99. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/executor/task_registry.py +0 -0
  100. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/executor/workflow_signal.py +0 -0
  101. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/human_input/__init__.py +0 -0
  102. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/human_input/handler.py +0 -0
  103. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/human_input/types.py +0 -0
  104. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/__init__.py +0 -0
  105. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/augmented_llm.py +0 -0
  106. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/augmented_llm_passthrough.py +0 -0
  107. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/augmented_llm_playback.py +0 -0
  108. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/memory.py +0 -0
  109. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/prompt_utils.py +0 -0
  110. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/provider_key_manager.py +0 -0
  111. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/__init__.py +0 -0
  112. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/anthropic_utils.py +0 -0
  113. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -0
  114. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_azure.py +0 -0
  115. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_deepseek.py +0 -0
  116. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_generic.py +0 -0
  117. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_openai.py +0 -0
  118. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_openrouter.py +0 -0
  119. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/augmented_llm_tensorzero.py +0 -0
  120. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/multipart_converter_anthropic.py +0 -0
  121. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/multipart_converter_openai.py +0 -0
  122. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/multipart_converter_tensorzero.py +0 -0
  123. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/openai_multipart.py +0 -0
  124. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/openai_utils.py +0 -0
  125. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -0
  126. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/providers/sampling_converter_openai.py +0 -0
  127. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/sampling_converter.py +0 -0
  128. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/llm/sampling_format_converter.py +0 -0
  129. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/__init__.py +0 -0
  130. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/events.py +0 -0
  131. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/json_serializer.py +0 -0
  132. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/listeners.py +0 -0
  133. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/logger.py +0 -0
  134. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/rich_progress.py +0 -0
  135. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/logging/transport.py +0 -0
  136. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/__init__.py +0 -0
  137. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/common.py +0 -0
  138. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/gen_client.py +0 -0
  139. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/helpers/__init__.py +0 -0
  140. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/helpers/content_helpers.py +0 -0
  141. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/interfaces.py +0 -0
  142. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/logger_textio.py +0 -0
  143. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/mime_utils.py +0 -0
  144. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompt_message_multipart.py +0 -0
  145. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompt_render.py +0 -0
  146. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompt_serialization.py +0 -0
  147. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
  148. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
  149. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/prompt_constants.py +0 -0
  150. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/prompt_helpers.py +0 -0
  151. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/prompt_load.py +0 -0
  152. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/prompt_server.py +0 -0
  153. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/prompts/prompt_template.py +0 -0
  154. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp/resource_utils.py +0 -0
  155. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp_server/__init__.py +0 -0
  156. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/mcp_server/agent_server.py +0 -0
  157. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/progress_display.py +0 -0
  158. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -0
  159. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
  160. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  161. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  162. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/in_dev/agent_build.py +0 -0
  163. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/in_dev/css-LICENSE.txt +0 -0
  164. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/in_dev/slides.py +0 -0
  165. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
  166. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
  167. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/history_transfer.py +0 -0
  168. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/job.py +0 -0
  169. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/prompt_category.py +0 -0
  170. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +0 -0
  171. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/simple.txt +0 -0
  172. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/sizer.py +0 -0
  173. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/internal/social.py +0 -0
  174. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_one.py +0 -0
  175. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_two.py +0 -0
  176. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
  177. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
  178. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/__init__.py +0 -0
  179. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/agent.py +0 -0
  180. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/delimited_prompt.txt +0 -0
  181. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +0 -0
  182. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/image_server.py +0 -0
  183. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/prompt1.txt +0 -0
  184. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/prompting/work_with_image.py +0 -0
  185. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
  186. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +0 -0
  187. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +0 -0
  188. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
  189. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
  190. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/evaluator.py +0 -0
  191. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
  192. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
  193. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/orchestrator.py +0 -0
  194. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/parallel.py +0 -0
  195. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
  196. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/resources/examples/workflows/short_story.txt +0 -0
  197. {fast_agent_mcp-0.2.27 → fast_agent_mcp-0.2.28}/src/mcp_agent/ui/console_display.py +0 -0
@@ -1,4 +1,4 @@
1
- s# Byte-compiled / optimized / DLL files
1
+ # Byte-compiled / optimized / DLL files
2
2
  __pycache__/
3
3
  *.py[cod]
4
4
  *$py.class
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.2.27
3
+ Version: 0.2.28
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>
6
6
  License: Apache License
@@ -214,11 +214,13 @@ Requires-Dist: aiohttp>=3.11.13
214
214
  Requires-Dist: anthropic>=0.49.0
215
215
  Requires-Dist: azure-identity>=1.14.0
216
216
  Requires-Dist: fastapi>=0.115.6
217
+ Requires-Dist: google-genai
217
218
  Requires-Dist: mcp==1.9.1
218
219
  Requires-Dist: openai>=1.63.2
219
220
  Requires-Dist: opentelemetry-distro>=0.50b0
220
221
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.29.0
221
222
  Requires-Dist: opentelemetry-instrumentation-anthropic>=0.39.3; python_version >= '3.10' and python_version < '4.0'
223
+ Requires-Dist: opentelemetry-instrumentation-google-genai>=0.2b0
222
224
  Requires-Dist: opentelemetry-instrumentation-mcp>=0.40.3; python_version >= '3.10' and python_version < '4.0'
223
225
  Requires-Dist: opentelemetry-instrumentation-openai>=0.39.3; python_version >= '3.10' and python_version < '4.0'
224
226
  Requires-Dist: prompt-toolkit>=3.0.50
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fast-agent-mcp"
3
- version = "0.2.27"
3
+ version = "0.2.28"
4
4
  description = "Define, Prompt and Test MCP enabled Agents and Workflows"
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -31,8 +31,12 @@ dependencies = [
31
31
  "a2a-types>=0.1.0",
32
32
  "opentelemetry-instrumentation-openai>=0.39.3; python_version >= '3.10' and python_version < '4.0'",
33
33
  "opentelemetry-instrumentation-anthropic>=0.39.3; python_version >= '3.10' and python_version < '4.0'",
34
- "tensorzero>=2025.4.7",
35
34
  "opentelemetry-instrumentation-mcp>=0.40.3; python_version >= '3.10' and python_version < '4.0'",
35
+ "google-genai",
36
+ "opentelemetry-instrumentation-google-genai>=0.2b0",
37
+ "tensorzero>=2025.4.7",
38
+ "google-genai",
39
+ "opentelemetry-instrumentation-google-genai>=0.2b0",
36
40
  ]
37
41
 
38
42
  [project.optional-dependencies]
@@ -75,27 +75,11 @@ class Agent(BaseAgent):
75
75
  async def send_wrapper(message, agent_name):
76
76
  return await self.send(message)
77
77
 
78
- # Define wrapper for apply_prompt function
79
- async def apply_prompt_wrapper(prompt_name, args, agent_name):
80
- # Just apply the prompt directly
81
- return await self.apply_prompt(prompt_name, args)
82
-
83
- # Define wrapper for list_prompts function
84
- async def list_prompts_wrapper(agent_name):
85
- # Always call list_prompts on this agent regardless of agent_name
86
- return await self.list_prompts()
87
-
88
- # Define wrapper for list_resources function
89
- async def list_resources_wrapper(agent_name):
90
- # Always call list_resources on this agent regardless of agent_name
91
- return await self.list_resources()
92
-
93
78
  # Start the prompt loop with just this agent
94
79
  return await prompt.prompt_loop(
95
80
  send_func=send_wrapper,
96
81
  default_agent=agent_name_str,
97
82
  available_agents=[agent_name_str], # Only this agent
98
- apply_prompt_func=apply_prompt_wrapper,
99
- list_prompts_func=list_prompts_wrapper,
83
+ prompt_provider=self, # Pass self as the prompt provider since we implement the protocol
100
84
  default=default_prompt,
101
85
  )
@@ -456,6 +456,7 @@ class BaseAgent(MCPAggregator, AgentProtocol):
456
456
  self,
457
457
  prompt_name: str,
458
458
  arguments: Dict[str, str] | None = None,
459
+ agent_name: str | None = None,
459
460
  server_name: str | None = None,
460
461
  ) -> str:
461
462
  """
@@ -468,6 +469,7 @@ class BaseAgent(MCPAggregator, AgentProtocol):
468
469
  Args:
469
470
  prompt_name: The name of the prompt to apply
470
471
  arguments: Optional dictionary of string arguments to pass to the prompt template
472
+ agent_name: Optional agent name (ignored at this level, used by multi-agent apps)
471
473
  server_name: Optional name of the server to get the prompt from
472
474
 
473
475
  Returns:
@@ -291,6 +291,9 @@ class Settings(BaseSettings):
291
291
  Default model for agents. Format is provider.model_name.<reasoning_effort>, for example openai.o3-mini.low
292
292
  Aliases are provided for common models e.g. sonnet, haiku, gpt-4.1, o3-mini etc.
293
293
  """
294
+
295
+ auto_sampling: bool = True
296
+ """Enable automatic sampling model selection if not explicitly configured"""
294
297
 
295
298
  anthropic: AnthropicSettings | None = None
296
299
  """Settings for using Anthropic models in the fast-agent application"""
@@ -11,6 +11,7 @@ from mcp import ServerSession
11
11
  from opentelemetry import trace
12
12
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
13
13
  from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
14
+ from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
14
15
  from opentelemetry.instrumentation.mcp import McpInstrumentor
15
16
  from opentelemetry.instrumentation.openai import OpenAIInstrumentor
16
17
  from opentelemetry.propagate import set_global_textmap
@@ -112,6 +113,7 @@ async def configure_otel(config: "Settings") -> None:
112
113
  trace.set_tracer_provider(tracer_provider)
113
114
  AnthropicInstrumentor().instrument()
114
115
  OpenAIInstrumentor().instrument()
116
+ GoogleGenAiSdkInstrumentor().instrument()
115
117
  McpInstrumentor().instrument()
116
118
 
117
119
 
@@ -129,6 +129,12 @@ class AgentApp:
129
129
  Returns:
130
130
  Dictionary mapping server names to lists of available prompts
131
131
  """
132
+ if not agent_name:
133
+ results = {}
134
+ for agent in self._agents.values():
135
+ curr_prompts = await agent.list_prompts(server_name=server_name)
136
+ results.update(curr_prompts)
137
+ return results
132
138
  return await self._agent(agent_name).list_prompts(server_name=server_name)
133
139
 
134
140
  async def get_prompt(
@@ -262,7 +268,6 @@ class AgentApp:
262
268
  send_func=send_wrapper,
263
269
  default_agent=target_name, # Pass the agent name, not the agent object
264
270
  available_agents=list(self._agents.keys()),
265
- apply_prompt_func=self.apply_prompt,
266
- list_prompts_func=self.list_prompts,
271
+ prompt_provider=self, # Pass self as the prompt provider
267
272
  default=default_prompt,
268
273
  )
@@ -10,12 +10,13 @@ Usage:
10
10
  send_func=agent_app.send,
11
11
  default_agent="default_agent",
12
12
  available_agents=["agent1", "agent2"],
13
- apply_prompt_func=agent_app.apply_prompt
13
+ prompt_provider=agent_app
14
14
  )
15
15
  """
16
16
 
17
- from typing import Dict, List, Optional
17
+ from typing import Awaitable, Callable, Dict, List, Mapping, Optional, Protocol, Union
18
18
 
19
+ from mcp.types import Prompt, PromptMessage
19
20
  from rich import print as rich_print
20
21
  from rich.console import Console
21
22
  from rich.table import Table
@@ -28,8 +29,24 @@ from mcp_agent.core.enhanced_prompt import (
28
29
  handle_special_commands,
29
30
  )
30
31
  from mcp_agent.mcp.mcp_aggregator import SEP # Import SEP once at the top
32
+ from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
31
33
  from mcp_agent.progress_display import progress_display
32
34
 
35
+ # Type alias for the send function
36
+ SendFunc = Callable[[Union[str, PromptMessage, PromptMessageMultipart], str], Awaitable[str]]
37
+
38
+
39
+ class PromptProvider(Protocol):
40
+ """Protocol for objects that can provide prompt functionality."""
41
+
42
+ async def list_prompts(self, server_name: Optional[str] = None, agent_name: Optional[str] = None) -> Mapping[str, List[Prompt]]:
43
+ """List available prompts."""
44
+ ...
45
+
46
+ async def apply_prompt(self, prompt_name: str, arguments: Optional[Dict[str, str]] = None, agent_name: Optional[str] = None, **kwargs) -> str:
47
+ """Apply a prompt."""
48
+ ...
49
+
33
50
 
34
51
  class InteractivePrompt:
35
52
  """
@@ -48,22 +65,20 @@ class InteractivePrompt:
48
65
 
49
66
  async def prompt_loop(
50
67
  self,
51
- send_func,
68
+ send_func: SendFunc,
52
69
  default_agent: str,
53
70
  available_agents: List[str],
54
- apply_prompt_func=None,
55
- list_prompts_func=None,
71
+ prompt_provider: Optional[PromptProvider] = None,
56
72
  default: str = "",
57
73
  ) -> str:
58
74
  """
59
75
  Start an interactive prompt session.
60
76
 
61
77
  Args:
62
- send_func: Function to send messages to agents (signature: async (message, agent_name))
78
+ send_func: Function to send messages to agents
63
79
  default_agent: Name of the default agent to use
64
80
  available_agents: List of available agent names
65
- apply_prompt_func: Optional function to apply prompts (signature: async (name, args, agent))
66
- list_prompts_func: Optional function to list available prompts (signature: async (agent_name))
81
+ prompt_provider: Optional provider that implements list_prompts and apply_prompt
67
82
  default: Default message to use when user presses enter
68
83
 
69
84
  Returns:
@@ -110,13 +125,11 @@ class InteractivePrompt:
110
125
  rich_print(f"[red]Agent '{new_agent}' not found[/red]")
111
126
  continue
112
127
  # Keep the existing list_prompts handler for backward compatibility
113
- elif "list_prompts" in command_result and list_prompts_func:
114
- # Use the list_prompts_func directly
115
- await self._list_prompts(list_prompts_func, agent)
128
+ elif "list_prompts" in command_result and prompt_provider:
129
+ # Use the prompt_provider directly
130
+ await self._list_prompts(prompt_provider, agent)
116
131
  continue
117
- elif "select_prompt" in command_result and (
118
- list_prompts_func and apply_prompt_func
119
- ):
132
+ elif "select_prompt" in command_result and prompt_provider:
120
133
  # Handle prompt selection, using both list_prompts and apply_prompt
121
134
  prompt_name = command_result.get("prompt_name")
122
135
  prompt_index = command_result.get("prompt_index")
@@ -124,7 +137,7 @@ class InteractivePrompt:
124
137
  # If a specific index was provided (from /prompt <number>)
125
138
  if prompt_index is not None:
126
139
  # First get a list of all prompts to look up the index
127
- all_prompts = await self._get_all_prompts(list_prompts_func, agent)
140
+ all_prompts = await self._get_all_prompts(prompt_provider, agent)
128
141
  if not all_prompts:
129
142
  rich_print("[yellow]No prompts available[/yellow]")
130
143
  continue
@@ -135,8 +148,7 @@ class InteractivePrompt:
135
148
  selected_prompt = all_prompts[prompt_index - 1]
136
149
  # Use the already created namespaced_name to ensure consistency
137
150
  await self._select_prompt(
138
- list_prompts_func,
139
- apply_prompt_func,
151
+ prompt_provider,
140
152
  agent,
141
153
  selected_prompt["namespaced_name"],
142
154
  )
@@ -145,11 +157,11 @@ class InteractivePrompt:
145
157
  f"[red]Invalid prompt number: {prompt_index}. Valid range is 1-{len(all_prompts)}[/red]"
146
158
  )
147
159
  # Show the prompt list for convenience
148
- await self._list_prompts(list_prompts_func, agent)
160
+ await self._list_prompts(prompt_provider, agent)
149
161
  else:
150
162
  # Use the name-based selection
151
163
  await self._select_prompt(
152
- list_prompts_func, apply_prompt_func, agent, prompt_name
164
+ prompt_provider, agent, prompt_name
153
165
  )
154
166
  continue
155
167
 
@@ -171,21 +183,21 @@ class InteractivePrompt:
171
183
 
172
184
  return result
173
185
 
174
- async def _get_all_prompts(self, list_prompts_func, agent_name):
186
+ async def _get_all_prompts(self, prompt_provider: PromptProvider, agent_name: Optional[str] = None):
175
187
  """
176
188
  Get a list of all available prompts.
177
189
 
178
190
  Args:
179
- list_prompts_func: Function to get available prompts
180
- agent_name: Name of the agent
191
+ prompt_provider: Provider that implements list_prompts
192
+ agent_name: Optional agent name (for multi-agent apps)
181
193
 
182
194
  Returns:
183
195
  List of prompt info dictionaries, sorted by server and name
184
196
  """
185
197
  try:
186
- # Pass None instead of agent_name to get prompts from all servers
187
- # the agent_name parameter should never be used as a server name
188
- prompt_servers = await list_prompts_func(None)
198
+ # Call list_prompts on the provider
199
+ prompt_servers = await prompt_provider.list_prompts(server_name=None, agent_name=agent_name)
200
+
189
201
  all_prompts = []
190
202
 
191
203
  # Process the returned prompt servers
@@ -219,14 +231,18 @@ class InteractivePrompt:
219
231
  }
220
232
  )
221
233
  else:
234
+ # Handle Prompt objects from mcp.types
235
+ prompt_name = getattr(prompt, "name", str(prompt))
236
+ description = getattr(prompt, "description", "No description")
237
+ arguments = getattr(prompt, "arguments", [])
222
238
  all_prompts.append(
223
239
  {
224
240
  "server": server_name,
225
- "name": str(prompt),
226
- "namespaced_name": f"{server_name}{SEP}{str(prompt)}",
227
- "description": "No description",
228
- "arg_count": 0,
229
- "arguments": [],
241
+ "name": prompt_name,
242
+ "namespaced_name": f"{server_name}{SEP}{prompt_name}",
243
+ "description": description,
244
+ "arg_count": len(arguments),
245
+ "arguments": arguments,
230
246
  }
231
247
  )
232
248
 
@@ -244,27 +260,22 @@ class InteractivePrompt:
244
260
  rich_print(f"[dim]{traceback.format_exc()}[/dim]")
245
261
  return []
246
262
 
247
- async def _list_prompts(self, list_prompts_func, agent_name) -> None:
263
+ async def _list_prompts(self, prompt_provider: PromptProvider, agent_name: str) -> None:
248
264
  """
249
265
  List available prompts for an agent.
250
266
 
251
267
  Args:
252
- list_prompts_func: Function to get available prompts
268
+ prompt_provider: Provider that implements list_prompts
253
269
  agent_name: Name of the agent
254
270
  """
255
- from rich import print as rich_print
256
- from rich.console import Console
257
- from rich.table import Table
258
-
259
271
  console = Console()
260
272
 
261
273
  try:
262
274
  # Directly call the list_prompts function for this agent
263
275
  rich_print(f"\n[bold]Fetching prompts for agent [cyan]{agent_name}[/cyan]...[/bold]")
264
276
 
265
- # Get all prompts using the helper function - pass None as server name
266
- # to get prompts from all available servers
267
- all_prompts = await self._get_all_prompts(list_prompts_func, None)
277
+ # Get all prompts using the helper function
278
+ all_prompts = await self._get_all_prompts(prompt_provider, agent_name)
268
279
 
269
280
  if all_prompts:
270
281
  # Create a table for better display
@@ -300,28 +311,24 @@ class InteractivePrompt:
300
311
  rich_print(f"[dim]{traceback.format_exc()}[/dim]")
301
312
 
302
313
  async def _select_prompt(
303
- self, list_prompts_func, apply_prompt_func, agent_name, requested_name=None
314
+ self, prompt_provider: PromptProvider, agent_name: str, requested_name: Optional[str] = None
304
315
  ) -> None:
305
316
  """
306
317
  Select and apply a prompt.
307
318
 
308
319
  Args:
309
- list_prompts_func: Function to get available prompts
310
- apply_prompt_func: Function to apply prompts
320
+ prompt_provider: Provider that implements list_prompts and apply_prompt
311
321
  agent_name: Name of the agent
312
322
  requested_name: Optional name of the prompt to apply
313
323
  """
314
- # We already imported these at the top
315
- from rich import print as rich_print
316
-
317
324
  console = Console()
318
325
 
319
326
  try:
320
- # Get all available prompts directly from the list_prompts function
327
+ # Get all available prompts directly from the prompt provider
321
328
  rich_print(f"\n[bold]Fetching prompts for agent [cyan]{agent_name}[/cyan]...[/bold]")
322
- # IMPORTANT: list_prompts_func gets MCP server prompts, not agent prompts
323
- # So we pass None to get prompts from all servers, not using agent_name as server name
324
- prompt_servers = await list_prompts_func(None)
329
+
330
+ # Call list_prompts on the provider
331
+ prompt_servers = await prompt_provider.list_prompts(server_name=None, agent_name=agent_name)
325
332
 
326
333
  if not prompt_servers:
327
334
  rich_print("[yellow]No prompts available for this agent[/yellow]")
@@ -542,8 +549,8 @@ class InteractivePrompt:
542
549
  namespaced_name = selected_prompt["namespaced_name"]
543
550
  rich_print(f"\n[bold]Applying prompt [cyan]{namespaced_name}[/cyan]...[/bold]")
544
551
 
545
- # Call apply_prompt function with the prompt name and arguments
546
- await apply_prompt_func(namespaced_name, arg_values, agent_name)
552
+ # Call apply_prompt on the provider with the prompt name and arguments
553
+ await prompt_provider.apply_prompt(namespaced_name, arg_values, agent_name)
547
554
 
548
555
  except Exception as e:
549
556
  import traceback
@@ -0,0 +1,42 @@
1
+ import asyncio
2
+ from typing import Any, List, Optional, Union
3
+
4
+ from mcp_agent.llm.augmented_llm import (
5
+ MessageParamT,
6
+ RequestParams,
7
+ )
8
+ from mcp_agent.llm.augmented_llm_passthrough import PassthroughLLM
9
+ from mcp_agent.llm.provider_types import Provider
10
+ from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
11
+
12
+
13
+ class SlowLLM(PassthroughLLM):
14
+ """
15
+ A specialized LLM implementation that sleeps for 3 seconds before responding like PassthroughLLM.
16
+
17
+ This is useful for testing scenarios where you want to simulate slow responses
18
+ or for debugging timing-related issues in parallel workflows.
19
+ """
20
+
21
+ def __init__(
22
+ self, provider=Provider.FAST_AGENT, name: str = "Slow", **kwargs: dict[str, Any]
23
+ ) -> None:
24
+ super().__init__(name=name, provider=provider, **kwargs)
25
+
26
+ async def generate_str(
27
+ self,
28
+ message: Union[str, MessageParamT, List[MessageParamT]],
29
+ request_params: Optional[RequestParams] = None,
30
+ ) -> str:
31
+ """Sleep for 3 seconds then return the input message as a string."""
32
+ await asyncio.sleep(3)
33
+ return await super().generate_str(message, request_params)
34
+
35
+ async def _apply_prompt_provider_specific(
36
+ self,
37
+ multipart_messages: List["PromptMessageMultipart"],
38
+ request_params: RequestParams | None = None,
39
+ ) -> PromptMessageMultipart:
40
+ """Sleep for 3 seconds then apply prompt like PassthroughLLM."""
41
+ await asyncio.sleep(3)
42
+ return await super()._apply_prompt_provider_specific(multipart_messages, request_params)
@@ -8,12 +8,14 @@ from mcp_agent.core.exceptions import ModelConfigError
8
8
  from mcp_agent.core.request_params import RequestParams
9
9
  from mcp_agent.llm.augmented_llm_passthrough import PassthroughLLM
10
10
  from mcp_agent.llm.augmented_llm_playback import PlaybackLLM
11
+ from mcp_agent.llm.augmented_llm_slow import SlowLLM
11
12
  from mcp_agent.llm.provider_types import Provider
12
13
  from mcp_agent.llm.providers.augmented_llm_anthropic import AnthropicAugmentedLLM
13
14
  from mcp_agent.llm.providers.augmented_llm_azure import AzureOpenAIAugmentedLLM
14
15
  from mcp_agent.llm.providers.augmented_llm_deepseek import DeepSeekAugmentedLLM
15
16
  from mcp_agent.llm.providers.augmented_llm_generic import GenericAugmentedLLM
16
- from mcp_agent.llm.providers.augmented_llm_google import GoogleAugmentedLLM
17
+ from mcp_agent.llm.providers.augmented_llm_google_native import GoogleNativeAugmentedLLM
18
+ from mcp_agent.llm.providers.augmented_llm_google_oai import GoogleOaiAugmentedLLM
17
19
  from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
18
20
  from mcp_agent.llm.providers.augmented_llm_openrouter import OpenRouterAugmentedLLM
19
21
  from mcp_agent.llm.providers.augmented_llm_tensorzero import TensorZeroAugmentedLLM
@@ -28,9 +30,13 @@ LLMClass = Union[
28
30
  Type[OpenAIAugmentedLLM],
29
31
  Type[PassthroughLLM],
30
32
  Type[PlaybackLLM],
33
+ Type[SlowLLM],
31
34
  Type[DeepSeekAugmentedLLM],
32
35
  Type[OpenRouterAugmentedLLM],
33
36
  Type[TensorZeroAugmentedLLM],
37
+ Type[GoogleNativeAugmentedLLM],
38
+ Type[GenericAugmentedLLM],
39
+ Type[AzureOpenAIAugmentedLLM],
34
40
  ]
35
41
 
36
42
 
@@ -60,13 +66,16 @@ class ModelFactory:
60
66
  "high": ReasoningEffort.HIGH,
61
67
  }
62
68
 
63
- # TODO -- add context window size information for display/management
64
- # TODO -- add audio supporting got-4o-audio-preview
65
- # TODO -- bring model parameter configuration here
66
- # Mapping of model names to their default providers
69
+ """
70
+ TODO -- add context window size information for display/management
71
+ TODO -- add audio supporting got-4o-audio-preview
72
+ TODO -- bring model parameter configuration here
73
+ Mapping of model names to their default providers
74
+ """
67
75
  DEFAULT_PROVIDERS = {
68
76
  "passthrough": Provider.FAST_AGENT,
69
77
  "playback": Provider.FAST_AGENT,
78
+ "slow": Provider.FAST_AGENT,
70
79
  "gpt-4o": Provider.OPENAI,
71
80
  "gpt-4o-mini": Provider.OPENAI,
72
81
  "gpt-4.1": Provider.OPENAI,
@@ -91,7 +100,9 @@ class ModelFactory:
91
100
  "claude-sonnet-4-20250514": Provider.ANTHROPIC,
92
101
  "claude-sonnet-4-0": Provider.ANTHROPIC,
93
102
  "deepseek-chat": Provider.DEEPSEEK,
94
- # "deepseek-reasoner": Provider.DEEPSEEK, reinstate on release
103
+ "gemini-2.0-flash": Provider.GOOGLE,
104
+ "gemini-2.5-flash-preview-05-20": Provider.GOOGLE,
105
+ "gemini-2.5-pro-preview-05-06": Provider.GOOGLE,
95
106
  }
96
107
 
97
108
  MODEL_ALIASES = {
@@ -108,6 +119,9 @@ class ModelFactory:
108
119
  "opus3": "claude-3-opus-latest",
109
120
  "deepseekv3": "deepseek-chat",
110
121
  "deepseek": "deepseek-chat",
122
+ "gemini2": "gemini-2.0-flash",
123
+ "gemini25": "gemini-2.5-flash-preview-05-20",
124
+ "gemini25pro": "gemini-2.5-pro-preview-05-06",
111
125
  }
112
126
 
113
127
  # Mapping of providers to their LLM classes
@@ -117,7 +131,8 @@ class ModelFactory:
117
131
  Provider.FAST_AGENT: PassthroughLLM,
118
132
  Provider.DEEPSEEK: DeepSeekAugmentedLLM,
119
133
  Provider.GENERIC: GenericAugmentedLLM,
120
- Provider.GOOGLE: GoogleAugmentedLLM, # type: ignore
134
+ Provider.GOOGLE_OAI: GoogleOaiAugmentedLLM,
135
+ Provider.GOOGLE: GoogleNativeAugmentedLLM,
121
136
  Provider.OPENROUTER: OpenRouterAugmentedLLM,
122
137
  Provider.TENSORZERO: TensorZeroAugmentedLLM,
123
138
  Provider.AZURE: AzureOpenAIAugmentedLLM,
@@ -127,48 +142,66 @@ class ModelFactory:
127
142
  # This overrides the provider-based class selection
128
143
  MODEL_SPECIFIC_CLASSES: Dict[str, LLMClass] = {
129
144
  "playback": PlaybackLLM,
145
+ "slow": SlowLLM,
130
146
  }
131
147
 
132
148
  @classmethod
133
149
  def parse_model_string(cls, model_string: str) -> ModelConfig:
134
150
  """Parse a model string into a ModelConfig object"""
135
- # Check if model string is an alias
136
151
  model_string = cls.MODEL_ALIASES.get(model_string, model_string)
137
152
  parts = model_string.split(".")
138
153
 
139
- # Start with all parts as the model name
140
- model_parts = parts.copy()
154
+ model_name_str = model_string # Default full string as model name initially
141
155
  provider = None
142
156
  reasoning_effort = None
157
+ parts_for_provider_model = []
143
158
 
144
- # Check last part for reasoning effort
159
+ # Check for reasoning effort first (last part)
145
160
  if len(parts) > 1 and parts[-1].lower() in cls.EFFORT_MAP:
146
161
  reasoning_effort = cls.EFFORT_MAP[parts[-1].lower()]
147
- model_parts = model_parts[:-1]
162
+ # Remove effort from parts list for provider/model name determination
163
+ parts_for_provider_model = parts[:-1]
164
+ else:
165
+ parts_for_provider_model = parts[:]
166
+
167
+ # Try to match longest possible provider string
168
+ identified_provider_parts = 0 # How many parts belong to the provider string
169
+
170
+ if len(parts_for_provider_model) >= 2:
171
+ potential_provider_str = f"{parts_for_provider_model[0]}.{parts_for_provider_model[1]}"
172
+ if any(p.value == potential_provider_str for p in Provider):
173
+ provider = Provider(potential_provider_str)
174
+ identified_provider_parts = 2
175
+
176
+ if provider is None and len(parts_for_provider_model) >= 1:
177
+ potential_provider_str = parts_for_provider_model[0]
178
+ if any(p.value == potential_provider_str for p in Provider):
179
+ provider = Provider(potential_provider_str)
180
+ identified_provider_parts = 1
181
+
182
+ # Construct model_name from remaining parts
183
+ if identified_provider_parts > 0:
184
+ model_name_str = ".".join(parts_for_provider_model[identified_provider_parts:])
185
+ else:
186
+ # If no provider prefix was matched, the whole string (after effort removal) is the model name
187
+ model_name_str = ".".join(parts_for_provider_model)
148
188
 
149
- # Check first part for provider
150
- if len(model_parts) > 1:
151
- potential_provider = model_parts[0]
152
- if any(provider.value == potential_provider for provider in Provider):
153
- provider = Provider(potential_provider)
154
- model_parts = model_parts[1:]
189
+ # If provider still None, try to get from DEFAULT_PROVIDERS using the model_name_str
190
+ if provider is None:
191
+ provider = cls.DEFAULT_PROVIDERS.get(model_name_str)
192
+ if provider is None:
193
+ raise ModelConfigError(
194
+ f"Unknown model or provider for: {model_string}. Model name parsed as '{model_name_str}'"
195
+ )
155
196
 
156
- if provider == Provider.TENSORZERO and not model_parts:
197
+ if provider == Provider.TENSORZERO and not model_name_str:
157
198
  raise ModelConfigError(
158
199
  f"TensorZero provider requires a function name after the provider "
159
200
  f"(e.g., tensorzero.my-function), got: {model_string}"
160
201
  )
161
- # Join remaining parts as model name
162
- model_name = ".".join(model_parts)
163
-
164
- # If no provider was found in the string, look it up in defaults
165
- if provider is None:
166
- provider = cls.DEFAULT_PROVIDERS.get(model_name)
167
- if provider is None:
168
- raise ModelConfigError(f"Unknown model: {model_name}")
169
202
 
170
203
  return ModelConfig(
171
- provider=provider, model_name=model_name, reasoning_effort=reasoning_effort
204
+ provider=provider, model_name=model_name_str, reasoning_effort=reasoning_effort
172
205
  )
173
206
 
174
207
  @classmethod
@@ -185,33 +218,37 @@ class ModelFactory:
185
218
  Returns:
186
219
  A callable that takes an agent parameter and returns an LLM instance
187
220
  """
188
- # Parse configuration up front
189
221
  config = cls.parse_model_string(model_string)
222
+
223
+ # Ensure provider is valid before trying to access PROVIDER_CLASSES with it
224
+ if (
225
+ config.provider not in cls.PROVIDER_CLASSES
226
+ and config.model_name not in cls.MODEL_SPECIFIC_CLASSES
227
+ ):
228
+ # This check is important if a provider (like old GOOGLE) is commented out from PROVIDER_CLASSES
229
+ raise ModelConfigError(
230
+ f"Provider '{config.provider}' not configured in PROVIDER_CLASSES and model '{config.model_name}' not in MODEL_SPECIFIC_CLASSES."
231
+ )
232
+
190
233
  if config.model_name in cls.MODEL_SPECIFIC_CLASSES:
191
234
  llm_class = cls.MODEL_SPECIFIC_CLASSES[config.model_name]
192
235
  else:
236
+ # This line is now safer due to the check above
193
237
  llm_class = cls.PROVIDER_CLASSES[config.provider]
194
238
 
195
- # Create a factory function matching the updated attach_llm protocol
196
239
  def factory(
197
240
  agent: Agent, request_params: Optional[RequestParams] = None, **kwargs
198
241
  ) -> AugmentedLLMProtocol:
199
- # Create base params with parsed model name
200
242
  base_params = RequestParams()
201
- base_params.model = config.model_name # Use the parsed model name, not the alias
202
-
203
- # Add reasoning effort if available
243
+ base_params.model = config.model_name
204
244
  if config.reasoning_effort:
205
245
  kwargs["reasoning_effort"] = config.reasoning_effort.value
206
-
207
- # Forward all arguments to LLM constructor
208
246
  llm_args = {
209
247
  "agent": agent,
210
248
  "model": config.model_name,
211
249
  "request_params": request_params,
212
250
  **kwargs,
213
251
  }
214
-
215
252
  llm: AugmentedLLMProtocol = llm_class(**llm_args)
216
253
  return llm
217
254