fast-agent-mcp 0.1.11__py3-none-any.whl → 0.1.13__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 (131) hide show
  1. {fast_agent_mcp-0.1.11.dist-info → fast_agent_mcp-0.1.13.dist-info}/METADATA +1 -1
  2. fast_agent_mcp-0.1.13.dist-info/RECORD +164 -0
  3. mcp_agent/agents/agent.py +37 -102
  4. mcp_agent/app.py +16 -27
  5. mcp_agent/cli/commands/bootstrap.py +22 -52
  6. mcp_agent/cli/commands/config.py +4 -4
  7. mcp_agent/cli/commands/setup.py +11 -26
  8. mcp_agent/cli/main.py +6 -9
  9. mcp_agent/cli/terminal.py +2 -2
  10. mcp_agent/config.py +1 -5
  11. mcp_agent/context.py +13 -26
  12. mcp_agent/context_dependent.py +3 -7
  13. mcp_agent/core/agent_app.py +46 -122
  14. mcp_agent/core/agent_types.py +29 -2
  15. mcp_agent/core/agent_utils.py +3 -5
  16. mcp_agent/core/decorators.py +6 -14
  17. mcp_agent/core/enhanced_prompt.py +25 -52
  18. mcp_agent/core/error_handling.py +1 -1
  19. mcp_agent/core/exceptions.py +8 -8
  20. mcp_agent/core/factory.py +30 -72
  21. mcp_agent/core/fastagent.py +48 -88
  22. mcp_agent/core/mcp_content.py +10 -19
  23. mcp_agent/core/prompt.py +8 -15
  24. mcp_agent/core/proxies.py +34 -25
  25. mcp_agent/core/request_params.py +46 -0
  26. mcp_agent/core/types.py +6 -6
  27. mcp_agent/core/validation.py +16 -16
  28. mcp_agent/executor/decorator_registry.py +11 -23
  29. mcp_agent/executor/executor.py +8 -17
  30. mcp_agent/executor/task_registry.py +2 -4
  31. mcp_agent/executor/temporal.py +28 -74
  32. mcp_agent/executor/workflow.py +3 -5
  33. mcp_agent/executor/workflow_signal.py +17 -29
  34. mcp_agent/human_input/handler.py +4 -9
  35. mcp_agent/human_input/types.py +2 -3
  36. mcp_agent/logging/events.py +1 -5
  37. mcp_agent/logging/json_serializer.py +7 -6
  38. mcp_agent/logging/listeners.py +20 -23
  39. mcp_agent/logging/logger.py +15 -17
  40. mcp_agent/logging/rich_progress.py +10 -8
  41. mcp_agent/logging/tracing.py +4 -6
  42. mcp_agent/logging/transport.py +24 -24
  43. mcp_agent/mcp/gen_client.py +4 -12
  44. mcp_agent/mcp/interfaces.py +107 -88
  45. mcp_agent/mcp/mcp_agent_client_session.py +11 -19
  46. mcp_agent/mcp/mcp_agent_server.py +8 -10
  47. mcp_agent/mcp/mcp_aggregator.py +49 -122
  48. mcp_agent/mcp/mcp_connection_manager.py +16 -37
  49. mcp_agent/mcp/prompt_message_multipart.py +12 -18
  50. mcp_agent/mcp/prompt_serialization.py +13 -38
  51. mcp_agent/mcp/prompts/prompt_load.py +99 -0
  52. mcp_agent/mcp/prompts/prompt_server.py +21 -128
  53. mcp_agent/mcp/prompts/prompt_template.py +20 -42
  54. mcp_agent/mcp/resource_utils.py +8 -17
  55. mcp_agent/mcp/sampling.py +62 -64
  56. mcp_agent/mcp/stdio.py +11 -8
  57. mcp_agent/mcp_server/__init__.py +1 -1
  58. mcp_agent/mcp_server/agent_server.py +10 -17
  59. mcp_agent/mcp_server_registry.py +13 -35
  60. mcp_agent/resources/examples/data-analysis/analysis-campaign.py +1 -1
  61. mcp_agent/resources/examples/data-analysis/analysis.py +1 -1
  62. mcp_agent/resources/examples/data-analysis/slides.py +110 -0
  63. mcp_agent/resources/examples/internal/agent.py +2 -1
  64. mcp_agent/resources/examples/internal/job.py +2 -1
  65. mcp_agent/resources/examples/internal/prompt_category.py +1 -1
  66. mcp_agent/resources/examples/internal/prompt_sizing.py +3 -5
  67. mcp_agent/resources/examples/internal/sizer.py +2 -1
  68. mcp_agent/resources/examples/internal/social.py +2 -1
  69. mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +1 -1
  70. mcp_agent/resources/examples/prompting/__init__.py +1 -1
  71. mcp_agent/resources/examples/prompting/agent.py +2 -1
  72. mcp_agent/resources/examples/prompting/image_server.py +5 -11
  73. mcp_agent/resources/examples/researcher/researcher-eval.py +1 -1
  74. mcp_agent/resources/examples/researcher/researcher-imp.py +3 -4
  75. mcp_agent/resources/examples/researcher/researcher.py +2 -1
  76. mcp_agent/resources/examples/workflows/agent_build.py +2 -1
  77. mcp_agent/resources/examples/workflows/chaining.py +2 -1
  78. mcp_agent/resources/examples/workflows/evaluator.py +2 -1
  79. mcp_agent/resources/examples/workflows/human_input.py +2 -1
  80. mcp_agent/resources/examples/workflows/orchestrator.py +2 -1
  81. mcp_agent/resources/examples/workflows/parallel.py +2 -1
  82. mcp_agent/resources/examples/workflows/router.py +2 -1
  83. mcp_agent/resources/examples/workflows/sse.py +1 -1
  84. mcp_agent/telemetry/usage_tracking.py +2 -1
  85. mcp_agent/ui/console_display.py +17 -41
  86. mcp_agent/workflows/embedding/embedding_base.py +1 -4
  87. mcp_agent/workflows/embedding/embedding_cohere.py +2 -2
  88. mcp_agent/workflows/embedding/embedding_openai.py +4 -13
  89. mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +23 -57
  90. mcp_agent/workflows/intent_classifier/intent_classifier_base.py +5 -8
  91. mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +7 -11
  92. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +4 -8
  93. mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +4 -8
  94. mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +11 -22
  95. mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +3 -3
  96. mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +4 -6
  97. mcp_agent/workflows/llm/anthropic_utils.py +8 -29
  98. mcp_agent/workflows/llm/augmented_llm.py +94 -332
  99. mcp_agent/workflows/llm/augmented_llm_anthropic.py +43 -76
  100. mcp_agent/workflows/llm/augmented_llm_openai.py +46 -100
  101. mcp_agent/workflows/llm/augmented_llm_passthrough.py +42 -20
  102. mcp_agent/workflows/llm/augmented_llm_playback.py +8 -6
  103. mcp_agent/workflows/llm/memory.py +103 -0
  104. mcp_agent/workflows/llm/model_factory.py +9 -21
  105. mcp_agent/workflows/llm/openai_utils.py +1 -1
  106. mcp_agent/workflows/llm/prompt_utils.py +39 -27
  107. mcp_agent/workflows/llm/providers/multipart_converter_anthropic.py +246 -184
  108. mcp_agent/workflows/llm/providers/multipart_converter_openai.py +212 -202
  109. mcp_agent/workflows/llm/providers/openai_multipart.py +19 -61
  110. mcp_agent/workflows/llm/providers/sampling_converter_anthropic.py +11 -212
  111. mcp_agent/workflows/llm/providers/sampling_converter_openai.py +13 -215
  112. mcp_agent/workflows/llm/sampling_converter.py +117 -0
  113. mcp_agent/workflows/llm/sampling_format_converter.py +12 -29
  114. mcp_agent/workflows/orchestrator/orchestrator.py +24 -67
  115. mcp_agent/workflows/orchestrator/orchestrator_models.py +14 -40
  116. mcp_agent/workflows/parallel/fan_in.py +17 -47
  117. mcp_agent/workflows/parallel/fan_out.py +6 -12
  118. mcp_agent/workflows/parallel/parallel_llm.py +9 -26
  119. mcp_agent/workflows/router/router_base.py +29 -59
  120. mcp_agent/workflows/router/router_embedding.py +11 -25
  121. mcp_agent/workflows/router/router_embedding_cohere.py +2 -2
  122. mcp_agent/workflows/router/router_embedding_openai.py +2 -2
  123. mcp_agent/workflows/router/router_llm.py +12 -28
  124. mcp_agent/workflows/swarm/swarm.py +20 -48
  125. mcp_agent/workflows/swarm/swarm_anthropic.py +2 -2
  126. mcp_agent/workflows/swarm/swarm_openai.py +2 -2
  127. fast_agent_mcp-0.1.11.dist-info/RECORD +0 -160
  128. mcp_agent/workflows/llm/llm_selector.py +0 -345
  129. {fast_agent_mcp-0.1.11.dist-info → fast_agent_mcp-0.1.13.dist-info}/WHEEL +0 -0
  130. {fast_agent_mcp-0.1.11.dist-info → fast_agent_mcp-0.1.13.dist-info}/entry_points.txt +0 -0
  131. {fast_agent_mcp-0.1.11.dist-info → fast_agent_mcp-0.1.13.dist-info}/licenses/LICENSE +0 -0
