fast-agent-mcp 0.2.22__tar.gz → 0.2.24__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/.gitignore +2 -3
  2. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/PKG-INFO +3 -2
  3. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/pyproject.toml +2 -2
  4. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/orchestrator_agent.py +2 -2
  5. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/commands/go.py +94 -29
  6. fast_agent_mcp-0.2.24/src/mcp_agent/cli/commands/url_parser.py +185 -0
  7. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/config.py +3 -1
  8. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/context.py +2 -0
  9. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/fastagent.py +2 -2
  10. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/request_params.py +5 -6
  11. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_openai.py +3 -1
  12. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/mcp_agent_client_session.py +41 -11
  13. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/mcp_aggregator.py +133 -2
  14. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/mcp_connection_manager.py +33 -7
  15. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/prompt_server.py +12 -4
  16. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp_server/agent_server.py +13 -10
  17. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp_server_registry.py +51 -9
  18. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +2 -2
  19. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/ui/console_display.py +7 -6
  20. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/LICENSE +0 -0
  21. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/README.md +0 -0
  22. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/data-analysis/analysis-campaign.py +0 -0
  23. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/data-analysis/analysis.py +0 -0
  24. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/data-analysis/fastagent.config.yaml +0 -0
  25. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  26. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/state-transfer/agent_one.py +0 -0
  27. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/state-transfer/agent_two.py +0 -0
  28. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
  29. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/vision-examples/example1.py +0 -0
  30. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/vision-examples/example2.py +0 -0
  31. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/vision-examples/example3.py +0 -0
  32. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/mcp/vision-examples/fastagent.config.yaml +0 -0
  33. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/otel/agent.py +0 -0
  34. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/otel/agent2.py +0 -0
  35. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/otel/docker-compose.yaml +0 -0
  36. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/otel/fastagent.config.yaml +0 -0
  37. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/researcher/fastagent.config.yaml +0 -0
  38. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/researcher/researcher-eval.py +0 -0
  39. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/researcher/researcher-imp.py +0 -0
  40. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/researcher/researcher.py +0 -0
  41. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/README.md +0 -0
  42. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/agent.py +0 -0
  43. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/docker-compose.yml +0 -0
  44. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/fastagent.config.yaml +0 -0
  45. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/image_demo.py +0 -0
  46. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/mcp_server/mcp_server.py +0 -0
  47. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/tensorzero/simple_agent.py +0 -0
  48. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/chaining.py +0 -0
  49. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/evaluator.py +0 -0
  50. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/fastagent.config.yaml +0 -0
  51. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/graded_report.md +0 -0
  52. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/human_input.py +0 -0
  53. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/orchestrator.py +0 -0
  54. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/parallel.py +0 -0
  55. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/router.py +0 -0
  56. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/short_story.md +0 -0
  57. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/examples/workflows/short_story.txt +0 -0
  58. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/__init__.py +0 -0
  59. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/__init__.py +0 -0
  60. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/agent.py +0 -0
  61. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/base_agent.py +0 -0
  62. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/__init__.py +0 -0
  63. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/chain_agent.py +0 -0
  64. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/evaluator_optimizer.py +0 -0
  65. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/orchestrator_models.py +0 -0
  66. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/orchestrator_prompts.py +0 -0
  67. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/parallel_agent.py +0 -0
  68. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/agents/workflow/router_agent.py +0 -0
  69. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/app.py +0 -0
  70. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/__init__.py +0 -0
  71. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/__main__.py +0 -0
  72. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/commands/check_config.py +0 -0
  73. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/commands/quickstart.py +0 -0
  74. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/commands/setup.py +0 -0
  75. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/main.py +0 -0
  76. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/cli/terminal.py +0 -0
  77. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/console.py +0 -0
  78. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/context_dependent.py +0 -0
  79. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/__init__.py +0 -0
  80. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/agent_app.py +0 -0
  81. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/agent_types.py +0 -0
  82. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/direct_decorators.py +0 -0
  83. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/direct_factory.py +0 -0
  84. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/enhanced_prompt.py +0 -0
  85. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/error_handling.py +0 -0
  86. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/exceptions.py +0 -0
  87. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/interactive_prompt.py +0 -0
  88. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/mcp_content.py +0 -0
  89. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/prompt.py +0 -0
  90. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/core/validation.py +0 -0
  91. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/event_progress.py +0 -0
  92. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/executor/__init__.py +0 -0
  93. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/executor/executor.py +0 -0
  94. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/executor/task_registry.py +0 -0
  95. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/executor/workflow_signal.py +0 -0
  96. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/human_input/__init__.py +0 -0
  97. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/human_input/handler.py +0 -0
  98. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/human_input/types.py +0 -0
  99. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/__init__.py +0 -0
  100. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/augmented_llm.py +0 -0
  101. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/augmented_llm_passthrough.py +0 -0
  102. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/augmented_llm_playback.py +0 -0
  103. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/memory.py +0 -0
  104. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/model_factory.py +0 -0
  105. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/prompt_utils.py +0 -0
  106. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/provider_key_manager.py +0 -0
  107. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/provider_types.py +0 -0
  108. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/__init__.py +0 -0
  109. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/anthropic_utils.py +0 -0
  110. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -0
  111. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_deepseek.py +0 -0
  112. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_generic.py +0 -0
  113. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_google.py +0 -0
  114. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_openrouter.py +0 -0
  115. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/augmented_llm_tensorzero.py +0 -0
  116. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/multipart_converter_anthropic.py +0 -0
  117. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/multipart_converter_openai.py +0 -0
  118. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/multipart_converter_tensorzero.py +0 -0
  119. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/openai_multipart.py +0 -0
  120. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/openai_utils.py +0 -0
  121. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -0
  122. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/providers/sampling_converter_openai.py +0 -0
  123. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/sampling_converter.py +0 -0
  124. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/llm/sampling_format_converter.py +0 -0
  125. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/__init__.py +0 -0
  126. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/events.py +0 -0
  127. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/json_serializer.py +0 -0
  128. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/listeners.py +0 -0
  129. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/logger.py +0 -0
  130. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/rich_progress.py +0 -0
  131. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/logging/transport.py +0 -0
  132. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/__init__.py +0 -0
  133. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/gen_client.py +0 -0
  134. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/helpers/__init__.py +0 -0
  135. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/helpers/content_helpers.py +0 -0
  136. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/interfaces.py +0 -0
  137. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/logger_textio.py +0 -0
  138. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/mime_utils.py +0 -0
  139. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompt_message_multipart.py +0 -0
  140. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompt_render.py +0 -0
  141. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompt_serialization.py +0 -0
  142. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
  143. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
  144. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/prompt_constants.py +0 -0
  145. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/prompt_helpers.py +0 -0
  146. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/prompt_load.py +0 -0
  147. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/prompts/prompt_template.py +0 -0
  148. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/resource_utils.py +0 -0
  149. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp/sampling.py +0 -0
  150. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/mcp_server/__init__.py +0 -0
  151. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/progress_display.py +0 -0
  152. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -0
  153. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
  154. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  155. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  156. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/in_dev/agent_build.py +0 -0
  157. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/in_dev/css-LICENSE.txt +0 -0
  158. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/in_dev/slides.py +0 -0
  159. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
  160. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
  161. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/history_transfer.py +0 -0
  162. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/job.py +0 -0
  163. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/prompt_category.py +0 -0
  164. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +0 -0
  165. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/simple.txt +0 -0
  166. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/sizer.py +0 -0
  167. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/internal/social.py +0 -0
  168. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_one.py +0 -0
  169. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_two.py +0 -0
  170. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
  171. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/__init__.py +0 -0
  172. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/agent.py +0 -0
  173. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/delimited_prompt.txt +0 -0
  174. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +0 -0
  175. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/image_server.py +0 -0
  176. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/prompt1.txt +0 -0
  177. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/prompting/work_with_image.py +0 -0
  178. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
  179. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +0 -0
  180. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +0 -0
  181. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
  182. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
  183. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/evaluator.py +0 -0
  184. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
  185. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
  186. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/orchestrator.py +0 -0
  187. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/parallel.py +0 -0
  188. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
  189. {fast_agent_mcp-0.2.22 → fast_agent_mcp-0.2.24}/src/mcp_agent/resources/examples/workflows/short_story.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Byte-compiled / optimized / DLL files
