fast-agent-mcp 0.3.13__py3-none-any.whl → 0.3.14__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 (33) hide show
  1. fast_agent/agents/llm_agent.py +14 -33
  2. fast_agent/agents/llm_decorator.py +13 -2
  3. fast_agent/agents/mcp_agent.py +18 -2
  4. fast_agent/agents/tool_agent.py +8 -10
  5. fast_agent/cli/commands/check_config.py +45 -1
  6. fast_agent/config.py +63 -0
  7. fast_agent/constants.py +3 -0
  8. fast_agent/context.py +42 -9
  9. fast_agent/core/logging/listeners.py +1 -1
  10. fast_agent/event_progress.py +2 -3
  11. fast_agent/interfaces.py +9 -2
  12. fast_agent/llm/model_factory.py +4 -0
  13. fast_agent/llm/provider_key_manager.py +1 -0
  14. fast_agent/llm/provider_types.py +1 -0
  15. fast_agent/llm/request_params.py +3 -1
  16. fast_agent/mcp/mcp_aggregator.py +313 -40
  17. fast_agent/mcp/mcp_connection_manager.py +39 -9
  18. fast_agent/mcp/skybridge.py +45 -0
  19. fast_agent/mcp/sse_tracking.py +287 -0
  20. fast_agent/mcp/transport_tracking.py +37 -3
  21. fast_agent/mcp/types.py +24 -0
  22. fast_agent/resources/examples/workflows/router.py +1 -0
  23. fast_agent/resources/setup/fastagent.config.yaml +5 -0
  24. fast_agent/ui/console_display.py +295 -18
  25. fast_agent/ui/enhanced_prompt.py +107 -58
  26. fast_agent/ui/interactive_prompt.py +57 -34
  27. fast_agent/ui/mcp_display.py +108 -27
  28. fast_agent/ui/rich_progress.py +4 -1
  29. {fast_agent_mcp-0.3.13.dist-info → fast_agent_mcp-0.3.14.dist-info}/METADATA +2 -2
  30. {fast_agent_mcp-0.3.13.dist-info → fast_agent_mcp-0.3.14.dist-info}/RECORD +33 -30
  31. {fast_agent_mcp-0.3.13.dist-info → fast_agent_mcp-0.3.14.dist-info}/WHEEL +0 -0
  32. {fast_agent_mcp-0.3.13.dist-info → fast_agent_mcp-0.3.14.dist-info}/entry_points.txt +0 -0
  33. {fast_agent_mcp-0.3.13.dist-info → fast_agent_mcp-0.3.14.dist-info}/licenses/LICENSE +0 -0
@@ -14,7 +14,7 @@ Usage:
14
14
  )