@@ -2,15 +2,16 @@
2
2
  Enhanced prompt functionality with advanced prompt_toolkit features.
3
3
  """
4
4
 
5
- from typing import List, Optional
6
5
  from importlib.metadata import version
6
+ from typing import List, Optional
7
+
7
8
  from prompt_toolkit import PromptSession
9
+ from prompt_toolkit.completion import Completer, Completion, WordCompleter
10
+ from prompt_toolkit.filters import Condition
8
11
  from prompt_toolkit.formatted_text import HTML
9
12
  from prompt_toolkit.history import InMemoryHistory
10
13
  from prompt_toolkit.key_binding import KeyBindings
11
- from prompt_toolkit.completion import Completer, Completion, WordCompleter
12
14
  from prompt_toolkit.lexers import PygmentsLexer
13
- from prompt_toolkit.filters import Condition
14
15
  from prompt_toolkit.styles import Style
15
16
  from pygments.lexers.python import PythonLexer
16
17
  from rich import print as rich_print
@@ -45,7 +46,7 @@ class AgentCompleter(Completer):
45
46
  commands: List[str] = None,
46
47
  agent_types: dict = None,
47
48
  is_human_input: bool = False,
48
- ):
49
+ ) -> None:
49
50
  self.agents = agents
50
51
  # Map commands to their descriptions for better completion hints
51
52
  self.commands = {
@@ -61,9 +62,7 @@ class AgentCompleter(Completer):
61
62
  if is_human_input:
62
63
  self.commands.pop("agents")
63
64
  self.commands.pop("prompts") # Remove prompts command in human input mode
64
- self.commands.pop(
65
- "prompt", None
66
- ) # Remove prompt command in human input mode
65
+ self.commands.pop("prompt", None) # Remove prompt command in human input mode
67
66
  self.agent_types = agent_types or {}
68
67
 
69
68
  def get_completions(self, document, complete_event):
@@ -103,23 +102,23 @@ def create_keybindings(on_toggle_multiline=None, app=None):
103
102
  kb = KeyBindings()
104
103
 
105
104
  @kb.add("c-m", filter=Condition(lambda: not in_multiline_mode))
106
- def _(event):
105
+ def _(event) -> None:
107
106
  """Enter: accept input when not in multiline mode."""
108
107
  event.current_buffer.validate_and_handle()
109
108
 
110
109
  @kb.add("c-m", filter=Condition(lambda: in_multiline_mode))
111
- def _(event):
110
+ def _(event) -> None:
112
111
  """Enter: insert newline when in multiline mode."""
113
112
  event.current_buffer.insert_text("\n")
114
113
 
115
114
  # Use c-j (Ctrl+J) as an alternative to represent Ctrl+Enter in multiline mode
116
115
  @kb.add("c-j", filter=Condition(lambda: in_multiline_mode))
117
- def _(event):
116
+ def _(event) -> None:
118
117
  """Ctrl+J (equivalent to Ctrl+Enter): Submit in multiline mode."""
119
118
  event.current_buffer.validate_and_handle()
120
119
 
121
120
  @kb.add("c-t")
122
- def _(event):
121
+ def _(event) -> None:
123
122
  """Ctrl+T: Toggle multiline mode."""
124
123
  global in_multiline_mode
125
124
  in_multiline_mode = not in_multiline_mode
@@ -138,7 +137,7 @@ def create_keybindings(on_toggle_multiline=None, app=None):
138
137
  # The toolbar will show the current mode
139
138
 
140
139
  @kb.add("c-l")
141
- def _(event):
140
+ def _(event) -> None:
142
141
  """Ctrl+L: Clear the input buffer."""
143
142
  event.current_buffer.text = ""
144
143
 
@@ -187,7 +186,7 @@ async def get_enhanced_input(
187
186
  agent_histories[agent_name] = InMemoryHistory()
188
187
 
189
188
  # Define callback for multiline toggle
190
- def on_multiline_toggle(enabled):
189
+ def on_multiline_toggle(enabled) -> None:
191
190
  nonlocal session
192
191
  if hasattr(session, "app") and session.app:
193
192
  session.app.invalidate()
@@ -209,9 +208,7 @@ async def get_enhanced_input(
209
208
  ("↑/↓", "History"),
210
209
  ]
211
210
 
212
- newline = (
213
- "Ctrl+<Enter>:Submit" if in_multiline_mode else "<Enter>:Submit"
214
- )
211
+ newline = "Ctrl+<Enter>:Submit" if in_multiline_mode else "<Enter>:Submit"
215
212
 
216
213
  # Only show relevant shortcuts based on mode
217
214
  shortcuts = [(k, v) for k, v in shortcuts if v]
@@ -250,9 +247,7 @@ async def get_enhanced_input(
250
247
  )
251
248
 
252
249
  # Create key bindings with a reference to the app
253
- bindings = create_keybindings(
254
- on_toggle_multiline=on_multiline_toggle, app=session.app
255
- )
250
+ bindings = create_keybindings(on_toggle_multiline=on_multiline_toggle, app=session.app)
256
251
  session.app.key_bindings = bindings
257
252
 
258
253
  # Create formatted prompt text
@@ -267,20 +262,14 @@ async def get_enhanced_input(
267
262
  if default == "STOP":
268
263
  rich_print("Enter a prompt, [red]STOP[/red] to finish")
269
264
  if default:
270
- rich_print(
271
- f"Press <ENTER> to use the default prompt:\n[cyan]{default}[/cyan]"
272
- )
265
+ rich_print(f"Press <ENTER> to use the default prompt:\n[cyan]{default}[/cyan]")
273
266
 
274
267
  # Mention available features but only on first usage globally
275
268
  if not help_message_shown:
276
269
  if is_human_input:
277
- rich_print(
278
- "[dim]Type /help for commands. Ctrl+T toggles multiline mode.[/dim]"
279
- )
270
+ rich_print("[dim]Type /help for commands. Ctrl+T toggles multiline mode.[/dim]")
280
271
  else:
281
- rich_print(
282
- "[dim]Type /help for commands, @agent to switch agent. Ctrl+T toggles multiline mode.[/dim]"
283
- )
272
+ rich_print("[dim]Type /help for commands, @agent to switch agent. Ctrl+T toggles multiline mode.[/dim]")
284
273
  rich_print()
285
274
  help_message_shown = True
286
275
 
@@ -366,9 +355,7 @@ async def get_selection_input(
366
355
 
367
356
  try:
368
357
  # Get user input
369
- selection = await prompt_session.prompt_async(
370
- prompt_text, default=default or ""
371
- )
358
+ selection = await prompt_session.prompt_async(prompt_text, default=default or "")
372
359
 
373
360
  # Handle cancellation
374
361
  if allow_cancel and not selection.strip():
@@ -409,9 +396,7 @@ async def get_argument_input(
409
396
  if description:
410
397
  rich_print(f" [dim]{arg_name}: {description}[/dim]")
411
398
 
412
- prompt_text = HTML(
413
- f"Enter value for <ansibrightcyan>{arg_name}</ansibrightcyan> {required_text}: "
414
- )
399
+ prompt_text = HTML(f"Enter value for <ansibrightcyan>{arg_name}</ansibrightcyan> {required_text}: ")
415
400
 
416
401
  # Create prompt session
417
402
  prompt_session = PromptSession()
@@ -452,13 +437,9 @@ async def handle_special_commands(command, agent_app=None):
452
437
  rich_print(" /prompt <name> - Apply a specific prompt by name")
453
438
  rich_print(" @agent_name - Switch to agent")
454
439
  rich_print(" STOP - Return control back to the workflow")
455
- rich_print(
456
- " EXIT - Exit fast-agent, terminating any running workflows"
457
- )
440
+ rich_print(" EXIT - Exit fast-agent, terminating any running workflows")
458
441
  rich_print("\n[bold]Keyboard Shortcuts:[/bold]")
459
- rich_print(
460
- " Enter - Submit (normal mode) / New line (multiline mode)"
461
- )
442
+ rich_print(" Enter - Submit (normal mode) / New line (multiline mode)")
462
443
  rich_print(" Ctrl+Enter - Always submit (in any mode)")
463
444
  rich_print(" Ctrl+T - Toggle multiline mode")
464
445
  rich_print(" Ctrl+L - Clear input")
@@ -489,14 +470,10 @@ async def handle_special_commands(command, agent_app=None):
489
470
  rich_print("\n[bold]Fetching available MCP prompts...[/bold]")
490
471
  return {"list_prompts": True}
491
472
  else:
492
- rich_print(
493
- "[yellow]Prompt listing is not available outside of an agent context[/yellow]"
494
- )
473
+ rich_print("[yellow]Prompt listing is not available outside of an agent context[/yellow]")
495
474
  return True
496
475
 
497
- elif command == "SELECT_PROMPT" or (
498
- isinstance(command, str) and command.startswith("SELECT_PROMPT:")
499
- ):
476
+ elif command == "SELECT_PROMPT" or (isinstance(command, str) and command.startswith("SELECT_PROMPT:")):
500
477
  # Handle prompt selection UI
501
478
  if agent_app:
502
479
  # If it's a specific prompt, extract the name
@@ -507,9 +484,7 @@ async def handle_special_commands(command, agent_app=None):
507
484
  # Return a dictionary with a select_prompt action to be handled by the caller
508
485
  return {"select_prompt": True, "prompt_name": prompt_name}
509
486
  else:
510
- rich_print(
511
- "[yellow]Prompt selection is not available outside of an agent context[/yellow]"
512
- )
487
+ rich_print("[yellow]Prompt selection is not available outside of an agent context[/yellow]")
513
488
  return True
514
489
 
515
490
  elif isinstance(command, str) and command.startswith("SWITCH:"):
@@ -519,9 +494,7 @@ async def handle_special_commands(command, agent_app=None):
519
494
  # rich_print(f"[green]Switching to agent: {agent_name}[/green]")
520
495
  return {"switch_agent": agent_name}
521
496
  else:
522
- rich_print(
523
- "[yellow]Agent switching not available in this context[/yellow]"
524
- )
497
+ rich_print("[yellow]Agent switching not available in this context[/yellow]")
525
498
  else:
526
499
  rich_print(f"[red]Unknown agent: {agent_name}[/red]")
527
500
  return True
@@ -20,4 +20,4 @@ def handle_error(e: Exception, error_type: str, suggestion: str = None) -> None:
20
20
  print("\nDetails:")
21
21
  print(e.details)
22
22
  if suggestion:
23
- print(f"\n{suggestion}")
23
+ print(f"\n{suggestion}")
@@ -7,7 +7,7 @@ Enables user-friendly error handling for common issues.
7
7
  class FastAgentError(Exception):
8
8
  """Base exception class for FastAgent errors"""
9
9
 
10
- def __init__(self, message: str, details: str = ""):
10
+ def __init__(self, message: str, details: str = "") -> None:
11
11
  self.message = message
12
12
  self.details = details
13
13
  super().__init__(f"{message}\n\n{details}" if details else message)
@@ -18,7 +18,7 @@ class ServerConfigError(FastAgentError):
18
18
  Example: Server name referenced in agent.servers[] but not defined in config
19
19
  """
