fast-agent-mcp 0.1.7__tar.gz → 0.1.8__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 (137) hide show
  1. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/PKG-INFO +12 -6
  2. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/pyproject.toml +15 -7
  3. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/agent_app.py +36 -31
  4. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/decorators.py +3 -2
  5. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/enhanced_prompt.py +106 -20
  6. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/factory.py +28 -66
  7. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/human_input/handler.py +4 -1
  8. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/mcp_aggregator.py +16 -12
  9. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +1 -1
  10. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/orchestrator.py +5 -4
  11. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/router.py +0 -2
  12. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +57 -87
  13. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/augmented_llm.py +25 -84
  14. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/augmented_llm_anthropic.py +8 -30
  15. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/augmented_llm_openai.py +34 -40
  16. fast_agent_mcp-0.1.8/src/mcp_agent/workflows/llm/augmented_llm_passthrough.py +61 -0
  17. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/model_factory.py +5 -3
  18. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/orchestrator/orchestrator.py +62 -153
  19. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/router_llm.py +18 -24
  20. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/.gitignore +0 -0
  21. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/LICENSE +0 -0
  22. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/README.md +0 -0
  23. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/__init__.py +0 -0
  24. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/agents/__init__.py +0 -0
  25. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/agents/agent.py +0 -0
  26. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/app.py +0 -0
  27. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/__init__.py +0 -0
  28. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/__main__.py +0 -0
  29. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/commands/bootstrap.py +0 -0
  30. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/commands/config.py +0 -0
  31. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/commands/setup.py +0 -0
  32. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/main.py +0 -0
  33. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/cli/terminal.py +0 -0
  34. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/config.py +0 -0
  35. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/console.py +0 -0
  36. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/context.py +0 -0
  37. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/context_dependent.py +0 -0
  38. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/__init__.py +0 -0
  39. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/agent_types.py +0 -0
  40. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/agent_utils.py +0 -0
  41. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/error_handling.py +0 -0
  42. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/exceptions.py +0 -0
  43. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/fastagent.py +0 -0
  44. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/proxies.py +0 -0
  45. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/server_validation.py +0 -0
  46. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/simulator_registry.py +0 -0
  47. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/types.py +0 -0
  48. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/core/validation.py +0 -0
  49. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/eval/__init__.py +0 -0
  50. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/event_progress.py +0 -0
  51. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/__init__.py +0 -0
  52. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/decorator_registry.py +0 -0
  53. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/executor.py +0 -0
  54. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/task_registry.py +0 -0
  55. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/temporal.py +0 -0
  56. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/workflow.py +0 -0
  57. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/executor/workflow_signal.py +0 -0
  58. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/human_input/__init__.py +0 -0
  59. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/human_input/types.py +0 -0
  60. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/__init__.py +0 -0
  61. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/events.py +0 -0
  62. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/json_serializer.py +0 -0
  63. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/listeners.py +0 -0
  64. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/logger.py +0 -0
  65. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/rich_progress.py +0 -0
  66. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/tracing.py +0 -0
  67. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/logging/transport.py +0 -0
  68. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/__init__.py +0 -0
  69. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/gen_client.py +0 -0
  70. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/mcp_activity.py +0 -0
  71. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/mcp_agent_client_session.py +0 -0
  72. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/mcp_agent_server.py +0 -0
  73. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/mcp_connection_manager.py +0 -0
  74. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp/stdio.py +0 -0
  75. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp_server/__init__.py +0 -0
  76. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp_server/agent_server.py +0 -0
  77. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/mcp_server_registry.py +0 -0
  78. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/progress_display.py +0 -0
  79. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -0
  80. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
  81. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  82. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  83. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
  84. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
  85. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/job.py +0 -0
  86. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/prompt_category.py +0 -0
  87. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +0 -0
  88. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/sizer.py +0 -0
  89. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/internal/social.py +0 -0
  90. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -0
  91. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
  92. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +0 -0
  93. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
  94. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/agent_build.py +0 -0
  95. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
  96. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/evaluator.py +0 -0
  97. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
  98. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
  99. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/parallel.py +0 -0
  100. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/resources/examples/workflows/sse.py +0 -0
  101. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/telemetry/__init__.py +0 -0
  102. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/telemetry/usage_tracking.py +0 -0
  103. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/ui/console_display.py +0 -0
  104. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/__init__.py +0 -0
  105. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/embedding/__init__.py +0 -0
  106. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/embedding/embedding_base.py +0 -0
  107. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/embedding/embedding_cohere.py +0 -0
  108. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/embedding/embedding_openai.py +0 -0
  109. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
  110. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/__init__.py +0 -0
  111. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -0
  112. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -0
  113. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -0
  114. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -0
  115. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -0
  116. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -0
  117. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -0
  118. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/__init__.py +0 -0
  119. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/enhanced_passthrough.py +0 -0
  120. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/llm_selector.py +0 -0
  121. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/llm/prompt_utils.py +0 -0
  122. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/orchestrator/__init__.py +0 -0
  123. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/orchestrator/orchestrator_models.py +0 -0
  124. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +0 -0
  125. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/parallel/__init__.py +0 -0
  126. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/parallel/fan_in.py +0 -0
  127. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/parallel/fan_out.py +0 -0
  128. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/parallel/parallel_llm.py +0 -0
  129. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/__init__.py +0 -0
  130. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/router_base.py +0 -0
  131. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/router_embedding.py +0 -0
  132. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/router_embedding_cohere.py +0 -0
  133. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/router/router_embedding_openai.py +0 -0
  134. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/swarm/__init__.py +0 -0
  135. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/swarm/swarm.py +0 -0
  136. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/swarm/swarm_anthropic.py +0 -0
  137. {fast_agent_mcp-0.1.7 → fast_agent_mcp-0.1.8}/src/mcp_agent/workflows/swarm/swarm_openai.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
