fast-agent-mcp 0.1.13__py3-none-any.whl → 0.2.0__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.
Files changed (147) hide show
  1. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
  2. fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
  3. mcp_agent/__init__.py +75 -0
  4. mcp_agent/agents/agent.py +59 -371
  5. mcp_agent/agents/base_agent.py +522 -0
  6. mcp_agent/agents/workflow/__init__.py +1 -0
  7. mcp_agent/agents/workflow/chain_agent.py +173 -0
  8. mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
  9. mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
  10. mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +27 -11
  11. mcp_agent/agents/workflow/parallel_agent.py +182 -0
  12. mcp_agent/agents/workflow/router_agent.py +307 -0
  13. mcp_agent/app.py +3 -1
  14. mcp_agent/cli/commands/bootstrap.py +18 -7
  15. mcp_agent/cli/commands/setup.py +12 -4
  16. mcp_agent/cli/main.py +1 -1
  17. mcp_agent/cli/terminal.py +1 -1
  18. mcp_agent/config.py +24 -35
  19. mcp_agent/context.py +3 -1
  20. mcp_agent/context_dependent.py +3 -1
  21. mcp_agent/core/agent_types.py +10 -7
  22. mcp_agent/core/direct_agent_app.py +179 -0
  23. mcp_agent/core/direct_decorators.py +443 -0
  24. mcp_agent/core/direct_factory.py +476 -0
  25. mcp_agent/core/enhanced_prompt.py +15 -20
  26. mcp_agent/core/fastagent.py +151 -337
  27. mcp_agent/core/interactive_prompt.py +424 -0
  28. mcp_agent/core/mcp_content.py +19 -11
  29. mcp_agent/core/prompt.py +6 -2
  30. mcp_agent/core/validation.py +89 -16
  31. mcp_agent/executor/decorator_registry.py +6 -2
  32. mcp_agent/executor/temporal.py +35 -11
  33. mcp_agent/executor/workflow_signal.py +8 -2
  34. mcp_agent/human_input/handler.py +3 -1
  35. mcp_agent/llm/__init__.py +2 -0
  36. mcp_agent/{workflows/llm → llm}/augmented_llm.py +131 -256
  37. mcp_agent/{workflows/llm → llm}/augmented_llm_passthrough.py +35 -107
  38. mcp_agent/llm/augmented_llm_playback.py +83 -0
  39. mcp_agent/{workflows/llm → llm}/model_factory.py +26 -8
  40. mcp_agent/llm/providers/__init__.py +8 -0
  41. mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +5 -1
  42. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +37 -141
  43. mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
  44. mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +112 -148
  45. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +78 -35
  46. mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +73 -44
  47. mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +18 -4
  48. mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +3 -3
  49. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +3 -3
  50. mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +3 -3
  51. mcp_agent/{workflows/llm → llm}/sampling_converter.py +0 -21
  52. mcp_agent/{workflows/llm → llm}/sampling_format_converter.py +16 -1
  53. mcp_agent/logging/logger.py +2 -2
  54. mcp_agent/mcp/gen_client.py +9 -3
  55. mcp_agent/mcp/interfaces.py +67 -45
  56. mcp_agent/mcp/logger_textio.py +97 -0
  57. mcp_agent/mcp/mcp_agent_client_session.py +12 -4
  58. mcp_agent/mcp/mcp_agent_server.py +3 -1
  59. mcp_agent/mcp/mcp_aggregator.py +124 -93
  60. mcp_agent/mcp/mcp_connection_manager.py +21 -7
  61. mcp_agent/mcp/prompt_message_multipart.py +59 -1
  62. mcp_agent/mcp/prompt_render.py +77 -0
  63. mcp_agent/mcp/prompt_serialization.py +20 -13
  64. mcp_agent/mcp/prompts/prompt_constants.py +18 -0
  65. mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
  66. mcp_agent/mcp/prompts/prompt_load.py +15 -5
  67. mcp_agent/mcp/prompts/prompt_server.py +154 -87
  68. mcp_agent/mcp/prompts/prompt_template.py +26 -35
  69. mcp_agent/mcp/resource_utils.py +3 -1
  70. mcp_agent/mcp/sampling.py +24 -15
  71. mcp_agent/mcp_server/agent_server.py +8 -5
  72. mcp_agent/mcp_server_registry.py +22 -9
  73. mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +1 -1
  74. mcp_agent/resources/examples/{data-analysis → in_dev}/slides.py +1 -1
  75. mcp_agent/resources/examples/internal/agent.py +4 -2
  76. mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
  77. mcp_agent/resources/examples/prompting/image_server.py +3 -1
  78. mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
  79. mcp_agent/ui/console_display.py +27 -7
  80. fast_agent_mcp-0.1.13.dist-info/RECORD +0 -164
  81. mcp_agent/core/agent_app.py +0 -570
  82. mcp_agent/core/agent_utils.py +0 -69
  83. mcp_agent/core/decorators.py +0 -448
  84. mcp_agent/core/factory.py +0 -422
  85. mcp_agent/core/proxies.py +0 -278
  86. mcp_agent/core/types.py +0 -22
  87. mcp_agent/eval/__init__.py +0 -0
  88. mcp_agent/mcp/stdio.py +0 -114
  89. mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
  90. mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
  91. mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
  92. mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
  93. mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
  94. mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
  95. mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
  96. mcp_agent/resources/examples/researcher/researcher-imp.py +0 -189
  97. mcp_agent/resources/examples/researcher/researcher.py +0 -39
  98. mcp_agent/resources/examples/workflows/chaining.py +0 -45
  99. mcp_agent/resources/examples/workflows/evaluator.py +0 -79
  100. mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
  101. mcp_agent/resources/examples/workflows/human_input.py +0 -26
  102. mcp_agent/resources/examples/workflows/orchestrator.py +0 -74
  103. mcp_agent/resources/examples/workflows/parallel.py +0 -79
  104. mcp_agent/resources/examples/workflows/router.py +0 -54
  105. mcp_agent/resources/examples/workflows/sse.py +0 -23
  106. mcp_agent/telemetry/__init__.py +0 -0
  107. mcp_agent/telemetry/usage_tracking.py +0 -19
  108. mcp_agent/workflows/__init__.py +0 -0
  109. mcp_agent/workflows/embedding/__init__.py +0 -0
  110. mcp_agent/workflows/embedding/embedding_base.py +0 -58
  111. mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
  112. mcp_agent/workflows/embedding/embedding_openai.py +0 -37
  113. mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
  114. mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -447
  115. mcp_agent/workflows/intent_classifier/__init__.py +0 -0
  116. mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -117
  117. mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -130
  118. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -41
  119. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -41
  120. mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -150
  121. mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
  122. mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -58
  123. mcp_agent/workflows/llm/__init__.py +0 -0
  124. mcp_agent/workflows/llm/augmented_llm_playback.py +0 -111
  125. mcp_agent/workflows/llm/providers/__init__.py +0 -8
  126. mcp_agent/workflows/orchestrator/__init__.py +0 -0
  127. mcp_agent/workflows/orchestrator/orchestrator.py +0 -535
  128. mcp_agent/workflows/parallel/__init__.py +0 -0
  129. mcp_agent/workflows/parallel/fan_in.py +0 -320
  130. mcp_agent/workflows/parallel/fan_out.py +0 -181
  131. mcp_agent/workflows/parallel/parallel_llm.py +0 -149
  132. mcp_agent/workflows/router/__init__.py +0 -0
  133. mcp_agent/workflows/router/router_base.py +0 -338
  134. mcp_agent/workflows/router/router_embedding.py +0 -226
  135. mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
  136. mcp_agent/workflows/router/router_embedding_openai.py +0 -59
  137. mcp_agent/workflows/router/router_llm.py +0 -304
  138. mcp_agent/workflows/swarm/__init__.py +0 -0
  139. mcp_agent/workflows/swarm/swarm.py +0 -292
  140. mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
  141. mcp_agent/workflows/swarm/swarm_openai.py +0 -41
  142. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
  143. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
  144. {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
  145. /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
  146. /mcp_agent/{workflows/llm → llm}/memory.py +0 -0
  147. /mcp_agent/{workflows/llm → llm}/prompt_utils.py +0 -0
@@ -1,38 +1,42 @@
1
1
  """
2
- Decorator-based interface for MCP Agent applications.
3
- Provides a simplified way to create and manage agents using decorators.
2
+ Direct FastAgent implementation that uses the simplified Agent architecture.
3
+ This replaces the traditional FastAgent with a more streamlined approach that
4
+ directly creates Agent instances without proxies.
4
5
  """
5
6
 
6
7
  import argparse
7
8
  import asyncio
9
+ import os
8
10
  from contextlib import asynccontextmanager
9
- from functools import partial
10
- from typing import (
11
- Any,
12
- Dict,
13
- Optional,
14
- TypeVar,
15
- )
11
+ from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar
16
12
 
17
13
  import yaml
18
14
 
19
- # TODO -- reinstate once Windows&Python 3.13 platform issues are fixed
20
- # import readline # noqa: F401
21
- from rich import print
22
-
23
15
  from mcp_agent.app import MCPApp
24
16
  from mcp_agent.config import Settings
25
- from mcp_agent.core.agent_app import AgentApp
26
- from mcp_agent.core.agent_types import AgentType
27
- from mcp_agent.core.decorators import (
28
- _create_decorator,
29
- agent,
30
- chain,
31
- evaluator_optimizer,
32
- orchestrator,
33
- parallel,
34
- passthrough,
35
- router,
17
+ from mcp_agent.context import Context
18
+ from mcp_agent.core.direct_agent_app import DirectAgentApp
19
+ from mcp_agent.core.direct_decorators import (
20
+ agent as agent_decorator,
21
+ )
22
+ from mcp_agent.core.direct_decorators import (
23
+ chain as chain_decorator,
24
+ )
25
+ from mcp_agent.core.direct_decorators import (
26
+ evaluator_optimizer as evaluator_optimizer_decorator,
27
+ )
28
+ from mcp_agent.core.direct_decorators import (
29
+ orchestrator as orchestrator_decorator,
30
+ )
31
+ from mcp_agent.core.direct_decorators import (
32
+ parallel as parallel_decorator,
33
+ )
34
+ from mcp_agent.core.direct_decorators import (
35
+ router as router_decorator,
36
+ )
37
+ from mcp_agent.core.direct_factory import (
38
+ create_agents_in_dependency_order,
39
+ get_model_factory,
36
40
  )
37
41
  from mcp_agent.core.error_handling import handle_error
38
42
  from mcp_agent.core.exceptions import (
@@ -44,27 +48,23 @@ from mcp_agent.core.exceptions import (
44
48
  ServerConfigError,
45
49
  ServerInitializationError,
46
50
  )
47
- from mcp_agent.core.factory import (
48
- create_agents_by_type,
49
- create_agents_in_dependency_order,
50
- create_basic_agents,
51
- get_model_factory,
52
- )
53
- from mcp_agent.core.proxies import LLMAgentProxy
54
- from mcp_agent.core.types import ProxyDict
55
51
  from mcp_agent.core.validation import (
56
52
  validate_server_references,
57
53
  validate_workflow_references,
58
54
  )
59
- from mcp_agent.mcp_server import AgentMCPServer
55
+ from mcp_agent.logging.logger import get_logger
56
+
57
+ if TYPE_CHECKING:
58
+ from mcp_agent.agents.agent import Agent
60
59
 
61
- T = TypeVar("T") # For the wrapper classes
60
+ F = TypeVar("F", bound=Callable[..., Any]) # For decorated functions
61
+ logger = get_logger(__name__)
62
62
 
63
63
 
64
64
  class FastAgent:
65
65
  """
66
- A decorator-based interface for MCP Agent applications.
67
- Provides a simplified way to create and manage agents using decorators.
66
+ A simplified FastAgent implementation that directly creates Agent instances
67
+ without using proxies.
68
68
  """
69
69
 
70
70
  def __init__(
@@ -74,20 +74,18 @@ class FastAgent:
74
74
  ignore_unknown_args: bool = False,
75
75
  ) -> None:
76
76
  """
77
- Initialize the decorator interface.
77
+ Initialize the DirectFastAgent application.
78
78
 
79
79
  Args:
80
80
  name: Name of the application
81
81
  config_path: Optional path to config file
82
+ ignore_unknown_args: Whether to ignore unknown command line arguments
82
83
  """
83
- # Initialize ContextDependent
84
- super().__init__()
85
-
86
84
  # Setup command line argument parsing
87
- parser = argparse.ArgumentParser(description="MCP Agent Application")
85
+ parser = argparse.ArgumentParser(description="DirectFastAgent Application")
88
86
  parser.add_argument(
89
87
  "--model",
90
- help="Override the default model for all agents. Precedence is default < config_file < command line < constructor",
88
+ help="Override the default model for all agents",
91
89
  )
92
90
  parser.add_argument(
93
91
  "--agent",
@@ -110,8 +108,6 @@ class FastAgent:
110
108
  else:
111
109
  self.args = parser.parse_args()
112
110
 
113
- # Quiet mode will be handled in _load_config()
114
-
115
111
  self.name = name
116
112
  self.config_path = config_path
117
113
  self._load_config()
@@ -121,194 +117,55 @@ class FastAgent:
121
117
  name=name,
122
118
  settings=Settings(**self.config) if hasattr(self, "config") else None,
123
119
  )
124
- self.agents: Dict[str, Dict[str, Any]] = {}
125
-
126
- # Bind decorator methods to this instance
127
- self._create_decorator = _create_decorator.__get__(self)
128
- self.agent = agent.__get__(self)
129
- self.orchestrator = orchestrator.__get__(self)
130
- self.parallel = parallel.__get__(self)
131
- self.evaluator_optimizer = evaluator_optimizer.__get__(self)
132
- self.router = router.__get__(self)
133
- self.chain = chain.__get__(self)
134
- self.passthrough = passthrough.__get__(self)
135
120
 
136
- # _create_proxy moved to factory.py
137
-
138
- @property
139
- def context(self):
140
- """Access the application context"""
141
- return self.app.context
121
+ # Dictionary to store agent configurations from decorators
122
+ self.agents: Dict[str, Dict[str, Any]] = {}
142
123
 
143
124
  def _load_config(self) -> None:
144
- """Load configuration from YAML file, properly handling without dotenv processing"""
125
+ """Load configuration from YAML file"""
145
126
  if self.config_path:
146
127
  with open(self.config_path) as f:
147
128
  self.config = yaml.safe_load(f) or {}
129
+ elif os.path.exists("fastagent.config.yaml"):
130
+ with open("fastagent.config.yaml") as f:
131
+ self.config = yaml.safe_load(f) or {}
132
+ else:
133
+ self.config = {}
148
134
 
149
- # Validation methods moved to validation.py
150
-
151
- def _get_model_factory(
152
- self,
153
- model: Optional[str] = None,
154
- request_params: Optional[Any] = None,
155
- ) -> Any:
156
- """
157
- Get model factory using specified or default model.
158
- Model string is parsed by ModelFactory to determine provider and reasoning effort.
159
-
160
- Args:
161
- model: Optional model specification string
162
- request_params: Optional RequestParams to configure LLM behavior
163
-
164
- Returns:
165
- ModelFactory instance for the specified or default model
166
- """
167
- # Wrap the factory function to use our context and CLI model
168
- return get_model_factory(
169
- self.context,
170
- model=model,
171
- request_params=request_params,
172
- cli_model=self.args.model if hasattr(self, "args") else None,
173
- )
174
-
175
- async def _create_agents_by_type(
176
- self,
177
- agent_app: MCPApp,
178
- agent_type: AgentType,
179
- active_agents: ProxyDict = None,
180
- **kwargs,
181
- ) -> ProxyDict:
182
- """
183
- Generic method to create agents of a specific type.
184
-
185
- Args:
186
- agent_app: The main application instance
187
- agent_type: Type of agents to create
188
- active_agents: Dictionary of already created agents/proxies (for dependencies)
189
- **kwargs: Additional type-specific parameters
190
-
191
- Returns:
192
- Dictionary of initialized agents wrapped in appropriate proxies
193
- """
194
- # Create a model factory function that we can pass to the factory module
195
- model_factory_func = partial(self._get_model_factory)
196
-
197
- return await create_agents_by_type(
198
- agent_app,
199
- self.agents,
200
- agent_type,
201
- active_agents,
202
- model_factory_func=model_factory_func,
203
- **kwargs,
204
- )
205
-
206
- async def _create_basic_agents(self, agent_app: MCPApp) -> ProxyDict:
207
- """
208
- Create and initialize basic agents with their configurations.
209
-
210
- Args:
211
- agent_app: The main application instance
212
-
213
- Returns:
214
- Dictionary of initialized basic agents wrapped in appropriate proxies
215
- """
216
- model_factory_func = partial(self._get_model_factory)
217
- return await create_basic_agents(agent_app, self.agents, model_factory_func)
218
-
219
- async def _create_orchestrators(self, agent_app: MCPApp, active_agents: ProxyDict) -> ProxyDict:
220
- """
221
- Create orchestrator agents.
222
-
223
- Args:
224
- agent_app: The main application instance
225
- active_agents: Dictionary of already created agents/proxies
226
-
227
- Returns:
228
- Dictionary of initialized orchestrator agents wrapped in appropriate proxies
229
- """
230
- return await self._create_agents_by_type(agent_app, AgentType.ORCHESTRATOR, active_agents)
231
-
232
- async def _create_evaluator_optimizers(self, agent_app: MCPApp, active_agents: ProxyDict) -> ProxyDict:
233
- """
234
- Create evaluator-optimizer workflows.
235
-
236
- Args:
237
- agent_app: The main application instance
238
- active_agents: Dictionary of already created agents/proxies
239
-
240
- Returns:
241
- Dictionary of initialized evaluator-optimizer workflows
242
- """
243
- return await self._create_agents_by_type(agent_app, AgentType.EVALUATOR_OPTIMIZER, active_agents)
244
-
245
- async def _create_parallel_agents(self, agent_app: MCPApp, active_agents: ProxyDict) -> ProxyDict:
246
- """
247
- Create parallel execution agents in dependency order.
248
-
249
- Args:
250
- agent_app: The main application instance
251
- active_agents: Dictionary of already created agents/proxies
252
-
253
- Returns:
254
- Dictionary of initialized parallel agents
255
- """
256
- model_factory_func = partial(self._get_model_factory)
257
- return await create_agents_in_dependency_order(
258
- agent_app,
259
- self.agents,
260
- active_agents,
261
- AgentType.PARALLEL,
262
- model_factory_func,
263
- )
264
-
265
- async def _create_agents_in_dependency_order(self, agent_app: MCPApp, active_agents: ProxyDict, agent_type: AgentType) -> ProxyDict:
266
- """
267
- Create agents in dependency order to avoid circular references.
268
- Works for both Parallel and Chain workflows.
269
-
270
- Args:
271
- agent_app: The main application instance
272
- active_agents: Dictionary of already created agents/proxies
273
- agent_type: Type of agents to create (AgentType.PARALLEL or AgentType.CHAIN)
274
-
275
- Returns:
276
- Dictionary of initialized agents
277
- """
278
- model_factory_func = partial(self._get_model_factory)
279
- return await create_agents_in_dependency_order(agent_app, self.agents, active_agents, agent_type, model_factory_func)
280
-
281
- async def _create_routers(self, agent_app: MCPApp, active_agents: ProxyDict) -> ProxyDict:
282
- """
283
- Create router agents.
284
-
285
- Args:
286
- agent_app: The main application instance
287
- active_agents: Dictionary of already created agents
135
+ @property
136
+ def context(self) -> Context:
137
+ """Access the application context"""
138
+ return self.app.context
288
139
 
289
- Returns:
290
- Dictionary of initialized router agents
291
- """
292
- return await self._create_agents_by_type(agent_app, AgentType.ROUTER, active_agents)
140
+ # Decorator methods with type-safe implementations
141
+ agent = agent_decorator
142
+ orchestrator = orchestrator_decorator
143
+ router = router_decorator
144
+ chain = chain_decorator
145
+ parallel = parallel_decorator
146
+ evaluator_optimizer = evaluator_optimizer_decorator
293
147
 
294
148
  @asynccontextmanager
295
149
  async def run(self):
296
150
  """
297
151
  Context manager for running the application.
298
- Performs validation and provides user-friendly error messages.
152
+ Initializes all registered agents.
299
153
  """
300
- active_agents = {}
154
+ active_agents: Dict[str, Agent] = {}
301
155
  had_error = False
302
156
  await self.app.initialize()
303
157
 
304
- # Handle quiet mode by disabling logger settings after initialization
158
+ # Handle quiet mode
305
159
  quiet_mode = hasattr(self, "args") and self.args.quiet
306
160
 
307
161
  try:
308
162
  async with self.app.run() as agent_app:
309
- # Apply quiet mode directly to the context's config if needed
310
- if quiet_mode and hasattr(agent_app.context, "config") and hasattr(agent_app.context.config, "logger"):
311
- # Apply after initialization but before agents are created
163
+ # Apply quiet mode if requested
164
+ if (
165
+ quiet_mode
166
+ and hasattr(agent_app.context, "config")
167
+ and hasattr(agent_app.context.config, "logger")
168
+ ):
312
169
  agent_app.context.config.logger.progress_display = False
313
170
  agent_app.context.config.logger.show_chat = False
314
171
  agent_app.context.config.logger.show_tools = False
@@ -316,59 +173,49 @@ class FastAgent:
316
173
  # Directly disable the progress display singleton
317
174
  from mcp_agent.progress_display import progress_display
318
175
 
319
- progress_display.stop() # This will stop and hide the display
176
+ progress_display.stop()
320
177
 
321
178
  # Pre-flight validation
322
179
  validate_server_references(self.context, self.agents)
323
180
  validate_workflow_references(self.agents)
324
181
 
325
- # Create all types of agents in dependency order
326
- # First create basic agents
327
- active_agents = await self._create_basic_agents(agent_app)
328
-
329
- # Create parallel agents next as they might be dependencies
330
- parallel_agents = await self._create_parallel_agents(agent_app, active_agents)
331
- active_agents.update(parallel_agents)
332
-
333
- # Create routers next
334
- routers = await self._create_routers(agent_app, active_agents)
335
- active_agents.update(routers)
336
-
337
- # Create chains next - MOVED UP because evaluator-optimizers might depend on chains
338
- chains = await self._create_agents_in_dependency_order(agent_app, active_agents, AgentType.CHAIN)
339
- active_agents.update(chains)
340
-
341
- # Now create evaluator-optimizers AFTER chains are available
342
- evaluator_optimizers = await self._create_evaluator_optimizers(agent_app, active_agents)
343
- active_agents.update(evaluator_optimizers)
344
-
345
- # Create orchestrators last as they might depend on any other agent type
346
- orchestrators = await self._create_orchestrators(agent_app, active_agents)
347
-
348
- # Add orchestrators to active_agents (other types were already added)
349
- active_agents.update(orchestrators)
350
-
351
- # Create wrapper with all agents
352
- wrapper = AgentApp(agent_app, active_agents)
353
-
354
- # Store reference to AgentApp in MCPApp for proxies to access
355
- agent_app._agent_app = wrapper
182
+ # Get a model factory function
183
+ def model_factory_func(model=None, request_params=None):
184
+ return get_model_factory(
185
+ self.context,
186
+ model=model,
187
+ request_params=request_params,
188
+ cli_model=self.args.model if hasattr(self, "args") else None,
189
+ )
190
+
191
+ # Create all agents in dependency order
192
+ active_agents = await create_agents_in_dependency_order(
193
+ self.app,
194
+ self.agents,
195
+ model_factory_func,
196
+ )
197
+
198
+ # Create a wrapper with all agents for simplified access
199
+ wrapper = DirectAgentApp(active_agents)
356
200
 
357
201
  # Handle direct message sending if --agent and --message are provided
358
- if self.args.agent and self.args.message:
202
+ if hasattr(self, "args") and self.args.agent and self.args.message:
359
203
  agent_name = self.args.agent
360
204
  message = self.args.message
361
205
 
362
206
  if agent_name not in active_agents:
363
207
  available_agents = ", ".join(active_agents.keys())
364
- print(f"\n\nError: Agent '{agent_name}' not found. Available agents: {available_agents}")
208
+ print(
209
+ f"\n\nError: Agent '{agent_name}' not found. Available agents: {available_agents}"
210
+ )
365
211
  raise SystemExit(1)
366
212
 
367
213
  try:
368
- # Get response
369
- response = await wrapper[agent_name].send(message)
214
+ # Get response from the agent
215
+ agent = active_agents[agent_name]
216
+ response = await agent.send(message)
370
217
 
371
- # Only print the response in quiet mode
218
+ # Print the response in quiet mode
372
219
  if self.args.quiet:
373
220
  print(f"{response}")
374
221
 
@@ -379,127 +226,90 @@ class FastAgent:
379
226
 
380
227
  yield wrapper
381
228
 
382
- except ServerConfigError as e:
229
+ except (
230
+ ServerConfigError,
231
+ ProviderKeyError,
232
+ AgentConfigError,
233
+ ServerInitializationError,
234
+ ModelConfigError,
235
+ CircularDependencyError,
236
+ PromptExitError,
237
+ ) as e:
383
238
  had_error = True
384
- self._handle_error(
239
+ self._handle_error(e)
240
+ raise SystemExit(1)
241
+
242
+ finally:
243
+ # Clean up any active agents
244
+ if active_agents and not had_error:
245
+ for agent in active_agents.values():
246
+ try:
247
+ await agent.shutdown()
248
+ except Exception:
249
+ pass
250
+
251
+ def _handle_error(self, e: Exception, error_type: Optional[str] = None) -> None:
252
+ """
253
+ Handle errors with consistent formatting and messaging.
254
+
255
+ Args:
256
+ e: The exception that was raised
257
+ error_type: Optional explicit error type
258
+ """
259
+ if isinstance(e, ServerConfigError):
260
+ handle_error(
385
261
  e,
386
262
  "Server Configuration Error",
387
263
  "Please check your 'fastagent.config.yaml' configuration file and add the missing server definitions.",
388
264
  )
389
- raise SystemExit(1)
390
-
391
- except ProviderKeyError as e:
392
- had_error = True
393
- self._handle_error(
265
+ elif isinstance(e, ProviderKeyError):
266
+ handle_error(
394
267
  e,
395
268
  "Provider Configuration Error",
396
269
  "Please check your 'fastagent.secrets.yaml' configuration file and ensure all required API keys are set.",
397
270
  )
398
- raise SystemExit(1)
399
-
400
- except AgentConfigError as e:
401
- had_error = True
402
- self._handle_error(
271
+ elif isinstance(e, AgentConfigError):
272
+ handle_error(
403
273
  e,
404
274
  "Workflow or Agent Configuration Error",
405
275
  "Please check your agent definition and ensure names and references are correct.",
406
276
  )
407
- raise SystemExit(1)
408
-
409
- except ServerInitializationError as e:
410
- had_error = True
411
- self._handle_error(
277
+ elif isinstance(e, ServerInitializationError):
278
+ handle_error(
412
279
  e,
413
280
  "MCP Server Startup Error",
414
281
  "There was an error starting up the MCP Server.",
415
282
  )
416
- raise SystemExit(1)
417
-
418
- except ModelConfigError as e:
419
- had_error = True
420
- self._handle_error(
283
+ elif isinstance(e, ModelConfigError):
284
+ handle_error(
421
285
  e,
422
286
  "Model Configuration Error",
423
287
  "Common models: gpt-4o, o3-mini, sonnet, haiku. for o3, set reasoning effort with o3-mini.high",
424
288
  )
425
- raise SystemExit(1)
426
-
427
- except CircularDependencyError as e:
428
- had_error = True
429
- self._handle_error(
289
+ elif isinstance(e, CircularDependencyError):
290
+ handle_error(
430
291
  e,
431
292
  "Circular Dependency Detected",
432
293
  "Check your agent configuration for circular dependencies.",
433
294
  )
434
- raise SystemExit(1)
435
-
436
- except PromptExitError as e:
437
- had_error = True
438
- self._handle_error(
295
+ elif isinstance(e, PromptExitError):
296
+ handle_error(
439
297
  e,
440
298
  "User requested exit",
441
299
  )
442
- raise SystemExit(1)
443
-
444
- finally:
445
- # Clean up any active agents without re-raising errors
446
- if active_agents and not had_error:
447
- for name, proxy in active_agents.items():
448
- if isinstance(proxy, LLMAgentProxy):
449
- try:
450
- await proxy._agent.__aexit__(None, None, None)
451
- except Exception as e:
452
- print(f"DEBUG {e.message}")
453
- pass # Ignore cleanup errors
454
-
455
- def _handle_error(self, e: Exception, error_type: str, suggestion: str = None) -> None:
456
- """
457
- Handle errors with consistent formatting and messaging.
458
-
459
- Args:
460
- e: The exception that was raised
461
- error_type: Type of error to display
462
- suggestion: Optional suggestion message to display
463
- """
464
- handle_error(e, error_type, suggestion)
465
-
466
- def _log_agent_load(self, agent_name: str) -> None:
467
- # This function is no longer needed - agent loading is now handled in factory.py
468
- pass
469
-
470
- def create_mcp_server(
471
- self,
472
- agent_app_instance: AgentApp,
473
- server_name: str = None,
474
- server_description: str = None,
475
- ) -> AgentMCPServer:
476
- """
477
- Create an MCP server that exposes the agents as tools.
478
-
479
- Args:
480
- agent_app_instance: The AgentApp instance with initialized agents
481
- server_name: Optional custom name for the MCP server
482
- server_description: Optional description for the MCP server
483
-
484
- Returns:
485
- An AgentMCPServer instance ready to be run
486
- """
487
- return AgentMCPServer(
488
- agent_app=agent_app_instance,
489
- server_name=server_name or f"{self.name}-MCP-Server",
490
- server_description=server_description,
491
- )
300
+ else:
301
+ handle_error(e, error_type or "Error", "An unexpected error occurred.")
492
302
 
493
303
  async def run_with_mcp_server(
494
304
  self,
495
305
  transport: str = "sse",
496
306
  host: str = "0.0.0.0",
497
307
  port: int = 8000,
498
- server_name: str = None,
499
- server_description: str = None,
308
+ server_name: Optional[str] = None,
309
+ server_description: Optional[str] = None,
500
310
  ) -> None:
501
311
  """
502
- Run the FastAgent application and expose agents through an MCP server.
312
+ Run the application and expose agents through an MCP server.
503
313
 
504
314
  Args:
505
315
  transport: Transport protocol to use ("stdio" or "sse")
@@ -508,16 +318,20 @@ class FastAgent:
508
318
  server_name: Optional custom name for the MCP server
509
319
  server_description: Optional description for the MCP server
510
320
  """
321
+ from mcp_agent.mcp_server import AgentMCPServer
322
+
511
323
  async with self.run() as agent_app:
512
324
  # Create the MCP server
513
- mcp_server = self.create_mcp_server(
514
- agent_app_instance=agent_app,
515
- server_name=server_name,
325
+ mcp_server = AgentMCPServer(
326
+ agent_app=agent_app,
327
+ server_name=server_name or f"{self.name}-MCP-Server",
516
328
  server_description=server_description,
517
329
  )
518
330
 
519
331
  # Run the MCP server in a separate task
520
- server_task = asyncio.create_task(mcp_server.run_async(transport=transport, host=host, port=port))
332
+ server_task = asyncio.create_task(
333
+ mcp_server.run_async(transport=transport, host=host, port=port)
334
+ )
521
335
 
522
336
  try:
523
337
  # Wait for the server task to complete (or be cancelled)