fast-agent-mcp 0.2.58__py3-none-any.whl → 0.3.1__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/__init__.py +127 -0
- fast_agent/agents/__init__.py +36 -0
- {mcp_agent/core → fast_agent/agents}/agent_types.py +2 -1
- fast_agent/agents/llm_agent.py +217 -0
- fast_agent/agents/llm_decorator.py +486 -0
- mcp_agent/agents/base_agent.py → fast_agent/agents/mcp_agent.py +377 -385
- fast_agent/agents/tool_agent.py +168 -0
- {mcp_agent → fast_agent}/agents/workflow/chain_agent.py +43 -33
- {mcp_agent → fast_agent}/agents/workflow/evaluator_optimizer.py +31 -35
- {mcp_agent → fast_agent}/agents/workflow/iterative_planner.py +56 -47
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_models.py +4 -4
- {mcp_agent → fast_agent}/agents/workflow/parallel_agent.py +34 -41
- {mcp_agent → fast_agent}/agents/workflow/router_agent.py +54 -39
- {mcp_agent → fast_agent}/cli/__main__.py +5 -3
- {mcp_agent → fast_agent}/cli/commands/check_config.py +95 -66
- {mcp_agent → fast_agent}/cli/commands/go.py +20 -11
- {mcp_agent → fast_agent}/cli/commands/quickstart.py +4 -4
- {mcp_agent → fast_agent}/cli/commands/server_helpers.py +1 -1
- {mcp_agent → fast_agent}/cli/commands/setup.py +75 -134
- {mcp_agent → fast_agent}/cli/commands/url_parser.py +9 -8
- {mcp_agent → fast_agent}/cli/main.py +36 -16
- {mcp_agent → fast_agent}/cli/terminal.py +2 -2
- {mcp_agent → fast_agent}/config.py +10 -2
- fast_agent/constants.py +8 -0
- {mcp_agent → fast_agent}/context.py +24 -19
- {mcp_agent → fast_agent}/context_dependent.py +9 -5
- fast_agent/core/__init__.py +52 -0
- {mcp_agent → fast_agent}/core/agent_app.py +39 -36
- fast_agent/core/core_app.py +135 -0
- {mcp_agent → fast_agent}/core/direct_decorators.py +12 -26
- {mcp_agent → fast_agent}/core/direct_factory.py +95 -73
- {mcp_agent → fast_agent/core}/executor/executor.py +4 -5
- {mcp_agent → fast_agent}/core/fastagent.py +32 -32
- fast_agent/core/logging/__init__.py +5 -0
- {mcp_agent → fast_agent/core}/logging/events.py +3 -3
- {mcp_agent → fast_agent/core}/logging/json_serializer.py +1 -1
- {mcp_agent → fast_agent/core}/logging/listeners.py +85 -7
- {mcp_agent → fast_agent/core}/logging/logger.py +7 -7
- {mcp_agent → fast_agent/core}/logging/transport.py +10 -11
- fast_agent/core/prompt.py +9 -0
- {mcp_agent → fast_agent}/core/validation.py +4 -4
- fast_agent/event_progress.py +61 -0
- fast_agent/history/history_exporter.py +44 -0
- {mcp_agent → fast_agent}/human_input/__init__.py +9 -12
- {mcp_agent → fast_agent}/human_input/elicitation_handler.py +26 -8
- {mcp_agent → fast_agent}/human_input/elicitation_state.py +7 -7
- {mcp_agent → fast_agent}/human_input/simple_form.py +6 -4
- {mcp_agent → fast_agent}/human_input/types.py +1 -18
- fast_agent/interfaces.py +228 -0
- fast_agent/llm/__init__.py +9 -0
- mcp_agent/llm/augmented_llm.py → fast_agent/llm/fastagent_llm.py +127 -218
- fast_agent/llm/internal/passthrough.py +137 -0
- mcp_agent/llm/augmented_llm_playback.py → fast_agent/llm/internal/playback.py +29 -25
- mcp_agent/llm/augmented_llm_silent.py → fast_agent/llm/internal/silent.py +10 -17
- fast_agent/llm/internal/slow.py +38 -0
- {mcp_agent → fast_agent}/llm/memory.py +40 -30
- {mcp_agent → fast_agent}/llm/model_database.py +35 -2
- {mcp_agent → fast_agent}/llm/model_factory.py +103 -77
- fast_agent/llm/model_info.py +126 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/anthropic_utils.py +7 -7
- fast_agent/llm/provider/anthropic/llm_anthropic.py +603 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/multipart_converter_anthropic.py +79 -86
- {mcp_agent/llm/providers → fast_agent/llm/provider/bedrock}/bedrock_utils.py +3 -1
- mcp_agent/llm/providers/augmented_llm_bedrock.py → fast_agent/llm/provider/bedrock/llm_bedrock.py +833 -717
- {mcp_agent/llm/providers → fast_agent/llm/provider/google}/google_converter.py +66 -14
- fast_agent/llm/provider/google/llm_google_native.py +431 -0
- mcp_agent/llm/providers/augmented_llm_aliyun.py → fast_agent/llm/provider/openai/llm_aliyun.py +6 -7
- mcp_agent/llm/providers/augmented_llm_azure.py → fast_agent/llm/provider/openai/llm_azure.py +4 -4
- mcp_agent/llm/providers/augmented_llm_deepseek.py → fast_agent/llm/provider/openai/llm_deepseek.py +10 -11
- mcp_agent/llm/providers/augmented_llm_generic.py → fast_agent/llm/provider/openai/llm_generic.py +4 -4
- mcp_agent/llm/providers/augmented_llm_google_oai.py → fast_agent/llm/provider/openai/llm_google_oai.py +4 -4
- mcp_agent/llm/providers/augmented_llm_groq.py → fast_agent/llm/provider/openai/llm_groq.py +14 -16
- mcp_agent/llm/providers/augmented_llm_openai.py → fast_agent/llm/provider/openai/llm_openai.py +133 -207
- mcp_agent/llm/providers/augmented_llm_openrouter.py → fast_agent/llm/provider/openai/llm_openrouter.py +6 -6
- mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py → fast_agent/llm/provider/openai/llm_tensorzero_openai.py +17 -16
- mcp_agent/llm/providers/augmented_llm_xai.py → fast_agent/llm/provider/openai/llm_xai.py +6 -6
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/multipart_converter_openai.py +125 -63
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_multipart.py +12 -12
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_utils.py +18 -16
- {mcp_agent → fast_agent}/llm/provider_key_manager.py +2 -2
- {mcp_agent → fast_agent}/llm/provider_types.py +2 -0
- {mcp_agent → fast_agent}/llm/sampling_converter.py +15 -12
- {mcp_agent → fast_agent}/llm/usage_tracking.py +23 -5
- fast_agent/mcp/__init__.py +54 -0
- {mcp_agent → fast_agent}/mcp/elicitation_factory.py +3 -3
- {mcp_agent → fast_agent}/mcp/elicitation_handlers.py +19 -10
- {mcp_agent → fast_agent}/mcp/gen_client.py +3 -3
- fast_agent/mcp/helpers/__init__.py +36 -0
- fast_agent/mcp/helpers/content_helpers.py +183 -0
- {mcp_agent → fast_agent}/mcp/helpers/server_config_helpers.py +8 -8
- {mcp_agent → fast_agent}/mcp/hf_auth.py +25 -23
- fast_agent/mcp/interfaces.py +93 -0
- {mcp_agent → fast_agent}/mcp/logger_textio.py +4 -4
- {mcp_agent → fast_agent}/mcp/mcp_agent_client_session.py +49 -44
- {mcp_agent → fast_agent}/mcp/mcp_aggregator.py +66 -115
- {mcp_agent → fast_agent}/mcp/mcp_connection_manager.py +16 -23
- {mcp_agent/core → fast_agent/mcp}/mcp_content.py +23 -15
- {mcp_agent → fast_agent}/mcp/mime_utils.py +39 -0
- fast_agent/mcp/prompt.py +159 -0
- mcp_agent/mcp/prompt_message_multipart.py → fast_agent/mcp/prompt_message_extended.py +27 -20
- {mcp_agent → fast_agent}/mcp/prompt_render.py +21 -19
- {mcp_agent → fast_agent}/mcp/prompt_serialization.py +46 -46
- fast_agent/mcp/prompts/__main__.py +7 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_helpers.py +31 -30
- {mcp_agent → fast_agent}/mcp/prompts/prompt_load.py +8 -8
- {mcp_agent → fast_agent}/mcp/prompts/prompt_server.py +11 -19
- {mcp_agent → fast_agent}/mcp/prompts/prompt_template.py +18 -18
- {mcp_agent → fast_agent}/mcp/resource_utils.py +1 -1
- {mcp_agent → fast_agent}/mcp/sampling.py +31 -26
- {mcp_agent/mcp_server → fast_agent/mcp/server}/__init__.py +1 -1
- {mcp_agent/mcp_server → fast_agent/mcp/server}/agent_server.py +5 -6
- fast_agent/mcp/ui_agent.py +48 -0
- fast_agent/mcp/ui_mixin.py +209 -0
- fast_agent/mcp_server_registry.py +90 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis-campaign.py +5 -4
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/forms_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character_handler.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/tool_call.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_one.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_two.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-eval.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-imp.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/tensorzero/agent.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/tensorzero/image_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/tensorzero/simple_agent.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/chaining.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/evaluator.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/human_input.py +5 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/orchestrator.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/parallel.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/workflows/router.py +5 -2
- fast_agent/resources/setup/.gitignore +24 -0
- fast_agent/resources/setup/agent.py +18 -0
- fast_agent/resources/setup/fastagent.config.yaml +44 -0
- fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
- fast_agent/resources/setup/pyproject.toml.tmpl +17 -0
- fast_agent/tools/elicitation.py +369 -0
- fast_agent/types/__init__.py +32 -0
- fast_agent/types/llm_stop_reason.py +77 -0
- fast_agent/ui/__init__.py +38 -0
- fast_agent/ui/console_display.py +1005 -0
- {mcp_agent/human_input → fast_agent/ui}/elicitation_form.py +17 -12
- mcp_agent/human_input/elicitation_forms.py → fast_agent/ui/elicitation_style.py +1 -1
- {mcp_agent/core → fast_agent/ui}/enhanced_prompt.py +96 -25
- {mcp_agent/core → fast_agent/ui}/interactive_prompt.py +330 -125
- fast_agent/ui/mcp_ui_utils.py +224 -0
- {mcp_agent → fast_agent/ui}/progress_display.py +2 -2
- {mcp_agent/logging → fast_agent/ui}/rich_progress.py +4 -4
- {mcp_agent/core → fast_agent/ui}/usage_display.py +3 -8
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/METADATA +7 -7
- fast_agent_mcp-0.3.1.dist-info/RECORD +203 -0
- fast_agent_mcp-0.3.1.dist-info/entry_points.txt +5 -0
- fast_agent_mcp-0.2.58.dist-info/RECORD +0 -193
- fast_agent_mcp-0.2.58.dist-info/entry_points.txt +0 -6
- mcp_agent/__init__.py +0 -114
- mcp_agent/agents/agent.py +0 -92
- mcp_agent/agents/workflow/__init__.py +0 -1
- mcp_agent/agents/workflow/orchestrator_agent.py +0 -597
- mcp_agent/app.py +0 -175
- mcp_agent/core/__init__.py +0 -26
- mcp_agent/core/prompt.py +0 -191
- mcp_agent/event_progress.py +0 -134
- mcp_agent/human_input/handler.py +0 -81
- mcp_agent/llm/__init__.py +0 -2
- mcp_agent/llm/augmented_llm_passthrough.py +0 -232
- mcp_agent/llm/augmented_llm_slow.py +0 -53
- mcp_agent/llm/providers/__init__.py +0 -8
- mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -718
- mcp_agent/llm/providers/augmented_llm_google_native.py +0 -496
- mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -57
- mcp_agent/llm/providers/sampling_converter_openai.py +0 -26
- mcp_agent/llm/sampling_format_converter.py +0 -37
- mcp_agent/logging/__init__.py +0 -0
- mcp_agent/mcp/__init__.py +0 -50
- mcp_agent/mcp/helpers/__init__.py +0 -25
- mcp_agent/mcp/helpers/content_helpers.py +0 -187
- mcp_agent/mcp/interfaces.py +0 -266
- mcp_agent/mcp/prompts/__init__.py +0 -0
- mcp_agent/mcp/prompts/__main__.py +0 -10
- mcp_agent/mcp_server_registry.py +0 -343
- mcp_agent/tools/tool_definition.py +0 -14
- mcp_agent/ui/console_display.py +0 -790
- mcp_agent/ui/console_display_legacy.py +0 -401
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_prompts.py +0 -0
- {mcp_agent/agents → fast_agent/cli}/__init__.py +0 -0
- {mcp_agent → fast_agent}/cli/constants.py +0 -0
- {mcp_agent → fast_agent}/core/error_handling.py +0 -0
- {mcp_agent → fast_agent}/core/exceptions.py +0 -0
- {mcp_agent/cli → fast_agent/core/executor}/__init__.py +0 -0
- {mcp_agent → fast_agent/core}/executor/task_registry.py +0 -0
- {mcp_agent → fast_agent/core}/executor/workflow_signal.py +0 -0
- {mcp_agent → fast_agent}/human_input/form_fields.py +0 -0
- {mcp_agent → fast_agent}/llm/prompt_utils.py +0 -0
- {mcp_agent/core → fast_agent/llm}/request_params.py +0 -0
- {mcp_agent → fast_agent}/mcp/common.py +0 -0
- {mcp_agent/executor → fast_agent/mcp/prompts}/__init__.py +0 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_constants.py +0 -0
- {mcp_agent → fast_agent}/py.typed +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_account_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_forms_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_game_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/researcher/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/.env.sample +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/Makefile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/README.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/crab.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/docker-compose.yml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/Dockerfile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/entrypoint.sh +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/mcp_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/pyproject.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_schema.json +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/graded_report.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.txt +0 -0
- {mcp_agent → fast_agent/ui}/console.py +0 -0
- {mcp_agent/core → fast_agent/ui}/mermaid_utils.py +0 -0
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,136 +7,38 @@ from rich.prompt import Confirm
|
|
|
7
7
|
app = typer.Typer()
|
|
8
8
|
console = Console()
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# MCP Servers
|
|
43
|
-
mcp:
|
|
44
|
-
servers:
|
|
45
|
-
fetch:
|
|
46
|
-
command: "uvx"
|
|
47
|
-
args: ["mcp-server-fetch"]
|
|
48
|
-
filesystem:
|
|
49
|
-
command: "npx"
|
|
50
|
-
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
|
|
51
|
-
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
FASTAGENT_SECRETS_TEMPLATE = """
|
|
55
|
-
# FastAgent Secrets Configuration
|
|
56
|
-
# WARNING: Keep this file secure and never commit to version control
|
|
57
|
-
|
|
58
|
-
# Alternatively set OPENAI_API_KEY, ANTHROPIC_API_KEY or other environment variables.
|
|
59
|
-
# Keys in the configuration file override environment variables.
|
|
60
|
-
|
|
61
|
-
openai:
|
|
62
|
-
api_key: <your-api-key-here>
|
|
63
|
-
anthropic:
|
|
64
|
-
api_key: <your-api-key-here>
|
|
65
|
-
deepseek:
|
|
66
|
-
api_key: <your-api-key-here>
|
|
67
|
-
openrouter:
|
|
68
|
-
api_key: <your-api-key-here>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
# Example of setting an MCP Server environment variable
|
|
72
|
-
mcp:
|
|
73
|
-
servers:
|
|
74
|
-
brave:
|
|
75
|
-
env:
|
|
76
|
-
BRAVE_API_KEY: <your_api_key_here>
|
|
77
|
-
|
|
78
|
-
"""
|
|
79
|
-
|
|
80
|
-
GITIGNORE_TEMPLATE = """
|
|
81
|
-
# FastAgent secrets file
|
|
82
|
-
fastagent.secrets.yaml
|
|
83
|
-
|
|
84
|
-
# Python
|
|
85
|
-
__pycache__/
|
|
86
|
-
*.py[cod]
|
|
87
|
-
*$py.class
|
|
88
|
-
*.so
|
|
89
|
-
.Python
|
|
90
|
-
build/
|
|
91
|
-
develop-eggs/
|
|
92
|
-
dist/
|
|
93
|
-
downloads/
|
|
94
|
-
eggs/
|
|
95
|
-
.eggs/
|
|
96
|
-
lib/
|
|
97
|
-
lib64/
|
|
98
|
-
parts/
|
|
99
|
-
sdist/
|
|
100
|
-
var/
|
|
101
|
-
wheels/
|
|
102
|
-
*.egg-info/
|
|
103
|
-
.installed.cfg
|
|
104
|
-
*.egg
|
|
105
|
-
|
|
106
|
-
# Virtual Environment
|
|
107
|
-
.env
|
|
108
|
-
.venv
|
|
109
|
-
env/
|
|
110
|
-
venv/
|
|
111
|
-
ENV/
|
|
112
|
-
|
|
113
|
-
# IDE
|
|
114
|
-
.idea/
|
|
115
|
-
.vscode/
|
|
116
|
-
*.swp
|
|
117
|
-
*.swo
|
|
118
|
-
"""
|
|
119
|
-
|
|
120
|
-
AGENT_EXAMPLE_TEMPLATE = """
|
|
121
|
-
import asyncio
|
|
122
|
-
from mcp_agent.core.fastagent import FastAgent
|
|
123
|
-
|
|
124
|
-
# Create the application
|
|
125
|
-
fast = FastAgent("fast-agent example")
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# Define the agent
|
|
129
|
-
@fast.agent(instruction="You are a helpful AI Agent")
|
|
130
|
-
async def main():
|
|
131
|
-
# use the --model command line switch or agent arguments to change model
|
|
132
|
-
async with fast.run() as agent:
|
|
133
|
-
await agent.interactive()
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if __name__ == "__main__":
|
|
137
|
-
asyncio.run(main())
|
|
138
|
-
|
|
139
|
-
"""
|
|
10
|
+
|
|
11
|
+
def load_template_text(filename: str) -> str:
|
|
12
|
+
"""Load template text from packaged resources only.
|
|
13
|
+
|
|
14
|
+
Special-case: when requesting 'fastagent.secrets.yaml', read the
|
|
15
|
+
'fastagent.secrets.yaml.example' template from resources, but still
|
|
16
|
+
return its contents so we can write out the real secrets file name
|
|
17
|
+
in the destination project.
|
|
18
|
+
"""
|
|
19
|
+
from importlib.resources import files
|
|
20
|
+
|
|
21
|
+
# Map requested filenames to resource templates
|
|
22
|
+
if filename == "fastagent.secrets.yaml":
|
|
23
|
+
res_name = "fastagent.secrets.yaml.example"
|
|
24
|
+
elif filename == "pyproject.toml":
|
|
25
|
+
res_name = "pyproject.toml.tmpl"
|
|
26
|
+
else:
|
|
27
|
+
res_name = filename
|
|
28
|
+
resource_path = (
|
|
29
|
+
files("fast_agent").joinpath("resources").joinpath("setup").joinpath(res_name)
|
|
30
|
+
)
|
|
31
|
+
if resource_path.is_file():
|
|
32
|
+
return resource_path.read_text()
|
|
33
|
+
|
|
34
|
+
raise RuntimeError(
|
|
35
|
+
f"Setup template missing: '{filename}'.\n"
|
|
36
|
+
f"Expected packaged resource at: {resource_path}.\n"
|
|
37
|
+
"This indicates a packaging issue. Please rebuild/reinstall fast-agent."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# (No embedded template defaults; templates are the single source of truth.)
|
|
140
42
|
|
|
141
43
|
|
|
142
44
|
def find_gitignore(path: Path) -> bool:
|
|
@@ -195,6 +97,7 @@ def init(
|
|
|
195
97
|
console.print(f" - {config_path}/fastagent.config.yaml")
|
|
196
98
|
console.print(f" - {config_path}/fastagent.secrets.yaml")
|
|
197
99
|
console.print(f" - {config_path}/agent.py")
|
|
100
|
+
console.print(f" - {config_path}/pyproject.toml")
|
|
198
101
|
if needs_gitignore:
|
|
199
102
|
console.print(f" - {config_path}/.gitignore")
|
|
200
103
|
|
|
@@ -203,21 +106,59 @@ def init(
|
|
|
203
106
|
|
|
204
107
|
# Create configuration files
|
|
205
108
|
created = []
|
|
206
|
-
if create_file(
|
|
109
|
+
if create_file(
|
|
110
|
+
config_path / "fastagent.config.yaml", load_template_text("fastagent.config.yaml"), force
|
|
111
|
+
):
|
|
207
112
|
created.append("fastagent.yaml")
|
|
208
113
|
|
|
209
|
-
if create_file(
|
|
114
|
+
if create_file(
|
|
115
|
+
config_path / "fastagent.secrets.yaml", load_template_text("fastagent.secrets.yaml"), force
|
|
116
|
+
):
|
|
210
117
|
created.append("fastagent.secrets.yaml")
|
|
211
118
|
|
|
212
|
-
if create_file(config_path / "agent.py",
|
|
119
|
+
if create_file(config_path / "agent.py", load_template_text("agent.py"), force):
|
|
213
120
|
created.append("agent.py")
|
|
214
121
|
|
|
122
|
+
# Create a minimal pyproject.toml so `uv run` installs dependencies
|
|
123
|
+
def _render_pyproject(template_text: str) -> str:
|
|
124
|
+
# Determine Python requirement from installed fast-agent-mcp metadata, fall back if missing
|
|
125
|
+
py_req = ">=3.13.7"
|
|
126
|
+
try:
|
|
127
|
+
from importlib.metadata import metadata
|
|
128
|
+
|
|
129
|
+
md = metadata("fast-agent-mcp")
|
|
130
|
+
req = md.get("Requires-Python")
|
|
131
|
+
if req:
|
|
132
|
+
py_req = req
|
|
133
|
+
except Exception:
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
# Always use latest fast-agent-mcp (no version pin)
|
|
137
|
+
fast_agent_dep = '"fast-agent-mcp"'
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
template_text.replace("{{python_requires}}", py_req)
|
|
141
|
+
.replace("{{fast_agent_dep}}", fast_agent_dep)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
pyproject_template = load_template_text("pyproject.toml")
|
|
145
|
+
pyproject_text = _render_pyproject(pyproject_template)
|
|
146
|
+
if create_file(config_path / "pyproject.toml", pyproject_text, force):
|
|
147
|
+
created.append("pyproject.toml")
|
|
148
|
+
|
|
215
149
|
# Only create .gitignore if none exists in parent directories
|
|
216
|
-
if needs_gitignore and create_file(
|
|
150
|
+
if needs_gitignore and create_file(
|
|
151
|
+
config_path / ".gitignore", load_template_text(".gitignore"), force
|
|
152
|
+
):
|
|
217
153
|
created.append(".gitignore")
|
|
218
154
|
|
|
219
155
|
if created:
|
|
220
156
|
console.print("\n[green]Setup completed successfully![/green]")
|
|
157
|
+
if not needs_gitignore:
|
|
158
|
+
console.print(
|
|
159
|
+
"[yellow]Note:[/yellow] Found an existing .gitignore in this or a parent directory. "
|
|
160
|
+
"Ensure it ignores 'fastagent.secrets.yaml' to avoid committing secrets."
|
|
161
|
+
)
|
|
221
162
|
if "fastagent.secrets.yaml" in created:
|
|
222
163
|
console.print("\n[yellow]Important:[/yellow] Remember to:")
|
|
223
164
|
console.print(
|
|
@@ -8,7 +8,7 @@ import re
|
|
|
8
8
|
from typing import Dict, List, Literal, Tuple
|
|
9
9
|
from urllib.parse import urlparse
|
|
10
10
|
|
|
11
|
-
from
|
|
11
|
+
from fast_agent.mcp.hf_auth import add_hf_auth_header
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def parse_server_url(
|
|
@@ -46,12 +46,13 @@ def parse_server_url(
|
|
|
46
46
|
|
|
47
47
|
# Determine transport type based on URL path
|
|
48
48
|
transport_type: Literal["http", "sse"] = "http"
|
|
49
|
-
|
|
49
|
+
path = parsed_url.path or ""
|
|
50
|
+
normalized_path = path.rstrip("/")
|
|
51
|
+
if normalized_path.endswith("/sse"):
|
|
50
52
|
transport_type = "sse"
|
|
51
|
-
elif not
|
|
52
|
-
# If path doesn't end with /mcp or /sse, append /mcp
|
|
53
|
-
url = url
|
|
54
|
-
url = f"{url}mcp"
|
|
53
|
+
elif not normalized_path.endswith("/mcp"):
|
|
54
|
+
# If path doesn't end with /mcp or /sse (handling trailing slash), append /mcp once
|
|
55
|
+
url = f"{url.rstrip('/')}" + "/mcp"
|
|
55
56
|
|
|
56
57
|
# Generate a server name based on hostname and port
|
|
57
58
|
server_name = generate_server_name(url)
|
|
@@ -133,10 +134,10 @@ def parse_server_urls(
|
|
|
133
134
|
result = []
|
|
134
135
|
for url in url_list:
|
|
135
136
|
server_name, transport_type, parsed_url = parse_server_url(url)
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
# Apply HuggingFace authentication if appropriate
|
|
138
139
|
final_headers = add_hf_auth_header(parsed_url, headers)
|
|
139
|
-
|
|
140
|
+
|
|
140
141
|
result.append((server_name, transport_type, parsed_url, final_headers))
|
|
141
142
|
|
|
142
143
|
return result
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"""Main CLI entry point for MCP Agent."""
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
|
-
from rich.console import Console
|
|
5
4
|
from rich.table import Table
|
|
6
5
|
|
|
7
|
-
from
|
|
8
|
-
from
|
|
6
|
+
from fast_agent.cli.commands import check_config, go, quickstart, setup
|
|
7
|
+
from fast_agent.cli.terminal import Application
|
|
8
|
+
from fast_agent.ui.console import console as shared_console
|
|
9
9
|
|
|
10
10
|
app = typer.Typer(
|
|
11
11
|
help="fast-agent - Build effective agents using Model Context Protocol",
|
|
@@ -21,34 +21,54 @@ app.add_typer(quickstart.app, name="quickstart", help="Create example applicatio
|
|
|
21
21
|
|
|
22
22
|
# Shared application context
|
|
23
23
|
application = Application()
|
|
24
|
-
console
|
|
24
|
+
# Use shared console to match app-wide styling
|
|
25
|
+
console = shared_console
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
def show_welcome() -> None:
|
|
28
|
-
"""Show a welcome message with available commands."""
|
|
29
|
+
"""Show a welcome message with available commands, using new styling."""
|
|
29
30
|
from importlib.metadata import version
|
|
30
31
|
|
|
32
|
+
from rich.text import Text
|
|
33
|
+
|
|
31
34
|
try:
|
|
32
35
|
app_version = version("fast-agent-mcp")
|
|
33
36
|
except: # noqa: E722
|
|
34
37
|
app_version = "unknown"
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
# Header in the same style used by check/console_display
|
|
40
|
+
def _print_section_header(title: str, color: str = "blue") -> None:
|
|
41
|
+
width = console.size.width
|
|
42
|
+
left = f"[{color}]▎[/{color}][dim {color}]▶[/dim {color}] [{color}]{title}[/{color}]"
|
|
43
|
+
left_text = Text.from_markup(left)
|
|
44
|
+
separator_count = max(1, width - left_text.cell_len - 1)
|
|
45
|
+
|
|
46
|
+
combined = Text()
|
|
47
|
+
combined.append_text(left_text)
|
|
48
|
+
combined.append(" ")
|
|
49
|
+
combined.append("─" * separator_count, style="dim")
|
|
50
|
+
|
|
51
|
+
console.print()
|
|
52
|
+
console.print(combined)
|
|
53
|
+
console.print()
|
|
54
|
+
|
|
55
|
+
header_title = f"fast-agent v{app_version}"
|
|
56
|
+
_print_section_header(header_title, color="blue")
|
|
57
|
+
|
|
58
|
+
# Commands list (no boxes), matching updated check styling
|
|
59
|
+
table = Table(show_header=True, box=None)
|
|
60
|
+
table.add_column("Command", style="green", header_style="bold bright_white")
|
|
61
|
+
table.add_column("Description", header_style="bold bright_white")
|
|
62
|
+
|
|
63
|
+
table.add_row("[bold]go[/bold]", "Start an interactive session")
|
|
64
|
+
table.add_row("check", "Show current configuration")
|
|
65
|
+
table.add_row("setup", "Create agent template and configuration")
|
|
46
66
|
table.add_row("quickstart", "Create example applications (workflow, researcher, etc.)")
|
|
47
67
|
|
|
48
68
|
console.print(table)
|
|
49
69
|
|
|
50
70
|
console.print(
|
|
51
|
-
"\
|
|
71
|
+
"\nVisit [cyan][link=https://fast-agent.ai]fast-agent.ai[/link][/cyan] for more information."
|
|
52
72
|
)
|
|
53
73
|
|
|
54
74
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from
|
|
1
|
+
from fast_agent.ui.console import console, error_console
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class Application:
|
|
@@ -14,7 +14,7 @@ class Application:
|
|
|
14
14
|
self.error_console = error_console
|
|
15
15
|
|
|
16
16
|
def log(self, message: str, level: str = "info") -> None:
|
|
17
|
-
if
|
|
17
|
+
if level == "info" or (level == "debug" and self.verbosity > 0) or level == "error":
|
|
18
18
|
if level == "error":
|
|
19
19
|
self.error_console.print(f"[{level.upper()}] {message}")
|
|
20
20
|
else:
|
|
@@ -84,10 +84,10 @@ class MCPServerSettings(BaseModel):
|
|
|
84
84
|
"""The timeout in seconds for the server connection."""
|
|
85
85
|
|
|
86
86
|
url: str | None = None
|
|
87
|
-
"""The URL for the server (e.g. for SSE transport)."""
|
|
87
|
+
"""The URL for the server (e.g. for SSE/SHTTP transport)."""
|
|
88
88
|
|
|
89
89
|
headers: Dict[str, str] | None = None
|
|
90
|
-
"""Headers dictionary for
|
|
90
|
+
"""Headers dictionary for HTTP connections"""
|
|
91
91
|
|
|
92
92
|
auth: MCPServerAuthSettings | None = None
|
|
93
93
|
"""The authentication configuration for the server."""
|
|
@@ -462,6 +462,14 @@ class Settings(BaseSettings):
|
|
|
462
462
|
logger: LoggerSettings | None = LoggerSettings()
|
|
463
463
|
"""Logger settings for the fast-agent application"""
|
|
464
464
|
|
|
465
|
+
# MCP UI integration mode for handling ui:// embedded resources from MCP tool results
|
|
466
|
+
mcp_ui_mode: Literal["disabled", "enabled", "auto"] = "enabled"
|
|
467
|
+
"""Controls handling of MCP UI embedded resources:
|
|
468
|
+
- "disabled": Do not process ui:// resources
|
|
469
|
+
- "enabled": Always extract ui:// resources into message channels (default)
|
|
470
|
+
- "auto": Extract and automatically open ui:// resources.
|
|
471
|
+
"""
|
|
472
|
+
|
|
465
473
|
@classmethod
|
|
466
474
|
def find_config(cls) -> Path | None:
|
|
467
475
|
"""Find the config file in the current directory or parent directories."""
|
fast_agent/constants.py
ADDED
|
@@ -7,15 +7,11 @@ import concurrent.futures
|
|
|
7
7
|
import uuid
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
9
9
|
|
|
10
|
-
from mcp import ServerSession
|
|
11
10
|
from opentelemetry import trace
|
|
12
11
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
13
12
|
|
|
14
13
|
# from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
|
15
|
-
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
|
|
16
|
-
|
|
17
14
|
# from opentelemetry.instrumentation.mcp import McpInstrumentor
|
|
18
|
-
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
|
19
15
|
from opentelemetry.propagate import set_global_textmap
|
|
20
16
|
from opentelemetry.sdk.resources import Resource
|
|
21
17
|
from opentelemetry.sdk.trace import TracerProvider
|
|
@@ -23,20 +19,18 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExport
|
|
|
23
19
|
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
24
20
|
from pydantic import BaseModel, ConfigDict
|
|
25
21
|
|
|
26
|
-
from
|
|
27
|
-
from
|
|
28
|
-
from
|
|
29
|
-
from
|
|
30
|
-
from
|
|
31
|
-
from
|
|
32
|
-
from
|
|
22
|
+
from fast_agent.config import Settings, get_settings
|
|
23
|
+
from fast_agent.core.executor.executor import AsyncioExecutor, Executor
|
|
24
|
+
from fast_agent.core.executor.task_registry import ActivityRegistry
|
|
25
|
+
from fast_agent.core.logging.events import EventFilter, StreamingExclusionFilter
|
|
26
|
+
from fast_agent.core.logging.logger import LoggingConfig, get_logger
|
|
27
|
+
from fast_agent.core.logging.transport import create_transport
|
|
28
|
+
from fast_agent.mcp_server_registry import ServerRegistry
|
|
33
29
|
|
|
34
30
|
if TYPE_CHECKING:
|
|
35
|
-
from
|
|
36
|
-
from mcp_agent.human_input.types import HumanInputCallback
|
|
31
|
+
from fast_agent.core.executor.workflow_signal import SignalWaitCallback
|
|
37
32
|
else:
|
|
38
33
|
# Runtime placeholders for the types
|
|
39
|
-
HumanInputCallback = Any
|
|
40
34
|
SignalWaitCallback = Any
|
|
41
35
|
|
|
42
36
|
logger = get_logger(__name__)
|
|
@@ -50,9 +44,8 @@ class Context(BaseModel):
|
|
|
50
44
|
|
|
51
45
|
config: Optional[Settings] = None
|
|
52
46
|
executor: Optional[Executor] = None
|
|
53
|
-
human_input_handler: Optional[
|
|
47
|
+
human_input_handler: Optional[Any] = None
|
|
54
48
|
signal_notification: Optional[SignalWaitCallback] = None
|
|
55
|
-
upstream_session: Optional[ServerSession] = None # TODO: saqadri - figure this out
|
|
56
49
|
|
|
57
50
|
# Registries
|
|
58
51
|
server_registry: Optional[ServerRegistry] = None
|
|
@@ -113,9 +106,21 @@ async def configure_otel(config: "Settings") -> None:
|
|
|
113
106
|
|
|
114
107
|
# Set as global tracer provider
|
|
115
108
|
trace.set_tracer_provider(tracer_provider)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
|
|
110
|
+
# Attempt to instrument optional SDKs if available; continue silently if missing
|
|
111
|
+
try:
|
|
112
|
+
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
|
113
|
+
|
|
114
|
+
OpenAIInstrumentor().instrument()
|
|
115
|
+
except Exception: # pragma: no cover - optional instrumentation
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
from opentelemetry.instrumentation.google_genai import GoogleGenAiSdkInstrumentor
|
|
120
|
+
|
|
121
|
+
GoogleGenAiSdkInstrumentor().instrument()
|
|
122
|
+
except Exception: # pragma: no cover - optional instrumentation
|
|
123
|
+
pass
|
|
119
124
|
|
|
120
125
|
|
|
121
126
|
# McpInstrumentor().instrument()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from contextlib import contextmanager
|
|
2
|
-
from typing import TYPE_CHECKING, Any
|
|
2
|
+
from typing import TYPE_CHECKING, Any
|
|
3
3
|
|
|
4
4
|
if TYPE_CHECKING:
|
|
5
|
-
from
|
|
5
|
+
from fast_agent.context import Context
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ContextDependent:
|
|
@@ -11,7 +11,11 @@ class ContextDependent:
|
|
|
11
11
|
Provides both global fallback and instance-specific context support.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
# Ensure the attribute always exists even if a subclass
|
|
15
|
+
# does not call this mixin's __init__.
|
|
16
|
+
_context: "Context | None" = None
|
|
17
|
+
|
|
18
|
+
def __init__(self, context: "Context | None" = None, **kwargs: dict[str, Any]) -> None:
|
|
15
19
|
self._context = context
|
|
16
20
|
super().__init__(**kwargs)
|
|
17
21
|
|
|
@@ -27,12 +31,12 @@ class ContextDependent:
|
|
|
27
31
|
|
|
28
32
|
try:
|
|
29
33
|
# Fall back to global context if available
|
|
30
|
-
from
|
|
34
|
+
from fast_agent.context import get_current_context
|
|
31
35
|
|
|
32
36
|
return get_current_context()
|
|
33
37
|
except Exception as e:
|
|
34
38
|
raise RuntimeError(
|
|
35
|
-
f"No context available for {self.__class__.__name__}. Either initialize
|
|
39
|
+
f"No context available for {self.__class__.__name__}. Either initialize Core first or pass context explicitly."
|
|
36
40
|
) from e
|
|
37
41
|
|
|
38
42
|
@contextmanager
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core interfaces and decorators for fast-agent.
|
|
3
|
+
|
|
4
|
+
Public API:
|
|
5
|
+
- `Core`: The core application container (lazy-loaded)
|
|
6
|
+
- `FastAgent`: High-level, decorator-driven application class (lazy-loaded)
|
|
7
|
+
- Decorators: `agent`, `custom`, `orchestrator`, `iterative_planner`,
|
|
8
|
+
`router`, `chain`, `parallel`, `evaluator_optimizer` (lazy-loaded)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Core",
|
|
13
|
+
"FastAgent",
|
|
14
|
+
# Decorators
|
|
15
|
+
"agent",
|
|
16
|
+
"custom",
|
|
17
|
+
"orchestrator",
|
|
18
|
+
"iterative_planner",
|
|
19
|
+
"router",
|
|
20
|
+
"chain",
|
|
21
|
+
"parallel",
|
|
22
|
+
"evaluator_optimizer",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __getattr__(name: str):
|
|
27
|
+
# Lazy imports to avoid heavy dependencies and circular imports at init time
|
|
28
|
+
if name == "Core":
|
|
29
|
+
from .core_app import Core
|
|
30
|
+
|
|
31
|
+
return Core
|
|
32
|
+
if name == "FastAgent":
|
|
33
|
+
from .fastagent import FastAgent
|
|
34
|
+
|
|
35
|
+
return FastAgent
|
|
36
|
+
|
|
37
|
+
# Decorators from direct_decorators
|
|
38
|
+
if name in {
|
|
39
|
+
"agent",
|
|
40
|
+
"custom",
|
|
41
|
+
"orchestrator",
|
|
42
|
+
"iterative_planner",
|
|
43
|
+
"router",
|
|
44
|
+
"chain",
|
|
45
|
+
"parallel",
|
|
46
|
+
"evaluator_optimizer",
|
|
47
|
+
}:
|
|
48
|
+
from . import direct_decorators as _dd
|
|
49
|
+
|
|
50
|
+
return getattr(_dd, name)
|
|
51
|
+
|
|
52
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|