20
20
 
21
- def __init__(self, message: str, details: str = ""):
21
+ def __init__(self, message: str, details: str = "") -> None:
22
22
  super().__init__(message, details)
23
23
 
24
24
 
@@ -27,7 +27,7 @@ class AgentConfigError(FastAgentError):
27
27
  Example: Parallel fan-in references unknown agent
28
28
  """
29
29
 
30
- def __init__(self, message: str, details: str = ""):
30
+ def __init__(self, message: str, details: str = "") -> None:
31
31
  super().__init__(message, details)
32
32
 
33
33
 
@@ -36,14 +36,14 @@ class ProviderKeyError(FastAgentError):
36
36
  Example: OpenAI/Anthropic key not configured but model requires it
37
37
  """
38
38
 
39
- def __init__(self, message: str, details: str = ""):
39
+ def __init__(self, message: str, details: str = "") -> None:
40
40
  super().__init__(message, details)
41
41
 
42
42
 
43
43
  class ServerInitializationError(FastAgentError):
44
44
  """Raised when a server fails to initialize properly."""
45
45
 
46
- def __init__(self, message: str, details: str = ""):
46
+ def __init__(self, message: str, details: str = "") -> None:
47
47
  super().__init__(message, details)
48
48
 
49
49
 
@@ -52,14 +52,14 @@ class ModelConfigError(FastAgentError):
52
52
  Example: Unknown model name in model specification string
