fast-agent-mcp 0.2.40__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.
- {fast_agent_mcp-0.2.40.dist-info → fast_agent_mcp-0.2.41.dist-info}/METADATA +1 -1
- {fast_agent_mcp-0.2.40.dist-info → fast_agent_mcp-0.2.41.dist-info}/RECORD +41 -37
- {fast_agent_mcp-0.2.40.dist-info → fast_agent_mcp-0.2.41.dist-info}/entry_points.txt +2 -2
- mcp_agent/cli/__main__.py +29 -3
- mcp_agent/cli/commands/check_config.py +140 -81
- mcp_agent/cli/commands/go.py +151 -38
- mcp_agent/cli/commands/quickstart.py +6 -2
- mcp_agent/cli/commands/server_helpers.py +106 -0
- mcp_agent/cli/constants.py +25 -0
- mcp_agent/cli/main.py +1 -1
- mcp_agent/config.py +94 -44
- mcp_agent/core/agent_app.py +104 -15
- mcp_agent/core/agent_types.py +1 -0
- mcp_agent/core/direct_decorators.py +9 -0
- mcp_agent/core/direct_factory.py +18 -4
- mcp_agent/core/enhanced_prompt.py +165 -13
- mcp_agent/core/fastagent.py +4 -0
- mcp_agent/core/interactive_prompt.py +37 -37
- mcp_agent/core/usage_display.py +11 -1
- mcp_agent/core/validation.py +21 -2
- mcp_agent/human_input/elicitation_form.py +53 -21
- mcp_agent/llm/augmented_llm.py +28 -9
- mcp_agent/llm/augmented_llm_silent.py +48 -0
- mcp_agent/llm/model_database.py +20 -0
- mcp_agent/llm/model_factory.py +12 -0
- mcp_agent/llm/provider_key_manager.py +22 -8
- mcp_agent/llm/provider_types.py +19 -12
- mcp_agent/llm/providers/augmented_llm_anthropic.py +7 -2
- mcp_agent/llm/providers/augmented_llm_azure.py +7 -1
- mcp_agent/llm/providers/augmented_llm_google_native.py +4 -1
- mcp_agent/llm/providers/augmented_llm_openai.py +9 -2
- mcp_agent/llm/providers/augmented_llm_xai.py +38 -0
- mcp_agent/llm/usage_tracking.py +28 -3
- mcp_agent/mcp/mcp_agent_client_session.py +2 -0
- mcp_agent/mcp/mcp_aggregator.py +38 -44
- mcp_agent/mcp/sampling.py +15 -11
- mcp_agent/resources/examples/mcp/elicitations/forms_demo.py +0 -6
- mcp_agent/resources/examples/workflows/router.py +9 -0
- mcp_agent/ui/console_display.py +125 -13
- {fast_agent_mcp-0.2.40.dist-info → fast_agent_mcp-0.2.41.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.40.dist-info → fast_agent_mcp-0.2.41.dist-info}/licenses/LICENSE +0 -0
mcp_agent/ui/console_display.py
CHANGED
|
@@ -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="
|
|
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="
|
|
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(
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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()
|
|
File without changes
|
|
File without changes
|