fast-agent-mcp 0.2.58__py3-none-any.whl → 0.3.1__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (234) hide show
  1. fast_agent/__init__.py +127 -0
  2. fast_agent/agents/__init__.py +36 -0
  3. {mcp_agent/core → fast_agent/agents}/agent_types.py +2 -1
  4. fast_agent/agents/llm_agent.py +217 -0
  5. fast_agent/agents/llm_decorator.py +486 -0
  6. mcp_agent/agents/base_agent.py → fast_agent/agents/mcp_agent.py +377 -385
  7. fast_agent/agents/tool_agent.py +168 -0
  8. {mcp_agent → fast_agent}/agents/workflow/chain_agent.py +43 -33
  9. {mcp_agent → fast_agent}/agents/workflow/evaluator_optimizer.py +31 -35
  10. {mcp_agent → fast_agent}/agents/workflow/iterative_planner.py +56 -47
  11. {mcp_agent → fast_agent}/agents/workflow/orchestrator_models.py +4 -4
  12. {mcp_agent → fast_agent}/agents/workflow/parallel_agent.py +34 -41
  13. {mcp_agent → fast_agent}/agents/workflow/router_agent.py +54 -39
  14. {mcp_agent → fast_agent}/cli/__main__.py +5 -3
  15. {mcp_agent → fast_agent}/cli/commands/check_config.py +95 -66
  16. {mcp_agent → fast_agent}/cli/commands/go.py +20 -11
  17. {mcp_agent → fast_agent}/cli/commands/quickstart.py +4 -4
  18. {mcp_agent → fast_agent}/cli/commands/server_helpers.py +1 -1
  19. {mcp_agent → fast_agent}/cli/commands/setup.py +75 -134
  20. {mcp_agent → fast_agent}/cli/commands/url_parser.py +9 -8
  21. {mcp_agent → fast_agent}/cli/main.py +36 -16
  22. {mcp_agent → fast_agent}/cli/terminal.py +2 -2
  23. {mcp_agent → fast_agent}/config.py +10 -2
  24. fast_agent/constants.py +8 -0
  25. {mcp_agent → fast_agent}/context.py +24 -19
  26. {mcp_agent → fast_agent}/context_dependent.py +9 -5
  27. fast_agent/core/__init__.py +52 -0
  28. {mcp_agent → fast_agent}/core/agent_app.py +39 -36
  29. fast_agent/core/core_app.py +135 -0
  30. {mcp_agent → fast_agent}/core/direct_decorators.py +12 -26
  31. {mcp_agent → fast_agent}/core/direct_factory.py +95 -73
  32. {mcp_agent → fast_agent/core}/executor/executor.py +4 -5
  33. {mcp_agent → fast_agent}/core/fastagent.py +32 -32
  34. fast_agent/core/logging/__init__.py +5 -0
  35. {mcp_agent → fast_agent/core}/logging/events.py +3 -3
  36. {mcp_agent → fast_agent/core}/logging/json_serializer.py +1 -1
  37. {mcp_agent → fast_agent/core}/logging/listeners.py +85 -7
  38. {mcp_agent → fast_agent/core}/logging/logger.py +7 -7
  39. {mcp_agent → fast_agent/core}/logging/transport.py +10 -11
  40. fast_agent/core/prompt.py +9 -0
  41. {mcp_agent → fast_agent}/core/validation.py +4 -4
  42. fast_agent/event_progress.py +61 -0
  43. fast_agent/history/history_exporter.py +44 -0
  44. {mcp_agent → fast_agent}/human_input/__init__.py +9 -12
  45. {mcp_agent → fast_agent}/human_input/elicitation_handler.py +26 -8
  46. {mcp_agent → fast_agent}/human_input/elicitation_state.py +7 -7
  47. {mcp_agent → fast_agent}/human_input/simple_form.py +6 -4
  48. {mcp_agent → fast_agent}/human_input/types.py +1 -18
  49. fast_agent/interfaces.py +228 -0
  50. fast_agent/llm/__init__.py +9 -0
  51. mcp_agent/llm/augmented_llm.py → fast_agent/llm/fastagent_llm.py +127 -218
  52. fast_agent/llm/internal/passthrough.py +137 -0
  53. mcp_agent/llm/augmented_llm_playback.py → fast_agent/llm/internal/playback.py +29 -25
  54. mcp_agent/llm/augmented_llm_silent.py → fast_agent/llm/internal/silent.py +10 -17
  55. fast_agent/llm/internal/slow.py +38 -0
  56. {mcp_agent → fast_agent}/llm/memory.py +40 -30
  57. {mcp_agent → fast_agent}/llm/model_database.py +35 -2
  58. {mcp_agent → fast_agent}/llm/model_factory.py +103 -77
  59. fast_agent/llm/model_info.py +126 -0
  60. {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/anthropic_utils.py +7 -7
  61. fast_agent/llm/provider/anthropic/llm_anthropic.py +603 -0
  62. {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/multipart_converter_anthropic.py +79 -86
  63. {mcp_agent/llm/providers → fast_agent/llm/provider/bedrock}/bedrock_utils.py +3 -1
  64. mcp_agent/llm/providers/augmented_llm_bedrock.py → fast_agent/llm/provider/bedrock/llm_bedrock.py +833 -717
  65. {mcp_agent/llm/providers → fast_agent/llm/provider/google}/google_converter.py +66 -14
  66. fast_agent/llm/provider/google/llm_google_native.py +431 -0
  67. mcp_agent/llm/providers/augmented_llm_aliyun.py → fast_agent/llm/provider/openai/llm_aliyun.py +6 -7
  68. mcp_agent/llm/providers/augmented_llm_azure.py → fast_agent/llm/provider/openai/llm_azure.py +4 -4
  69. mcp_agent/llm/providers/augmented_llm_deepseek.py → fast_agent/llm/provider/openai/llm_deepseek.py +10 -11
  70. mcp_agent/llm/providers/augmented_llm_generic.py → fast_agent/llm/provider/openai/llm_generic.py +4 -4
  71. mcp_agent/llm/providers/augmented_llm_google_oai.py → fast_agent/llm/provider/openai/llm_google_oai.py +4 -4
  72. mcp_agent/llm/providers/augmented_llm_groq.py → fast_agent/llm/provider/openai/llm_groq.py +14 -16
  73. mcp_agent/llm/providers/augmented_llm_openai.py → fast_agent/llm/provider/openai/llm_openai.py +133 -207
  74. mcp_agent/llm/providers/augmented_llm_openrouter.py → fast_agent/llm/provider/openai/llm_openrouter.py +6 -6
  75. mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py → fast_agent/llm/provider/openai/llm_tensorzero_openai.py +17 -16
  76. mcp_agent/llm/providers/augmented_llm_xai.py → fast_agent/llm/provider/openai/llm_xai.py +6 -6
  77. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/multipart_converter_openai.py +125 -63
  78. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_multipart.py +12 -12
  79. {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_utils.py +18 -16
  80. {mcp_agent → fast_agent}/llm/provider_key_manager.py +2 -2
  81. {mcp_agent → fast_agent}/llm/provider_types.py +2 -0
  82. {mcp_agent → fast_agent}/llm/sampling_converter.py +15 -12
  83. {mcp_agent → fast_agent}/llm/usage_tracking.py +23 -5
  84. fast_agent/mcp/__init__.py +54 -0
  85. {mcp_agent → fast_agent}/mcp/elicitation_factory.py +3 -3
  86. {mcp_agent → fast_agent}/mcp/elicitation_handlers.py +19 -10
  87. {mcp_agent → fast_agent}/mcp/gen_client.py +3 -3
  88. fast_agent/mcp/helpers/__init__.py +36 -0
  89. fast_agent/mcp/helpers/content_helpers.py +183 -0
  90. {mcp_agent → fast_agent}/mcp/helpers/server_config_helpers.py +8 -8
  91. {mcp_agent → fast_agent}/mcp/hf_auth.py +25 -23
  92. fast_agent/mcp/interfaces.py +93 -0
  93. {mcp_agent → fast_agent}/mcp/logger_textio.py +4 -4
  94. {mcp_agent → fast_agent}/mcp/mcp_agent_client_session.py +49 -44
  95. {mcp_agent → fast_agent}/mcp/mcp_aggregator.py +66 -115
  96. {mcp_agent → fast_agent}/mcp/mcp_connection_manager.py +16 -23
  97. {mcp_agent/core → fast_agent/mcp}/mcp_content.py +23 -15
  98. {mcp_agent → fast_agent}/mcp/mime_utils.py +39 -0
  99. fast_agent/mcp/prompt.py +159 -0
  100. mcp_agent/mcp/prompt_message_multipart.py → fast_agent/mcp/prompt_message_extended.py +27 -20
  101. {mcp_agent → fast_agent}/mcp/prompt_render.py +21 -19
  102. {mcp_agent → fast_agent}/mcp/prompt_serialization.py +46 -46
  103. fast_agent/mcp/prompts/__main__.py +7 -0
  104. {mcp_agent → fast_agent}/mcp/prompts/prompt_helpers.py +31 -30
  105. {mcp_agent → fast_agent}/mcp/prompts/prompt_load.py +8 -8
  106. {mcp_agent → fast_agent}/mcp/prompts/prompt_server.py +11 -19
  107. {mcp_agent → fast_agent}/mcp/prompts/prompt_template.py +18 -18
  108. {mcp_agent → fast_agent}/mcp/resource_utils.py +1 -1
  109. {mcp_agent → fast_agent}/mcp/sampling.py +31 -26
  110. {mcp_agent/mcp_server → fast_agent/mcp/server}/__init__.py +1 -1
  111. {mcp_agent/mcp_server → fast_agent/mcp/server}/agent_server.py +5 -6
  112. fast_agent/mcp/ui_agent.py +48 -0
  113. fast_agent/mcp/ui_mixin.py +209 -0
  114. fast_agent/mcp_server_registry.py +90 -0
  115. {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis-campaign.py +5 -4
  116. {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis.py +1 -1
  117. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/forms_demo.py +3 -3
  118. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character.py +2 -2
  119. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character_handler.py +1 -1
  120. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/tool_call.py +1 -1
  121. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_one.py +1 -1
  122. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_two.py +1 -1
  123. {mcp_agent → fast_agent}/resources/examples/researcher/researcher-eval.py +1 -1
  124. {mcp_agent → fast_agent}/resources/examples/researcher/researcher-imp.py +1 -1
  125. {mcp_agent → fast_agent}/resources/examples/researcher/researcher.py +1 -1
  126. {mcp_agent → fast_agent}/resources/examples/tensorzero/agent.py +2 -2
  127. {mcp_agent → fast_agent}/resources/examples/tensorzero/image_demo.py +3 -3
  128. {mcp_agent → fast_agent}/resources/examples/tensorzero/simple_agent.py +1 -1
  129. {mcp_agent → fast_agent}/resources/examples/workflows/chaining.py +1 -1
  130. {mcp_agent → fast_agent}/resources/examples/workflows/evaluator.py +3 -3
  131. {mcp_agent → fast_agent}/resources/examples/workflows/human_input.py +5 -3
  132. {mcp_agent → fast_agent}/resources/examples/workflows/orchestrator.py +1 -1
  133. {mcp_agent → fast_agent}/resources/examples/workflows/parallel.py +2 -2
  134. {mcp_agent → fast_agent}/resources/examples/workflows/router.py +5 -2
  135. fast_agent/resources/setup/.gitignore +24 -0
  136. fast_agent/resources/setup/agent.py +18 -0
  137. fast_agent/resources/setup/fastagent.config.yaml +44 -0
  138. fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
  139. fast_agent/resources/setup/pyproject.toml.tmpl +17 -0
  140. fast_agent/tools/elicitation.py +369 -0
  141. fast_agent/types/__init__.py +32 -0
  142. fast_agent/types/llm_stop_reason.py +77 -0
  143. fast_agent/ui/__init__.py +38 -0
  144. fast_agent/ui/console_display.py +1005 -0
  145. {mcp_agent/human_input → fast_agent/ui}/elicitation_form.py +17 -12
  146. mcp_agent/human_input/elicitation_forms.py → fast_agent/ui/elicitation_style.py +1 -1
  147. {mcp_agent/core → fast_agent/ui}/enhanced_prompt.py +96 -25
  148. {mcp_agent/core → fast_agent/ui}/interactive_prompt.py +330 -125
  149. fast_agent/ui/mcp_ui_utils.py +224 -0
  150. {mcp_agent → fast_agent/ui}/progress_display.py +2 -2
  151. {mcp_agent/logging → fast_agent/ui}/rich_progress.py +4 -4
  152. {mcp_agent/core → fast_agent/ui}/usage_display.py +3 -8
  153. {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/METADATA +7 -7
  154. fast_agent_mcp-0.3.1.dist-info/RECORD +203 -0
  155. fast_agent_mcp-0.3.1.dist-info/entry_points.txt +5 -0
  156. fast_agent_mcp-0.2.58.dist-info/RECORD +0 -193
  157. fast_agent_mcp-0.2.58.dist-info/entry_points.txt +0 -6
  158. mcp_agent/__init__.py +0 -114
  159. mcp_agent/agents/agent.py +0 -92
  160. mcp_agent/agents/workflow/__init__.py +0 -1
  161. mcp_agent/agents/workflow/orchestrator_agent.py +0 -597
  162. mcp_agent/app.py +0 -175
  163. mcp_agent/core/__init__.py +0 -26
  164. mcp_agent/core/prompt.py +0 -191
  165. mcp_agent/event_progress.py +0 -134
  166. mcp_agent/human_input/handler.py +0 -81
  167. mcp_agent/llm/__init__.py +0 -2
  168. mcp_agent/llm/augmented_llm_passthrough.py +0 -232
  169. mcp_agent/llm/augmented_llm_slow.py +0 -53
  170. mcp_agent/llm/providers/__init__.py +0 -8
  171. mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -718
  172. mcp_agent/llm/providers/augmented_llm_google_native.py +0 -496
  173. mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -57
  174. mcp_agent/llm/providers/sampling_converter_openai.py +0 -26
  175. mcp_agent/llm/sampling_format_converter.py +0 -37
  176. mcp_agent/logging/__init__.py +0 -0
  177. mcp_agent/mcp/__init__.py +0 -50
  178. mcp_agent/mcp/helpers/__init__.py +0 -25
  179. mcp_agent/mcp/helpers/content_helpers.py +0 -187
  180. mcp_agent/mcp/interfaces.py +0 -266
  181. mcp_agent/mcp/prompts/__init__.py +0 -0
  182. mcp_agent/mcp/prompts/__main__.py +0 -10
  183. mcp_agent/mcp_server_registry.py +0 -343
  184. mcp_agent/tools/tool_definition.py +0 -14
  185. mcp_agent/ui/console_display.py +0 -790
  186. mcp_agent/ui/console_display_legacy.py +0 -401
  187. {mcp_agent → fast_agent}/agents/workflow/orchestrator_prompts.py +0 -0
  188. {mcp_agent/agents → fast_agent/cli}/__init__.py +0 -0
  189. {mcp_agent → fast_agent}/cli/constants.py +0 -0
  190. {mcp_agent → fast_agent}/core/error_handling.py +0 -0
  191. {mcp_agent → fast_agent}/core/exceptions.py +0 -0
  192. {mcp_agent/cli → fast_agent/core/executor}/__init__.py +0 -0
  193. {mcp_agent → fast_agent/core}/executor/task_registry.py +0 -0
  194. {mcp_agent → fast_agent/core}/executor/workflow_signal.py +0 -0
  195. {mcp_agent → fast_agent}/human_input/form_fields.py +0 -0
  196. {mcp_agent → fast_agent}/llm/prompt_utils.py +0 -0
  197. {mcp_agent/core → fast_agent/llm}/request_params.py +0 -0
  198. {mcp_agent → fast_agent}/mcp/common.py +0 -0
  199. {mcp_agent/executor → fast_agent/mcp/prompts}/__init__.py +0 -0
  200. {mcp_agent → fast_agent}/mcp/prompts/prompt_constants.py +0 -0
  201. {mcp_agent → fast_agent}/py.typed +0 -0
  202. {mcp_agent → fast_agent}/resources/examples/data-analysis/fastagent.config.yaml +0 -0
  203. {mcp_agent → fast_agent}/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
  204. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_account_server.py +0 -0
  205. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_forms_server.py +0 -0
  206. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_game_server.py +0 -0
  207. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.config.yaml +0 -0
  208. {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +0 -0
  209. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
  210. {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
  211. {mcp_agent → fast_agent}/resources/examples/researcher/fastagent.config.yaml +0 -0
  212. {mcp_agent → fast_agent}/resources/examples/tensorzero/.env.sample +0 -0
  213. {mcp_agent → fast_agent}/resources/examples/tensorzero/Makefile +0 -0
  214. {mcp_agent → fast_agent}/resources/examples/tensorzero/README.md +0 -0
  215. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
  216. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/crab.png +0 -0
  217. {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
  218. {mcp_agent → fast_agent}/resources/examples/tensorzero/docker-compose.yml +0 -0
  219. {mcp_agent → fast_agent}/resources/examples/tensorzero/fastagent.config.yaml +0 -0
  220. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/Dockerfile +0 -0
  221. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/entrypoint.sh +0 -0
  222. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/mcp_server.py +0 -0
  223. {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/pyproject.toml +0 -0
  224. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_schema.json +0 -0
  225. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +0 -0
  226. {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +0 -0
  227. {mcp_agent → fast_agent}/resources/examples/workflows/fastagent.config.yaml +0 -0
  228. {mcp_agent → fast_agent}/resources/examples/workflows/graded_report.md +0 -0
  229. {mcp_agent → fast_agent}/resources/examples/workflows/short_story.md +0 -0
  230. {mcp_agent → fast_agent}/resources/examples/workflows/short_story.txt +0 -0
  231. {mcp_agent → fast_agent/ui}/console.py +0 -0
  232. {mcp_agent/core → fast_agent/ui}/mermaid_utils.py +0 -0
  233. {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/WHEEL +0 -0
  234. {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/licenses/LICENSE +0 -0
mcp_agent/app.py DELETED
@@ -1,175 +0,0 @@
1
- import asyncio
2
- from contextlib import asynccontextmanager
3
- from typing import TYPE_CHECKING, Dict, Optional, Type, TypeVar
4
-
5
- from mcp_agent.config import Settings
6
- from mcp_agent.context import Context, cleanup_context, initialize_context
7
- from mcp_agent.event_progress import ProgressAction
8
- from mcp_agent.executor.workflow_signal import SignalWaitCallback
9
- from mcp_agent.human_input.handler import console_input_callback
10
- from mcp_agent.human_input.types import HumanInputCallback
11
- from mcp_agent.logging.logger import get_logger
12
-
13
- if TYPE_CHECKING:
14
- from mcp import ServerSession
15
-
16
- R = TypeVar("R")
17
-
18
-
19
- class MCPApp:
20
- """
21
- Main application class that manages global state and can host workflows.
22
-
23
- Example usage:
24
- app = MCPApp()
25
-
26
- @app.workflow
27
- class MyWorkflow(Workflow[str]):
28
- @app.task
29
- async def my_task(self):
30
- pass
31
-
32
- async def run(self):
33
- await self.my_task()
34
-
35
- async with app.run() as running_app:
36
- workflow = MyWorkflow()
37
- result = await workflow.execute()
38
- """
39
-
40
- def __init__(
41
- self,
42
- name: str = "mcp_application",
43
- settings: Optional[Settings] | str = None,
44
- human_input_callback: Optional[HumanInputCallback] = console_input_callback,
45
- signal_notification: Optional[SignalWaitCallback] = None,
46
- upstream_session: Optional["ServerSession"] = None,
47
- ) -> None:
48
- """
49
- Initialize the application with a name and optional settings.
50
- Args:
51
- name: Name of the application
52
- settings: Application configuration - If unspecified, the settings are loaded from mcp_agent.config.yaml.
53
- If this is a string, it is treated as the path to the config file to load.
54
- human_input_callback: Callback for handling human input
55
- signal_notification: Callback for getting notified on workflow signals/events.
56
- upstream_session: Optional upstream session if the MCPApp is running as a server to an MCP client.
57
- """
58
- self.name = name
59
-
60
- # We use these to initialize the context in initialize()
61
- self._config_or_path = settings
62
- self._human_input_callback = human_input_callback
63
- self._signal_notification = signal_notification
64
- self._upstream_session = upstream_session
65
-
66
- self._workflows: Dict[str, Type] = {} # id to workflow class
67
- self._logger = None
68
- self._context: Optional[Context] = None
69
- self._initialized = False
70
-
71
- @property
72
- def context(self) -> Context:
73
- if self._context is None:
74
- raise RuntimeError(
75
- "MCPApp not initialized, please call initialize() first, or use async with app.run()."
76
- )
77
- return self._context
78
-
79
- @property
80
- def config(self):
81
- return self._context.config
82
-
83
- @property
84
- def server_registry(self):
85
- return self._context.server_registry
86
-
87
- @property
88
- def executor(self):
89
- return self._context.executor
90
-
91
- @property
92
- def engine(self):
93
- return self.executor.execution_engine
94
-
95
- @property
96
- def upstream_session(self):
97
- return self._context.upstream_session
98
-
99
- @upstream_session.setter
100
- def upstream_session(self, value) -> None:
101
- self._context.upstream_session = value
102
-
103
- @property
104
- def workflows(self):
105
- return self._workflows
106
-
107
- @property
108
- def tasks(self):
109
- return self.context.task_registry.list_activities()
110
-
111
- @property
112
- def logger(self):
113
- if self._logger is None:
114
- self._logger = get_logger(f"mcp_agent.{self.name}")
115
- return self._logger
116
-
117
- async def initialize(self) -> None:
118
- """Initialize the application."""
119
- if self._initialized:
120
- return
121
-
122
- self._context = await initialize_context(self._config_or_path, store_globally=True)
123
-
124
- # Set the properties that were passed in the constructor
125
- self._context.human_input_handler = self._human_input_callback
126
- self._context.signal_notification = self._signal_notification
127
- self._context.upstream_session = self._upstream_session
128
-
129
- self._initialized = True
130
- self.logger.info(
131
- "MCPAgent initialized",
132
- data={
133
- "progress_action": "Running",
134
- "target": self.name or "mcp_application",
135
- "agent_name": self.name or "fastagent loop",
136
- },
137
- )
138
-
139
- async def cleanup(self) -> None:
140
- """Cleanup application resources."""
141
- if not self._initialized:
142
- return
143
-
144
- # Updatre progress display before logging is shut down
145
- self.logger.info(
146
- "MCPAgent cleanup",
147
- data={
148
- "progress_action": ProgressAction.FINISHED,
149
- "target": self.name or "mcp_application",
150
- "agent_name": self.name or "fastagent loop",
151
- },
152
- )
153
- try:
154
- await cleanup_context()
155
- except asyncio.CancelledError:
156
- self.logger.debug("Cleanup cancelled error during shutdown")
157
-
158
- self._context = None
159
- self._initialized = False
160
-
161
- @asynccontextmanager
162
- async def run(self):
163
- """
164
- Run the application. Use as context manager.
165
-
166
- Example:
167
- async with app.run() as running_app:
168
- # App is initialized here
169
- pass
170
- """
171
- await self.initialize()
172
- try:
173
- yield self
174
- finally:
175
- await self.cleanup()
@@ -1,26 +0,0 @@
1
- """
2
- Core components and utilities for MCP Agent.
3
- """
4
-
5
- from .mcp_content import (
6
- Assistant,
7
- MCPContentType,
8
- MCPFile,
9
- MCPImage,
10
- MCPPrompt,
11
- MCPText,
12
- User,
13
- create_message,
14
- )
15
-
16
- __all__ = [
17
- # MCP content creation functions
18
- "MCPText",
19
- "MCPImage",
20
- "MCPFile",
21
- "MCPPrompt",
22
- "User",
23
- "Assistant",
24
- "create_message",
25
- "MCPContentType",
26
- ]
mcp_agent/core/prompt.py DELETED
@@ -1,191 +0,0 @@
1
- """
2
- Prompt class for easily creating and working with MCP prompt content.
3
- """
4
-
5
- from pathlib import Path
6
- from typing import List, Literal, Union
7
-
8
- from mcp.types import PromptMessage
9
-
10
- from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
11
-
12
- # Import our content helper functions
13
- from .mcp_content import Assistant, MCPContentType, MCPPrompt, User
14
-
15
-
16
- class Prompt:
17
- """
18
- A helper class for working with MCP prompt content.
19
-
20
- This class provides static methods to create:
21
- - PromptMessage instances
22
- - PromptMessageMultipart instances
23
- - Lists of messages for conversations
24
-
25
- All methods intelligently handle various content types:
26
- - Strings become TextContent
27
- - Image file paths become ImageContent
28
- - Other file paths become EmbeddedResource
29
- - TextContent objects are used directly
30
- - ImageContent objects are used directly
31
- - EmbeddedResource objects are used directly
32
- - Pre-formatted messages pass through unchanged
33
- """
34
-
35
- @classmethod
36
- def user(cls, *content_items: Union[str, Path, bytes, dict, MCPContentType, PromptMessage, PromptMessageMultipart]) -> PromptMessageMultipart:
37
- """
38
- Create a user PromptMessageMultipart with various content items.
39
-
40
- Args:
41
- *content_items: Content items in various formats:
42
- - Strings: Converted to TextContent
43
- - Path objects: Converted based on file type (image/text/binary)
44
- - Bytes: Treated as image data
45
- - Dicts with role/content: Content extracted
46
- - TextContent: Used directly
47
- - ImageContent: Used directly
48
- - EmbeddedResource: Used directly
49
- - PromptMessage: Content extracted
50
- - PromptMessageMultipart: Content extracted with role changed to user
51
-
52
- Returns:
53
- A PromptMessageMultipart with user role and the specified content
54
- """
55
- # Handle PromptMessage and PromptMessageMultipart directly
56
- if len(content_items) == 1:
57
- item = content_items[0]
58
- if isinstance(item, PromptMessage):
59
- return PromptMessageMultipart(role="user", content=[item.content])
60
- elif isinstance(item, PromptMessageMultipart):
61
- # Keep the content but change role to user
62
- return PromptMessageMultipart(role="user", content=item.content)
63
-
64
- # Use the original implementation for other types
65
- messages = User(*content_items)
66
- return PromptMessageMultipart(role="user", content=[msg["content"] for msg in messages])
67
-
68
- @classmethod
69
- def assistant(cls, *content_items: Union[str, Path, bytes, dict, MCPContentType, PromptMessage, PromptMessageMultipart]) -> PromptMessageMultipart:
70
- """
71
- Create an assistant PromptMessageMultipart with various content items.
72
-
73
- Args:
74
- *content_items: Content items in various formats:
75
- - Strings: Converted to TextContent
76
- - Path objects: Converted based on file type (image/text/binary)
77
- - Bytes: Treated as image data
78
- - Dicts with role/content: Content extracted
79
- - TextContent: Used directly
80
- - ImageContent: Used directly
81
- - EmbeddedResource: Used directly
82
- - PromptMessage: Content extracted
83
- - PromptMessageMultipart: Content extracted with role changed to assistant
84
-
85
- Returns:
86
- A PromptMessageMultipart with assistant role and the specified content
87
- """
88
- # Handle PromptMessage and PromptMessageMultipart directly
89
- if len(content_items) == 1:
90
- item = content_items[0]
91
- if isinstance(item, PromptMessage):
92
- return PromptMessageMultipart(role="assistant", content=[item.content])
93
- elif isinstance(item, PromptMessageMultipart):
94
- # Keep the content but change role to assistant
95
- return PromptMessageMultipart(role="assistant", content=item.content)
96
-
97
- # Use the original implementation for other types
98
- messages = Assistant(*content_items)
99
- return PromptMessageMultipart(
100
- role="assistant", content=[msg["content"] for msg in messages]
101
- )
102
-
103
- @classmethod
104
- def message(
105
- cls, *content_items: Union[str, Path, bytes, dict, MCPContentType, PromptMessage, PromptMessageMultipart],
106
- role: Literal["user", "assistant"] = "user"
107
- ) -> PromptMessageMultipart:
108
- """
109
- Create a PromptMessageMultipart with the specified role and content items.
110
-
111
- Args:
112
- *content_items: Content items in various formats:
113
- - Strings: Converted to TextContent
114
- - Path objects: Converted based on file type (image/text/binary)
115
- - Bytes: Treated as image data
116
- - Dicts with role/content: Content extracted
117
- - TextContent: Used directly
118
- - ImageContent: Used directly
119
- - EmbeddedResource: Used directly
120
- - PromptMessage: Content extracted
121
- - PromptMessageMultipart: Content extracted with role changed as specified
122
- role: Role for the message (user or assistant)
123
-
124
- Returns:
125
- A PromptMessageMultipart with the specified role and content
126
- """
127
- # Handle PromptMessage and PromptMessageMultipart directly
128
- if len(content_items) == 1:
129
- item = content_items[0]
130
- if isinstance(item, PromptMessage):
131
- return PromptMessageMultipart(role=role, content=[item.content])
132
- elif isinstance(item, PromptMessageMultipart):
133
- # Keep the content but change role as specified
134
- return PromptMessageMultipart(role=role, content=item.content)
135
-
136
- # Use the original implementation for other types
137
- messages = MCPPrompt(*content_items, role=role)
138
- return PromptMessageMultipart(
139
- role=messages[0]["role"] if messages else role,
140
- content=[msg["content"] for msg in messages],
141
- )
142
-
143
- @classmethod
144
- def conversation(cls, *messages) -> List[PromptMessage]:
145
- """
146
- Create a list of PromptMessages from various inputs.
147
-
148
- This method accepts:
149
- - PromptMessageMultipart instances
150
- - Dictionaries with role and content
151
- - Lists of dictionaries with role and content
152
-
153
- Args:
154
- *messages: Messages to include in the conversation
155
-
156
- Returns:
157
- A list of PromptMessage objects for the conversation
158
- """
159
- result = []
160
-
161
- for item in messages:
162
- if isinstance(item, PromptMessageMultipart):
163
- # Convert PromptMessageMultipart to a list of PromptMessages
164
- result.extend(item.from_multipart())
165
- elif isinstance(item, dict) and "role" in item and "content" in item:
166
- # Convert a single message dict to PromptMessage
167
- result.append(PromptMessage(**item))
168
- elif isinstance(item, list):
169
- # Process each item in the list
170
- for msg in item:
171
- if isinstance(msg, dict) and "role" in msg and "content" in msg:
172
- result.append(PromptMessage(**msg))
173
- # Ignore other types
174
-
175
- return result
176
-
177
- @classmethod
178
- def from_multipart(cls, multipart: List[PromptMessageMultipart]) -> List[PromptMessage]:
179
- """
180
- Convert a list of PromptMessageMultipart objects to PromptMessages.
181
-
182
- Args:
183
- multipart: List of PromptMessageMultipart objects
184
-
185
- Returns:
186
- A flat list of PromptMessage objects
187
- """
188
- result = []
189
- for mp in multipart:
190
- result.extend(mp.from_multipart())
191
- return result
@@ -1,134 +0,0 @@
1
- """Module for converting log events to progress events."""
2
-
3
- from enum import Enum
4
- from typing import Optional
5
-
6
- from pydantic import BaseModel
7
-
8
- from mcp_agent.logging.events import Event
9
-
10
-
11
- class ProgressAction(str, Enum):
12
- """Progress actions available in the system."""
13
-
14
- STARTING = "Starting"
15
- LOADED = "Loaded"
16
- INITIALIZED = "Initialized"
17
- CHATTING = "Chatting"
18
- STREAMING = "Streaming" # Special action for real-time streaming updates
19
- ROUTING = "Routing"
20
- PLANNING = "Planning"
21
- READY = "Ready"
22
- CALLING_TOOL = "Calling Tool"
23
- TOOL_PROGRESS = "Tool Progress"
24
- UPDATED = "Updated"
25
- FINISHED = "Finished"
26
- SHUTDOWN = "Shutdown"
27
- AGGREGATOR_INITIALIZED = "Running"
28
- SERVER_OFFLINE = "Offline"
29
- SERVER_RECONNECTING = "Reconnecting"
30
- SERVER_ONLINE = "Online"
31
- FATAL_ERROR = "Error"
32
-
33
-
34
- class ProgressEvent(BaseModel):
35
- """Represents a progress event converted from a log event."""
36
-
37
- action: ProgressAction
38
- target: str
39
- details: Optional[str] = None
40
- agent_name: Optional[str] = None
41
- streaming_tokens: Optional[str] = None # Special field for streaming token count
42
- progress: Optional[float] = None # Current progress value
43
- total: Optional[float] = None # Total value for progress calculation
44
-
45
- def __str__(self) -> str:
46
- """Format the progress event for display."""
47
- # Special handling for streaming - show token count in action position
48
- if self.action == ProgressAction.STREAMING and self.streaming_tokens:
49
- # For streaming, show just the token count instead of "Streaming"
50
- action_display = self.streaming_tokens.ljust(11)
51
- base = f"{action_display}. {self.target}"
52
- if self.details:
53
- base += f" - {self.details}"
54
- else:
55
- base = f"{self.action.ljust(11)}. {self.target}"
56
- if self.details:
57
- base += f" - {self.details}"
58
-
59
- if self.agent_name:
60
- base = f"[{self.agent_name}] {base}"
61
- return base
62
-
63
-
64
- def convert_log_event(event: Event) -> Optional[ProgressEvent]:
65
- """Convert a log event to a progress event if applicable."""
66
-
67
- # Check to see if there is any additional data
68
- if not event.data:
69
- return None
70
-
71
- event_data = event.data.get("data")
72
- if not isinstance(event_data, dict):
73
- return None
74
-
75
- progress_action = event_data.get("progress_action")
76
- if not progress_action:
77
- return None
78
-
79
- # Build target string based on the event type.
80
- # Progress display is currently [time] [event] --- [target] [details]
81
- namespace = event.namespace
82
- agent_name = event_data.get("agent_name")
83
- target = agent_name
84
- details = ""
85
- if progress_action == ProgressAction.FATAL_ERROR:
86
- details = event_data.get("error_message", "An error occurred")
87
- elif "mcp_aggregator" in namespace:
88
- server_name = event_data.get("server_name", "")
89
- tool_name = event_data.get("tool_name")
90
- if tool_name:
91
- # fetch(fetch)
92
- details = f"{server_name} ({tool_name})"
93
- else:
94
- details = f"{server_name}"
95
-
96
- # For TOOL_PROGRESS, use progress message if available, otherwise keep default
97
- if progress_action == ProgressAction.TOOL_PROGRESS:
98
- progress_message = event_data.get("details", "")
99
- if progress_message: # Only override if message is non-empty
100
- details = progress_message
101
-
102
- elif "augmented_llm" in namespace:
103
- model = event_data.get("model", "")
104
-
105
- # For all augmented_llm events, put model info in details column
106
- details = f"{model}"
107
- chat_turn = event_data.get("chat_turn")
108
- if chat_turn is not None:
109
- details = f"{model} turn {chat_turn}"
110
- else:
111
- if not target:
112
- target = event_data.get("target", "unknown")
113
-
114
- # Extract streaming token count for STREAMING actions
115
- streaming_tokens = None
116
- if progress_action == ProgressAction.STREAMING:
117
- streaming_tokens = event_data.get("details", "")
118
-
119
- # Extract progress data for TOOL_PROGRESS actions
120
- progress = None
121
- total = None
122
- if progress_action == ProgressAction.TOOL_PROGRESS:
123
- progress = event_data.get("progress")
124
- total = event_data.get("total")
125
-
126
- return ProgressEvent(
127
- action=ProgressAction(progress_action),
128
- target=target or "unknown",
129
- details=details,
130
- agent_name=event_data.get("agent_name"),
131
- streaming_tokens=streaming_tokens,
132
- progress=progress,
133
- total=total,
134
- )
@@ -1,81 +0,0 @@
1
- import asyncio
2
-
3
- from rich.panel import Panel
4
-
5
- from mcp_agent.console import console
6
- from mcp_agent.core.enhanced_prompt import get_enhanced_input, handle_special_commands
7
- from mcp_agent.human_input.types import (
8
- HumanInputRequest,
9
- HumanInputResponse,
10
- )
11
- from mcp_agent.progress_display import progress_display
12
-
13
-
14
- async def console_input_callback(request: HumanInputRequest) -> HumanInputResponse:
15
- """Request input from a human user via console using prompt_toolkit."""
16
-
17
- # Prepare the prompt text
18
- prompt_text = request.prompt
19
- if request.description:
20
- prompt_text = f"[bold]{request.description}[/bold]\n\n{request.prompt}"
21
-
22
- # Create a panel with the prompt
23
- panel = Panel(
24
- prompt_text,
25
- title="[HUMAN INPUT REQUESTED]",
26
- title_align="left",
27
- style="green",
28
- border_style="bold white",
29
- padding=(1, 2),
30
- )
31
-
32
- # Extract agent name from metadata dictionary
33
- agent_name = (
34
- request.metadata.get("agent_name", "Unknown Agent") if request.metadata else "Unknown Agent"
35
- )
36
-
37
- # Use the context manager to pause the progress display while getting input
38
- with progress_display.paused():
39
- console.print(panel)
40
-
41
- try:
42
- if request.timeout_seconds:
43
- try:
44
- # Use get_enhanced_input with empty agent list to disable agent switching
45
- response = await asyncio.wait_for(
46
- get_enhanced_input(
47
- agent_name=agent_name,
48
- available_agent_names=[], # No agents for selection
49
- show_stop_hint=False,
50
- is_human_input=True,
51
- toolbar_color="ansimagenta",
52
- ),
53
- request.timeout_seconds,
54
- )
55
- except asyncio.TimeoutError:
56
- console.print("\n[red]Timeout waiting for input[/red]")
57
- raise TimeoutError("No response received within timeout period")
58
- else:
59
- response = await get_enhanced_input(
60
- agent_name=agent_name,
61
- available_agent_names=[], # No agents for selection
62
- show_stop_hint=False,
63
- is_human_input=True,
64
- toolbar_color="ansimagenta",
65
- )
66
-
67
- # Handle special commands but ignore dictionary results as they require app context
68
- command_result = await handle_special_commands(response)
69
- if isinstance(command_result, dict) and "list_prompts" in command_result:
70
- from rich import print as rich_print
71
-
72
- rich_print("[yellow]Prompt listing not available in human input context[/yellow]")
73
-
74
- except KeyboardInterrupt:
75
- console.print("\n[yellow]Input interrupted[/yellow]")
76
- response = ""
77
- except EOFError:
78
- console.print("\n[yellow]Input terminated[/yellow]")
79
- response = ""
80
-
81
- return HumanInputResponse(request_id=request.request_id, response=response.strip())
mcp_agent/llm/__init__.py DELETED
@@ -1,2 +0,0 @@
1
- # LLM module
2
- # Contains code for working with large language models