53
53
  """
54
54
 
55
- def __init__(self, message: str, details: str = ""):
55
+ def __init__(self, message: str, details: str = "") -> None:
56
56
  super().__init__(message, details)
57
57
 
58
58
 
59
59
  class CircularDependencyError(FastAgentError):
60
60
  """Raised when we detect a Circular Dependency in the workflow"""
61
61
 
62
- def __init__(self, message: str, details: str = ""):
62
+ def __init__(self, message: str, details: str = "") -> None:
63
63
  super().__init__(message, details)
64
64
 
65
65
 
@@ -67,5 +67,5 @@ class PromptExitError(FastAgentError):
67
67
  """Raised from enhanced_prompt when the user requests hard exits"""
68
68
 
69
69
  # TODO an exception for flow control :(
70
- def __init__(self, message: str, details: str = ""):
70
+ def __init__(self, message: str, details: str = "") -> None:
71
71
  super().__init__(message, details)
mcp_agent/core/factory.py CHANGED
@@ -2,10 +2,22 @@
2
2
  Factory functions for creating agent and workflow instances.
3
3
  """
4
4
 
5
- from typing import Dict, Any, Optional, TypeVar, Callable
5
+ from typing import Any, Callable, Dict, Optional, TypeVar
6
6
 
7
+ from mcp_agent.agents.agent import Agent
7
8
  from mcp_agent.app import MCPApp