1
+ s# Byte-compiled / optimized / DLL files
2
2
  __pycache__/
3
3
  *.py[cod]
4
4
  *$py.class
@@ -197,6 +197,5 @@ tests/integration/prompt-state/history.json
197
197
  !tests/integration/api/fastagent.secrets.yaml
198
198
  fastagent.jsonl
199
199
 
200
- # JetBrains IDEs
201
- .idea/
202
200
  tests/e2e/smoke/base/weather_location.txt
201
+ tests/integration/roots/fastagent.jsonl
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.2.22
3
+ Version: 0.2.24
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
- Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
5
+ Author-email: Shaun Smith <fastagent@llmindset.co.uk>
6
6
  License: Apache License
7
7
  Version 2.0, January 2004
8
8
  http://www.apache.org/licenses/
@@ -218,6 +218,7 @@ Requires-Dist: openai>=1.63.2
218
218
  Requires-Dist: opentelemetry-distro>=0.50b0
219
219
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.29.0
220
220
  Requires-Dist: opentelemetry-instrumentation-anthropic>=0.39.3
221
+ Requires-Dist: opentelemetry-instrumentation-mcp>=0.40.3
221
222
  Requires-Dist: opentelemetry-instrumentation-openai>=0.39.3
222
223
  Requires-Dist: prompt-toolkit>=3.0.50