15
15
  """
16
16
 
17
- from typing import TYPE_CHECKING, Awaitable, Callable, Dict, List, Optional, Union
17
+ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Union, cast
18
18
 
19
19
  if TYPE_CHECKING:
20
20
  from fast_agent.core.agent_app import AgentApp
@@ -25,6 +25,7 @@ from rich import print as rich_print
25
25
  from fast_agent.agents.agent_types import AgentType
26
26
  from fast_agent.history.history_exporter import HistoryExporter
27
27
  from fast_agent.mcp.mcp_aggregator import SEP
28
+ from fast_agent.mcp.types import McpAgentProtocol
28
29
  from fast_agent.types import PromptMessageExtended
29
30
  from fast_agent.ui.enhanced_prompt import (
30
31
  _display_agent_info_helper,
@@ -114,8 +115,9 @@ class InteractivePrompt:
114
115
 
115
116
  # Check if we should switch agents
116
117
  if isinstance(command_result, dict):
117
- if "switch_agent" in command_result:
118
- new_agent = command_result["switch_agent"]
118
+ command_dict: Dict[str, Any] = command_result
119
+ if "switch_agent" in command_dict:
120
+ new_agent = command_dict["switch_agent"]
119
121
  if new_agent in available_agents_set:
120
122
  agent = new_agent
121
123
  # Display new agent info immediately when switching
@@ -126,14 +128,14 @@ class InteractivePrompt:
126
128
  rich_print(f"[red]Agent '{new_agent}' not found[/red]")
127
129
  continue
128
130
  # Keep the existing list_prompts handler for backward compatibility
129
- elif "list_prompts" in command_result:
131
+ elif "list_prompts" in command_dict:
130
132
  # Use the prompt_provider directly
131
133
  await self._list_prompts(prompt_provider, agent)
132
134
  continue
133
- elif "select_prompt" in command_result:
135
+ elif "select_prompt" in command_dict:
134
136
  # Handle prompt selection, using both list_prompts and apply_prompt
135
- prompt_name = command_result.get("prompt_name")
136
- prompt_index = command_result.get("prompt_index")
137
+ prompt_name = command_dict.get("prompt_name")
138
+ prompt_index = command_dict.get("prompt_index")
137
139
 
138
140
  # If a specific index was provided (from /prompt <number>)
139
141
  if prompt_index is not None:
@@ -163,16 +165,20 @@ class InteractivePrompt:
163
165
  # Use the name-based selection
164
166
  await self._select_prompt(prompt_provider, agent, prompt_name)
165
167
  continue
166
- elif "list_tools" in command_result:
168
+ elif "list_tools" in command_dict:
167
169
  # Handle tools list display
168
170
  await self._list_tools(prompt_provider, agent)
169
171
  continue
170
- elif "show_usage" in command_result:
172
+ elif "show_usage" in command_dict:
171
173
  # Handle usage display
172
174
  await self._show_usage(prompt_provider, agent)
173
175
  continue
174
- elif "show_history" in command_result:
175
- target_agent = command_result.get("show_history", {}).get("agent") or agent
176
+ elif "show_history" in command_dict:
177
+ history_info = command_dict.get("show_history")
178
+ history_agent = (
179
+ history_info.get("agent") if isinstance(history_info, dict) else None
180
+ )
181
+ target_agent = history_agent or agent
176
182
  try:
177
183
  agent_obj = prompt_provider._agent(target_agent)
178
184
  except Exception:
@@ -183,8 +189,12 @@ class InteractivePrompt:
183
189
  usage = getattr(agent_obj, "usage_accumulator", None)
184
190
  display_history_overview(target_agent, history, usage)
185
191
  continue
186
- elif "clear_history" in command_result:
187
- target_agent = command_result.get("clear_history", {}).get("agent") or agent
192
+ elif "clear_history" in command_dict:
193
+ clear_info = command_dict.get("clear_history")
194
+ clear_agent = (
195
+ clear_info.get("agent") if isinstance(clear_info, dict) else None
196
+ )
197
+ target_agent = clear_agent or agent
188
198
  try:
189
199
  agent_obj = prompt_provider._agent(target_agent)
190
200
  except Exception:
@@ -194,7 +204,9 @@ class InteractivePrompt:
194
204
  if hasattr(agent_obj, "clear"):
195
205
  try:
196
206
  agent_obj.clear()
197
- rich_print(f"[green]History cleared for agent '{target_agent}'.[/green]")
207
+ rich_print(
208
+ f"[green]History cleared for agent '{target_agent}'.[/green]"
209
+ )
198
210
  except Exception as exc:
199
211
  rich_print(
200
212
  f"[red]Failed to clear history for '{target_agent}': {exc}[/red]"
@@ -204,21 +216,21 @@ class InteractivePrompt:
204
216
  f"[yellow]Agent '{target_agent}' does not support clearing history.[/yellow]"
205
217
  )
206
218
  continue
207
- elif "show_system" in command_result:
219
+ elif "show_system" in command_dict:
208
220
  # Handle system prompt display
209
221
  await self._show_system(prompt_provider, agent)
210
222
  continue
211
- elif "show_markdown" in command_result:
223
+ elif "show_markdown" in command_dict:
212
224
  # Handle markdown display
213
225
  await self._show_markdown(prompt_provider, agent)
214
226
  continue
215
- elif "show_mcp_status" in command_result:
227
+ elif "show_mcp_status" in command_dict:
216
228
  rich_print()
217
229
  await show_mcp_status(agent, prompt_provider)
218
230
  continue
219
- elif "save_history" in command_result:
231
+ elif "save_history" in command_dict:
220
232
  # Save history for the current agent
221
- filename = command_result.get("filename")
233
+ filename = command_dict.get("filename")
222
234
  try:
223
235
  agent_obj = prompt_provider._agent(agent)
224
236
 
@@ -353,15 +365,16 @@ class InteractivePrompt:
353
365
  )
354
366
  else:
355
367
  # Handle Prompt objects from mcp.types
368
+ prompt_obj = cast("Prompt", prompt)
356
369
  all_prompts.append(
357
370
  {
358
371
  "server": server_name,
359
- "name": prompt.name,
360
- "namespaced_name": f"{server_name}{SEP}{prompt.name}",
361
- "title": prompt.title or None,
362
- "description": prompt.description or "No description",
363
- "arg_count": len(prompt.arguments or []),
364
- "arguments": prompt.arguments or [],
372
+ "name": prompt_obj.name,
373
+ "namespaced_name": f"{server_name}{SEP}{prompt_obj.name}",
374
+ "title": prompt_obj.title or None,
375
+ "description": prompt_obj.description or "No description",
376
+ "arg_count": len(prompt_obj.arguments or []),
377
+ "arguments": prompt_obj.arguments or [],
365
378
  }
366
379
  )
367
380
 
@@ -856,6 +869,10 @@ class InteractivePrompt:
856
869
  if tool.title and tool.title.strip():
857
870
  tool_line.append(f" {tool.title}", style="default")
858
871
 
872
+ meta = getattr(tool, "meta", {}) or {}
873
+ if meta.get("openai/skybridgeEnabled"):
874
+ tool_line.append(" (skybridge)", style="cyan")
875
+
859
876
  rich_print(tool_line)
860
877
 
861
878
  # Description lines - show 2-3 rows if needed
@@ -909,6 +926,11 @@ class InteractivePrompt:
909
926
  args_text = args_text[:77] + "..."
910
927
  rich_print(f" [dim magenta]args: {args_text}[/dim magenta]")
911
928
 
929
+ if meta.get("openai/skybridgeEnabled"):
930
+ template = meta.get("openai/skybridgeTemplate")
931
+ if template:
932
+ rich_print(f" [dim magenta]template:[/dim magenta] {template}")
933
+
912
934
  rich_print() # Space between tools
913
935
 
914
936
  except Exception as e:
@@ -962,22 +984,23 @@ class InteractivePrompt:
962
984
 
963
985
  # Get server count for display
964
986
  server_count = 0
965
- if hasattr(agent, "_aggregator") and hasattr(agent._aggregator, "server_names"):
966
- server_count = (
967
- len(agent._aggregator.server_names) if agent._aggregator.server_names else 0
968
- )
987
+ if isinstance(agent, McpAgentProtocol):
988
+ server_names = agent.aggregator.server_names
989
+ server_count = len(server_names) if server_names else 0
969
990
 
970
991
  # Use the display utility to show the system prompt
971
- if hasattr(agent, "display") and agent.display:
972
- agent.display.show_system_message(
992
+ agent_display = getattr(agent, "display", None)
993
+ if agent_display:
994
+ agent_display.show_system_message(
973
995
  system_prompt=system_prompt, agent_name=agent_name, server_count=server_count
974
996
  )
975
997
  else:
976
998
  # Fallback to basic display
977
999
  from fast_agent.ui.console_display import ConsoleDisplay
978
1000
 
1001
+ agent_context = getattr(agent, "context", None)
979
1002
  display = ConsoleDisplay(
980
- config=agent.context.config if hasattr(agent, "context") else None
1003
+ config=agent_context.config if hasattr(agent_context, "config") else None
981
1004
  )
982
1005
  display.show_system_message(
983
1006
  system_prompt=system_prompt, agent_name=agent_name, server_count=server_count
@@ -1005,11 +1028,11 @@ class InteractivePrompt:
1005
1028
  agent = prompt_provider._agent(agent_name)
1006
1029
 
1007
1030
  # Check if agent has message history
1008
- if not hasattr(agent, "_llm") or not agent._llm:
1031
+ if not agent.llm:
1009
1032
  rich_print("[yellow]No message history available[/yellow]")
1010
1033
  return
1011
1034
 
1012
- message_history = agent._llm.message_history
1035
+ message_history = agent.llm.message_history
1013
1036
  if not message_history:
1014
1037
  rich_print("[yellow]No messages in history[/yellow]")
1015
1038
  return
@@ -39,6 +39,7 @@ class Colours:
39
39
  # Capability token states
40
40
  TOKEN_ERROR = "bright_red"
41
41
  TOKEN_WARNING = "bright_cyan"
42
+ TOKEN_CAUTION = "bright_yellow"
42
43
  TOKEN_DISABLED = "dim"
43
44
  TOKEN_HIGHLIGHTED = "bright_yellow"
44
45
  TOKEN_ENABLED = "bright_green"
@@ -104,6 +105,38 @@ def _format_compact_duration(seconds: float | None) -> str | None:
104
105
  return f"{days}d{hours:02d}h"
105
106
 
106
107
 
108
+ def _format_timeline_label(total_seconds: int) -> str:
109
+ total = max(0, int(total_seconds))
110
+ if total == 0:
111
+ return "0s"
112
+
113
+ days, remainder = divmod(total, 86400)
114
+ if days:
115
+ if remainder == 0:
116
+ return f"{days}d"
117
+ hours = remainder // 3600
118
+ if hours == 0:
119
+ return f"{days}d"
120
+ return f"{days}d{hours}h"
121
+
122
+ hours, remainder = divmod(total, 3600)
123
+ if hours:
124
+ if remainder == 0:
125
+ return f"{hours}h"
126
+ minutes = remainder // 60
127
+ if minutes == 0:
128
+ return f"{hours}h"
129
+ return f"{hours}h{minutes:02d}m"
130
+
131
+ minutes, seconds = divmod(total, 60)
132
+ if minutes:
133
+ if seconds == 0:
134
+ return f"{minutes}m"
135
+ return f"{minutes}m{seconds:02d}s"
136
+
137
+ return f"{seconds}s"
138
+
139
+
107
140
  def _summarise_call_counts(call_counts: dict[str, int]) -> str | None:
108
141
  if not call_counts:
109
142
  return None
@@ -200,6 +233,18 @@ def _format_capability_shorthand(
200
233
  else:
201
234
  entries.append(("In", "blue", False))
202
235
 
236
+ skybridge_config = getattr(status, "skybridge", None)
237
+ if not skybridge_config:
238
+ entries.append(("Sk", False, False))
239
+ else:
240
+ has_warnings = bool(getattr(skybridge_config, "warnings", None))
241
+ if has_warnings:
242
+ entries.append(("Sk", "warn", False))
243
+ elif getattr(skybridge_config, "enabled", False):
244
+ entries.append(("Sk", True, False))
245
+ else:
246
+ entries.append(("Sk", False, False))
247
+
203
248
  if status.roots_configured:
204
249
  entries.append(("Ro", True, False))
205
250
  else:
@@ -228,6 +273,8 @@ def _format_capability_shorthand(
228
273
  return Colours.TOKEN_ERROR
229
274
  if supported == "blue":
230
275
  return Colours.TOKEN_WARNING
276
+ if supported == "warn":
277
+ return Colours.TOKEN_CAUTION
231
278
  if not supported:
232
279
  return Colours.TOKEN_DISABLED
233
280
  if highlighted:
@@ -268,10 +315,28 @@ def _format_label(label: str, width: int = 10) -> str:
268
315
  return f"{label:<{width}}" if len(label) < width else label
269
316
 
270
317
 
271
- def _build_inline_timeline(buckets: Iterable[str]) -> str:
318
+ def _build_inline_timeline(
319
+ buckets: Iterable[str],
320
+ *,
321
+ bucket_seconds: int | None = None,
322
+ bucket_count: int | None = None,
323
+ ) -> str:
272
324
  """Build a compact timeline string for inline display."""
273
- timeline = " [dim]10m[/dim] "
274
- for state in buckets:
325
+ bucket_list = list(buckets)
326
+ count = bucket_count or len(bucket_list)
327
+ if count <= 0:
328
+ count = len(bucket_list) or 1
329
+
330
+ seconds = bucket_seconds or 30
331
+ total_window = seconds * count
332
+ timeline = f" [dim]{_format_timeline_label(total_window)}[/dim] "
333
+
334
+ if len(bucket_list) < count:
335
+ bucket_list.extend(["none"] * (count - len(bucket_list)))
336
+ elif len(bucket_list) > count:
337
+ bucket_list = bucket_list[-count:]
338
+
339
+ for state in bucket_list:
275
340
  color = TIMELINE_COLORS.get(state, Colours.NONE)
276
341
  if state in {"idle", "none"}:
277
342
  symbol = SYMBOL_IDLE
@@ -297,6 +362,10 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
297
362
  if snapshot is None:
298
363
  return
299
364
 
365
+ transport_value = getattr(status, "transport", None)
366
+ transport_lower = (transport_value or "").lower()
367
+ is_sse_transport = transport_lower == "sse"
368
+
300
369
  # Show channel types based on what's available
301
370
  entries: list[tuple[str, str, ChannelSnapshot | None]] = []
302
371
 
@@ -311,12 +380,13 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
311
380
  stdio_channel = getattr(snapshot, "stdio", None)
312
381
 
313
382
  if any(channel is not None for channel in http_channels):
314
- # HTTP transport - show the original three channels
383
+ # HTTP or SSE transport - show available channels
315
384
  entries = [
316
385
  ("GET (SSE)", "◀", getattr(snapshot, "get", None)),
317
386
  ("POST (SSE)", "▶", getattr(snapshot, "post_sse", None)),
318
- ("POST (JSON)", "▶", getattr(snapshot, "post_json", None)),
319
387
  ]
388
+ if not is_sse_transport:
389
+ entries.append(("POST (JSON)", "▶", getattr(snapshot, "post_json", None)))
320
390
  elif stdio_channel is not None:
321
391
  # STDIO transport - show single bidirectional channel
322
392
  entries = [
@@ -332,36 +402,31 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
332
402
  # Determine if we're showing stdio or HTTP channels
333
403
  is_stdio = stdio_channel is not None
334
404
 
405
+ default_bucket_seconds = getattr(snapshot, "activity_bucket_seconds", None) or 30
406
+ default_bucket_count = getattr(snapshot, "activity_bucket_count", None) or 20
407
+ timeline_header_label = _format_timeline_label(default_bucket_seconds * default_bucket_count)
408
+
409
+ # Total characters before the metrics section in each row (excluding indent)
410
+ # Structure: "│ " + arrow + " " + label(13) + timeline_label + " " + buckets + " now"
411
+ metrics_prefix_width = 22 + len(timeline_header_label) + default_bucket_count
412
+
335
413
  # Get transport type for display
336
- transport = getattr(status, "transport", None) or "unknown"
414
+ transport = transport_value or "unknown"
337
415
  transport_display = transport.upper() if transport != "unknown" else "Channels"
338
416
 
339
417
  # Header with column labels
340
418
  header = Text(indent)
341
- header.append(f"┌ {transport_display} ", style="dim")
419
+ header_intro = f"┌ {transport_display} "
420
+ header.append(header_intro, style="dim")
342
421
 
343
422
  # Calculate padding needed based on transport display length
344
- # Base structure: "┌ " (2) + transport_display + " " (1) + "─" padding to align with columns
345
- header_prefix_len = 3 + len(transport_display)
423
+ header_prefix_len = len(header_intro)
346
424
 
425
+ dash_count = max(1, metrics_prefix_width - header_prefix_len + 2)
347
426
  if is_stdio:
348
- # Simplified header for stdio: just activity column
349
- # Need to align with "│ ⇄ STDIO 10m ●●●●●●●●●●●●●●●●●●●● now 29"
350
- # That's: "│ " + arrow + " " + label(13) + "10m " + dots(20) + " now" = 47 chars
351
- # Then: " " + activity(8) = 10 chars
352
- # Total content width = 47 + 10 = 57 chars
353
- # So we need 47 - header_prefix_len dashes before "activity"
354
- dash_count = max(1, 47 - header_prefix_len)
355
427
  header.append("─" * dash_count, style="dim")
356
428
  header.append(" activity", style="dim")
357
429
  else:
358
- # Original header for HTTP channels
359
- # Need to align with the req/resp/notif/ping columns
360
- # Structure: "│ " + arrow + " " + label(13) + "10m " + dots(20) + " now" = 47 chars
361
- # Then: " " + req(5) + " " + resp(5) + " " + notif(5) + " " + ping(5) = 25 chars
362
- # Total content width = 47 + 25 = 72 chars
363
- # So we need 47 - header_prefix_len dashes before the column headers
364
- dash_count = max(1, 47 - header_prefix_len)
365
430
  header.append("─" * dash_count, style="dim")
366
431
  header.append(" req resp notif ping", style="dim")
367
432
 
@@ -449,10 +514,24 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
449
514
  line.append(f" {label:<13}", style=label_style)
450
515
 
451
516
  # Always show timeline (dim black dots if no data)
452
- line.append("10m ", style="dim")
453
- if channel and channel.activity_buckets:
517
+ channel_bucket_seconds = (
518
+ getattr(channel, "activity_bucket_seconds", None) or default_bucket_seconds
519
+ )
520
+ bucket_count = (
521
+ len(channel.activity_buckets)
522
+ if channel and channel.activity_buckets
523
+ else getattr(channel, "activity_bucket_count", None)
524
+ )
525
+ if not bucket_count or bucket_count <= 0:
526
+ bucket_count = default_bucket_count
527
+ total_window_seconds = channel_bucket_seconds * bucket_count
528
+ timeline_label = _format_timeline_label(total_window_seconds)
529
+
530
+ line.append(f"{timeline_label} ", style="dim")
531
+ bucket_states = channel.activity_buckets if channel and channel.activity_buckets else None
532
+ if bucket_states:
454
533
  # Show actual activity
455
- for bucket_state in channel.activity_buckets:
534
+ for bucket_state in bucket_states:
456
535
  color = timeline_color_map.get(bucket_state, "dim")
457
536
  if bucket_state in {"idle", "none"}:
458
537
  symbol = SYMBOL_IDLE
@@ -473,7 +552,7 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
473
552
  line.append(symbol, style=f"bold {color}")
474
553
  else:
475
554
  # Show dim dots for no activity
476
- for _ in range(20):
555
+ for _ in range(bucket_count):
477
556
  line.append(SYMBOL_IDLE, style="black dim")
478
557
  line.append(" now", style="dim")
479
558
 
@@ -588,6 +667,8 @@ def _render_channel_summary(status: ServerStatus, indent: str, total_width: int)
588
667
  symbol = SYMBOL_ERROR
589
668
  elif name == "ping":
590
669
  symbol = SYMBOL_PING
670
+ elif is_stdio and name == "activity":
671
+ symbol = SYMBOL_STDIO_ACTIVITY
591
672
  else:
592
673
  symbol = SYMBOL_RESPONSE
593
674
  footer.append(symbol, style=f"{color}")
@@ -78,6 +78,7 @@ class RichProgressDisplay:
78
78
  ProgressAction.INITIALIZED: "dim green",
79
79
  ProgressAction.CHATTING: "bold blue",
80
80
  ProgressAction.STREAMING: "bold green", # Assistant Colour
81
+ ProgressAction.THINKING: "bold yellow", # Assistant Colour
81
82
  ProgressAction.ROUTING: "bold blue",
82
83
  ProgressAction.PLANNING: "bold blue",
83
84
  ProgressAction.READY: "dim green",
@@ -108,7 +109,9 @@ class RichProgressDisplay:
108
109
 
109
110
  # Ensure no None values in the update
110
111
  # For streaming, use custom description immediately to avoid flashing
111
- if event.action == ProgressAction.STREAMING and event.streaming_tokens:
112
+ if (
113
+ event.action == ProgressAction.STREAMING or event.action == ProgressAction.THINKING
114
+ ) and event.streaming_tokens:
112
115
  # Account for [dim][/dim] tags (11 characters) in padding calculation
113
116
  formatted_tokens = f"▎[dim]◀[/dim] {event.streaming_tokens.strip()}".ljust(17 + 11)
114
117
  description = f"[{self._get_action_style(event.action)}]{formatted_tokens}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fast-agent-mcp
3
- Version: 0.3.13
3
+ Version: 0.3.14
4
4
  Summary: Define, Prompt and Test MCP enabled Agents and Workflows
5
5
  Author-email: Shaun Smith <fastagent@llmindset.co.uk>
6
6
  License: Apache License
@@ -219,7 +219,7 @@ Requires-Dist: email-validator>=2.2.0
219
219
  Requires-Dist: fastapi>=0.115.6
220
220
  Requires-Dist: google-genai>=1.33.0
221
221
  Requires-Dist: keyring>=24.3.1
222
- Requires-Dist: mcp==1.16.0
222
+ Requires-Dist: mcp==1.17.0
223
223
  Requires-Dist: openai>=2.1.0
224
224
  Requires-Dist: opentelemetry-distro>=0.55b0
225
225
  Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.7.0
@@ -1,18 +1,18 @@
1
1
  fast_agent/__init__.py,sha256=ns6CPmjOL5y7cyV4XgFTfMGcfLnuBJwVTbcjJ5Co3x4,4152
2
- fast_agent/config.py,sha256=tKnAhGAADpuwU7DggScG0VESs7el4R1Y1T3MUPzD5_U,22509
3
- fast_agent/constants.py,sha256=IoXL5m4L0iLlcRrKerMaK3ZPcS6KCJgK8b_bj1BAR60,345
4
- fast_agent/context.py,sha256=nBelOqehSH91z3aG2nYhwETP-biRzz-iuA2fqmKdHP8,7700
2
+ fast_agent/config.py,sha256=sewLcvcywqWiDuLUbjds8VMhLszgu3ZW3h88CLa3uTU,24789
3
+ fast_agent/constants.py,sha256=GQZw66l9_X58T1fwSnOQZbPnj3ydJxWdwzvLo0RnGYU,520
4
+ fast_agent/context.py,sha256=kHCWvj6Smo2WwfcKHF4bFdnqD7H2HdCmiTWePos-4NM,8890
5
5
  fast_agent/context_dependent.py,sha256=KU1eydVBoIt4bYOZroqxDgE1AUexDaZi7hurE26QsF4,1584
6
- fast_agent/event_progress.py,sha256=OETeh-4jJGyxvvPAlVTzW4JsCbFUmOTo-ti0ROgtG5M,1999
7
- fast_agent/interfaces.py,sha256=XktRxJjLfCMPbC5ReV23dP-dRy0gDNtYfMCvSp0QD0I,6373
6
+ fast_agent/event_progress.py,sha256=iTGlD-tAG3n_mLnUr7h03nPMSZK8piyLeaA-IB9erBw,2064
7
+ fast_agent/interfaces.py,sha256=SF-ITigHU4J5zJPJzn5pzO0_cME_RSCPvqTRpIKvL3c,6588
8
8
  fast_agent/mcp_server_registry.py,sha256=TDCNpQIehsh1PK4y7AWp_rkQMcwYx7FaouUbK3kWNZo,2635
9
9
  fast_agent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  fast_agent/agents/__init__.py,sha256=WfgtR9MgmJUJI7rb-CUH_10s7308LjxYIYzJRIBZ_9Y,2644
11
11
  fast_agent/agents/agent_types.py,sha256=xAFEFWIvOtSnTNDcqqfaAnBx_lFLhnS2_b4hm9xKMo8,1719
12
- fast_agent/agents/llm_agent.py,sha256=1lO-DtgeaOoYshHxGKNUIViR_gFJjW6GudEWxRFdVU4,10697
13
- fast_agent/agents/llm_decorator.py,sha256=OezFrnjLwcl3W-1K1sGPtTqD_zVp67wlBUb4SxTesKw,29702
14
- fast_agent/agents/mcp_agent.py,sha256=O9CrjjUrkmbNYsXQevZy2b8EG4B0KdNSH3wtnbe2HI4,39279
15
- fast_agent/agents/tool_agent.py,sha256=bR0V06zCjuPVtOpOQQzym2Mmyt6EsDzAodJmQOEMoFI,8883
12
+ fast_agent/agents/llm_agent.py,sha256=q8tXXRIUquIm8Cz4-7dFmzFQ4gQI87kAzKst6hqSrXc,9908
13
+ fast_agent/agents/llm_decorator.py,sha256=aJ3ynv_YMARCOh7Lk9Srf-sWOt3ax1rDkjvNiabW4-A,30135
14
+ fast_agent/agents/mcp_agent.py,sha256=UysCZTO9RbkFUS8RRhTdqKu8ewBb9Cl2K1yRDqcIhYg,39869
15
+ fast_agent/agents/tool_agent.py,sha256=D4NrDkH8BtFOIc058GiqikZq5H9kUsIK-OdDrgenyec,8832
16
16
  fast_agent/agents/workflow/chain_agent.py,sha256=Pd8dOH_YdKu3LXsKa4fwqzY_B2qVuhzdfCUiKi5v17s,6293
17
17
  fast_agent/agents/workflow/evaluator_optimizer.py,sha256=rhzazy8Aj-ydId6kmBC77TmtYZ5mirSe7eV6PPMWkBA,12040
18
18
  fast_agent/agents/workflow/iterative_planner.py,sha256=CTtDpK-YGrFFZMQQmFeE-2I_9-cZv23pNwUoh8w5voA,20478
@@ -26,7 +26,7 @@ fast_agent/cli/constants.py,sha256=flYDsml3_8wVcGg7T1t5mPFT9CC1M-XMjBigXjX6PuI,5
26
26
  fast_agent/cli/main.py,sha256=tERbfQjure3kgKYqzZCNDSLyiVZGXCH2coZ8YBwvq64,4398
27
27
  fast_agent/cli/terminal.py,sha256=tDN1fJ91Nc_wZJTNafkQuD7Z7gFscvo1PHh-t7Wl-5s,1066
28
28
  fast_agent/cli/commands/auth.py,sha256=nJEC7zrz5UXYUz5O6AgGZnfJPHIrgHk68CUwGo-7Nyg,15063
29
- fast_agent/cli/commands/check_config.py,sha256=D0emHGl6yc9XRq-HjAwS4KfS7a9r5gkA55MyiIRptGQ,26638
29
+ fast_agent/cli/commands/check_config.py,sha256=FsC3gXS8qjSKIHARAd4w5jGkCKuQcyK4eGQKmlqyAMo,28407
30
30
  fast_agent/cli/commands/go.py,sha256=mZJv1jXO9xqVUzuDCO5iWKI8ubBUACHO6i3lZwu5NFU,15148
31
31
  fast_agent/cli/commands/quickstart.py,sha256=UOTqAbaVGLECHkTvpUNQ41PWXssqCijVvrqh30YUqnM,20624
32
32
  fast_agent/cli/commands/server_helpers.py,sha256=Nuded8sZb4Rybwoq5LbXXUgwtJZg-OO04xhmPUp6e98,4073
@@ -49,7 +49,7 @@ fast_agent/core/executor/workflow_signal.py,sha256=Cg1uZBk3fn8kXhPOg-wINNuVaf3v9
49
49
  fast_agent/core/logging/__init__.py,sha256=dFW2bbTtz45zebUuQs7RVi7mg1RJm4DHH6TGfBMhW14,167
50
50
  fast_agent/core/logging/events.py,sha256=WTjr26uIxtbxhnoLNPROVUIt0HNJrzK1g1fUMZ-zVsQ,4207
51
51
  fast_agent/core/logging/json_serializer.py,sha256=kQDkwTHIkHSQgbhDOJhMoetNvfJVMZGOScaKoLX8kmw,5797
52
- fast_agent/core/logging/listeners.py,sha256=LVZMf274gN-T-MKNpkmwaE_FbJX2AS0HoHdROrrkmdQ,9400
52
+ fast_agent/core/logging/listeners.py,sha256=U4RpiUTFRUXO9YmujKiBsvVmwNablDtZdLePs6mG34g,9446
53
53
  fast_agent/core/logging/logger.py,sha256=L-hLfUGFCIABoNYDiUkNHWvFxL6j-6zn5Pc5E7aC44M,11074
54
54
  fast_agent/core/logging/transport.py,sha256=i_WYXk5mqyfetT72bCYrbdrMWcuL1HJCyeQKfQg7U2w,16994
55
55
  fast_agent/history/history_exporter.py,sha256=oqkw7qC5rrW73u20tkIqt8yBWPoVzCTC61x2Q2rOKGs,1404
@@ -63,12 +63,12 @@ fast_agent/llm/__init__.py,sha256=MCsrkfnTQXYvn0SofJ-JFmp1l1jX_eidgvegbWbgpsw,18
63
63
  fast_agent/llm/fastagent_llm.py,sha256=GyvBGAgwd1frWUzSiBANNQdFX-a50ps97WPEX7q2uw8,25119
64
64
  fast_agent/llm/memory.py,sha256=POFoBVMHK0wX4oLd3Gz-6Ru3uC4kTCvAqsVQ77e7KJA,8551
65
65
  fast_agent/llm/model_database.py,sha256=qhC4CX_dKNDTQ3bJA_YCq2wIJK5YP_xlbqNuI1K-a6g,12948
66
- fast_agent/llm/model_factory.py,sha256=y0gmgFzk15UJHZuTbnp5ExYG4DhlX0X1YzzUc1leNVo,13043
66
+ fast_agent/llm/model_factory.py,sha256=tLOT1c1LXvZAe-XExj7apkjLcot-tyVcCiXRktsupSc,13209
67
67
  fast_agent/llm/model_info.py,sha256=DAIMW70W-EFqNLIudhjHJE2gobHUAKg90gkwOPuaFUc,4125
68
68
  fast_agent/llm/prompt_utils.py,sha256=1WU67G-BFqftja5I8FKPMMzsvDk1K_1jDi9A9kkFdOg,4899
69
- fast_agent/llm/provider_key_manager.py,sha256=igzs1ghXsUp0wA4nJVVfWCWiYOib8Ux4jMGlhWbgXu8,3396
70
- fast_agent/llm/provider_types.py,sha256=Ya0MGo_4cE0oCwinqPvr9SJUwx4hEJ7CFbCrLB_27FI,1142
71
- fast_agent/llm/request_params.py,sha256=lQxDmPDpqkbKQPI0WxL8Y4FDweovI6lTbxsHPZ_agq8,1735
69
+ fast_agent/llm/provider_key_manager.py,sha256=O8jhoqzLgMbY57TbJxztNwElbsQPC0GMIwgiaz_5SuQ,3455
70
+ fast_agent/llm/provider_types.py,sha256=JyJoyyCI3htgX9VCvvyz2Lx9fBQtdrLbXma0oc9vfsw,1185
71
+ fast_agent/llm/request_params.py,sha256=HjzGLvEvRMXPMDOxDzbVyb4X_QOt0WErdv1nbCEaZnY,1812
72
72
  fast_agent/llm/sampling_converter.py,sha256=YEUpdVeZlJNDljCuwrXyhsb40o0-1QuWGTuorQnvhbo,3102
73
73
  fast_agent/llm/usage_tracking.py,sha256=6FRIIimIaAoSlYTCGVG00GuavGRIFbOBEBWHvfBxWw0,16791
74
74
  fast_agent/llm/internal/passthrough.py,sha256=0P7qc13_xTV1aMHJmZ2KQEtMtGtu0H7ArkEL6hiy5_M,5209
@@ -104,8 +104,8 @@ fast_agent/mcp/hf_auth.py,sha256=ndDvR7E9LCc5dBiMsStFXtvvX9lYrL-edCq_qJw4lDw,447
104
104
  fast_agent/mcp/interfaces.py,sha256=xCWONGXe4uQSmmBlMZRD3mflPegTJnz2caVNihEl3ok,2411
105
105
  fast_agent/mcp/logger_textio.py,sha256=4YLVXlXghdGm1s_qp1VoAWEX_eWufBfD2iD7l08yoak,3170
106
106
  fast_agent/mcp/mcp_agent_client_session.py,sha256=VTPEjNjPMrxZopeCr7bXjlvr_2MTzdqEjjBOeQri04g,16050
107
- fast_agent/mcp/mcp_aggregator.py,sha256=HzNyKuUelAlp5JBkjMAaOB2JvdMgpm0ItEPGjidI9l0,67198
108
- fast_agent/mcp/mcp_connection_manager.py,sha256=g19Y-gNH6wmMtFcN9awgQ9yRGmqWa1wi9CpaV80pdfk,25367
107
+ fast_agent/mcp/mcp_aggregator.py,sha256=bgqETI-hFtkweW-lcQkA2nvmokiVUv3Z0NohdkhnJwg,77890
108
+ fast_agent/mcp/mcp_connection_manager.py,sha256=57trQyXYCI5MjyiEBSBpyzv4qDyty-MEaqQSAl2_UYA,26515
109
109
  fast_agent/mcp/mcp_content.py,sha256=F9bgJ57EO9sgWg1m-eTNM6xd9js79mHKf4e9O8K8jrI,8829
110
110
  fast_agent/mcp/mime_utils.py,sha256=D6YXNdZJ351BjacSW5o0sVF_hrWuRHD6UyWS4TDlLZI,2915
111
111
  fast_agent/mcp/oauth_client.py,sha256=3shN3iwsJNXrk7nbcfUgrzNos3i2RuMuLXA80nR8r6Y,17104
@@ -115,9 +115,12 @@ fast_agent/mcp/prompt_render.py,sha256=AqDaQqM6kqciV9X79S5rsRr3VjcQ_2JOiLaHqpRzs
115
115
  fast_agent/mcp/prompt_serialization.py,sha256=QMbY0aa_UlJ7bbxl_muOm2TYeYbBVTEeEMHFmEy99ss,20182
116
116
  fast_agent/mcp/resource_utils.py,sha256=cu-l9aOy-NFs8tPihYRNjsB2QSuime8KGOGpUvihp84,6589
117
117
  fast_agent/mcp/sampling.py,sha256=6S9bpGCFGC5azIGE-zxODvKgBbBn1x6amL5mc4sMg_4,7491
118
+ fast_agent/mcp/skybridge.py,sha256=IdaZE3BoXLCxI1Tt9Q3L44t94JBNh1ei4IyUkZDKvCQ,1333
119
+ fast_agent/mcp/sse_tracking.py,sha256=BG4Y84oVE3r8Ggsbda3zEh4yHYPsBzVnl9O_sithMxM,11748
118
120
  fast_agent/mcp/stdio_tracking_simple.py,sha256=T6kCIb6YjwqKtXHz_6HvlLLYiSCbuggt2xCXSihVnIg,1918
119
121
  fast_agent/mcp/streamable_http_tracking.py,sha256=bcNNReokho6WMjWEH13F33bUSkjJ2F5l3qnegkDqdMA,11465
120
- fast_agent/mcp/transport_tracking.py,sha256=tsc2Ntf47KbKXs8DzRkqvG0U-FbpwU2VxemNfRbJBpo,24088
122
+ fast_agent/mcp/transport_tracking.py,sha256=Qm0c-QjlU4DJW3lI8oYR1CCia9gYxOHecKPY8hHFXYU,25617
123
+ fast_agent/mcp/types.py,sha256=BSKto-ArpIt1xiMaISF32xsPNlWVaFkf9rUnl085Q7o,643
121
124
  fast_agent/mcp/ui_agent.py,sha256=OBGEuFpOPPK7EthPRwzxmtzu1SDIeZy-vHwdRsyDNQk,1424
122
125
  fast_agent/mcp/ui_mixin.py,sha256=iOlSNJVPwiMUun0clCiWyot59Qgy8R7ZvUgH2afRnQA,7662
123
126
  fast_agent/mcp/helpers/__init__.py,sha256=o6-HuX6bEVFnfT_wgclFOVb1NxtOsJEOnHX8L2IqDdw,857
@@ -178,12 +181,12 @@ fast_agent/resources/examples/workflows/graded_report.md,sha256=QVF38xEtDIO1a2P-
178
181
  fast_agent/resources/examples/workflows/human_input.py,sha256=gFuptgiU0mMMtv3F1XI7syCSyVV8tyi5qTOn9ziJdWI,792
179
182
  fast_agent/resources/examples/workflows/orchestrator.py,sha256=YWSgH8cDqEuWercgof2aZLbrO0idiSL932ym3lrniNM,2526
180
183
  fast_agent/resources/examples/workflows/parallel.py,sha256=kROiRueTm0Wql4EWVjFSyonV5A4gPepm1jllz5alias,1826
181
- fast_agent/resources/examples/workflows/router.py,sha256=lxMxz6g0_XjYnwzEwKdl9l2hxRsD4PSsaIlhH5nLuQY,2075
184
+ fast_agent/resources/examples/workflows/router.py,sha256=_xVOLzSHY3ZcNfUjvtqVrkiiML5atgGp8Xti7z-U_ZY,2109
182
185
  fast_agent/resources/examples/workflows/short_story.md,sha256=XN9I2kzCcMmke3dE5F2lyRH5iFUZUQ8Sy-hS3rm_Wlc,1153
183
186
  fast_agent/resources/examples/workflows/short_story.txt,sha256=X3y_1AyhLFN2AKzCKvucJtDgAFIJfnlbsbGZO5bBWu0,1187
184
187
  fast_agent/resources/setup/.gitignore,sha256=bksf0bkvBXtm3F5Nd4F9FB2LaO2RcTbHujYWjq5JKPo,305
185
188
  fast_agent/resources/setup/agent.py,sha256=IlZecsc9vTtH2rj9BFF4M6BUgClg5fQ2HasYV1PPIHA,518
186
- fast_agent/resources/setup/fastagent.config.yaml,sha256=4lYdNTUqBwp7DiyeoUDqBDlqfnFi9JTihOTnix3V9M0,1464
189
+ fast_agent/resources/setup/fastagent.config.yaml,sha256=kQPSopSJ03r6YeevPTlXo9NNE9TChN94_lymE57z5yQ,1703
187
190
  fast_agent/resources/setup/fastagent.secrets.yaml.example,sha256=ht-i2_SpAyeXG2OnG_vOA1n7gRsGIInxp9g5Nio-jpI,1038
188
191
  fast_agent/resources/setup/pyproject.toml.tmpl,sha256=SxyVPXbtD67yFOx9wIrzq6Yxo4W2PkSR1rrnPkmpjwA,478
189
192
  fast_agent/tools/elicitation.py,sha256=8FaNvuN__LAM328VSJ5T4Bg3m8auHraqYvIYv6Eh4KU,13464
@@ -191,21 +194,21 @@ fast_agent/types/__init__.py,sha256=y-53m-C4drf4Rx8Bbnk_GAhko9LdNYCyRUWya8e0mos,
191
194
  fast_agent/types/llm_stop_reason.py,sha256=bWe97OfhALUe8uQeAQOnTdPlYzJiabIfo8u38kPgj3Q,2293
192
195
  fast_agent/ui/__init__.py,sha256=MXxTQjFdF7mI_3JHxBPd-aoZYLlxV_-51-Trqgv5-3w,1104
193
196
  fast_agent/ui/console.py,sha256=Gjf2QLFumwG1Lav__c07X_kZxxEUSkzV-1_-YbAwcwo,813
194
- fast_agent/ui/console_display.py,sha256=brDhUR-VoQWV3-YWrmvWS1q9zYFL3eJkO1Uxs_1AwA4,44017
197
+ fast_agent/ui/console_display.py,sha256=SQCGq0wlu_s0032Mf0tklFdx1WOSUP5hf3v_G4IOTHk,55736
195
198
  fast_agent/ui/elicitation_form.py,sha256=t3UhBG44YmxTLu1RjCnHwW36eQQaroE45CiBGJB2czg,29410
196
199
  fast_agent/ui/elicitation_style.py,sha256=-WqXgVjVs65oNwhCDw3E0A9cCyw95IOe6LYCJgjT6ok,3939
197
- fast_agent/ui/enhanced_prompt.py,sha256=TPJmC1zKQaiqDbtlI0WcxUoH5uw1sY23uJ8uEeYiMCY,45018
200
+ fast_agent/ui/enhanced_prompt.py,sha256=NTbO81GzSpa1kUxZgz2ppKHWqsKgACM8fcA5Al6W1Rk,47015
198
201
  fast_agent/ui/history_display.py,sha256=b7l-pXohSnn1YK1g-8BUmY479x-d-wf5sG2pItG2_ps,19024
199
- fast_agent/ui/interactive_prompt.py,sha256=KI2jSO4roWNivfOeyibiu44J9pu5RU6PiB7Fd59iCYw,46699
200
- fast_agent/ui/mcp_display.py,sha256=piDn0F98yqvlHx1cxuKqTfefpvZkGiGK2QHujJltMtA,28422
202
+ fast_agent/ui/interactive_prompt.py,sha256=2nKETLjLOizYP8MPSDlrPSmp59CPjFenZPUZxDzbP7g,47790
203
+ fast_agent/ui/mcp_display.py,sha256=YSpfb0DLtThDs6xEP-USeYAsnejfaYhIgNx7gtrJ9-Q,30791
201
204
  fast_agent/ui/mcp_ui_utils.py,sha256=hV7z-yHX86BgdH6CMmN5qyOUjyiegQXLJOa5n5A1vQs,8476
202
205
  fast_agent/ui/mermaid_utils.py,sha256=MpcRyVCPMTwU1XeIxnyFg0fQLjcyXZduWRF8NhEqvXE,5332
203
206
  fast_agent/ui/notification_tracker.py,sha256=-hiBwR47SdnwhvrGIXcgsVaqMlMudmrKAf9Xi_E5Eok,5850
204
207
  fast_agent/ui/progress_display.py,sha256=hajDob65PttiJ2mPS6FsCtnmTcnyvDWGn-UqQboXqkQ,361
205
- fast_agent/ui/rich_progress.py,sha256=4n5NmsRQTT1GX18faP43yLPhB_gZJqJeWX6-j7g1_zI,7731
208
+ fast_agent/ui/rich_progress.py,sha256=s0HAaZHR3R7ubqtV20SX64RmkwvGCLXuJ8y29VjVKZs,7870
206
209
  fast_agent/ui/usage_display.py,sha256=ltJpn_sDzo8PDNSXWx-QdEUbQWUnhmajCItNt5mA5rM,7285
207
- fast_agent_mcp-0.3.13.dist-info/METADATA,sha256=BJ3SgQEi3XsnCjuK6aiPTtvGKq6khx_w8HD5NAE0gX8,32003
208
- fast_agent_mcp-0.3.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
209
- fast_agent_mcp-0.3.13.dist-info/entry_points.txt,sha256=i6Ujja9J-hRxttOKqTYdbYP_tyaS4gLHg53vupoCSsg,199
210
- fast_agent_mcp-0.3.13.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
211
- fast_agent_mcp-0.3.13.dist-info/RECORD,,
210
+ fast_agent_mcp-0.3.14.dist-info/METADATA,sha256=Lcp_aH3GGNC7mK0GgGa_5nPjZKBFWMaQTcInnBM_DEc,32003
211
+ fast_agent_mcp-0.3.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
212
+ fast_agent_mcp-0.3.14.dist-info/entry_points.txt,sha256=i6Ujja9J-hRxttOKqTYdbYP_tyaS4gLHg53vupoCSsg,199
213
+ fast_agent_mcp-0.3.14.dist-info/licenses/LICENSE,sha256=Gx1L3axA4PnuK4FxsbX87jQ1opoOkSFfHHSytW6wLUU,10935
214
+ fast_agent_mcp-0.3.14.dist-info/RECORD,,