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