6
6
  License: Apache License
@@ -209,9 +209,9 @@ Classifier: License :: OSI Approved :: Apache Software License
209
209
  Classifier: Operating System :: OS Independent
210
210
  Classifier: Programming Language :: Python :: 3
211
211
  Requires-Python: >=3.10
212
- Requires-Dist: anthropic>=0.42.0
212
+ Requires-Dist: aiohttp>=3.11.13
213
+ Requires-Dist: anthropic>=0.49.0
213
214
  Requires-Dist: fastapi>=0.115.6
214
- Requires-Dist: instructor>=1.7.2
215
215
  Requires-Dist: mcp==1.2.1
216
216
  Requires-Dist: numpy>=2.2.1
217
217
  Requires-Dist: openai>=1.63.2
@@ -224,11 +224,17 @@ Requires-Dist: pyyaml>=6.0.2
224
224
  Requires-Dist: rich>=13.9.4
225
225
  Requires-Dist: scikit-learn>=1.6.0
226
226
  Requires-Dist: typer>=0.15.1
227
- Provides-Extra: anthropic
228
- Requires-Dist: anthropic>=0.42.0; extra == 'anthropic'
229
- Requires-Dist: instructor[anthropic]>=1.7.2; extra == 'anthropic'
230
227
  Provides-Extra: cohere
231
228
  Requires-Dist: cohere>=5.13.4; extra == 'cohere'
229
+ Provides-Extra: dev
230
+ Requires-Dist: anthropic>=0.42.0; extra == 'dev'
231
+ Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
232
+ Requires-Dist: pydantic>=2.10.4; extra == 'dev'
233
+ Requires-Dist: pytest-asyncio>=0.21.1; extra == 'dev'
234
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
235
+ Requires-Dist: pyyaml>=6.0.2; extra == 'dev'
236
+ Requires-Dist: ruff>=0.8.4; extra == 'dev'
237
+ Requires-Dist: tomli>=2.2.1; extra == 'dev'
232
238
  Provides-Extra: openai
