Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/reference/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ Recent CLI changes fold the old `quickstart` command into `mcp-agent init`. You
| `agent-factory` | Agent factory with declarative routing rules. |
| `basic-agent-server`, `reference-agent-server` | Complete MCP server implementations (asyncio + reference). |
| `elicitation`, `sampling`, `notifications` | Packaged MCP server variations installed via `mcp_agent.data.examples`. |
| `hello-world` | Basic cloud-deployable example with simple tool calls. |
| `mcp` | Comprehensive MCP server example showcasing tools, sampling, elicitation, notifications, prompts, and resources. |
| `temporal` | Temporal integration example with durable workflows and pause/resume patterns. |
| `chatgpt-app` | ChatGPT App with interactive UI widgets (coin flip example with React frontend). |

Examples:

Expand Down
125 changes: 32 additions & 93 deletions src/mcp_agent/cli/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

from __future__ import annotations

import shutil
from pathlib import Path
from importlib import resources
from importlib.resources import files as _pkg_files

import typer
from rich.console import Console
Expand All @@ -18,9 +16,6 @@
console = Console()
err_console = Console(stderr=True)

# Path to repository examples
EXAMPLE_ROOT = Path(__file__).parents[4] / "examples"


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


def _copy_tree(src: Path, dst: Path, force: bool) -> int:
"""Copy a directory tree from src to dst.

Returns 1 on success, 0 on failure.
"""
if not src.exists():
err_console.print(f"[red]Source not found: {src}[/red]")
return 0
try:
if dst.exists():
if force:
shutil.rmtree(dst)
else:
return 0
shutil.copytree(src, dst)
return 1
except Exception as e:
err_console.print(f"[red]Error copying tree: {e}[/red]")
return 0


def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
"""Copy packaged examples from mcp_agent.data/examples/<pkg_rel> into dst.

Expand All @@ -109,8 +83,7 @@ def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
"""
try:
root = (
_pkg_files("mcp_agent")
.joinpath("data")
resources.files("mcp_agent.data")
.joinpath("examples")
.joinpath(pkg_rel)
)
Expand Down Expand Up @@ -180,10 +153,35 @@ def init(
"elicitation": "Elicitation server example",
"sampling": "Sampling server example",
"notifications": "Notifications server example",
"hello-world": "Basic hello world cloud example",
"mcp": "Comprehensive MCP server example with tools, sampling, elicitation",
"temporal": "Temporal integration with durable workflows",
"chatgpt-app": "ChatGPT App with interactive UI widgets",
}

templates = {**scaffolding_templates, **example_templates}

# Map template names to their source paths (shared by quickstart and template modes)
# Format: "name": (dest_name, pkg_rel) - all examples are packaged in mcp_agent.data/examples
example_map = {
"workflow": ("workflow", "workflows"),
"researcher": ("researcher", "usecases/mcp_researcher"),
"data-analysis": ("data-analysis", "usecases/mcp_financial_analyzer"),
"state-transfer": ("state-transfer", "workflows/workflow_router"),
"basic-agent-server": ("basic_agent_server", "mcp_agent_server/asyncio"),
"mcp-basic-agent": ("mcp_basic_agent", "basic/mcp_basic_agent"),
"token-counter": ("token_counter", "basic/token_counter"),
"agent-factory": ("agent_factory", "basic/agent_factory"),
"reference-agent-server": ("reference_agent_server", "mcp_agent_server/reference"),
"elicitation": ("elicitation", "mcp_agent_server/elicitation"),
"sampling": ("sampling", "mcp_agent_server/sampling"),
"notifications": ("notifications", "mcp_agent_server/notifications"),
"hello-world": ("hello_world", "cloud/hello_world"),
"mcp": ("mcp", "cloud/mcp"),
"temporal": ("temporal", "cloud/temporal"),
"chatgpt-app": ("chatgpt_app", "cloud/chatgpt_app"),
}

if list_templates:
console.print("\n[bold]Available Templates:[/bold]\n")

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

