-
Notifications
You must be signed in to change notification settings - Fork 781
merge init and quickstart #569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
253263e to
1fe7425
Compare
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThe PR consolidates the standalone quickstart CLI command into the init command. The quickstart.py module is deleted, its functionality (copying example templates via helper functions) is migrated to init.py with a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes The changes involve heterogeneous modifications across CLI structure and initialization logic. The primary complexity stems from the migration of file-copying logic and example handling into init.py, including resource packaging interactions via importlib. While the refactoring is cohesive and follows a clear consolidation pattern, verifying correct integration of example copying, error handling, and interactive mode wiring requires careful attention. Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
1fe7425 to
a2c38bc
Compare
a2c38bc to
4a71c20
Compare
5ec4d74 to
739380f
Compare
4a71c20 to
160ccb8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/cli-reference.mdx (2)
218-223: Align aliases with CLI: only ‘deploy’ and ‘login’ are top-level.Docs list
logoutandwhoamias top-level aliases, but main.py registers onlydeployandlogin. Adjust docs or add aliases in code.-These commands are available at the top level for convenience: -- `mcp-agent deploy` - Deploy to cloud (alias for `cloud deploy`) -- `mcp-agent login` - Authenticate (alias for `cloud auth login`) -- `mcp-agent logout` - Sign out (alias for `cloud auth logout`) -- `mcp-agent whoami` - Show current identity (alias for `cloud auth whoami`) +These commands are available at the top level for convenience: +- `mcp-agent deploy` - Deploy to cloud (alias for `cloud deploy`) +- `mcp-agent login` - Authenticate (alias for `cloud auth login`) + +Other auth helpers are available under `mcp-agent cloud auth`.
442-457: Replace non-existent template ‘temporal’ with a valid one.
temporalisn’t inscaffolding_templates. Useserver(orbasic) in examples.-# Initialize project -mcp-agent init --template temporal +# Initialize project +mcp-agent init --template server @@ -# Create examples -mcp-agent init --quickstart workflow +# Create examples +mcp-agent init --quickstart workflow
🧹 Nitpick comments (3)
src/mcp_agent/cli/commands/init.py (2)
222-235: Deduplicate example_map and favor packaged resources first.example_map is defined twice; this will drift. Move a single EXAMPLES_MAP constant to module scope and reuse in both quickstart and template flows. Also prefer _copy_pkg_tree first for all entries, then fall back to EXAMPLE_ROOT when developing from repo.
@@ - 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"), - } +# At top-level (near EXAMPLE_ROOT) +EXAMPLES_MAP = { + # pkg_rel preferred (packaged), repo_rel fallback for dev + "workflow": {"dst": "workflow", "pkg_rel": "workflows", "repo_rel": ["workflows"]}, + "researcher": {"dst": "researcher", "pkg_rel": "usecases/mcp_researcher", "repo_rel": ["usecases", "mcp_researcher"]}, + "data-analysis": {"dst": "data-analysis", "pkg_rel": "usecases/mcp_financial_analyzer", "repo_rel": ["usecases", "mcp_financial_analyzer"]}, + "state-transfer": {"dst": "state-transfer", "pkg_rel": "workflows/workflow_router", "repo_rel": ["workflows", "workflow_router"]}, + "basic-agent-server": {"dst": "basic_agent_server", "pkg_rel": "mcp_agent_server/asyncio", "repo_rel": ["mcp_agent_server", "asyncio"]}, + "mcp-basic-agent": {"dst": "mcp_basic_agent", "pkg_rel": "basic/mcp_basic_agent"}, + "token-counter": {"dst": "token_counter", "pkg_rel": "basic/token_counter"}, + "agent-factory": {"dst": "agent_factory", "pkg_rel": "basic/agent_factory"}, + "reference-agent-server": {"dst": "reference_agent_server", "pkg_rel": "mcp_agent_server/reference"}, + "elicitation": {"dst": "elicitation", "pkg_rel": "mcp_agent_server/elicitation"}, + "sampling": {"dst": "sampling", "pkg_rel": "mcp_agent_server/sampling"}, + "notifications": {"dst": "notifications", "pkg_rel": "mcp_agent_server/notifications"}, +} @@ - mapping = example_map.get(quickstart) + mapping = EXAMPLES_MAP.get(quickstart) @@ - 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) + info = mapping + dst = base_dir / info["dst"] + copied = 0 + if "pkg_rel" in info: + copied = _copy_pkg_tree(info["pkg_rel"], dst, force) + if not copied and "repo_rel" in info: + repo_src = EXAMPLE_ROOT.joinpath(*info["repo_rel"]) + if repo_src.exists(): + copied = _copy_tree(repo_src, dst, force) @@ - example_map = { ... } # duplicate removed - mapping = example_map.get(template) + mapping = EXAMPLES_MAP.get(template) @@ - 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) + info = mapping + dst = dir / info["dst"] + copied = 0 + if "pkg_rel" in info: + copied = _copy_pkg_tree(info["pkg_rel"], dst, force) + if not copied and "repo_rel" in info: + repo_src = EXAMPLE_ROOT.joinpath(*info["repo_rel"]) + if repo_src.exists(): + copied = _copy_tree(repo_src, dst, force)Also applies to: 306-319
91-97: Avoid destructive rmtree; improve failure messaging.
- Using rmtree on dst is heavy-handed; prefer shutil.copytree(..., dirs_exist_ok=force) (Python 3.8+).
- Quickstart failure message blames destination only; also surface source-not-found.
@@ - if dst.exists(): - if force: - shutil.rmtree(dst) - else: - return 0 - shutil.copytree(src, dst) + # Copy allowing overwrite when force=True + shutil.copytree(src, dst, dirs_exist_ok=force) return 1 @@ - else: - console.print(f"[yellow]Could not copy '{quickstart}' - destination may already exist[/yellow]") - console.print("Use --force to overwrite") + else: + console.print(f"[yellow]Could not copy '{quickstart}'[/yellow]") + console.print("Possible causes: destination exists without --force, or example not found in package/repo.") + console.print("Use --list to see names and --force to overwrite.")Also applies to: 258-263
docs/cli-reference.mdx (1)
49-55: Docs sync with code: options and template categories look good; keep them in lockstep.Minor wording nit: “copy example only without config files” → “copy example without config files” (remove ‘only’ for consistency with CLI help).
-| `--quickstart` | Quickstart mode: copy example only without config files | - | +| `--quickstart` | Quickstart mode: copy example without config files | - |Also applies to: 56-79, 80-97
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
docs/cli-reference.mdx(2 hunks)src/mcp_agent/cli/commands/__init__.py(0 hunks)src/mcp_agent/cli/commands/init.py(6 hunks)src/mcp_agent/cli/commands/quickstart.py(0 hunks)src/mcp_agent/cli/main.py(1 hunks)
💤 Files with no reviewable changes (2)
- src/mcp_agent/cli/commands/init.py
- src/mcp_agent/cli/commands/quickstart.py
🔇 Additional comments (1)
src/mcp_agent/cli/main.py (1)
146-146: LGTM: init help reflects merged quickstart.
| console = Console() | ||
|
|
||
| # Path to repository examples | ||
| EXAMPLE_ROOT = Path(__file__).parents[4] / "examples" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use absolute path here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was taken from the old quickstart implementation. Not sure how we can have an absolute path from the repo root?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this won't work. The quickstart samples need to ship with the package. i.e. look at how init materializes the basic agent from the data directory and use that logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok. This was confusing because we have the init command which uses the src/data/examples and src/data/templates to generate init projects from the mcp-agent src. This here is copying from the repo itself so it won't work if you run it in your own project folder. But looks like this is how quickstart currently does it (I just tried it in a new project dir and it fails for each of them).
So is the change needed here just to duplicate those examples under src/data/examples or try and fetch the examples from the repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just duplicated them under data/examples in a followup PR
160ccb8 to
20288a3
Compare
20288a3 to
b52015f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (2)
src/mcp_agent/cli/commands/init.py (2)
17-20: Good fix: stderr handling with a dedicated Rich console.Defining err_console and using it for error output resolves the previous TypeError from Console.print(err=True).
556-565: Don’t manually construct Typer.Context; get the current one.Manual Context() construction is brittle. Use typer.get_current_context(), and you don’t need to pass quickstart explicitly.
Apply:
- ctx = typer.Context(init) - init( - ctx=ctx, + ctx = typer.get_current_context() + init( + ctx=ctx, dir=dir, template=template_name, - quickstart=None, force=False, no_gitignore=False, list_templates=False, )
🧹 Nitpick comments (3)
src/mcp_agent/cli/commands/init.py (3)
216-222: Harden quickstart guard and route errors to stderr.Be explicit about type and print errors via err_console.
Apply:
- if quickstart: - if quickstart not in example_templates: - console.print(f"[red]Unknown quickstart example: {quickstart}[/red]") - console.print(f"Available examples: {', '.join(example_templates.keys())}") - console.print("[dim]Use --list to see all available templates[/dim]") + if isinstance(quickstart, str) and quickstart: + if quickstart not in example_templates: + err_console.print(f"[red]Unknown quickstart example: {quickstart}[/red]") + err_console.print(f"Available examples: {', '.join(example_templates.keys())}") + err_console.print("[dim]Use --list to see all available templates[/dim]") raise typer.Exit(1)
35-51: Send error logs to stderr console consistently.Use err_console for failures in _load_template and _write for consistent UX and easier piping.
Apply:
- except Exception as e: - console.print(f"[red]Error loading template {template_name}: {e}[/red]") + except Exception as e: + err_console.print(f"[red]Error loading template {template_name}: {e}[/red]") return "" @@ - except Exception as e: - console.print(f"[red]Error writing {path}: {e}[/red]") + except Exception as e: + err_console.print(f"[red]Error writing {path}: {e}[/red]") return False
210-211: Improve help text to include quickstart usage.Clarify that examples can be copied via --quickstart.
Apply:
- console.print("\n[dim]Use: mcp-agent init --template <name>[/dim]") + console.print("\n[dim]Use: mcp-agent init --template <name> or mcp-agent init --quickstart <name>[/dim]")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/mcp_agent/cli/commands/__init__.py(0 hunks)src/mcp_agent/cli/commands/init.py(7 hunks)src/mcp_agent/cli/commands/quickstart.py(0 hunks)src/mcp_agent/cli/main.py(1 hunks)
💤 Files with no reviewable changes (2)
- src/mcp_agent/cli/commands/init.py
- src/mcp_agent/cli/commands/quickstart.py
🚧 Files skipped from review as they are similar to previous changes (1)
- src/mcp_agent/cli/main.py
| try: | ||
| root = ( | ||
| _pkg_files("mcp_agent") | ||
| .joinpath("data") | ||
| .joinpath("examples") | ||
| .joinpath(pkg_rel) | ||
| ) | ||
| except Exception: | ||
| return 0 | ||
| if not root.exists(): | ||
| return 0 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: importlib.resources Traversable has no .exists(); use .is_dir() and handle existing dst.
Calling root.exists() on a Traversable will raise AttributeError at runtime. Also, mirror _copy_tree semantics when dst exists.
Apply:
def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
@@
- try:
- root = (
- _pkg_files("mcp_agent")
- .joinpath("data")
- .joinpath("examples")
- .joinpath(pkg_rel)
- )
- except Exception:
- return 0
- if not root.exists():
- return 0
+ try:
+ root = (
+ _pkg_files("mcp_agent")
+ .joinpath("data")
+ .joinpath("examples")
+ .joinpath(pkg_rel)
+ )
+ except Exception:
+ return 0
+ # Traversable doesn't define `.exists()`; use `.is_dir()`
+ if not root.is_dir():
+ return 0
+
+ # Align behavior with _copy_tree when destination already exists
+ if dst.exists():
+ if force:
+ shutil.rmtree(dst)
+ else:
+ return 0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try: | |
| root = ( | |
| _pkg_files("mcp_agent") | |
| .joinpath("data") | |
| .joinpath("examples") | |
| .joinpath(pkg_rel) | |
| ) | |
| except Exception: | |
| return 0 | |
| if not root.exists(): | |
| return 0 | |
| try: | |
| root = ( | |
| _pkg_files("mcp_agent") | |
| .joinpath("data") | |
| .joinpath("examples") | |
| .joinpath(pkg_rel) | |
| ) | |
| except Exception: | |
| return 0 | |
| # Traversable doesn't define `.exists()`; use `.is_dir()` | |
| if not root.is_dir(): | |
| return 0 | |
| # Align behavior with _copy_tree when destination already exists | |
| if dst.exists(): | |
| if force: | |
| shutil.rmtree(dst) | |
| else: | |
| return 0 | |
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 110 to 121, the code calls
root.exists() on an importlib.resources Traversable which raises AttributeError;
replace that check with root.is_dir() (or root.is_file() as appropriate) and
ensure you treat a non-directory as absent; additionally, when copying the tree
to the destination, mirror the semantics of _copy_tree by handling an existing
dst (e.g., merge files, skip existing files, or overwrite according to the
project's policy) rather than unconditionally failing—update the copy logic to
check for dst existence and perform the merge/skip/overwrite behavior used by
_copy_tree.
| example_templates = { | ||
| "workflow": "Workflow examples (from examples/workflows)", | ||
| "researcher": "MCP researcher use case (from examples/usecases/mcp_researcher)", | ||
| "data-analysis": "Financial data analysis example", | ||
| "state-transfer": "Workflow router with state transfer", | ||
| "mcp-basic-agent": "Basic MCP agent example", | ||
| "token-counter": "Token counting with monitoring", | ||
| "agent-factory": "Agent factory pattern", | ||
| "basic-agent-server": "Basic agent server (asyncio)", | ||
| "reference-agent-server": "Reference agent server implementation", | ||
| "elicitation": "Elicitation server example", | ||
| "sampling": "Sampling server example", | ||
| "notifications": "Notifications server example", | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlisted quickstarts: examples present in mapping but not shown with --list.
hello-world, mcp, temporal, chatgpt-app are selectable via mapping but omitted from example_templates. Add them so users can discover them.
Apply:
example_templates = {
"workflow": "Workflow examples (from examples/workflows)",
"researcher": "MCP researcher use case (from examples/usecases/mcp_researcher)",
"data-analysis": "Financial data analysis example",
"state-transfer": "Workflow router with state transfer",
"mcp-basic-agent": "Basic MCP agent example",
"token-counter": "Token counting with monitoring",
"agent-factory": "Agent factory pattern",
"basic-agent-server": "Basic agent server (asyncio)",
"reference-agent-server": "Reference agent server implementation",
"elicitation": "Elicitation server example",
"sampling": "Sampling server example",
"notifications": "Notifications server example",
+ "hello-world": "Cloud hello world example",
+ "mcp": "Cloud MCP example",
+ "temporal": "Cloud Temporal example",
+ "chatgpt-app": "Cloud ChatGPT app example",
}🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 170 to 184, the
example_templates mapping is missing entries for quickstarts that exist
elsewhere (hello-world, mcp, temporal, chatgpt-app); update the
example_templates dict to include those four keys with descriptive values (e.g.,
"Hello World quickstart", "MCP quickstart", "Temporal quickstart", "ChatGPT app
quickstart") so they appear when users run --list.
| 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"), | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Repo path reliance breaks in installed wheels; use packaged examples for all entries.
Several quickstarts only reference EXAMPLE_ROOT; those won’t exist when the package is installed. Prefer packaged resources first, then fall back to repo paths in dev.
Apply:
- 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"),
- }
+ example_map = {
+ # Prefer packaged examples; repo fallback happens below if needed
+ "workflow": (None, "workflow", "workflows"),
+ "researcher": (None, "researcher", "usecases/mcp_researcher"),
+ "data-analysis": (None, "data-analysis", "usecases/mcp_financial_analyzer"),
+ "state-transfer": (None, "state-transfer", "workflows/workflow_router"),
+ "basic-agent-server": (None, "basic_agent_server", "mcp_agent_server/asyncio"),
+ "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": (None, "hello_world", "cloud/hello_world"),
+ "mcp": (None, "mcp", "cloud/mcp"),
+ "temporal": (None, "temporal", "cloud/temporal"),
+ "chatgpt-app": (None, "chatgpt_app", "cloud/chatgpt_app"),
+ }Committable suggestion skipped: line range outside the PR's diff.
| 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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fallback to repo path uses an incorrect join.
pkg_rel.replace("/", "_") won’t match the repo layout; join the original segments under EXAMPLE_ROOT.
Apply:
- if not copied:
- src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
+ if not copied:
+ # Dev fallback: repo examples mirror the packaged relative path
+ src = EXAMPLE_ROOT / Path(pkg_rel)
if src.exists():
copied = _copy_tree(src, dst, force)🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 250 to 258, the fallback
constructs src with EXAMPLE_ROOT / pkg_rel.replace("/", "_") which produces the
wrong path; split pkg_rel on "/" and join the segments under EXAMPLE_ROOT (e.g.
EXAMPLE_ROOT.joinpath(*pkg_rel.split("/")) or EXAMPLE_ROOT /
Path(*pkg_rel.split("/"))) so the repo layout is preserved, then check
src.exists() and use _copy_tree(src, dst, force) as before.
| # 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"), | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same packaging issue for --template flow; mirror the quickstart fix.
The template example_map also relies on EXAMPLE_ROOT for many entries. Use packaged paths with repo fallback.
Apply:
- 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"),
- }
+ example_map = {
+ "workflow": (None, "workflow", "workflows"),
+ "researcher": (None, "researcher", "usecases/mcp_researcher"),
+ "data-analysis": (None, "data-analysis", "usecases/mcp_financial_analyzer"),
+ "state-transfer": (None, "state-transfer", "workflows/workflow_router"),
+ "basic-agent-server": (None, "basic_agent_server", "mcp_agent_server/asyncio"),
+ "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": (None, "hello_world", "cloud/hello_world"),
+ "mcp": (None, "mcp", "cloud/mcp"),
+ "temporal": (None, "temporal", "cloud/temporal"),
+ "chatgpt-app": (None, "chatgpt_app", "cloud/chatgpt_app"),
+ }🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 306 to 328, the example_map
currently hardcodes many entries to EXAMPLE_ROOT rather than using packaged
resource paths with a repository fallback (same bug fixed for quickstart);
update the mapping so entries prefer packaged paths (i.e., use tuples of the
form (None, dest_name, pkg_rel) for packaged examples) and for repo-only
examples keep the EXAMPLE_ROOT tuples, then adjust the code that resolves
examples to first try loading from the package path and only fall back to
EXAMPLE_ROOT if the packaged resource is not present, ensuring parity with the
quickstart fix approach.
| src = EXAMPLE_ROOT / pkg_rel.replace("/", "_") | ||
| if src.exists(): | ||
| copied = _copy_tree(src, dst, force) | ||
| else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same incorrect fallback join as quickstart.
Use EXAMPLE_ROOT / Path(pkg_rel), not underscore replacement.
Apply:
- if not copied:
- src = EXAMPLE_ROOT / pkg_rel.replace("/", "_")
+ if not copied:
+ src = EXAMPLE_ROOT / Path(pkg_rel)
if src.exists():
copied = _copy_tree(src, dst, force)🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 340 to 343, the code
incorrectly builds the example path using pkg_rel.replace("/", "_"); change it
to use a Path join such as EXAMPLE_ROOT / Path(pkg_rel) so the directory
structure is preserved. Replace the underscore-replacement expression with
Path(pkg_rel) (ensure pathlib.Path is imported or already available), keep the
existing exists() check and _copy_tree call, and remove the replace("/") usage.
Merge activity
|
### TL;DR
Unified project initialization by merging `init` and `quickstart` commands into a single enhanced `init` command with improved template management.
### What changed?
- Consolidated `mcp-agent quickstart` functionality into `mcp-agent init` with a new `--quickstart` flag for backward compatibility
- Organized templates into two categories: scaffolding templates and example templates
- Added `--list` option to display all available templates with descriptions
- Enhanced CLI options with short forms (`-d`, `-t`, `-f`, `-l`)
- Added new option `--no-gitignore` to skip creating .gitignore files
- Improved documentation with clearer examples and template descriptions
- Removed the standalone `quickstart.py` module as its functionality is now in `init.py`
- Updated CLI reference documentation to reflect these changes
### How to test?
```bash
# List all available templates
mcp-agent init --list
# Create scaffolding project with config files
mcp-agent init --template basic
# Copy complete example with config files
mcp-agent init --template workflow --dir ./my-project
# Use quickstart mode (backward compatible with old command)
mcp-agent init --quickstart workflow
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
- **New Features**
- Added `--quickstart` option to the init command for copying curated example templates alongside project scaffolding.
- Example templates now available during project initialization.
- **Chores**
- Consolidated quickstart functionality into the init command; separate quickstart command group removed.
- Updated init help text to reflect dual-mode scaffolding capabilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

TL;DR
Unified project initialization by merging
initandquickstartcommands into a single enhancedinitcommand with improved template management.What changed?
mcp-agent quickstartfunctionality intomcp-agent initwith a new--quickstartflag for backward compatibility--listoption to display all available templates with descriptions-d,-t,-f,-l)--no-gitignoreto skip creating .gitignore filesquickstart.pymodule as its functionality is now ininit.pyHow to test?
Summary by CodeRabbit
--quickstartoption to the init command for copying curated example templates alongside project scaffolding.