233
239
  Requires-Dist: openai>=1.58.1; extra == 'openai'
234
240
  Provides-Extra: temporal
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fast-agent-mcp"
3
- version = "0.1.7"
3
+ version = "0.1.8"
4
4
  description = "Define, Prompt and Test MCP enabled Agents and Workflows"
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -16,7 +16,6 @@ classifiers = [
16
16
  requires-python = ">=3.10"
17
17
  dependencies = [
18
18
  "fastapi>=0.115.6",
19
- "instructor>=1.7.2",
20
19
  "mcp==1.2.1",
21
20
  "opentelemetry-distro>=0.50b0",
22
21
  "opentelemetry-exporter-otlp-proto-http>=1.29.0",
@@ -27,25 +26,32 @@ dependencies = [
27
26
  "typer>=0.15.1",
28
27
  "numpy>=2.2.1",
29
28
  "scikit-learn>=1.6.0",
30
- "anthropic>=0.42.0",
29
+ "anthropic>=0.49.0",
31
30
  "openai>=1.63.2",
32
31
  "prompt-toolkit>=3.0.50",
32
+ "aiohttp>=3.11.13",
33
33
  ]
34
34
 
35
35
  [project.optional-dependencies]
36
36
  temporal = [
37
37
  "temporalio>=1.8.0",
38
38
  ]
39
- anthropic = [
40
- "anthropic>=0.42.0",
41
- "instructor[anthropic]>=1.7.2",
42
- ]
43
39
  openai = [
44
40
  "openai>=1.58.1",
45
41
  ]
46
42
  cohere = [
47
43
  "cohere>=5.13.4",
48
44
  ]
45
+ dev = [
46
+ "anthropic>=0.42.0",
47
+ "pre-commit>=4.0.1",
48
+ "pydantic>=2.10.4",
49
+ "pyyaml>=6.0.2",
50
+ "ruff>=0.8.4",
51
+ "tomli>=2.2.1",
52
+ "pytest>=7.4.0",
53
+ "pytest-asyncio>=0.21.1",
54
+ ]
49
55
 
50
56
  [build-system]
51
57
  requires = ["hatchling"]
@@ -74,6 +80,8 @@ dev = [
74
80
  "pyyaml>=6.0.2",
75
81
  "ruff>=0.8.4",
76
82
  "tomli>=2.2.1",
83
+ "pytest>=7.4.0",
84
+ "pytest-asyncio>=0.21.1",
77
85
  ]
78
86
 
79
87
  [project.scripts]
@@ -177,9 +177,6 @@ class AgentApp:
177
177
  from rich import print as rich_print
178
178
  from rich.table import Table
179
179
  from rich.console import Console
180
- from prompt_toolkit import PromptSession
181
- from prompt_toolkit.formatted_text import HTML
182
- from prompt_toolkit.completion import WordCompleter
183
180
 
184
181
  console = Console()
185
182
 
@@ -325,8 +322,11 @@ class AgentApp:
325
322
  )
326
323
 
327
324
  # Ask user to select one
328
- prompt_session = PromptSession()
329
- selection = await prompt_session.prompt_async(
325
+ from mcp_agent.core.enhanced_prompt import (
326
+ get_selection_input,
327
+ )
328
+
329
+ selection = await get_selection_input(
330
330
  "Enter prompt number to select: ", default="1"
331
331
  )
332
332
 
@@ -381,12 +381,16 @@ class AgentApp:
381
381
  prompt_names = [
382
382
  str(i + 1) for i in range(len(all_prompts))
383
383
  ]
384
- completer = WordCompleter(prompt_names)
385
384
 
386
385
  # Ask user to select a prompt
387
- prompt_session = PromptSession(completer=completer)
388
- selection = await prompt_session.prompt_async(
389
- "Enter prompt number to select (or press Enter to cancel): "
386
+ from mcp_agent.core.enhanced_prompt import (
387
+ get_selection_input,
388
+ )
389
+
390
+ selection = await get_selection_input(
391
+ "Enter prompt number to select (or press Enter to cancel): ",
392
+ options=prompt_names,
393
+ allow_cancel=True,
390
394
  )
391
395
 
392
396
  # Make cancellation easier
@@ -437,37 +441,38 @@ class AgentApp:
437
441
 
438
442
  # Collect required arguments
439
443
  for arg_name in required_args:
440
- # Show description if available
444
+ # Get description if available
441
445
  description = arg_descriptions.get(arg_name, "")
442
- if description:
443
- rich_print(
444
- f" [dim]{arg_name}: {description}[/dim]"
445
- )
446
-
446
+
447
447
  # Collect required argument value
448
- arg_value = await PromptSession().prompt_async(
449
- HTML(
450
- f"Enter value for <ansibrightcyan>{arg_name}</ansibrightcyan> (required): "
451
- )
448
+ from mcp_agent.core.enhanced_prompt import (
449
+ get_argument_input,
450
+ )
451
+
452
+ arg_value = await get_argument_input(
453
+ arg_name=arg_name,
454
+ description=description,
455
+ required=True,
452
456
  )
453
- # Add to arg_values
454
- arg_values[arg_name] = arg_value
457
+ # Add to arg_values if a value was provided
458
+ if arg_value is not None:
459
+ arg_values[arg_name] = arg_value
455
460
 
456
461
  # Only include non-empty values for optional arguments
457
462
  if optional_args:
458
463
  # Collect optional arguments
459
464
  for arg_name in optional_args:
460
- # Show description if available
465
+ # Get description if available
461
466
  description = arg_descriptions.get(arg_name, "")
462
- if description:
463
- rich_print(
464
- f" [dim]{arg_name}: {description}[/dim]"
465
- )
466
-
467
- arg_value = await PromptSession().prompt_async(
468
- HTML(
469
- f"Enter value for <ansibrightcyan>{arg_name}</ansibrightcyan> (optional, press Enter to skip): "
470
- )
467
+
468
+ from mcp_agent.core.enhanced_prompt import (
469
+ get_argument_input,
470
+ )
471
+
472
+ arg_value = await get_argument_input(
473
+ arg_name=arg_name,
474
+ description=description,
475
+ required=False,
471
476
  )
472
477
  # Only include non-empty values for optional arguments
473
478
  if arg_value:
@@ -256,7 +256,8 @@ def parallel(
256
256
  self.agents[passthrough_name] = {
257
257
  "config": AgentConfig(
258
258
  name=passthrough_name,
259
- instruction=f"Passthrough fan-in for {name}",
259
+ model="passthrough",
260
+ instruction=f"This agent combines the results from the fan-out agents verbatim. {name}",
260
261
  servers=[],
261
262
  use_history=use_history,
262
263
  ),
@@ -452,4 +453,4 @@ def passthrough(
452
453
  name=name,
453
454
  use_history=use_history,
454
455
  )
455
- return decorator
456
+ return decorator
@@ -2,13 +2,13 @@
2
2
  Enhanced prompt functionality with advanced prompt_toolkit features.
3
3
  """
4
4
 
5
- from typing import List
5
+ from typing import List, Optional
6
6
  from importlib.metadata import version
7
7
  from prompt_toolkit import PromptSession
8
8
  from prompt_toolkit.formatted_text import HTML
9
9
  from prompt_toolkit.history import InMemoryHistory
10
10
  from prompt_toolkit.key_binding import KeyBindings
11
- from prompt_toolkit.completion import Completer, Completion
11
+ from prompt_toolkit.completion import Completer, Completion, WordCompleter
12
12
  from prompt_toolkit.lexers import PygmentsLexer
13
13
  from prompt_toolkit.filters import Condition
14
14
  from prompt_toolkit.styles import Style
@@ -330,6 +330,110 @@ async def get_enhanced_input(
330
330
  # Log and gracefully handle other exceptions
331
331
  print(f"\nInput error: {type(e).__name__}: {e}")
332
332
  return "STOP"
333
+ finally:
334
+ # Ensure the prompt session is properly cleaned up
335
+ # This is especially important on Windows to prevent resource leaks
336
+ if session.app.is_running:
337
+ session.app.exit()
338
+
339
+
340
+ async def get_selection_input(
341
+ prompt_text: str,
342
+ options: List[str] = None,
343
+ default: str = None,
344
+ allow_cancel: bool = True,
345
+ complete_options: bool = True,
346
+ ) -> Optional[str]:
347
+ """
348
+ Display a selection prompt and return the user's selection.
349
+
350
+ Args:
351
+ prompt_text: Text to display as the prompt
352
+ options: List of valid options (for auto-completion)
353
+ default: Default value if user presses enter
354
+ allow_cancel: Whether to allow cancellation with empty input
355
+ complete_options: Whether to use the options for auto-completion
356
+
357
+ Returns:
358
+ Selected value, or None if cancelled
359
+ """
360
+ try:
361
+ # Initialize completer if options provided and completion requested
362
+ completer = WordCompleter(options) if options and complete_options else None
363
+
364
+ # Create prompt session
365
+ prompt_session = PromptSession(completer=completer)
366
+
367
+ try:
368
+ # Get user input
369
+ selection = await prompt_session.prompt_async(
370
+ prompt_text, default=default or ""
371
+ )
372
+
373
+ # Handle cancellation
374
+ if allow_cancel and not selection.strip():
375
+ return None
376
+
377
+ return selection
378
+ finally:
379
+ # Ensure prompt session cleanup
380
+ if prompt_session.app.is_running:
381
+ prompt_session.app.exit()
382
+ except (KeyboardInterrupt, EOFError):
383
+ return None
384
+ except Exception as e:
385
+ rich_print(f"\n[red]Error getting selection: {e}[/red]")
386
+ return None
387
+
388
+
389
+ async def get_argument_input(
390
+ arg_name: str,
391
+ description: str = None,
392
+ required: bool = True,
393
+ ) -> Optional[str]:
394
+ """
395
+ Prompt for an argument value with formatting and help text.
396
+
397
+ Args:
398
+ arg_name: Name of the argument
399
+ description: Optional description of the argument
400
+ required: Whether this argument is required
401
+
402
+ Returns:
403
+ Input value, or None if cancelled/skipped
404
+ """
405
+ # Format the prompt differently based on whether it's required
406
+ required_text = "(required)" if required else "(optional, press Enter to skip)"
407
+
408
+ # Show description if available
409
+ if description:
410
+ rich_print(f" [dim]{arg_name}: {description}[/dim]")
411
+
412
+ prompt_text = HTML(
413
+ f"Enter value for <ansibrightcyan>{arg_name}</ansibrightcyan> {required_text}: "
414
+ )
415
+
416
+ # Create prompt session
417
+ prompt_session = PromptSession()
418
+
419
+ try:
420
+ # Get user input
421
+ arg_value = await prompt_session.prompt_async(prompt_text)
422
+
423
+ # For optional arguments, empty input means skip
424
+ if not required and not arg_value:
425
+ return None
426
+
427
+ return arg_value
428
+ except (KeyboardInterrupt, EOFError):
429
+ return None
430
+ except Exception as e:
431
+ rich_print(f"\n[red]Error getting input: {e}[/red]")
432
+ return None
433
+ finally:
434
+ # Ensure prompt session cleanup
435
+ if prompt_session.app.is_running:
436
+ prompt_session.app.exit()
333
437
 
334
438
 
335
439
  async def handle_special_commands(command, agent_app=None):
@@ -408,24 +512,6 @@ async def handle_special_commands(command, agent_app=None):
408
512
  )
409
513
  return True
410
514
 
411
- elif command == "SELECT_PROMPT" or (
412
- isinstance(command, str) and command.startswith("SELECT_PROMPT:")
413
- ):
414
- # Handle prompt selection UI (previously named "list_prompts" action)
415
- if agent_app:
416
- # If it's a specific prompt, extract the name
417
- prompt_name = None
418
- if isinstance(command, str) and command.startswith("SELECT_PROMPT:"):
419
- prompt_name = command.split(":", 1)[1].strip()
420
-
421
- # Return a dictionary with a select_prompt action to be handled by the caller
422
- return {"select_prompt": True, "prompt_name": prompt_name}
423
- else:
424
- rich_print(
425
- "[yellow]Prompt selection is not available outside of an agent context[/yellow]"
426
- )
427
- return True
428
-
429
515
  elif isinstance(command, str) and command.startswith("SWITCH:"):
430
516
  agent_name = command.split(":", 1)[1]
431
517
  if agent_name in available_agents:
@@ -34,10 +34,7 @@ T = TypeVar("T") # For the wrapper classes
34
34
 
35
35
 
36
36
  def create_proxy(
37
- app: MCPApp,
38
- name: str,
39
- instance: AgentOrWorkflow,
40
- agent_type: str
37
+ app: MCPApp, name: str, instance: AgentOrWorkflow, agent_type: str
41
38
  ) -> BaseAgentProxy:
42
39
  """Create appropriate proxy type based on agent type and validate instance type
43
40
 
@@ -61,9 +58,7 @@ def create_proxy(
61
58
  log_agent_load(app, name)
62
59
  if agent_type == AgentType.BASIC.value:
63
60
  if not isinstance(instance, Agent):
64
- raise TypeError(
65
- f"Expected Agent instance for {name}, got {type(instance)}"
66
- )
61
+ raise TypeError(f"Expected Agent instance for {name}, got {type(instance)}")
67
62
  return LLMAgentProxy(app, name, instance)
68
63
  elif agent_type == AgentType.ORCHESTRATOR.value:
69
64
  if not isinstance(instance, Orchestrator):
@@ -177,42 +172,18 @@ async def create_agents_by_type(
177
172
  if agent_type == AgentType.BASIC:
178
173
  # Get the agent name for special handling
179
174
  agent_name = agent_data["config"].name
175
+ agent = Agent(config=config, context=app_instance.context)
180
176
 
181
- # Check if this is an agent that should use the PassthroughLLM
182
- if agent_name.endswith("_fan_in") or agent_name.startswith(
183
- "passthrough"
184
- ):
185
- # Import here to avoid circular imports
186
- from mcp_agent.workflows.llm.augmented_llm import PassthroughLLM
187
-
188
- # Create basic agent with configuration
189
- agent = Agent(config=config, context=app_instance.context)
190
-
191
- # Set up a PassthroughLLM directly
192
- async with agent:
193
- agent._llm = PassthroughLLM(
194
- name=f"{config.name}_llm",
195
- context=app_instance.context,
196
- agent=agent,
197
- default_request_params=config.default_request_params,
198
- )
199
-
200
- # Store the agent
201
- instance = agent
202
- else:
203
- # Standard basic agent with LLM
204
- agent = Agent(config=config, context=app_instance.context)
205
-
206
- # Set up LLM with proper configuration
207
- async with agent:
208
- llm_factory = model_factory_func(
209
- model=config.model,
210
- request_params=config.default_request_params,
211
- )
212
- agent._llm = await agent.attach_llm(llm_factory)
177
+ # Set up LLM with proper configuration
178
+ async with agent:
179
+ llm_factory = model_factory_func(
180
+ model=config.model,
181
+ request_params=config.default_request_params,
182
+ )
183
+ agent._llm = await agent.attach_llm(llm_factory)
213
184
 
214
- # Store the agent
215
- instance = agent
185
+ # Store the agent
186
+ instance = agent
216
187
 
217
188
  elif agent_type == AgentType.ORCHESTRATOR:
218
189
  # Get base params configured with model settings
@@ -276,12 +247,8 @@ async def create_agents_by_type(
276
247
 
277
248
  elif agent_type == AgentType.EVALUATOR_OPTIMIZER:
278
249
  # Get the referenced agents - unwrap from proxies
279
- generator = unwrap_proxy(
280
- active_agents[agent_data["generator"]]
281
- )
282
- evaluator = unwrap_proxy(
283
- active_agents[agent_data["evaluator"]]
284
- )
250
+ generator = unwrap_proxy(active_agents[agent_data["generator"]])
251
+ evaluator = unwrap_proxy(active_agents[agent_data["evaluator"]])
285
252
 
286
253
  if not generator or not evaluator:
287
254
  raise ValueError(
@@ -294,7 +261,9 @@ async def create_agents_by_type(
294
261
  optimizer_model = None
295
262
  if isinstance(generator, Agent):
296
263
  optimizer_model = generator.config.model
297
- elif hasattr(generator, '_sequence') and hasattr(generator, '_agent_proxies'):
264
+ elif hasattr(generator, "_sequence") and hasattr(
265
+ generator, "_agent_proxies"
266
+ ):
298
267
  # For ChainProxy, use the config model directly
299
268
  optimizer_model = config.model
300
269
 
@@ -311,9 +280,7 @@ async def create_agents_by_type(
311
280
 
312
281
  elif agent_type == AgentType.ROUTER:
313
282
  # Get the router's agents - unwrap proxies
314
- router_agents = get_agent_instances(
315
- agent_data["agents"], active_agents
316
- )
283
+ router_agents = get_agent_instances(agent_data["agents"], active_agents)
317
284
 
318
285
  # Create the router with proper configuration
319
286
  llm_factory = model_factory_func(
@@ -376,20 +343,15 @@ async def create_agents_by_type(
376
343
  "continue_with_final", True
377
344
  )
378
345
  # Set cumulative behavior from configuration
379
- instance._cumulative = agent_data.get(
380
- "cumulative", False
381
- )
346
+ instance._cumulative = agent_data.get("cumulative", False)
382
347
 
383
348
  elif agent_type == AgentType.PARALLEL:
384
- # Get fan-out agents (could be basic agents or other parallels)
385
349
  fan_out_agents = get_agent_instances(
386
350
  agent_data["fan_out"], active_agents
387
351
  )
388
352
 
389
353
  # Get fan-in agent - unwrap proxy
390
- fan_in_agent = unwrap_proxy(
391
- active_agents[agent_data["fan_in"]]
392
- )
354
+ fan_in_agent = unwrap_proxy(active_agents[agent_data["fan_in"]])
393
355
 
394
356
  # Create the parallel workflow
395
357
  llm_factory = model_factory_func(config.model)
@@ -416,7 +378,7 @@ async def create_agents_by_type(
416
378
 
417
379
 
418
380
  async def create_basic_agents(
419
- app_instance: MCPApp,
381
+ app_instance: MCPApp,
420
382
  agents_dict: Dict[str, Dict[str, Any]],
421
383
  model_factory_func: Callable,
422
384
  ) -> ProxyDict:
@@ -432,17 +394,17 @@ async def create_basic_agents(
432
394
  Dictionary of initialized basic agents wrapped in appropriate proxies
433
395
  """
434
396
  return await create_agents_by_type(
435
- app_instance,
436
- agents_dict,
437
- AgentType.BASIC,
438
- model_factory_func=model_factory_func
397
+ app_instance,
398
+ agents_dict,
399
+ AgentType.BASIC,
400
+ model_factory_func=model_factory_func,
439
401
  )
440
402
 
441
403
 
442
404
  async def create_agents_in_dependency_order(
443
- app_instance: MCPApp,
405
+ app_instance: MCPApp,
444
406
  agents_dict: Dict[str, Dict[str, Any]],
445
- active_agents: ProxyDict,
407
+ active_agents: ProxyDict,
446
408
  agent_type: AgentType,
447
409
  model_factory_func: Callable,
448
410
  ) -> ProxyDict:
@@ -498,4 +460,4 @@ async def create_agents_in_dependency_order(
498
460
  if agent_name in agent_result:
499
461
  result_agents[agent_name] = agent_result[agent_name]
500
462
 
501
- return result_agents
463
+ return result_agents
@@ -69,7 +69,10 @@ async def console_input_callback(request: HumanInputRequest) -> HumanInputRespon
69
69
  command_result = await handle_special_commands(response)
70
70
  if isinstance(command_result, dict) and "list_prompts" in command_result:
71
71
  from rich import print as rich_print
72
- rich_print("[yellow]Prompt listing not available in human input context[/yellow]")
72
+
73
+ rich_print(
74
+ "[yellow]Prompt listing not available in human input context[/yellow]"
75
+ )
73
76
 
74
77
  except KeyboardInterrupt:
75
78
  console.print("\n[yellow]Input interrupted[/yellow]")
@@ -788,19 +788,23 @@ class MCPAggregator(ContextDependent):
788
788
  # Add empty list to results for this server
789
789
  results[s_name] = []
790
790
 
791
- # Gather prompts from supported servers concurrently
791
+ # Process servers sequentially to ensure proper resource cleanup
792
+ # This helps prevent resource leaks especially on Windows
792
793
  if supported_servers:
793
- tasks = [
794
- self._execute_on_server(
795
- server_name=s_name,
796
- operation_type="prompts-list",
797
- operation_name="",
798
- method_name="list_prompts",
799
- error_factory=lambda _: [],
800
- )
801
- for s_name in supported_servers
802
- ]
803
- server_results = await gather(*tasks, return_exceptions=True)
794
+ server_results = []
795
+ for s_name in supported_servers:
796
+ try:
797
+ result = await self._execute_on_server(
798
+ server_name=s_name,
799
+ operation_type="prompts-list",
800
+ operation_name="",
801
+ method_name="list_prompts",
802
+ error_factory=lambda _: [],
803
+ )
804
+ server_results.append(result)
805
+ except Exception as e:
806
+ logger.debug(f"Error fetching prompts from {s_name}: {e}")
807
+ server_results.append(e)
804
808
 
805
809
  for i, result in enumerate(server_results):
806
810
  if isinstance(result, BaseException):
@@ -2,7 +2,7 @@ import asyncio
2
2
 
3
3
  from mcp_agent.core.fastagent import FastAgent
4
4
 
5
- agents = FastAgent(name="Researcher")
5
+ agents = FastAgent(name="Researcher Agent (EO)")
6
6
 
7
7
 
8
8
  @agents.agent(
@@ -45,13 +45,14 @@ fast = FastAgent("Orchestrator-Workers")
45
45
  @fast.orchestrator(
46
46
  name="orchestrate",
47
47
  agents=["finder", "writer", "proofreader"],
48
- plan_type="full",
48
+ plan_type="iterative",
49
49
  )
50
50
  async def main():
51
51
  async with fast.run() as agent:
52
- await agent.author(
53
- "write a 250 word short story about kittens discovering a castle, and save it to short_story.md"
54
- )
52
+ await agent()
53
+ # await agent.author(
54
+ # "write a 250 word short story about kittens discovering a castle, and save it to short_story.md"
55
+ # )
55
56
 
56
57
  # The orchestrator can be used just like any other agent
57
58
  task = (
@@ -25,7 +25,6 @@ SAMPLE_REQUESTS = [
25
25
  name="fetcher",
26
26
  instruction="""You are an agent, with a tool enabling you to fetch URLs.""",
27
27
  servers=["fetch"],
28
- model="haiku",
29
28
  )
30
29
  @fast.agent(
31
30
  name="code_expert",
@@ -33,7 +32,6 @@ SAMPLE_REQUESTS = [
33
32
  When asked about code, architecture, or development practices,
34
33
  you provide thorough and practical insights.""",
35
34
  servers=["filesystem"],
36
- model="gpt-4o",
37
35
  )
38
36
  @fast.agent(
39
37
  name="general_assistant",