example_map = {
"workflow": (EXAMPLE_ROOT / "workflows", "workflow"),
"researcher": (EXAMPLE_ROOT / "usecases" / "mcp_researcher", "researcher"),
"data-analysis": (EXAMPLE_ROOT / "usecases" / "mcp_financial_analyzer", "data-analysis"),
"state-transfer": (EXAMPLE_ROOT / "workflows" / "workflow_router", "state-transfer"),
"basic-agent-server": (EXAMPLE_ROOT / "mcp_agent_server" / "asyncio", "basic_agent_server"),
"mcp-basic-agent": (None, "mcp_basic_agent", "basic/mcp_basic_agent"),
"token-counter": (None, "token_counter", "basic/token_counter"),
"agent-factory": (None, "agent_factory", "basic/agent_factory"),
"reference-agent-server": (None, "reference_agent_server", "mcp_agent_server/reference"),
"elicitation": (None, "elicitation", "mcp_agent_server/elicitation"),
"sampling": (None, "sampling", "mcp_agent_server/sampling"),
"notifications": (None, "notifications", "mcp_agent_server/notifications"),
"hello-world": (EXAMPLE_ROOT / "cloud" / "hello_world", "hello_world"),
"mcp": (EXAMPLE_ROOT / "cloud" / "mcp", "mcp"),
"temporal": (EXAMPLE_ROOT / "cloud" / "temporal", "temporal"),
"chatgpt-app": (EXAMPLE_ROOT / "cloud" / "chatgpt_app", "chatgpt_app"),
}

mapping = example_map.get(quickstart)
if not mapping:
console.print(f"[red]Quickstart example '{quickstart}' not found[/red]")
Expand All @@ -247,18 +226,9 @@ def init(
base_dir = dir.resolve()
base_dir.mkdir(parents=True, exist_ok=True)

if len(mapping) == 3:
_, dst_name, pkg_rel = mapping
dst = base_dir / dst_name
copied = _copy_pkg_tree(pkg_rel, dst, force)
if not copied:
src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
if src.exists():
copied = _copy_tree(src, dst, force)
else:
src, dst_name = mapping
dst = base_dir / dst_name
copied = _copy_tree(src, dst, force)
dst_name, pkg_rel = mapping
dst = base_dir / dst_name
copied = _copy_pkg_tree(pkg_rel, dst, force)

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

# Handle example templates (copy from repository or package)
if template in example_templates:
# Map template names to their source paths
# Format: "name": (repo_path, dest_name) for repo examples
# "name": (None, dest_name, pkg_rel) for packaged examples
example_map = {
"workflow": (EXAMPLE_ROOT / "workflows", "workflow"),
"researcher": (EXAMPLE_ROOT / "usecases" / "mcp_researcher", "researcher"),
"data-analysis": (EXAMPLE_ROOT / "usecases" / "mcp_financial_analyzer", "data-analysis"),
"state-transfer": (EXAMPLE_ROOT / "workflows" / "workflow_router", "state-transfer"),
"basic-agent-server": (EXAMPLE_ROOT / "mcp_agent_server" / "asyncio", "basic_agent_server"),
"mcp-basic-agent": (None, "mcp_basic_agent", "basic/mcp_basic_agent"),
"token-counter": (None, "token_counter", "basic/token_counter"),
"agent-factory": (None, "agent_factory", "basic/agent_factory"),
"reference-agent-server": (None, "reference_agent_server", "mcp_agent_server/reference"),
"elicitation": (None, "elicitation", "mcp_agent_server/elicitation"),
"sampling": (None, "sampling", "mcp_agent_server/sampling"),
"notifications": (None, "notifications", "mcp_agent_server/notifications"),
"hello-world": (EXAMPLE_ROOT / "cloud" / "hello_world", "hello_world"),
"mcp": (EXAMPLE_ROOT / "cloud" / "mcp", "mcp"),
"temporal": (EXAMPLE_ROOT / "cloud" / "temporal", "temporal"),
"chatgpt-app": (EXAMPLE_ROOT / "cloud" / "chatgpt_app", "chatgpt_app"),
}

mapping = example_map.get(template)
if not mapping:
console.print(f"[red]Example template '{template}' not found[/red]")
raise typer.Exit(1)

if len(mapping) == 3:
_, dst_name, pkg_rel = mapping
dst = dir / dst_name
copied = _copy_pkg_tree(pkg_rel, dst, force)
if not copied:
src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
if src.exists():
copied = _copy_tree(src, dst, force)
else:
src, dst_name = mapping
dst = dir / dst_name
copied = _copy_tree(src, dst, force)
dst_name, pkg_rel = mapping
dst = dir / dst_name
copied = _copy_pkg_tree(pkg_rel, dst, force)

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