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
@@ -13,7 +13,9 @@ class DecoratorRegistry:
13
13
 
14
14
  def __init__(self) -> None:
15
15
  self._workflow_defn_decorators: Dict[str, Callable[[Type], Type]] = {}
16
- self._workflow_run_decorators: Dict[str, Callable[[Callable[..., R]], Callable[..., R]]] = {}
16
+ self._workflow_run_decorators: Dict[
17
+ str, Callable[[Callable[..., R]], Callable[..., R]]
18
+ ] = {}
17
19
 
18
20
  def register_workflow_defn_decorator(
19
21
  self,
@@ -60,7 +62,9 @@ class DecoratorRegistry:
60
62
  )
61
63
  self._workflow_run_decorators[executor_name] = decorator
62
64
 
63
- def get_workflow_run_decorator(self, executor_name: str) -> Callable[[Callable[..., R]], Callable[..., R]]:
65
+ def get_workflow_run_decorator(
66
+ self, executor_name: str
67
+ ) -> Callable[[Callable[..., R]], Callable[..., R]]:
64
68
  """
65
69
  Retrieves a workflow run decorator for a given executor.
66
70
 
@@ -43,7 +43,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
43
43
 
44
44
  async def wait_for_signal(self, signal, timeout_seconds=None) -> SignalValueT:
45
45
  if not workflow._Runtime.current():
46
- raise RuntimeError("TemporalSignalHandler.wait_for_signal must be called from within a workflow")
46
+ raise RuntimeError(
47
+ "TemporalSignalHandler.wait_for_signal must be called from within a workflow"
48
+ )
47
49
 
48
50
  unique_signal_name = f"{signal.name}_{uuid.uuid4()}"
49
51
  registration = SignalRegistration(
@@ -77,13 +79,19 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
77
79
  async with self._lock:
78
80
  # Remove ourselves from _pending_signals
79
81
  if signal.name in self._pending_signals:
80
- self._pending_signals[signal.name] = [sr for sr in self._pending_signals[signal.name] if sr.unique_name != unique_signal_name]
82
+ self._pending_signals[signal.name] = [
83
+ sr
84
+ for sr in self._pending_signals[signal.name]
85
+ if sr.unique_name != unique_signal_name
86
+ ]
81
87
  if not self._pending_signals[signal.name]:
82
88
  del self._pending_signals[signal.name]
83
89
 
84
90
  # Remove ourselves from _handlers
85
91
  if signal.name in self._handlers:
86
- self._handlers[signal.name] = [h for h in self._handlers[signal.name] if h[0] != unique_signal_name]
92
+ self._handlers[signal.name] = [
93
+ h for h in self._handlers[signal.name] if h[0] != unique_signal_name
94
+ ]
87
95
  if not self._handlers[signal.name]:
88
96
  del self._handlers[signal.name]
89
97
 
@@ -128,7 +136,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
128
136
  registration = pending_signal.registration
129
137
  if registration.workflow_id == signal.workflow_id:
130
138
  # Only signal for registrations of that workflow
131
- signal_tasks.append(workflow_handle.signal(registration.unique_name, signal.payload))
139
+ signal_tasks.append(
140
+ workflow_handle.signal(registration.unique_name, signal.payload)
141
+ )
132
142
  else:
133
143
  continue
134
144
 
@@ -143,7 +153,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
143
153
  super().validate_signal(signal)
144
154
  # Add TemporalSignalHandler-specific validation
145
155
  if signal.workflow_id is None:
146
- raise ValueError("No workflow_id provided on Signal. That is required for Temporal signals")
156
+ raise ValueError(
157
+ "No workflow_id provided on Signal. That is required for Temporal signals"
158
+ )
147
159
 
148
160
 
149
161
  class TemporalExecutorConfig(ExecutorConfig, TemporalSettings):
@@ -171,7 +183,9 @@ class TemporalExecutor(Executor):
171
183
  context=context,
172
184
  **kwargs,
173
185
  )
174
- self.config: TemporalExecutorConfig = config or self.context.config.temporal or TemporalExecutorConfig()
186
+ self.config: TemporalExecutorConfig = (
187
+ config or self.context.config.temporal or TemporalExecutorConfig()
188
+ )
175
189
  self.client = client
176
190
  self._worker = None
177
191
  self._activity_semaphore = None
@@ -204,7 +218,9 @@ class TemporalExecutor(Executor):
204
218
 
205
219
  return wrapped_activity
206
220
 
207
- async def _execute_task_as_async(self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any) -> R | BaseException:
221
+ async def _execute_task_as_async(
222
+ self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any
223
+ ) -> R | BaseException:
208
224
  async def run_task(task: Callable[..., R] | Coroutine[Any, Any, R]) -> R:
209
225
  try:
210
226
  if asyncio.iscoroutine(task):
@@ -237,7 +253,9 @@ class TemporalExecutor(Executor):
237
253
  else:
238
254
  return await run_task(task)
239
255
 
240
- async def _execute_task(self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any) -> R | BaseException:
256
+ async def _execute_task(
257
+ self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any
258
+ ) -> R | BaseException:
241
259
  func = task.func if isinstance(task, functools.partial) else task
242
260
  is_workflow_task = getattr(func, "is_workflow_task", False)
243
261
  if not is_workflow_task:
@@ -250,7 +268,9 @@ class TemporalExecutor(Executor):
250
268
  if not activity_name:
251
269
  activity_name = f"{func.__module__}.{func.__qualname__}"
252
270
 
253
- schedule_to_close = execution_metadata.get("schedule_to_close_timeout", self.config.timeout_seconds)
271
+ schedule_to_close = execution_metadata.get(
272
+ "schedule_to_close_timeout", self.config.timeout_seconds
273
+ )
254
274
 
255
275
  retry_policy = execution_metadata.get("retry_policy", None)
256
276
 
@@ -296,7 +316,9 @@ class TemporalExecutor(Executor):
296
316
  **kwargs: Any,
297
317
  ) -> AsyncIterator[R | BaseException]:
298
318
  if not workflow._Runtime.current():
299
- raise RuntimeError("TemporalExecutor.execute_streaming must be called from within a workflow")
319
+ raise RuntimeError(
320
+ "TemporalExecutor.execute_streaming must be called from within a workflow"
321
+ )
300
322
 
301
323
  # TODO: saqadri - validate if async with self.execution_context() is needed here
302
324
  async with self.execution_context():
@@ -354,6 +376,8 @@ class TemporalExecutor(Executor):
354
376
  activities=activities,
355
377
  workflows=[], # We'll auto-load by Python scanning or let the user specify
356
378
  )
357
- print(f"Starting Temporal Worker on task queue '{self.config.task_queue}' with {len(activities)} activities.")
379
+ print(
380
+ f"Starting Temporal Worker on task queue '{self.config.task_queue}' with {len(activities)} activities."
381
+ )
358
382
 
359
383
  await self._worker.run()
@@ -147,7 +147,9 @@ class ConsoleSignalHandler(SignalHandler[str]):
147
147
  loop = asyncio.get_event_loop()
148
148
  if timeout_seconds is not None:
149
149
  try:
150
- value = await asyncio.wait_for(loop.run_in_executor(None, input, "Enter value: "), timeout_seconds)
150
+ value = await asyncio.wait_for(
151
+ loop.run_in_executor(None, input, "Enter value: "), timeout_seconds
152
+ )
151
153
  except asyncio.TimeoutError:
152
154
  print("\nTimeout waiting for input")
153
155
  raise
@@ -220,7 +222,11 @@ class AsyncioSignalHandler(BaseSignalHandler[SignalValueT]):
220
222
  async with self._lock:
221
223
  # Remove from pending signals
222
224
  if signal.name in self._pending_signals:
223
- self._pending_signals[signal.name] = [ps for ps in self._pending_signals[signal.name] if ps.registration.unique_name != unique_name]
225
+ self._pending_signals[signal.name] = [
226
+ ps
227
+ for ps in self._pending_signals[signal.name]
228
+ if ps.registration.unique_name != unique_name
229
+ ]
224
230
  if not self._pending_signals[signal.name]:
225
231
  del self._pending_signals[signal.name]
226
232
 
@@ -30,7 +30,9 @@ async def console_input_callback(request: HumanInputRequest) -> HumanInputRespon
30
30
  )
31
31
 
32
32
  # Extract agent name from metadata dictionary
33
- agent_name = request.metadata.get("agent_name", "Unknown Agent") if request.metadata else "Unknown Agent"
33
+ agent_name = (
34
+ request.metadata.get("agent_name", "Unknown Agent") if request.metadata else "Unknown Agent"
35
+ )
34
36
 
35
37
  # Use the context manager to pause the progress display while getting input
36
38
  with progress_display.paused():
@@ -0,0 +1,2 @@
1
+ # LLM module
2
+ # Contains code for working with large language models