8
- from mcp_agent.agents.agent import Agent, AgentConfig
9
+ from mcp_agent.core.agent_types import AgentConfig, AgentType
10
+ from mcp_agent.core.agent_utils import get_agent_instances, log_agent_load, unwrap_proxy
11
+ from mcp_agent.core.exceptions import AgentConfigError
12
+ from mcp_agent.core.proxies import (
13
+ BaseAgentProxy,
14
+ ChainProxy,
15
+ LLMAgentProxy,
16
+ RouterProxy,
17
+ WorkflowProxy,
18
+ )
19
+ from mcp_agent.core.types import AgentOrWorkflow, ProxyDict
20
+ from mcp_agent.core.validation import get_dependencies
9
21
  from mcp_agent.event_progress import ProgressAction
10
22
  from mcp_agent.workflows.evaluator_optimizer.evaluator_optimizer import (
11
23
  EvaluatorOptimizerLLM,
@@ -17,25 +29,10 @@ from mcp_agent.workflows.orchestrator.orchestrator import Orchestrator
17
29
  from mcp_agent.workflows.parallel.parallel_llm import ParallelLLM
18
30
  from mcp_agent.workflows.router.router_llm import LLMRouter
19
31
 
20
- from mcp_agent.core.agent_types import AgentType
21
- from mcp_agent.core.exceptions import AgentConfigError
22
- from mcp_agent.core.proxies import (
23
- BaseAgentProxy,
24
- LLMAgentProxy,
25
- WorkflowProxy,
26
- RouterProxy,
27
- ChainProxy,
28
- )
29
- from mcp_agent.core.types import AgentOrWorkflow, ProxyDict
30
- from mcp_agent.core.agent_utils import log_agent_load, unwrap_proxy, get_agent_instances
31
- from mcp_agent.core.validation import get_dependencies
32
-
33
32
  T = TypeVar("T") # For the wrapper classes
34
33
 
35
34
 
36
- def create_proxy(
37
- app: MCPApp, name: str, instance: AgentOrWorkflow, agent_type: str
38
- ) -> BaseAgentProxy:
35
+ def create_proxy(app: MCPApp, name: str, instance: AgentOrWorkflow, agent_type: str) -> BaseAgentProxy:
39
36
  """Create appropriate proxy type based on agent type and validate instance type
40
37
 
41
38
  Args:
@@ -62,27 +59,19 @@ def create_proxy(
62
59
  return LLMAgentProxy(app, name, instance)
63
60
  elif agent_type == AgentType.ORCHESTRATOR.value:
64
61
  if not isinstance(instance, Orchestrator):
65
- raise TypeError(
66
- f"Expected Orchestrator instance for {name}, got {type(instance)}"
67
- )
62
+ raise TypeError(f"Expected Orchestrator instance for {name}, got {type(instance)}")
68
63
  return WorkflowProxy(app, name, instance)
69
64
  elif agent_type == AgentType.PARALLEL.value:
70
65
  if not isinstance(instance, ParallelLLM):
71
- raise TypeError(
72
- f"Expected ParallelLLM instance for {name}, got {type(instance)}"
73
- )
66
+ raise TypeError(f"Expected ParallelLLM instance for {name}, got {type(instance)}")
74
67
  return WorkflowProxy(app, name, instance)
75
68
  elif agent_type == AgentType.EVALUATOR_OPTIMIZER.value:
76
69
  if not isinstance(instance, EvaluatorOptimizerLLM):
77
- raise TypeError(
78
- f"Expected EvaluatorOptimizerLLM instance for {name}, got {type(instance)}"
79
- )
70
+ raise TypeError(f"Expected EvaluatorOptimizerLLM instance for {name}, got {type(instance)}")
80
71
  return WorkflowProxy(app, name, instance)
81
72
  elif agent_type == AgentType.ROUTER.value:
82
73
  if not isinstance(instance, LLMRouter):
83
- raise TypeError(
84
- f"Expected LLMRouter instance for {name}, got {type(instance)}"
85
- )
74
+ raise TypeError(f"Expected LLMRouter instance for {name}, got {type(instance)}")
86
75
  return RouterProxy(app, name, instance)
87
76
  elif agent_type == AgentType.CHAIN.value:
88
77
  # Chain proxy is directly returned from _create_agents_by_type
@@ -188,11 +177,7 @@ async def create_agents_by_type(
188
177
 
189
178
  elif agent_type == AgentType.ORCHESTRATOR:
190
179
  # Get base params configured with model settings
191
- base_params = (
192
- config.default_request_params.model_copy()
193
- if config.default_request_params
194
- else RequestParams()
195
- )
180
+ base_params = config.default_request_params.model_copy() if config.default_request_params else RequestParams()
196
181
  base_params.use_history = False # Force no history for orchestrator
197
182
 
198
183
  # Get the child agents - need to unwrap proxies and validate LLM config
@@ -232,7 +217,6 @@ async def create_agents_by_type(
232
217
  )
233
218
 
234
219
  planner = await planner_agent.attach_llm(planner_factory)
235
- await planner.initialize()
236
220
  # Create the orchestrator with pre-configured planner
237
221
  instance = Orchestrator(
238
222
  name=config.name,
@@ -240,9 +224,7 @@ async def create_agents_by_type(
240
224
  available_agents=child_agents,
241
225
  context=app_instance.context,
242
226
  request_params=planner.default_request_params, # Base params already include model settings
243
- plan_type=agent_data.get(
244
- "plan_type", "full"
245
- ), # Get plan_type from agent_data
227
+ plan_type=agent_data.get("plan_type", "full"), # Get plan_type from agent_data
246
228
  verb=ProgressAction.PLANNING,
247
229
  )
248
230
 
@@ -252,19 +234,13 @@ async def create_agents_by_type(
252
234
  evaluator = unwrap_proxy(active_agents[agent_data["evaluator"]])
253
235
 
254
236
  if not generator or not evaluator:
255
- raise ValueError(
256
- f"Missing agents for workflow {name}: "
257
- f"generator={agent_data['generator']}, "
258
- f"evaluator={agent_data['evaluator']}"
259
- )
237
+ raise ValueError(f"Missing agents for workflow {name}: generator={agent_data['generator']}, evaluator={agent_data['evaluator']}")
260
238
 
261
239
  # Get model from generator if it's an Agent, or from config otherwise
262
240
  optimizer_model = None
263
241
  if isinstance(generator, Agent):
264
242
  optimizer_model = generator.config.model
265
- elif hasattr(generator, "_sequence") and hasattr(
266
- generator, "_agent_proxies"
267
- ):
243
+ elif hasattr(generator, "_sequence") and hasattr(generator, "_agent_proxies"):
268
244
  # For ChainProxy, use the config model directly
269
245
  optimizer_model = config.model
270
246
 
@@ -329,27 +305,19 @@ async def create_agents_by_type(
329
305
 
330
306
  # Generate a better description
331
307
  if agent_names:
332
- server_part = (
333
- f" with access to servers: {', '.join(sorted(all_servers))}"
334
- if all_servers
335
- else ""
336
- )
308
+ server_part = f" with access to servers: {', '.join(sorted(all_servers))}" if all_servers else ""
337
309
  config.instruction = f"Sequence of agents: {', '.join(agent_names)}{server_part}."
338
310
 
339
311
  # Create a ChainProxy without needing a new instance
340
312
  # Just pass the agent proxies and sequence
341
313
  instance = ChainProxy(app_instance, name, sequence, active_agents)
342
314
  # Set continue_with_final behavior from configuration
343
- instance._continue_with_final = agent_data.get(
344
- "continue_with_final", True
345
- )
315
+ instance._continue_with_final = agent_data.get("continue_with_final", True)
346
316
  # Set cumulative behavior from configuration
347
317
  instance._cumulative = agent_data.get("cumulative", False)
348
318
 
349
319
  elif agent_type == AgentType.PARALLEL:
350
- fan_out_agents = get_agent_instances(
351
- agent_data["fan_out"], active_agents
352
- )
320
+ fan_out_agents = get_agent_instances(agent_data["fan_out"], active_agents)
353
321
 
354
322
  # Get fan-in agent - unwrap proxy
355
323
  fan_in_agent = unwrap_proxy(active_agents[agent_data["fan_in"]])
@@ -371,9 +339,7 @@ async def create_agents_by_type(
371
339
  raise ValueError(f"Unsupported agent type: {agent_type}")
372
340
 
373
341
  # Create the appropriate proxy and store in results
374
- result_agents[name] = create_proxy(
375
- app_instance, name, instance, agent_type.value
376
- )
342
+ result_agents[name] = create_proxy(app_instance, name, instance, agent_type.value)
377
343
 
378
344
  return result_agents
379
345
 
@@ -427,24 +393,16 @@ async def create_agents_in_dependency_order(
427
393
  visited = set()
428
394
 
429
395
  # Get all agents of the specified type
430
- agent_names = [
431
- name
432
- for name, agent_data in agents_dict.items()
433
- if agent_data["type"] == agent_type.value
434
- ]
396
+ agent_names = [name for name, agent_data in agents_dict.items() if agent_data["type"] == agent_type.value]
435
397
 
436
398
  # Create agents in dependency order
437
399
  for name in agent_names:
438
400
  # Get ordered dependencies if not already processed
439
401
  if name not in visited:
440
402
  try:
441
- ordered_agents = get_dependencies(
442
- name, agents_dict, visited, set(), agent_type
443
- )
403
+ ordered_agents = get_dependencies(name, agents_dict, visited, set(), agent_type)
444
404
  except ValueError as e:
445
- raise ValueError(
446
- f"Error creating {agent_type.name.lower()} agent {name}: {str(e)}"
447
- )
405
+ raise ValueError(f"Error creating {agent_type.name.lower()} agent {name}: {str(e)}")
448
406
 
449
407
  # Create each agent in order
450
408
  for agent_name in ordered_agents: