fast-agent-mcp 0.2.39__py3-none-any.whl → 0.2.41__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (41) hide show
  1. {fast_agent_mcp-0.2.39.dist-info → fast_agent_mcp-0.2.41.dist-info}/METADATA +1 -1
  2. {fast_agent_mcp-0.2.39.dist-info → fast_agent_mcp-0.2.41.dist-info}/RECORD +41 -37
  3. {fast_agent_mcp-0.2.39.dist-info → fast_agent_mcp-0.2.41.dist-info}/entry_points.txt +2 -2
  4. mcp_agent/cli/__main__.py +29 -3
  5. mcp_agent/cli/commands/check_config.py +140 -81
  6. mcp_agent/cli/commands/go.py +151 -38
  7. mcp_agent/cli/commands/quickstart.py +8 -4
  8. mcp_agent/cli/commands/server_helpers.py +106 -0
  9. mcp_agent/cli/constants.py +25 -0
  10. mcp_agent/cli/main.py +1 -1
  11. mcp_agent/config.py +94 -44
  12. mcp_agent/core/agent_app.py +104 -15
  13. mcp_agent/core/agent_types.py +1 -0
  14. mcp_agent/core/direct_decorators.py +9 -0
  15. mcp_agent/core/direct_factory.py +18 -4
  16. mcp_agent/core/enhanced_prompt.py +165 -13
  17. mcp_agent/core/fastagent.py +4 -0
  18. mcp_agent/core/interactive_prompt.py +37 -37
  19. mcp_agent/core/usage_display.py +11 -1
  20. mcp_agent/core/validation.py +21 -2
  21. mcp_agent/human_input/elicitation_form.py +55 -22
  22. mcp_agent/llm/augmented_llm.py +28 -9
  23. mcp_agent/llm/augmented_llm_silent.py +48 -0
  24. mcp_agent/llm/model_database.py +20 -0
  25. mcp_agent/llm/model_factory.py +12 -0
  26. mcp_agent/llm/provider_key_manager.py +22 -8
  27. mcp_agent/llm/provider_types.py +19 -12
  28. mcp_agent/llm/providers/augmented_llm_anthropic.py +7 -2
  29. mcp_agent/llm/providers/augmented_llm_azure.py +7 -1
  30. mcp_agent/llm/providers/augmented_llm_google_native.py +4 -1
  31. mcp_agent/llm/providers/augmented_llm_openai.py +9 -2
  32. mcp_agent/llm/providers/augmented_llm_xai.py +38 -0
  33. mcp_agent/llm/usage_tracking.py +28 -3
  34. mcp_agent/mcp/mcp_agent_client_session.py +2 -0
  35. mcp_agent/mcp/mcp_aggregator.py +38 -44
  36. mcp_agent/mcp/sampling.py +15 -11
  37. mcp_agent/resources/examples/mcp/elicitations/forms_demo.py +0 -6
  38. mcp_agent/resources/examples/workflows/router.py +9 -0
  39. mcp_agent/ui/console_display.py +125 -13
  40. {fast_agent_mcp-0.2.39.dist-info → fast_agent_mcp-0.2.41.dist-info}/WHEEL +0 -0
  41. {fast_agent_mcp-0.2.39.dist-info → fast_agent_mcp-0.2.41.dist-info}/licenses/LICENSE +0 -0
@@ -28,7 +28,7 @@ class ConsoleDisplay:
28
28
  self.config = config
29
29
  self._markup = config.logger.enable_markup if config else True
30
30
 
31
- def show_tool_result(self, result: CallToolResult) -> None:
31
+ def show_tool_result(self, result: CallToolResult, name: Optional[str] = None) -> None:
32
32
  """Display a tool result in a formatted panel."""
33
33
  if not self.config or not self.config.logger.show_tools:
34
34
  return
@@ -37,10 +37,10 @@ class ConsoleDisplay:
37
37
 
38
38
  panel = Panel(
39
39
  Text(str(result.content), overflow="..."),
40
- title="[TOOL RESULT]",
40
+ title=f"[TOOL RESULT]{f' ({name})' if name else ''}",
41
41
  title_align="right",
42
42
  style=style,
43
- border_style="bold white",
43
+ border_style="white",
44
44
  padding=(1, 2),
45
45
  )
46
46
 
@@ -51,17 +51,17 @@ class ConsoleDisplay:
51
51
  console.console.print(panel, markup=self._markup)
52
52
  console.console.print("\n")
53
53
 
54
- def show_oai_tool_result(self, result) -> None:
54
+ def show_oai_tool_result(self, result, name: Optional[str] = None) -> None:
55
55
  """Display an OpenAI tool result in a formatted panel."""
56
56
  if not self.config or not self.config.logger.show_tools:
57
57
  return
58
58
 
59
59
  panel = Panel(
60
60
  Text(str(result), overflow="..."),
61
- title="[TOOL RESULT]",
61
+ title=f"[TOOL RESULT]{f' ({name})' if name else ''}",
62
62
  title_align="right",
63
63
  style="magenta",
64
- border_style="bold white",
64
+ border_style="white",
65
65
  padding=(1, 2),
66
66
  )
67
67
 
@@ -72,7 +72,9 @@ class ConsoleDisplay:
72
72
  console.console.print(panel, markup=self._markup)
73
73
  console.console.print("\n")
74
74
 
75
- def show_tool_call(self, available_tools, tool_name, tool_args) -> None:
75
+ def show_tool_call(
76
+ self, available_tools, tool_name, tool_args, name: Optional[str] = None
77
+ ) -> None:
76
78
  """Display a tool call in a formatted panel."""
77
79
  if not self.config or not self.config.logger.show_tools:
78
80
  return
@@ -81,10 +83,10 @@ class ConsoleDisplay:
81
83
 
82
84
  panel = Panel(
83
85
  Text(str(tool_args), overflow="ellipsis"),
84
- title="[TOOL CALL]",
86
+ title=f"[TOOL CALL]{f' ({name})' if name else ''}",
85
87
  title_align="left",
86
88
  style="magenta",
87
- border_style="bold white",
89
+ border_style="white",
88
90
  subtitle=display_tool_list,
89
91
  subtitle_align="left",
90
92
  padding=(1, 2),
@@ -114,7 +116,7 @@ class ConsoleDisplay:
114
116
  title="[TOOL UPDATE]",
115
117
  title_align="left",
116
118
  style="green",
117
- border_style="bold white",
119
+ border_style="white",
118
120
  padding=(1, 2),
119
121
  subtitle=display_server_list,
120
122
  subtitle_align="left",
@@ -195,7 +197,7 @@ class ConsoleDisplay:
195
197
  title=f"[{title}]{f' ({name})' if name else ''}",
196
198
  title_align="left",
197
199
  style="green",
198
- border_style="bold white",
200
+ border_style="white",
199
201
  padding=(1, 2),
200
202
  subtitle=display_server_list,
201
203
  subtitle_align="left",
@@ -219,7 +221,7 @@ class ConsoleDisplay:
219
221
  title=f"{f'({name}) [USER]' if name else '[USER]'}",
220
222
  title_align="right",
221
223
  style="blue",
222
- border_style="bold white",
224
+ border_style="white",
223
225
  padding=(1, 2),
224
226
  subtitle=subtitle_text,
225
227
  subtitle_align="left",
@@ -292,7 +294,7 @@ class ConsoleDisplay:
292
294
  title="[PROMPT LOADED]",
293
295
  title_align="right",
294
296
  style="cyan",
295
- border_style="bold white",
297
+ border_style="white",
296
298
  padding=(1, 2),
297
299
  subtitle=display_server_list,
298
300
  subtitle_align="left",
@@ -300,3 +302,113 @@ class ConsoleDisplay:
300
302
 
301
303
  console.console.print(panel, markup=self._markup)
302
304
  console.console.print("\n")
305
+
306
+ def show_parallel_results(self, parallel_agent) -> None:
307
+ """Display parallel agent results in a clean, organized format.
308
+
309
+ Args:
310
+ parallel_agent: The parallel agent containing fan_out_agents with results
311
+ """
312
+ from rich.markdown import Markdown
313
+ from rich.text import Text
314
+
315
+ if self.config and not self.config.logger.show_chat:
316
+ return
317
+
318
+ if not parallel_agent or not hasattr(parallel_agent, 'fan_out_agents'):
319
+ return
320
+
321
+ # Collect results and agent information
322
+ agent_results = []
323
+
324
+ for agent in parallel_agent.fan_out_agents:
325
+ # Get the last response text from this agent
326
+ message_history = agent.message_history
327
+ if not message_history:
328
+ continue
329
+
330
+ last_message = message_history[-1]
331
+ content = last_message.last_text()
332
+
333
+ # Get model name
334
+ model = 'unknown'
335
+ if hasattr(agent, '_llm') and agent._llm and hasattr(agent._llm, 'default_request_params'):
336
+ model = getattr(agent._llm.default_request_params, 'model', 'unknown')
337
+
338
+ # Get usage information
339
+ tokens = 0
340
+ tool_calls = 0
341
+ if hasattr(agent, 'usage_accumulator') and agent.usage_accumulator:
342
+ summary = agent.usage_accumulator.get_summary()
343
+ tokens = summary.get('cumulative_input_tokens', 0) + summary.get('cumulative_output_tokens', 0)
344
+ tool_calls = summary.get('cumulative_tool_calls', 0)
345
+
346
+ agent_results.append({
347
+ 'name': agent.name,
348
+ 'model': model,
349
+ 'content': content,
350
+ 'tokens': tokens,
351
+ 'tool_calls': tool_calls
352
+ })
353
+
354
+ if not agent_results:
355
+ return
356
+
357
+ # Display header
358
+ console.console.print()
359
+ console.console.print("[dim]Parallel execution complete[/dim]")
360
+ console.console.print()
361
+
362
+ # Display results for each agent
363
+ for i, result in enumerate(agent_results):
364
+ if i > 0:
365
+ # Simple full-width separator
366
+ console.console.print()
367
+ console.console.print("─" * console.console.size.width, style="dim")
368
+ console.console.print()
369
+
370
+ # Two column header: model name (green) + usage info (dim)
371
+ left = f"[green]▎[/green] [bold green]{result['model']}[/bold green]"
372
+
373
+ # Build right side with tokens and tool calls if available
374
+ right_parts = []
375
+ if result['tokens'] > 0:
376
+ right_parts.append(f"{result['tokens']:,} tokens")
377
+ if result['tool_calls'] > 0:
378
+ right_parts.append(f"{result['tool_calls']} tools")
379
+
380
+ right = f"[dim]{' • '.join(right_parts) if right_parts else 'no usage data'}[/dim]"
381
+
382
+ # Calculate padding to right-align usage info
383
+ width = console.console.size.width
384
+ left_text = Text.from_markup(left)
385
+ right_text = Text.from_markup(right)
386
+ padding = max(1, width - left_text.cell_len - right_text.cell_len)
387
+
388
+ console.console.print(left + " " * padding + right, markup=self._markup)
389
+ console.console.print()
390
+
391
+ # Display content as markdown if it looks like markdown, otherwise as text
392
+ content = result['content']
393
+ if any(marker in content for marker in ['##', '**', '*', '`', '---', '###']):
394
+ md = Markdown(content)
395
+ console.console.print(md, markup=self._markup)
396
+ else:
397
+ console.console.print(content, markup=self._markup)
398
+
399
+ # Summary
400
+ console.console.print()
401
+ console.console.print("─" * console.console.size.width, style="dim")
402
+
403
+ total_tokens = sum(result['tokens'] for result in agent_results)
404
+ total_tools = sum(result['tool_calls'] for result in agent_results)
405
+
406
+ summary_parts = [f"{len(agent_results)} models"]
407
+ if total_tokens > 0:
408
+ summary_parts.append(f"{total_tokens:,} tokens")
409
+ if total_tools > 0:
410
+ summary_parts.append(f"{total_tools} tools")
411
+
412
+ summary_text = " • ".join(summary_parts)
413
+ console.console.print(f"[dim]{summary_text}[/dim]")
414
+ console.console.print()