Skip to content

Commit 446de06

Browse files
authored
add quickstart examples (#577)
### TL;DR Added new cloud-based example templates to the MCP Agent CLI initialization command. ### How to test? ``` mcp init --template hello-world my-hello-world mcp init --template mcp my-mcp-example mcp init --template temporal my-temporal-workflow mcp init --template chatgpt-app my-chatgpt-app ```
1 parent 5b1081c commit 446de06

File tree

103 files changed

+17834
-93
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+17834
-93
lines changed

docs/reference/cli.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ Recent CLI changes fold the old `quickstart` command into `mcp-agent init`. You
7272
| `agent-factory` | Agent factory with declarative routing rules. |
7373
| `basic-agent-server`, `reference-agent-server` | Complete MCP server implementations (asyncio + reference). |
7474
| `elicitation`, `sampling`, `notifications` | Packaged MCP server variations installed via `mcp_agent.data.examples`. |
75+
| `hello-world` | Basic cloud-deployable example with simple tool calls. |
76+
| `mcp` | Comprehensive MCP server example showcasing tools, sampling, elicitation, notifications, prompts, and resources. |
77+
| `temporal` | Temporal integration example with durable workflows and pause/resume patterns. |
78+
| `chatgpt-app` | ChatGPT App with interactive UI widgets (coin flip example with React frontend). |
7579

7680
Examples:
7781

src/mcp_agent/cli/commands/init.py

Lines changed: 32 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44

55
from __future__ import annotations
66

7-
import shutil
87
from pathlib import Path
98
from importlib import resources
10-
from importlib.resources import files as _pkg_files
119

1210
import typer
1311
from rich.console import Console
@@ -18,9 +16,6 @@
1816
console = Console()
1917
err_console = Console(stderr=True)
2018

21-
# Path to repository examples
22-
EXAMPLE_ROOT = Path(__file__).parents[4] / "examples"
23-
2419

2520
def _load_template(template_name: str) -> str:
2621
"""Load a template file from the data/templates directory."""
@@ -80,27 +75,6 @@ def _write_readme(dir_path: Path, content: str, force: bool) -> str | None:
8075
return None
8176

8277

83-
def _copy_tree(src: Path, dst: Path, force: bool) -> int:
84-
"""Copy a directory tree from src to dst.
85-
86-
Returns 1 on success, 0 on failure.
87-
"""
88-
if not src.exists():
89-
err_console.print(f"[red]Source not found: {src}[/red]")
90-
return 0
91-
try:
92-
if dst.exists():
93-
if force:
94-
shutil.rmtree(dst)
95-
else:
96-
return 0
97-
shutil.copytree(src, dst)
98-
return 1
99-
except Exception as e:
100-
err_console.print(f"[red]Error copying tree: {e}[/red]")
101-
return 0
102-
103-
10478
def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
10579
"""Copy packaged examples from mcp_agent.data/examples/<pkg_rel> into dst.
10680
@@ -109,8 +83,7 @@ def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
10983
"""
11084
try:
11185
root = (
112-
_pkg_files("mcp_agent")
113-
.joinpath("data")
86+
resources.files("mcp_agent.data")
11487
.joinpath("examples")
11588
.joinpath(pkg_rel)
11689
)
@@ -180,10 +153,35 @@ def init(
180153
"elicitation": "Elicitation server example",
181154
"sampling": "Sampling server example",
182155
"notifications": "Notifications server example",
156+
"hello-world": "Basic hello world cloud example",
157+
"mcp": "Comprehensive MCP server example with tools, sampling, elicitation",
158+
"temporal": "Temporal integration with durable workflows",
159+
"chatgpt-app": "ChatGPT App with interactive UI widgets",
183160
}
184161

185162
templates = {**scaffolding_templates, **example_templates}
186163

164+
# Map template names to their source paths (shared by quickstart and template modes)
165+
# Format: "name": (dest_name, pkg_rel) - all examples are packaged in mcp_agent.data/examples
166+
example_map = {
167+
"workflow": ("workflow", "workflows"),
168+
"researcher": ("researcher", "usecases/mcp_researcher"),
169+
"data-analysis": ("data-analysis", "usecases/mcp_financial_analyzer"),
170+
"state-transfer": ("state-transfer", "workflows/workflow_router"),
171+
"basic-agent-server": ("basic_agent_server", "mcp_agent_server/asyncio"),
172+
"mcp-basic-agent": ("mcp_basic_agent", "basic/mcp_basic_agent"),
173+
"token-counter": ("token_counter", "basic/token_counter"),
174+
"agent-factory": ("agent_factory", "basic/agent_factory"),
175+
"reference-agent-server": ("reference_agent_server", "mcp_agent_server/reference"),
176+
"elicitation": ("elicitation", "mcp_agent_server/elicitation"),
177+
"sampling": ("sampling", "mcp_agent_server/sampling"),
178+
"notifications": ("notifications", "mcp_agent_server/notifications"),
179+
"hello-world": ("hello_world", "cloud/hello_world"),
180+
"mcp": ("mcp", "cloud/mcp"),
181+
"temporal": ("temporal", "cloud/temporal"),
182+
"chatgpt-app": ("chatgpt_app", "cloud/chatgpt_app"),
183+
}
184+
187185
if list_templates:
188186
console.print("\n[bold]Available Templates:[/bold]\n")
189187

@@ -220,25 +218,6 @@ def init(
220218
console.print("[dim]Use --list to see all available templates[/dim]")
221219
raise typer.Exit(1)
222220

223-
example_map = {
224-
"workflow": (EXAMPLE_ROOT / "workflows", "workflow"),
225-
"researcher": (EXAMPLE_ROOT / "usecases" / "mcp_researcher", "researcher"),
226-
"data-analysis": (EXAMPLE_ROOT / "usecases" / "mcp_financial_analyzer", "data-analysis"),
227-
"state-transfer": (EXAMPLE_ROOT / "workflows" / "workflow_router", "state-transfer"),
228-
"basic-agent-server": (EXAMPLE_ROOT / "mcp_agent_server" / "asyncio", "basic_agent_server"),
229-
"mcp-basic-agent": (None, "mcp_basic_agent", "basic/mcp_basic_agent"),
230-
"token-counter": (None, "token_counter", "basic/token_counter"),
231-
"agent-factory": (None, "agent_factory", "basic/agent_factory"),
232-
"reference-agent-server": (None, "reference_agent_server", "mcp_agent_server/reference"),
233-
"elicitation": (None, "elicitation", "mcp_agent_server/elicitation"),
234-
"sampling": (None, "sampling", "mcp_agent_server/sampling"),
235-
"notifications": (None, "notifications", "mcp_agent_server/notifications"),
236-
"hello-world": (EXAMPLE_ROOT / "cloud" / "hello_world", "hello_world"),
237-
"mcp": (EXAMPLE_ROOT / "cloud" / "mcp", "mcp"),
238-
"temporal": (EXAMPLE_ROOT / "cloud" / "temporal", "temporal"),
239-
"chatgpt-app": (EXAMPLE_ROOT / "cloud" / "chatgpt_app", "chatgpt_app"),
240-
}
241-
242221
mapping = example_map.get(quickstart)
243222
if not mapping:
244223
console.print(f"[red]Quickstart example '{quickstart}' not found[/red]")
@@ -247,18 +226,9 @@ def init(
247226
base_dir = dir.resolve()
248227
base_dir.mkdir(parents=True, exist_ok=True)
249228

250-
if len(mapping) == 3:
251-
_, dst_name, pkg_rel = mapping
252-
dst = base_dir / dst_name
253-
copied = _copy_pkg_tree(pkg_rel, dst, force)
254-
if not copied:
255-
src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
256-
if src.exists():
257-
copied = _copy_tree(src, dst, force)
258-
else:
259-
src, dst_name = mapping
260-
dst = base_dir / dst_name
261-
copied = _copy_tree(src, dst, force)
229+
dst_name, pkg_rel = mapping
230+
dst = base_dir / dst_name
231+
copied = _copy_pkg_tree(pkg_rel, dst, force)
262232

263233
if copied:
264234
console.print(f"Copied {copied} set(s) to {dst}")
@@ -305,45 +275,14 @@ def init(
305275

306276
# Handle example templates (copy from repository or package)
307277
if template in example_templates:
308-
# Map template names to their source paths
309-
# Format: "name": (repo_path, dest_name) for repo examples
310-
# "name": (None, dest_name, pkg_rel) for packaged examples
311-
example_map = {
312-
"workflow": (EXAMPLE_ROOT / "workflows", "workflow"),
313-
"researcher": (EXAMPLE_ROOT / "usecases" / "mcp_researcher", "researcher"),
314-
"data-analysis": (EXAMPLE_ROOT / "usecases" / "mcp_financial_analyzer", "data-analysis"),
315-
"state-transfer": (EXAMPLE_ROOT / "workflows" / "workflow_router", "state-transfer"),
316-
"basic-agent-server": (EXAMPLE_ROOT / "mcp_agent_server" / "asyncio", "basic_agent_server"),
317-
"mcp-basic-agent": (None, "mcp_basic_agent", "basic/mcp_basic_agent"),
318-
"token-counter": (None, "token_counter", "basic/token_counter"),
319-
"agent-factory": (None, "agent_factory", "basic/agent_factory"),
320-
"reference-agent-server": (None, "reference_agent_server", "mcp_agent_server/reference"),
321-
"elicitation": (None, "elicitation", "mcp_agent_server/elicitation"),
322-
"sampling": (None, "sampling", "mcp_agent_server/sampling"),
323-
"notifications": (None, "notifications", "mcp_agent_server/notifications"),
324-
"hello-world": (EXAMPLE_ROOT / "cloud" / "hello_world", "hello_world"),
325-
"mcp": (EXAMPLE_ROOT / "cloud" / "mcp", "mcp"),
326-
"temporal": (EXAMPLE_ROOT / "cloud" / "temporal", "temporal"),
327-
"chatgpt-app": (EXAMPLE_ROOT / "cloud" / "chatgpt_app", "chatgpt_app"),
328-
}
329-
330278
mapping = example_map.get(template)
331279
if not mapping:
332280
console.print(f"[red]Example template '{template}' not found[/red]")
333281
raise typer.Exit(1)
334282

335-
if len(mapping) == 3:
336-
_, dst_name, pkg_rel = mapping
337-
dst = dir / dst_name
338-
copied = _copy_pkg_tree(pkg_rel, dst, force)
339-
if not copied:
340-
src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
341-
if src.exists():
342-
copied = _copy_tree(src, dst, force)
343-
else:
344-
src, dst_name = mapping
345-
dst = dir / dst_name
346-
copied = _copy_tree(src, dst, force)
283+
dst_name, pkg_rel = mapping
284+
dst = dir / dst_name
285+
copied = _copy_pkg_tree(pkg_rel, dst, force)
347286

348287
if copied:
349288
console.print(f"\n[green]✅ Successfully copied example '{template}'![/green]")

0 commit comments

Comments
 (0)