fast-agent-mcp 0.0.7__py3-none-any.whl → 0.0.9__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.0.7.dist-info → fast_agent_mcp-0.0.9.dist-info}/METADATA +24 -57
- {fast_agent_mcp-0.0.7.dist-info → fast_agent_mcp-0.0.9.dist-info}/RECORD +31 -24
- mcp_agent/agents/agent.py +8 -4
- mcp_agent/app.py +5 -1
- mcp_agent/cli/commands/bootstrap.py +183 -121
- mcp_agent/cli/commands/setup.py +20 -16
- mcp_agent/core/__init__.py +0 -0
- mcp_agent/core/exceptions.py +47 -0
- mcp_agent/core/fastagent.py +250 -124
- mcp_agent/core/server_validation.py +44 -0
- mcp_agent/event_progress.py +4 -1
- mcp_agent/logging/rich_progress.py +11 -0
- mcp_agent/mcp/mcp_connection_manager.py +11 -2
- mcp_agent/resources/examples/data-analysis/analysis.py +35 -0
- mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +22 -0
- mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +1471 -0
- mcp_agent/resources/examples/workflows/chaining.py +31 -0
- mcp_agent/resources/examples/{decorator/optimizer.py → workflows/evaluator.py} +7 -10
- mcp_agent/resources/examples/workflows/fastagent.config.yaml +9 -0
- mcp_agent/resources/examples/workflows/human_input.py +25 -0
- mcp_agent/resources/examples/{decorator → workflows}/orchestrator.py +20 -17
- mcp_agent/resources/examples/{decorator → workflows}/parallel.py +14 -18
- mcp_agent/resources/examples/{decorator → workflows}/router.py +9 -10
- mcp_agent/workflows/llm/augmented_llm_anthropic.py +54 -14
- mcp_agent/workflows/llm/augmented_llm_openai.py +38 -9
- mcp_agent/workflows/orchestrator/orchestrator.py +53 -108
- mcp_agent/resources/examples/decorator/main.py +0 -26
- mcp_agent/resources/examples/decorator/tiny.py +0 -22
- {fast_agent_mcp-0.0.7.dist-info → fast_agent_mcp-0.0.9.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.0.7.dist-info → fast_agent_mcp-0.0.9.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.0.7.dist-info → fast_agent_mcp-0.0.9.dist-info}/licenses/LICENSE +0 -0
- /mcp_agent/resources/examples/mcp_researcher/{main-evalopt.py → researcher-eval.py} +0 -0
- /mcp_agent/resources/examples/mcp_researcher/{main.py → researcher.py} +0 -0
|
@@ -8,40 +8,45 @@ from rich.table import Table
|
|
|
8
8
|
from rich.panel import Panel
|
|
9
9
|
|
|
10
10
|
app = typer.Typer(
|
|
11
|
-
help="Create example applications
|
|
12
|
-
no_args_is_help=
|
|
11
|
+
help="Create example applications",
|
|
12
|
+
no_args_is_help=False, # Allow showing our custom help instead
|
|
13
13
|
)
|
|
14
14
|
console = Console()
|
|
15
15
|
|
|
16
16
|
EXAMPLE_TYPES = {
|
|
17
|
-
"
|
|
18
|
-
"description": "
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
- Compose agents using the decorator pattern
|
|
22
|
-
- Add capabilities like optimization and routing
|
|
23
|
-
- Run agents in parallel
|
|
24
|
-
- Handle complex agent interactions
|
|
25
|
-
""",
|
|
17
|
+
"workflow": {
|
|
18
|
+
"description": "Example workflows, demonstrating each of the patterns in Anthropic's\n"
|
|
19
|
+
"'Building Effective Agents' paper. Some agents use the 'fetch'\n"
|
|
20
|
+
"and filesystem MCP Servers.",
|
|
26
21
|
"files": [
|
|
27
|
-
"
|
|
28
|
-
"
|
|
22
|
+
"chaining.py",
|
|
23
|
+
"evaluator.py",
|
|
24
|
+
"human_input.py",
|
|
29
25
|
"orchestrator.py",
|
|
30
26
|
"parallel.py",
|
|
31
27
|
"router.py",
|
|
32
|
-
"tiny.py",
|
|
33
28
|
],
|
|
29
|
+
"create_subdir": False,
|
|
34
30
|
},
|
|
35
31
|
"researcher": {
|
|
36
|
-
"description": "Research agent example with evaluation
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
32
|
+
"description": "Research agent example with additional evaluation/optimization\n"
|
|
33
|
+
"example. Uses Brave Search and Docker MCP Servers.\n"
|
|
34
|
+
"Creates examples in a 'researcher' subdirectory.",
|
|
35
|
+
"files": [
|
|
36
|
+
"researcher.py",
|
|
37
|
+
"researcher-eval.py",
|
|
38
|
+
"mcp_agent.secrets.yaml.example",
|
|
39
|
+
],
|
|
40
|
+
"create_subdir": True,
|
|
41
|
+
},
|
|
42
|
+
"data-analysis": {
|
|
43
|
+
"description": "Data analysis agent examples that demonstrate working with\n"
|
|
44
|
+
"datasets, performing statistical analysis, and generating visualizations.\n"
|
|
45
|
+
"Creates examples in a 'data-analysis' subdirectory with mount-point for data.\n"
|
|
46
|
+
"Uses MCP 'roots' feature for mapping",
|
|
47
|
+
"files": ["analysis.py", "fastagent.config.yaml"],
|
|
48
|
+
"mount_point_files": ["WA_Fn-UseC_-HR-Employee-Attrition.csv"],
|
|
49
|
+
"create_subdir": True,
|
|
45
50
|
},
|
|
46
51
|
}
|
|
47
52
|
|
|
@@ -52,19 +57,35 @@ def copy_example_files(
|
|
|
52
57
|
"""Copy example files from resources to target directory."""
|
|
53
58
|
created = []
|
|
54
59
|
|
|
55
|
-
#
|
|
60
|
+
# Determine if we should create a subdirectory for this example type
|
|
61
|
+
example_info = EXAMPLE_TYPES[example_type]
|
|
62
|
+
if example_info["create_subdir"]:
|
|
63
|
+
target_dir = target_dir / example_type
|
|
64
|
+
if not target_dir.exists():
|
|
65
|
+
target_dir.mkdir(parents=True)
|
|
66
|
+
console.print(f"Created subdirectory: {target_dir}")
|
|
67
|
+
|
|
68
|
+
# Create mount-point directory if needed
|
|
69
|
+
mount_point_files = example_info.get("mount_point_files", [])
|
|
70
|
+
if mount_point_files:
|
|
71
|
+
mount_point_dir = target_dir / "mount-point"
|
|
72
|
+
if not mount_point_dir.exists():
|
|
73
|
+
mount_point_dir.mkdir(parents=True)
|
|
74
|
+
console.print(f"Created mount-point directory: {mount_point_dir}")
|
|
75
|
+
|
|
76
|
+
# Use the resources directory from the package
|
|
56
77
|
source_dir = (
|
|
57
78
|
Path(__file__).parent.parent.parent
|
|
58
79
|
/ "resources"
|
|
59
80
|
/ "examples"
|
|
60
|
-
/ ("
|
|
81
|
+
/ ("workflows" if example_type == "workflow" else f"{example_type}")
|
|
61
82
|
)
|
|
62
83
|
|
|
63
84
|
if not source_dir.exists():
|
|
64
85
|
console.print(f"[red]Error: Source directory not found: {source_dir}[/red]")
|
|
65
86
|
return created
|
|
66
87
|
|
|
67
|
-
for filename in
|
|
88
|
+
for filename in example_info["files"]:
|
|
68
89
|
source = source_dir / filename
|
|
69
90
|
target = target_dir / filename
|
|
70
91
|
|
|
@@ -78,125 +99,143 @@ def copy_example_files(
|
|
|
78
99
|
continue
|
|
79
100
|
|
|
80
101
|
shutil.copy2(source, target)
|
|
81
|
-
created.append(
|
|
82
|
-
console.print(f"[green]Created[/green] {
|
|
102
|
+
created.append(str(target.relative_to(target_dir.parent)))
|
|
103
|
+
console.print(f"[green]Created[/green] {created[-1]}")
|
|
83
104
|
|
|
84
105
|
except Exception as e:
|
|
85
106
|
console.print(f"[red]Error copying {filename}: {str(e)}[/red]")
|
|
86
107
|
|
|
108
|
+
# Copy mount-point files if any
|
|
109
|
+
if mount_point_files:
|
|
110
|
+
source_mount_point = source_dir / "mount-point"
|
|
111
|
+
for filename in mount_point_files:
|
|
112
|
+
source = source_mount_point / filename
|
|
113
|
+
target = mount_point_dir / filename
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
if not source.exists():
|
|
117
|
+
console.print(f"[red]Error: Source file not found: {source}[/red]")
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
if target.exists() and not force:
|
|
121
|
+
console.print(
|
|
122
|
+
f"[yellow]Skipping[/yellow] mount-point/{filename} (already exists)"
|
|
123
|
+
)
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
shutil.copy2(source, target)
|
|
127
|
+
created.append(f"{example_type}/mount-point/{filename}")
|
|
128
|
+
console.print(f"[green]Created[/green] mount-point/{filename}")
|
|
129
|
+
|
|
130
|
+
except Exception as e:
|
|
131
|
+
console.print(
|
|
132
|
+
f"[red]Error copying mount-point/{filename}: {str(e)}[/red]"
|
|
133
|
+
)
|
|
134
|
+
|
|
87
135
|
return created
|
|
88
136
|
|
|
89
137
|
|
|
90
|
-
def
|
|
91
|
-
"""
|
|
92
|
-
console.print("\n[bold]
|
|
93
|
-
console.print("
|
|
138
|
+
def show_overview():
|
|
139
|
+
"""Display an overview of available examples in a nicely formatted table."""
|
|
140
|
+
console.print("\n[bold cyan]FastAgent Example Applications[/bold cyan]")
|
|
141
|
+
console.print("Build agents and compose workflows through practical examples\n")
|
|
94
142
|
|
|
95
|
-
# Create a table for
|
|
96
|
-
table = Table(
|
|
97
|
-
|
|
143
|
+
# Create a table for better organization
|
|
144
|
+
table = Table(
|
|
145
|
+
show_header=True, header_style="bold magenta", box=None, padding=(0, 2)
|
|
146
|
+
)
|
|
147
|
+
table.add_column("Example")
|
|
98
148
|
table.add_column("Description")
|
|
99
|
-
table.add_column("Files"
|
|
149
|
+
table.add_column("Files")
|
|
100
150
|
|
|
101
151
|
for name, info in EXAMPLE_TYPES.items():
|
|
102
|
-
|
|
152
|
+
files_list = "\n".join(f"• {f}" for f in info["files"])
|
|
153
|
+
if "mount_point_files" in info:
|
|
154
|
+
files_list += "\n[blue]mount-point:[/blue]\n" + "\n".join(
|
|
155
|
+
f"• {f}" for f in info["mount_point_files"]
|
|
156
|
+
)
|
|
157
|
+
table.add_row(f"[green]{name}[/green]", info["description"], files_list)
|
|
103
158
|
|
|
104
159
|
console.print(table)
|
|
105
160
|
|
|
106
|
-
# Show usage instructions
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
console.print(" mcp-agent bootstrap create decorator")
|
|
119
|
-
console.print(
|
|
120
|
-
" mcp-agent bootstrap create researcher --directory ./research-agent"
|
|
161
|
+
# Show usage instructions in a panel
|
|
162
|
+
usage_text = (
|
|
163
|
+
"[bold]Commands:[/bold]\n"
|
|
164
|
+
" fastagent bootstrap workflow DIR Create workflow examples in DIR\n"
|
|
165
|
+
" fastagent bootstrap researcher DIR Create researcher example in 'researcher' subdirectory\n"
|
|
166
|
+
" fastagent bootstrap data-analysis DIR Create data analysis examples in 'data-analysis' subdirectory\n\n"
|
|
167
|
+
"[bold]Options:[/bold]\n"
|
|
168
|
+
" --force Overwrite existing files\n\n"
|
|
169
|
+
"[bold]Examples:[/bold]\n"
|
|
170
|
+
" fastagent bootstrap workflow . Create in current directory\n"
|
|
171
|
+
" fastagent bootstrap researcher . Create in researcher subdirectory\n"
|
|
172
|
+
" fastagent bootstrap data-analysis . --force Force overwrite files in data-analysis subdirectory"
|
|
121
173
|
)
|
|
174
|
+
console.print(Panel(usage_text, title="Usage", border_style="blue"))
|
|
122
175
|
|
|
123
176
|
|
|
124
|
-
@app.
|
|
125
|
-
def
|
|
126
|
-
|
|
177
|
+
@app.command()
|
|
178
|
+
def workflow(
|
|
179
|
+
directory: Path = typer.Argument(
|
|
180
|
+
Path("."),
|
|
181
|
+
help="Directory where workflow examples will be created",
|
|
182
|
+
),
|
|
183
|
+
force: bool = typer.Option(
|
|
184
|
+
False, "--force", "-f", help="Force overwrite existing files"
|
|
185
|
+
),
|
|
186
|
+
):
|
|
187
|
+
"""Create workflow pattern examples."""
|
|
188
|
+
target_dir = directory.resolve()
|
|
189
|
+
if not target_dir.exists():
|
|
190
|
+
target_dir.mkdir(parents=True)
|
|
191
|
+
console.print(f"Created directory: {target_dir}")
|
|
127
192
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"""
|
|
131
|
-
if ctx.invoked_subcommand is None:
|
|
132
|
-
show_examples_overview()
|
|
193
|
+
created = copy_example_files("workflow", target_dir, force)
|
|
194
|
+
_show_completion_message("workflow", created)
|
|
133
195
|
|
|
134
196
|
|
|
135
197
|
@app.command()
|
|
136
|
-
def
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
directory: str = typer.Option(
|
|
141
|
-
".", "--directory", "-d", help="Directory where example files will be created"
|
|
198
|
+
def researcher(
|
|
199
|
+
directory: Path = typer.Argument(
|
|
200
|
+
Path("."),
|
|
201
|
+
help="Directory where researcher examples will be created (in 'researcher' subdirectory)",
|
|
142
202
|
),
|
|
143
203
|
force: bool = typer.Option(
|
|
144
204
|
False, "--force", "-f", help="Force overwrite existing files"
|
|
145
205
|
),
|
|
146
206
|
):
|
|
147
|
-
"""Create
|
|
148
|
-
|
|
149
|
-
This will create a set of example files based on the chosen type:
|
|
150
|
-
|
|
151
|
-
\b
|
|
152
|
-
- decorator: Decorator pattern example showing different agent composition approaches
|
|
153
|
-
- researcher: Research agent example with evaluation optimization
|
|
154
|
-
"""
|
|
155
|
-
if not example_type:
|
|
156
|
-
show_examples_overview()
|
|
157
|
-
return
|
|
158
|
-
|
|
159
|
-
example_type = example_type.lower()
|
|
160
|
-
if example_type not in EXAMPLE_TYPES:
|
|
161
|
-
console.print(f"[red]Error:[/red] Unknown example type '{example_type}'")
|
|
162
|
-
console.print("\nAvailable types:")
|
|
163
|
-
for name in EXAMPLE_TYPES:
|
|
164
|
-
console.print(f" - {name}")
|
|
165
|
-
raise typer.Exit(1)
|
|
166
|
-
|
|
167
|
-
target_dir = Path(directory).resolve()
|
|
207
|
+
"""Create researcher pattern examples."""
|
|
208
|
+
target_dir = directory.resolve()
|
|
168
209
|
if not target_dir.exists():
|
|
169
210
|
target_dir.mkdir(parents=True)
|
|
170
211
|
console.print(f"Created directory: {target_dir}")
|
|
171
212
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
console.print(
|
|
175
|
-
Panel(
|
|
176
|
-
EXAMPLE_TYPES[example_type]["details"].strip(),
|
|
177
|
-
title="About this example",
|
|
178
|
-
expand=False,
|
|
179
|
-
)
|
|
180
|
-
)
|
|
213
|
+
created = copy_example_files("researcher", target_dir, force)
|
|
214
|
+
_show_completion_message("researcher", created)
|
|
181
215
|
|
|
182
|
-
if not force:
|
|
183
|
-
# Check for existing files first
|
|
184
|
-
existing = []
|
|
185
|
-
for f in EXAMPLE_TYPES[example_type]["files"]:
|
|
186
|
-
if (target_dir / f).exists():
|
|
187
|
-
existing.append(f)
|
|
188
216
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
217
|
+
@app.command()
|
|
218
|
+
def data_analysis(
|
|
219
|
+
directory: Path = typer.Argument(
|
|
220
|
+
Path("."),
|
|
221
|
+
help="Directory where data analysis examples will be created (creates 'data-analysis' subdirectory with mount-point)",
|
|
222
|
+
),
|
|
223
|
+
force: bool = typer.Option(
|
|
224
|
+
False, "--force", "-f", help="Force overwrite existing files"
|
|
225
|
+
),
|
|
226
|
+
):
|
|
227
|
+
"""Create data analysis examples with sample dataset."""
|
|
228
|
+
target_dir = directory.resolve()
|
|
229
|
+
if not target_dir.exists():
|
|
230
|
+
target_dir.mkdir(parents=True)
|
|
231
|
+
console.print(f"Created directory: {target_dir}")
|
|
197
232
|
|
|
198
|
-
created = copy_example_files(
|
|
233
|
+
created = copy_example_files("data-analysis", target_dir, force)
|
|
234
|
+
_show_completion_message("data-analysis", created)
|
|
199
235
|
|
|
236
|
+
|
|
237
|
+
def _show_completion_message(example_type: str, created: list[str]):
|
|
238
|
+
"""Show completion message and next steps."""
|
|
200
239
|
if created:
|
|
201
240
|
console.print("\n[green]Setup completed successfully![/green]")
|
|
202
241
|
console.print("\nCreated files:")
|
|
@@ -204,18 +243,41 @@ def create(
|
|
|
204
243
|
console.print(f" - {f}")
|
|
205
244
|
|
|
206
245
|
console.print("\n[bold]Next Steps:[/bold]")
|
|
207
|
-
if example_type == "
|
|
208
|
-
console.print("1. Review
|
|
209
|
-
console.print("2. Check other
|
|
210
|
-
console.print(" - optimizer.py: Add optimization capabilities")
|
|
211
|
-
console.print(" - router.py: Route requests to different agents")
|
|
246
|
+
if example_type == "workflow":
|
|
247
|
+
console.print("1. Review chaining.py for the basic workflow example")
|
|
248
|
+
console.print("2. Check other examples:")
|
|
212
249
|
console.print(" - parallel.py: Run agents in parallel")
|
|
213
|
-
console.print("
|
|
214
|
-
|
|
215
|
-
console.print("
|
|
250
|
+
console.print(" - router.py: Route requests between agents")
|
|
251
|
+
console.print(" - evaluator.py: Add evaluation capabilities")
|
|
252
|
+
console.print(" - human_input.py: Incorporate human feedback")
|
|
253
|
+
console.print("3. Run an example with: uv run <example>.py")
|
|
254
|
+
console.print(
|
|
255
|
+
"4. Try a different model with --model=<model>, or update the agent config"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
elif example_type == "researcher":
|
|
259
|
+
console.print(
|
|
260
|
+
"1. Set up the Brave MCP Server (get an API key from https://brave.com/search/api/)"
|
|
261
|
+
)
|
|
262
|
+
console.print("2. Try `uv run researcher.py` for the basic version")
|
|
263
|
+
console.print(
|
|
264
|
+
"3. Try `uv run researcher-eval.py` for the eval/optimize version"
|
|
265
|
+
)
|
|
266
|
+
elif example_type == "data-analysis":
|
|
267
|
+
console.print(
|
|
268
|
+
"1. Run uv `analysis.py` to perform data analysis and visualization"
|
|
269
|
+
)
|
|
270
|
+
console.print("2. The dataset is available in the mount-point directory:")
|
|
271
|
+
console.print(" - mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv")
|
|
216
272
|
console.print(
|
|
217
|
-
"
|
|
273
|
+
"On Windows platforms, please edit the fastagent.config.yaml and adjust the volume mount point."
|
|
218
274
|
)
|
|
219
|
-
console.print("3. Run with: python main.py or python main-evalopt.py")
|
|
220
275
|
else:
|
|
221
276
|
console.print("\n[yellow]No files were created.[/yellow]")
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
@app.callback(invoke_without_command=True)
|
|
280
|
+
def main(ctx: typer.Context):
|
|
281
|
+
"""Create example applications and learn FastAgent patterns."""
|
|
282
|
+
if ctx.invoked_subcommand is None:
|
|
283
|
+
show_overview()
|
mcp_agent/cli/commands/setup.py
CHANGED
|
@@ -22,28 +22,31 @@ FASTAGENT_CONFIG_TEMPLATE = """
|
|
|
22
22
|
default_model: sonnet
|
|
23
23
|
|
|
24
24
|
# Logging and Console Configuration:
|
|
25
|
-
|
|
25
|
+
logger:
|
|
26
26
|
# level: "debug" | "info" | "warning" | "error"
|
|
27
27
|
# type: "none" | "console" | "file" | "http"
|
|
28
28
|
# path: "/path/to/logfile.jsonl"
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
# Switch the progress display on or off
|
|
32
|
-
|
|
32
|
+
progress_display: true
|
|
33
33
|
|
|
34
34
|
# Show chat User/Assistant messages on the console
|
|
35
|
-
|
|
35
|
+
show_chat: true
|
|
36
36
|
# Show tool calls on the console
|
|
37
|
-
|
|
37
|
+
show_tools: true
|
|
38
38
|
# Truncate long tool responses on the console
|
|
39
|
-
|
|
39
|
+
truncate_tools: true
|
|
40
40
|
|
|
41
41
|
# MCP Servers
|
|
42
42
|
mcp:
|
|
43
43
|
servers:
|
|
44
44
|
fetch:
|
|
45
45
|
command: "uvx"
|
|
46
|
-
args: ["mcp-server-fetch"]
|
|
46
|
+
args: ["mcp-server-fetch"]
|
|
47
|
+
filesystem:
|
|
48
|
+
command: "npx"
|
|
49
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
|
|
47
50
|
|
|
48
51
|
"""
|
|
49
52
|
|
|
@@ -51,6 +54,8 @@ FASTAGENT_SECRETS_TEMPLATE = """
|
|
|
51
54
|
# FastAgent Secrets Configuration
|
|
52
55
|
# WARNING: Keep this file secure and never commit to version control
|
|
53
56
|
|
|
57
|
+
# Alternatively set OPENAI_API_KEY and ANTHROPIC_API_KEY environment variables. Config file takes precedence.
|
|
58
|
+
|
|
54
59
|
openai:
|
|
55
60
|
api_key: <your-api-key-here>
|
|
56
61
|
anthropic:
|
|
@@ -110,17 +115,14 @@ import asyncio
|
|
|
110
115
|
from mcp_agent.core.fastagent import FastAgent
|
|
111
116
|
|
|
112
117
|
# Create the application
|
|
113
|
-
|
|
114
|
-
# Uncomment the below to disable human input callback tool
|
|
115
|
-
# agent_app.app._human_input_callback = None
|
|
118
|
+
fast = FastAgent("FastAgent Example")
|
|
116
119
|
|
|
117
120
|
|
|
118
121
|
# Define the agent
|
|
119
|
-
@
|
|
120
|
-
# @agent_app.agent(servers=["fetch"])
|
|
122
|
+
@fast.agent(servers=["fetch"])
|
|
121
123
|
async def main():
|
|
122
|
-
# use the --model
|
|
123
|
-
async with
|
|
124
|
+
# use the --model command line switch or agent arguments to change model
|
|
125
|
+
async with fast.run() as agent:
|
|
124
126
|
await agent()
|
|
125
127
|
|
|
126
128
|
|
|
@@ -217,11 +219,13 @@ def init(
|
|
|
217
219
|
|
|
218
220
|
if created:
|
|
219
221
|
console.print("\n[green]Setup completed successfully![/green]")
|
|
220
|
-
if "fastagent
|
|
222
|
+
if "fastagent.secrets.yaml" in created:
|
|
221
223
|
console.print("\n[yellow]Important:[/yellow] Remember to:")
|
|
222
|
-
console.print("1. Add your API keys to fastagent-secrets.yaml")
|
|
223
224
|
console.print(
|
|
224
|
-
"
|
|
225
|
+
"1. Add your API keys to fastagent-secrets.yaml or set OPENAI_API_KEY and ANTHROPIC_API_KEY environment variables"
|
|
226
|
+
)
|
|
227
|
+
console.print(
|
|
228
|
+
"2. Keep fastagent.secrets.yaml secure and never commit it to version control"
|
|
225
229
|
)
|
|
226
230
|
console.print("\nTo get started, run:")
|
|
227
231
|
console.print(" uv run agent.py")
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom exceptions for the FastAgent framework.
|
|
3
|
+
Enables user-friendly error handling for common issues.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FastAgentError(Exception):
|
|
8
|
+
"""Base exception class for FastAgent errors"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, message: str, details: str = ""):
|
|
11
|
+
self.message = message
|
|
12
|
+
self.details = details
|
|
13
|
+
super().__init__(f"{message}\n\n{details}" if details else message)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ServerConfigError(FastAgentError):
|
|
17
|
+
"""Raised when there are issues with MCP server configuration
|
|
18
|
+
Example: Server name referenced in agent.servers[] but not defined in config
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, message: str, details: str = ""):
|
|
22
|
+
super().__init__(message, details)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AgentConfigError(FastAgentError):
|
|
26
|
+
"""Raised when there are issues with Agent or Workflow configuration
|
|
27
|
+
Example: Parallel fan-in references unknown agent
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, message: str, details: str = ""):
|
|
31
|
+
super().__init__(message, details)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ProviderKeyError(FastAgentError):
|
|
35
|
+
"""Raised when there are issues with LLM provider API keys
|
|
36
|
+
Example: OpenAI/Anthropic key not configured but model requires it
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, message: str, details: str = ""):
|
|
40
|
+
super().__init__(message, details)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ServerInitializationError(FastAgentError):
|
|
44
|
+
"""Raised when a server fails to initialize properly."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, message: str, details: str = ""):
|
|
47
|
+
super().__init__(message, details)
|