223
224
  Requires-Dist: pydantic-settings>=2.7.0
@@ -1,12 +1,11 @@
1
1
  [project]
2
2
  name = "fast-agent-mcp"
3
- version = "0.2.22"
3
+ version = "0.2.24"
4
4
  description = "Define, Prompt and Test MCP enabled Agents and Workflows"
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
7
7
  authors = [
8
8
  { name = "Shaun Smith", email = "fastagent@llmindset.co.uk"},
9
- { name = "Sarmad Qadri", email = "sarmad@lastmileai.dev" }
10
9
  ]
11
10
  classifiers = [
12
11
  "Programming Language :: Python :: 3",
@@ -32,6 +31,7 @@ dependencies = [
32
31
  "opentelemetry-instrumentation-openai>=0.39.3",
33
32
  "opentelemetry-instrumentation-anthropic>=0.39.3",
34
33
  "tensorzero>=2025.4.7",
34
+ "opentelemetry-instrumentation-mcp>=0.40.3",
35
35
  ]
36
36
 
37
37
  [project.optional-dependencies]
@@ -229,7 +229,7 @@ class OrchestratorAgent(BaseAgent):
229
229
  self.logger.warning(
230
230
  f"Reached maximum step limit ({max_steps}) without completing objective"
231
231
  )
232
- plan_result.max_steps_reached = True
232
+ plan_result.max_iterations_reached = True
233
233
  break
234
234
 
235
235
  # Execute the step and collect results
@@ -239,7 +239,7 @@ class OrchestratorAgent(BaseAgent):
239
239
  total_steps_executed += 1
240
240
 
241
241
  # Check if we need to break due to hitting max steps
242
- if getattr(plan_result, "max_steps_reached", False):
242
+ if getattr(plan_result, "max_iterations_reached", False):
243
243
  break
244
244
 
245
245
  # If the plan is marked complete, finalize the result
@@ -2,16 +2,18 @@
2
2
 
3
3
  import asyncio
4
4
  import sys
5
- from typing import List, Optional
5
+ from typing import Dict, List, Optional
6
6
 
7
7
  import typer
8
8
 
9
+ from mcp_agent.cli.commands.url_parser import generate_server_configs, parse_server_urls
9
10
  from mcp_agent.core.fastagent import FastAgent
10
11
 
11
12
  app = typer.Typer(
12
13
  help="Run an interactive agent directly from the command line without creating an agent.py file"
13
14
  )
14
15
 
16
+
15
17
  async def _run_agent(
16
18
  name: str = "FastAgent CLI",
17
19
  instruction: str = "You are a helpful AI Agent.",
@@ -19,33 +21,61 @@ async def _run_agent(
19
21
  server_list: Optional[List[str]] = None,
20
22
  model: Optional[str] = None,
21
23
  message: Optional[str] = None,
22
- prompt_file: Optional[str] = None
24
+ prompt_file: Optional[str] = None,
25
+ url_servers: Optional[Dict[str, Dict[str, str]]] = None,
23
26
  ) -> None:
24
27
  """Async implementation to run an interactive agent."""
25
28
  from pathlib import Path
26
29
 
30
+ from mcp_agent.config import MCPServerSettings, MCPSettings
27
31
  from mcp_agent.mcp.prompts.prompt_load import load_prompt_multipart
28
32
 
29
- # Create the FastAgent instance with CLI arg parsing enabled
30
- # It will automatically parse args like --model, --quiet, etc.
33
+ # Create the FastAgent instance
31
34
  fast_kwargs = {
32
35
  "name": name,
33
36
  "config_path": config_path,
34
37
  "ignore_unknown_args": True,
35
38
  "parse_cli_args": False, # Don't parse CLI args, we're handling it ourselves
36
39
  }
37
-
40
+
38
41
  fast = FastAgent(**fast_kwargs)
39
42
 
43
+ # Add URL-based servers to the context configuration
44
+ if url_servers:
45
+ # Initialize the app to ensure context is ready
46
+ await fast.app.initialize()
47
+
48
+ # Initialize mcp settings if needed
49
+ if not hasattr(fast.app.context.config, "mcp"):
50
+ fast.app.context.config.mcp = MCPSettings()
51
+
52
+ # Initialize servers dictionary if needed
53
+ if (
54
+ not hasattr(fast.app.context.config.mcp, "servers")
55
+ or fast.app.context.config.mcp.servers is None
56
+ ):
57
+ fast.app.context.config.mcp.servers = {}
58
+
59
+ # Add each URL server to the config
60
+ for server_name, server_config in url_servers.items():
61
+ server_settings = {"transport": server_config["transport"], "url": server_config["url"]}
62
+
63
+ # Add headers if present in the server config
64
+ if "headers" in server_config:
65
+ server_settings["headers"] = server_config["headers"]
66
+
67
+ fast.app.context.config.mcp.servers[server_name] = MCPServerSettings(**server_settings)
68
+
40
69
  # Define the agent with specified parameters
41
70
  agent_kwargs = {"instruction": instruction}
42
71
  if server_list:
43
72
  agent_kwargs["servers"] = server_list
44
73
  if model:
45
74
  agent_kwargs["model"] = model
46
-
75
+
47
76
  # Handle prompt file and message options
48
77
  if message or prompt_file:
78
+
49
79
  @fast.agent(**agent_kwargs)
50
80
  async def cli_agent():
51
81
  async with fast.run() as agent:
@@ -55,7 +85,7 @@ async def _run_agent(
55
85
  print(response)
56
86
  elif prompt_file:
57
87
  prompt = load_prompt_multipart(Path(prompt_file))
58
- response = await agent.generate(prompt)
88
+ response = await agent.default.generate(prompt)
59
89
  # Print the response text and exit
60
90
  print(response.last_text())
61
91
  else:
@@ -68,18 +98,37 @@ async def _run_agent(
68
98
  # Run the agent
69
99
  await cli_agent()
70
100
 
101
+
71
102
  def run_async_agent(
72
- name: str,
73
- instruction: str,
74
- config_path: Optional[str] = None,
103
+ name: str,
104
+ instruction: str,
105
+ config_path: Optional[str] = None,
75
106
  servers: Optional[str] = None,
107
+ urls: Optional[str] = None,
108
+ auth: Optional[str] = None,
76
109
  model: Optional[str] = None,
77
110
  message: Optional[str] = None,
78
- prompt_file: Optional[str] = None
111
+ prompt_file: Optional[str] = None,
79
112
  ):
80
113
  """Run the async agent function with proper loop handling."""
81
- server_list = servers.split(',') if servers else None
82
-
114
+ server_list = servers.split(",") if servers else None
115
+
116
+ # Parse URLs and generate server configurations if provided
117
+ url_servers = None
118
+ if urls:
119
+ try:
120
+ parsed_urls = parse_server_urls(urls, auth)
121
+ url_servers = generate_server_configs(parsed_urls)
122
+ # If we have servers from URLs, add their names to the server_list
123
+ if url_servers and not server_list:
124
+ server_list = list(url_servers.keys())
125
+ elif url_servers and server_list:
126
+ # Merge both lists
127
+ server_list.extend(list(url_servers.keys()))
128
+ except ValueError as e:
129
+ print(f"Error parsing URLs: {e}")
130
+ return
131
+
83
132
  # Check if we're already in an event loop
84
133
  try:
85
134
  loop = asyncio.get_event_loop()
@@ -92,24 +141,27 @@ def run_async_agent(
92
141
  # No event loop exists, so we'll create one
93
142
  loop = asyncio.new_event_loop()
94
143
  asyncio.set_event_loop(loop)
95
-
144
+
96
145
  try:
97
- loop.run_until_complete(_run_agent(
98
- name=name,
99
- instruction=instruction,
100
- config_path=config_path,
101
- server_list=server_list,
102
- model=model,
103
- message=message,
104
- prompt_file=prompt_file
105
- ))
146
+ loop.run_until_complete(
147
+ _run_agent(
148
+ name=name,
149
+ instruction=instruction,
150
+ config_path=config_path,
151
+ server_list=server_list,
152
+ model=model,
153
+ message=message,
154
+ prompt_file=prompt_file,
155
+ url_servers=url_servers,
156
+ )
157
+ )
106
158
  finally:
107
159
  try:
108
160
  # Clean up the loop
109
161
  tasks = asyncio.all_tasks(loop)
110
162
  for task in tasks:
111
163
  task.cancel()
112
-
164
+
113
165
  # Run the event loop until all tasks are done
114
166
  if sys.version_info >= (3, 7):
115
167
  loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))
@@ -118,6 +170,7 @@ def run_async_agent(
118
170
  except Exception:
119
171
  pass
120
172
 
173
+
121
174
  @app.callback(invoke_without_command=True)
122
175
  def go(
123
176
  ctx: typer.Context,
@@ -131,6 +184,12 @@ def go(
131
184
  servers: Optional[str] = typer.Option(
132
185
  None, "--servers", help="Comma-separated list of server names to enable from config"
133
186
  ),
187
+ urls: Optional[str] = typer.Option(
188
+ None, "--url", help="Comma-separated list of HTTP/SSE URLs to connect to"
189
+ ),
190
+ auth: Optional[str] = typer.Option(
191
+ None, "--auth", help="Bearer token for authorization with URL-based servers"
192
+ ),
134
193
  model: Optional[str] = typer.Option(
135
194
  None, "--model", help="Override the default model (e.g., haiku, sonnet, gpt-4)"
136
195
  ),
@@ -148,6 +207,8 @@ def go(
148
207
  fast-agent go --model=haiku --instruction="You are a coding assistant" --servers=fetch,filesystem
149
208
  fast-agent go --message="What is the weather today?" --model=haiku
150
209
  fast-agent go --prompt-file=my-prompt.txt --model=haiku
210
+ fast-agent go --url=http://localhost:8001/mcp,http://api.example.com/sse
211
+ fast-agent go --url=https://api.example.com/mcp --auth=YOUR_API_TOKEN
151
212
 
152
213
  This will start an interactive session with the agent, using the specified model
153
214
  and instruction. It will use the default configuration from fastagent.config.yaml
@@ -157,15 +218,19 @@ def go(
157
218
  --model Override the default model (e.g., --model=haiku)
158
219
  --quiet Disable progress display and logging
159
220
  --servers Comma-separated list of server names to enable from config
221
+ --url Comma-separated list of HTTP/SSE URLs to connect to
222
+ --auth Bearer token for authorization with URL-based servers
160
223
  --message, -m Send a single message and exit
161
224
  --prompt-file, -p Use a prompt file instead of interactive mode
162
225
  """
163
226
  run_async_agent(
164
- name=name,
165
- instruction=instruction,
166
- config_path=config_path,
227
+ name=name,
228
+ instruction=instruction,
229
+ config_path=config_path,
167
230
  servers=servers,
231
+ urls=urls,
232
+ auth=auth,
168
233
  model=model,
169
234
  message=message,
170
- prompt_file=prompt_file
171
- )
235
+ prompt_file=prompt_file,
236
+ )
@@ -0,0 +1,185 @@
1
+ """
2
+ URL parsing utility for the fast-agent CLI.
3
+ Provides functions to parse URLs and determine MCP server configurations.
4
+ """
5
+
6
+ import hashlib
7
+ import re
8
+ from typing import Dict, List, Literal, Tuple
9
+ from urllib.parse import urlparse
10
+
11
+
12
+ def parse_server_url(
13
+ url: str,
14
+ ) -> Tuple[str, Literal["http", "sse"], str]:
15
+ """
16
+ Parse a server URL and determine the transport type and server name.
17
+
18
+ Args:
19
+ url: The URL to parse
20
+
21
+ Returns:
22
+ Tuple containing:
23
+ - server_name: A generated name for the server
24
+ - transport_type: Either "http" or "sse" based on URL
25
+ - url: The parsed and validated URL
26
+
27
+ Raises:
28
+ ValueError: If the URL is invalid or unsupported
29
+ """
30
+ # Basic URL validation
31
+ if not url:
32
+ raise ValueError("URL cannot be empty")
33
+
34
+ # Parse the URL
35
+ parsed_url = urlparse(url)
36
+
37
+ # Ensure scheme is present and is either http or https
38
+ if not parsed_url.scheme or parsed_url.scheme not in ("http", "https"):
39
+ raise ValueError(f"URL must have http or https scheme: {url}")
40
+
41
+ # Ensure netloc (hostname) is present
42
+ if not parsed_url.netloc:
43
+ raise ValueError(f"URL must include a hostname: {url}")
44
+
45
+ # Determine transport type based on URL path
46
+ transport_type: Literal["http", "sse"] = "http"
47
+ if parsed_url.path.endswith("/sse"):
48
+ transport_type = "sse"
49
+ elif not parsed_url.path.endswith("/mcp"):
50
+ # If path doesn't end with /mcp or /sse, append /mcp
51
+ url = url if url.endswith("/") else f"{url}/"
52
+ url = f"{url}mcp"
53
+
54
+ # Generate a server name based on hostname and port
55
+ server_name = generate_server_name(url)
56
+
57
+ return server_name, transport_type, url
58
+
59
+
60
+ def generate_server_name(url: str) -> str:
61
+ """
62
+ Generate a unique and readable server name from a URL.
63
+
64
+ Args:
65
+ url: The URL to generate a name for
66
+
67
+ Returns:
68
+ A server name string
69
+ """
70
+ parsed_url = urlparse(url)
71
+
72
+ # Extract hostname and port
73
+ hostname = parsed_url.netloc.split(":")[0]
74
+
75
+ # Clean the hostname for use in a server name
76
+ # Replace non-alphanumeric characters with underscores
77
+ clean_hostname = re.sub(r"[^a-zA-Z0-9]", "_", hostname)
78
+
79
+ if len(clean_hostname) > 15:
80
+ clean_hostname = clean_hostname[:9] + clean_hostname[-5:]
81
+
82
+ # If it's localhost or an IP, add a more unique identifier
83
+ if clean_hostname in ("localhost", "127_0_0_1") or re.match(r"^(\d+_){3}\d+$", clean_hostname):
84
+ # Use the path as part of the name for uniqueness
85
+ path = parsed_url.path.strip("/")
86
+ path = re.sub(r"[^a-zA-Z0-9]", "_", path)
87
+
88
+ # Include port if specified
89
+ port = ""
90
+ if ":" in parsed_url.netloc:
91
+ port = f"_{parsed_url.netloc.split(':')[1]}"
92
+
93
+ if path:
94
+ return f"{clean_hostname}{port}_{path[:20]}" # Limit path length
95
+ else:
96
+ # Use a hash if no path for uniqueness
97
+ url_hash = hashlib.md5(url.encode()).hexdigest()[:8]
98
+ return f"{clean_hostname}{port}_{url_hash}"
99
+
100
+ return clean_hostname
101
+
102
+
103
+ def parse_server_urls(
104
+ urls_param: str, auth_token: str = None
105
+ ) -> List[Tuple[str, Literal["http", "sse"], str, Dict[str, str] | None]]:
106
+ """
107
+ Parse a comma-separated list of URLs into server configurations.
108
+
109
+ Args:
110
+ urls_param: Comma-separated list of URLs
111
+ auth_token: Optional bearer token for authorization
112
+
113
+ Returns:
114
+ List of tuples containing (server_name, transport_type, url, headers)
115
+
116
+ Raises:
117
+ ValueError: If any URL is invalid
118
+ """
119
+ if not urls_param:
120
+ return []
121
+
122
+ # Split by comma and strip whitespace
123
+ url_list = [url.strip() for url in urls_param.split(",")]
124
+
125
+ # Prepare headers if auth token is provided
126
+ headers = None
127
+ if auth_token:
128
+ headers = {"Authorization": f"Bearer {auth_token}"}
129
+
130
+ # Parse each URL
131
+ result = []
132
+ for url in url_list:
133
+ server_name, transport_type, parsed_url = parse_server_url(url)
134
+ result.append((server_name, transport_type, parsed_url, headers))
135
+
136
+ return result
137
+
138
+
139
+ def generate_server_configs(
140
+ parsed_urls: List[Tuple[str, Literal["http", "sse"], str, Dict[str, str] | None]],
141
+ ) -> Dict[str, Dict[str, str | Dict[str, str]]]:
142
+ """
143
+ Generate server configurations from parsed URLs.
144
+
145
+ Args:
146
+ parsed_urls: List of tuples containing (server_name, transport_type, url, headers)
147
+
148
+ Returns:
149
+ Dictionary of server configurations
150
+ """
151
+ server_configs = {}
152
+ # Keep track of server name occurrences to handle collisions
153
+ name_counts = {}
154
+
155
+ for server_name, transport_type, url, headers in parsed_urls:
156
+ # Handle name collisions by adding a suffix
157
+ final_name = server_name
158
+ if server_name in server_configs:
159
+ # Initialize counter if we haven't seen this name yet
160
+ if server_name not in name_counts:
161
+ name_counts[server_name] = 1
162
+
163
+ # Generate a new name with suffix
164
+ suffix = name_counts[server_name]
165
+ final_name = f"{server_name}_{suffix}"
166
+ name_counts[server_name] += 1
167
+
168
+ # Ensure the new name is also unique
169
+ while final_name in server_configs:
170
+ suffix = name_counts[server_name]
171
+ final_name = f"{server_name}_{suffix}"
172
+ name_counts[server_name] += 1
173
+
174
+ config = {
175
+ "transport": transport_type,
176
+ "url": url,
177
+ }
178
+
179
+ # Add headers if provided
180
+ if headers:
181
+ config["headers"] = headers
182
+
183
+ server_configs[final_name] = config
184
+
185
+ return server_configs
@@ -60,7 +60,7 @@ class MCPServerSettings(BaseModel):
60
60
  description: str | None = None
61
61
  """The description of the server."""
62
62
 
63
- transport: Literal["stdio", "sse"] = "stdio"
63
+ transport: Literal["stdio", "sse", "http"] = "stdio"
64
64
  """The transport mechanism."""
65
65
 
66
66
  command: str | None = None
@@ -249,6 +249,8 @@ class LoggerSettings(BaseModel):
249
249
  """Show MCP Sever tool calls on the console"""
250
250
  truncate_tools: bool = True
251
251
  """Truncate display of long tool calls"""
252
+ enable_markup: bool = True
253
+ """Enable markup in console output. Disable for outputs that may conflict with rich console formatting"""
252
254
 
253
255
 
254
256
  class Settings(BaseSettings):
@@ -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.mcp import McpInstrumentor
14
15
  from opentelemetry.instrumentation.openai import OpenAIInstrumentor
15
16
  from opentelemetry.propagate import set_global_textmap
16
17
  from opentelemetry.sdk.resources import Resource
@@ -111,6 +112,7 @@ async def configure_otel(config: "Settings") -> None:
111
112
  trace.set_tracer_provider(tracer_provider)
112
113
  AnthropicInstrumentor().instrument()
113
114
  OpenAIInstrumentor().instrument()
115
+ McpInstrumentor().instrument()
114
116
 
115
117
 
116
118
  async def configure_logger(config: "Settings") -> None:
@@ -131,8 +131,8 @@ class FastAgent:
131
131
  )
132
132
  parser.add_argument(
133
133
  "--transport",
134
- choices=["sse", "stdio"],
135
- default="sse",
134
+ choices=["sse", "http", "stdio"],
135
+ default="http",
136
136
  help="Transport protocol to use when running as a server (sse or stdio)",
137
137
  )
138
138
  parser.add_argument(
@@ -25,24 +25,23 @@ class RequestParams(CreateMessageRequestParams):
25
25
 
26
26
  model: str | None = None
27
27
  """
28
- The model to use for the LLM generation.
28
+ The model to use for the LLM generation. This can only be set during Agent creation.
29
29
  If specified, this overrides the 'modelPreferences' selection criteria.
30
30
  """
31
31
 
32
32
  use_history: bool = True
33
33
  """
34
- Include the message history in the generate request.
34
+ Agent/LLM maintains conversation history. Does not include applied Prompts
35
35
  """
36
36
 
37
- max_iterations: int = 10
37
+ max_iterations: int = 20
38
38
  """
39
- The maximum number of iterations to run the LLM for.
39
+ The maximum number of tool calls allowed in a conversation turn
40
40
  """
41
41
 
42
42
  parallel_tool_calls: bool = True
43
43
  """
44
- Whether to allow multiple tool calls per iteration.
45
- Also known as multi-step tool use.
44
+ Whether to allow simultaneous tool calls
46
45
  """
47
46
  response_format: Any | None = None
48
47
  """
@@ -274,7 +274,9 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
274
274
  # Calculate new conversation messages (excluding prompts)
275
275
  new_messages = messages[len(prompt_messages) :]
276
276
 
277
- # Update conversation history
277
+ if system_prompt:
278
+ new_messages = new_messages[1:]
279
+
278
280
  self.history.set(new_messages)
279
281
 
280
282
  self._log_chat_finished(model=self.default_request_params.model)
@@ -6,21 +6,16 @@ It adds logging and supports sampling requests.
6
6
  from datetime import timedelta
7
7
  from typing import TYPE_CHECKING, Optional
8
8
 
9
- from mcp import ClientSession
9
+ from mcp import ClientSession, ServerNotification
10
10
  from mcp.shared.session import (
11
- ReceiveNotificationT,
12
11
  ReceiveResultT,
13
12
  RequestId,
14
13
  SendNotificationT,
15
14
  SendRequestT,
16
15
  SendResultT,
17
16
  )
18
- from mcp.types import (
19
- ErrorData,
20
- ListRootsResult,
21
- Root,
22
- )
23
- from pydantic import AnyUrl
17
+ from mcp.types import ErrorData, ListRootsResult, Root, ToolListChangedNotification
18
+ from pydantic import FileUrl
24
19
 
25
20
  from mcp_agent.context_dependent import ContextDependent
26
21
  from mcp_agent.logging.logger import get_logger
@@ -45,7 +40,7 @@ async def list_roots(ctx: ClientSession) -> ListRootsResult:
45
40
  ):
46
41
  roots = [
47
42
  Root(
48
- uri=AnyUrl(
43
+ uri=FileUrl(
49
44
  root.server_uri_alias or root.uri,
50
45
  ),
51
46
  name=root.name,
@@ -67,6 +62,11 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
67
62
  """
68
63
 
69
64
  def __init__(self, *args, **kwargs) -> None:
65
+ # Extract server_name if provided in kwargs
66
+ self.session_server_name = kwargs.pop("server_name", None)
67
+ # Extract the notification callbacks if provided
68
+ self._tool_list_changed_callback = kwargs.pop("tool_list_changed_callback", None)
69
+
70
70
  super().__init__(*args, **kwargs, list_roots_callback=list_roots, sampling_callback=sample)
71
71
  self.server_config: Optional[MCPServerSettings] = None
72
72
 
@@ -104,7 +104,7 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
104
104
  )
105
105
  return await super()._send_response(request_id, response)
106
106
 
107
- async def _received_notification(self, notification: ReceiveNotificationT) -> None:
107
+ async def _received_notification(self, notification: ServerNotification) -> None:
108
108
  """
109
109
  Can be overridden by subclasses to handle a notification without needing
110
110
  to listen on the message stream.
@@ -113,7 +113,37 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
113
113
  "_received_notification: notification=",
114
114
  data=notification.model_dump(),
115
115
  )
116
- return await super()._received_notification(notification)
116
+
117
+ # Call parent notification handler first
118
+ await super()._received_notification(notification)
119
+
120
+ # Then process our specific notification types
121
+ match notification.root:
122
+ case ToolListChangedNotification():
123
+ # Simple notification handling - just call the callback if it exists
124
+ if self._tool_list_changed_callback and self.session_server_name:
125
+ logger.info(
126
+ f"Tool list changed for server '{self.session_server_name}', triggering callback"
127
+ )
128
+ # Use asyncio.create_task to prevent blocking the notification handler
129
+ import asyncio
130
+ asyncio.create_task(self._handle_tool_list_change_callback(self.session_server_name))
131
+ else:
132
+ logger.debug(
133
+ f"Tool list changed for server '{self.session_server_name}' but no callback registered"
134
+ )
135
+
136
+ return None
137
+
138
+ async def _handle_tool_list_change_callback(self, server_name: str) -> None:
139
+ """
140
+ Helper method to handle tool list change callback in a separate task
141
+ to prevent blocking the notification handler
142
+ """
143
+ try:
144
+ await self._tool_list_changed_callback(server_name)
145
+ except Exception as e:
146
+ logger.error(f"Error in tool list changed callback: {e}")
117
147
 
118
148
  async def send_progress_notification(
119
149
  self, progress_token: str | int, progress: float, total: float | None = None