Skip to content

Conversation

@saqadri
Copy link
Collaborator

@saqadri saqadri commented Sep 13, 2025

  • Consolidates runtime commands under dev
  • Smarter defaults for servers based on mcp_agent.config.yaml
  • Keeps cloud commands curated at top-level

Motivation

  • Reduce cognitive load at top-level -- there are a lot of commands in the CLI
  • Make first-run smoother: scripts and servers are auto-detected wherever possible.
  • Align init output and docs with the expected layout.

What changed

  • CLI layout (src/mcp_agent/cli/main.py, src/mcp_agent/cli/__main__.py)

    • Curated top-level: init, config, quickstart, doctor, cloud, plus aliases deploy, login
    • New umbrella: mcp-agent dev
      • dev start (replaces old dev)
      • dev chat, dev invoke, dev serve, dev go, dev server, dev build, dev logs, dev check, dev keys, dev models, dev client
    • Calling mcp-agent dev with no subcommand behaves like dev start
    • Convenience routing: bare chat-like invocations and mcp-agent go … route to dev go …
  • Smart server defaults

    • New helper resolves active servers:
      • If --servers provided ⇒ use it
      • Else, include dynamically attached URL/stdio servers
      • Else, use all servers from mcp_agent.config.yaml
    • Applied in chat, go, invoke so flags are optional for common cases
  • Init UX (src/mcp_agent/cli/commands/init.py)

    • Basic template writes to main.py (asks to overwrite or choose another name)
    • “Next steps” now print exact commands with the chosen script:
      • uv run <file>
      • mcp-agent dev start --script <file>
      • mcp-agent dev serve --script <file>
      • mcp-agent config edit
  • Client helpers

    • Mounted as mcp-agent dev client … (same functionality as configure module, clearer noun)
  • Small docs/help alignments

    • doctor example updated to mcp-agent dev start --script main.py
    • Serve/test messages reference main.py first

New helpers

  • detect_default_script(explicit) in src/mcp_agent/cli/core/utils.py
  • select_servers_from_config(servers_csv, url_servers, stdio_servers) in the same module

Breaking/behavior notes

  • Runtime commands moved under dev; use dev start, dev serve, etc.
  • go remains available via dev go; top-level go is routed for convenience.
  • Script defaults changed to prefer main.py; existing agent.py projects continue to work.

How to test

  • Scaffold and run

    mcp-agent init
    mcp-agent dev start              # auto-detects main.py
    mcp-agent dev serve --transport http --port 8080
  • Smart server defaults

    # With configured servers in mcp_agent.config.yaml
    mcp-agent dev chat -m "hello"    # should auto-enable configured servers
    mcp-agent dev go --uvx "mcp-server-fetch" -m "fetch https://example.com"
  • Invoke agent/workflow

    mcp-agent dev invoke --agent demo -m "Hi"
    mcp-agent dev invoke --workflow orchestrator --vars '{"task":"grade"}'
  • Serve test

    mcp-agent dev serve test         # prefers main.py, clear hint if missing

Files touched (high level)

  • src/mcp_agent/cli/main.py (layout, groups, aliases)
  • src/mcp_agent/cli/__main__.py (routing convenience)
  • src/mcp_agent/cli/core/utils.py (new helpers)
  • src/mcp_agent/cli/commands/dev.py (auto-detect script)
  • src/mcp_agent/cli/commands/serve.py (auto-detect script; improved messages; test)
  • src/mcp_agent/cli/commands/chat.py, go.py, invoke.py (auto-detect script; smart server defaults)
  • src/mcp_agent/cli/commands/init.py (write to main.py; improved next steps)
  • src/mcp_agent/cli/commands/doctor.py (example alignment)

Follow-ups (optional)

  • Add top-level client alias (in addition to dev client) if you want higher discoverability
  • Standardize -s short flag for --script across chat/go/invoke for parity with serve
  • Update full CLI docs to reflect the new dev umbrella and examples

Summary by CodeRabbit

  • New Features

    • Unified "dev" umbrella command grouping local run, chat, invoke, serve, and tools.
    • Added "doctor" diagnostics command.
    • Automatic entry-script detection (prefers main.py); --script optional.
    • Smart server selection from config/flags and backward-compatible routing for legacy "go" invocations.
  • Refactor

    • Curated top-level commands; many moved under "dev"; top-level aliases added for deploy and login.
  • Bug Fixes

    • Updated Anthropic key-test endpoint used when validating keys.
  • Documentation

    • Init/quick-start updated to dynamic entry script and uv run examples.

@saqadri saqadri requested a review from StreetLamb September 13, 2025 04:15
@coderabbitai
Copy link

coderabbitai bot commented Sep 13, 2025

Walkthrough

Reworks CLI dispatch and top-level commands into a curated set and a new "dev" umbrella group; adds detect_default_script and select_servers_from_config utilities; centralizes script auto-detection and server resolution across many commands; makes init template script selectable and updates examples/messages.

Changes

Cohort / File(s) Summary
Top-level dispatch & CLI grouping
src/mcp_agent/cli/__main__.py, src/mcp_agent/cli/main.py
Rewrote KNOWN commands, added dev_group Typer with callback, moved many runtime/dev commands under dev, added doctor, top-level aliases for deploy/login, removed some legacy top-level aliases, and added backward-compatible routing for legacy go invocations.
Core utilities & app loading
src/mcp_agent/cli/core/utils.py
Added detect_default_script(explicit: Optional[Path]) and select_servers_from_config(...); extended load_user_app(..., settings_override: Optional[Settings]=None) to apply settings overrides to discovered MCPApp.
Commands — auto-detect script & server resolution
src/mcp_agent/cli/commands/*
chat.py, go.py, invoke.py, serve.py, dev.py
Changed --script defaults from Path("agent.py") to None; call detect_default_script(...); compute resolved_server_list via select_servers_from_config(...); propagate resolved script and servers into single/multi-model flows, REPL, listing, and invocation paths.
Init template & examples
src/mcp_agent/cli/commands/init.py
Made basic template entry script selectable (default main.py, fallback prompt to agent.py), write chosen filename, update next-step instructions to use uv run and mcp-agent dev ..., and adjust other template run examples.
Doctor docs only
src/mcp_agent/cli/commands/doctor.py
Updated Quick Start example text to mcp-agent dev start --script main.py; no logic changes.
Keys provider endpoint change
src/mcp_agent/cli/commands/keys.py
Changed Anthropic test endpoint from /v1/messages to /v1/models for key validation requests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as CLI (__main__/main)
  participant Dev as dev_group
  participant Cmd as Subcommand
  User->>CLI: mcp-agent [args]
  alt first arg ∈ KNOWN
    CLI->>Cmd: Dispatch directly
  else first arg == "go"
    CLI->>Dev: Inject "dev"
    Dev->>Cmd: go
  else any arg matches GO_OPTIONS
    CLI->>Dev: Inject "dev" + "go"
    Dev->>Cmd: go
  end
  note right of Dev: dev_group callback → dev start when no subcommand
Loading
sequenceDiagram
  autonumber
  participant Cmd as Command (go/chat/serve/invoke/dev)
  participant Utils1 as detect_default_script
  participant Utils2 as select_servers_from_config
  Cmd->>Utils1: detect_default_script(script)
  Utils1-->>Cmd: resolved_script
  Cmd->>Utils2: select_servers_from_config(csv, url_servers, stdio_servers)
  Utils2-->>Cmd: resolved_server_list
  Cmd->>Cmd: Execute using resolved_script and resolved_server_list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • rholinshead
  • jtcorbett

Poem

I twitch my whiskers, find main or agent.py,
Old "go" hops under dev — no need to cry.
Servers gather neatly, names set in a row,
Templates pick a script and off we go.
UV run, dev start — a rabbit's CLI hi-ho! 🐇✦

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely and accurately summarizes the PR’s primary changes: consolidating runtime commands under a "dev" umbrella, preferring main.py as the default entry script, introducing smart server defaults, and clarifying the init UX. It is specific, directly related to the changeset and the modified files, and not vague.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/cli_reordering

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/mcp_agent/cli/commands/chat.py (1)

575-581: Use resolved_server_list for /prompt to honor smart defaults

Mixing server_list here ignores config/dynamic defaults and can break tool/resource resolution.

-                                prompt_msgs = await ag.create_prompt(
+                                prompt_msgs = await ag.create_prompt(
                                     prompt_name=prompt_name,
                                     arguments=arguments,
-                                    server_names=server_list or [],
+                                    server_names=resolved_server_list or [],
                                 )
src/mcp_agent/cli/main.py (1)

189-197: Don't swallow typer.Exit; preserve expected exit codes (e.g., --version).

Catching Exception here also catches typer.Exit, turning normal exits into failures. Handle typer.Exit separately and re-raise.

 def run() -> None:
     """Run the CLI application."""
     try:
-        app()
-    except Exception as e:
+        app()
+    except typer.Exit:
+        # Allow intended exits (e.g., --version) to propagate
+        raise
+    except Exception as e:
         # Unexpected errors - log full exception and show clean error to user
         logging.exception("Unhandled exception in CLI")
         print_error(f"An unexpected error occurred: {str(e)}")
         raise typer.Exit(1) from e
🧹 Nitpick comments (10)
src/mcp_agent/cli/commands/init.py (1)

103-103: Keep Python 3.9 compatibility: avoid str | None.

| unions require Python 3.10+. If you haven’t raised the floor, use Optional[str].

Apply:

-    entry_script_name: str | None = None
+    entry_script_name: Optional[str] = None

And add the import:

 from __future__ import annotations
+from typing import Optional
src/mcp_agent/cli/commands/doctor.py (1)

410-416: Update quick-start to also show 'serve' and 'uv run' paths

Great swap to dev start. Consider listing HTTP serve and uv run to mirror PR guidance.

             "• Start chat: [cyan]mcp-agent chat --model anthropic.haiku[/cyan]\n"
-            "• Run agent: [cyan]mcp-agent dev start --script main.py[/cyan]",
+            "• Run agent: [cyan]mcp-agent dev start --script main.py[/cyan]\n"
+            "• Serve over HTTP: [cyan]mcp-agent dev serve --script main.py --transport http --port 8000[/cyan]\n"
+            "• Run directly: [cyan]uv run main.py[/cyan]",
src/mcp_agent/cli/commands/serve.py (1)

121-124: Docstring example still references agent.py

Prefer main.py to keep examples consistent.

-        mcp-agent serve --script agent.py
+        mcp-agent serve --script main.py
src/mcp_agent/cli/commands/dev.py (1)

53-55: Add explicit missing-script check for friendlier DX

Currently Python errors out if main.py/agent.py is absent. Mirror serve.py’s helpful message.

-    # Resolve script path with auto-detection (main.py preferred)
-    script = detect_default_script(script)
+    # Resolve script path with auto-detection (main.py preferred)
+    script = detect_default_script(script)
+    if not script.exists():
+        console.print(f"[red]Script not found: {script}[/red]")
+        console.print("\n[dim]Create a main.py (preferred) or agent.py file, or specify --script[/dim]")
+        raise typer.Exit(1)
src/mcp_agent/cli/commands/invoke.py (2)

56-63: Handle missing script early to avoid raw tracebacks

Align with serve/test for consistent UX.

-        script_path = detect_default_script(Path(script) if script else None)
-        app_obj = load_user_app(script_path)
+        script_path = detect_default_script(Path(script) if script else None)
+        if not script_path.exists():
+            typer.secho(f"Script not found: {script_path}", err=True, fg=typer.colors.RED)
+            typer.secho("Create main.py (preferred) or agent.py, or pass --script", err=True, fg=typer.colors.YELLOW)
+            raise typer.Exit(1)
+        app_obj = load_user_app(script_path)

32-33: Avoid shadowing built-in 'vars'

Rename local to vars_json (CLI flag remains --vars).

-    vars: Optional[str] = typer.Option(None, "--vars", help="JSON structured inputs"),
+    vars_json: Optional[str] = typer.Option(None, "--vars", help="JSON structured inputs"),
@@
-        payload = json.loads(vars) if vars else {}
+        payload = json.loads(vars_json) if vars_json else {}

Also applies to: 50-53

src/mcp_agent/cli/core/utils.py (1)

121-133: Deduplicate server names and preserve order

Merging inputs can introduce duplicates. Return stable-ordered unique names.

-    if names:
-        return names
+    if names:
+        # Stable dedupe
+        return list(dict.fromkeys(names))
@@
-    if settings.mcp and settings.mcp.servers:
-        return list(settings.mcp.servers.keys())
+    if settings.mcp and settings.mcp.servers:
+        return list(settings.mcp.servers.keys())
src/mcp_agent/cli/commands/go.py (2)

275-277: Add missing-script guard after auto-detect

Prevents unhandled FileNotFoundError from load_user_app and matches serve/chat UX.

-    # Resolve script with auto-detection
-    script = detect_default_script(script)
+    # Resolve script with auto-detection
+    script = detect_default_script(script)
+    if not script.exists():
+        typer.secho(f"Script not found: {script}", err=True, fg=typer.colors.RED)
+        typer.secho("Create main.py (preferred) or agent.py, or pass --script", err=True, fg=typer.colors.YELLOW)
+        raise typer.Exit(1)

311-314: Optional: ensure unique server list

If both URL and stdio add same name, duplicates can leak through.

 resolved_server_list = select_servers_from_config(
     ",".join(server_list) if server_list else None, url_servers, stdio_servers
 )
+# Stable dedupe
+resolved_server_list = list(dict.fromkeys(resolved_server_list))
src/mcp_agent/cli/commands/chat.py (1)

112-114: Add missing-script check after auto-detect

Mirror serve/test to avoid raw errors when no script is present.

 # Resolve script with auto-detection
 script = detect_default_script(script)
+if not script.exists():
+    typer.secho(f"Script not found: {script}", err=True, fg=typer.colors.RED)
+    typer.secho("Create main.py (preferred) or agent.py, or pass --script", err=True, fg=typer.colors.YELLOW)
+    raise typer.Exit(1)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4502f71 and f553b98.

📒 Files selected for processing (10)
  • src/mcp_agent/cli/__main__.py (1 hunks)
  • src/mcp_agent/cli/commands/chat.py (15 hunks)
  • src/mcp_agent/cli/commands/dev.py (2 hunks)
  • src/mcp_agent/cli/commands/doctor.py (1 hunks)
  • src/mcp_agent/cli/commands/go.py (5 hunks)
  • src/mcp_agent/cli/commands/init.py (3 hunks)
  • src/mcp_agent/cli/commands/invoke.py (2 hunks)
  • src/mcp_agent/cli/commands/serve.py (3 hunks)
  • src/mcp_agent/cli/core/utils.py (2 hunks)
  • src/mcp_agent/cli/main.py (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
src/mcp_agent/cli/commands/dev.py (1)
src/mcp_agent/cli/core/utils.py (1)
  • detect_default_script (84-103)
src/mcp_agent/cli/commands/init.py (1)
src/mcp_agent/cli/commands/config.py (1)
  • _load_template (35-48)
src/mcp_agent/cli/core/utils.py (1)
src/mcp_agent/config.py (3)
  • MCPServerSettings (52-113)
  • MCPSettings (116-124)
  • get_settings (727-826)
src/mcp_agent/cli/commands/invoke.py (1)
src/mcp_agent/cli/core/utils.py (3)
  • load_user_app (30-72)
  • detect_default_script (84-103)
  • select_servers_from_config (106-132)
src/mcp_agent/cli/commands/serve.py (1)
src/mcp_agent/cli/core/utils.py (1)
  • detect_default_script (84-103)
src/mcp_agent/cli/__main__.py (1)
src/mcp_agent/cli/main.py (1)
  • main (104-143)
src/mcp_agent/cli/commands/go.py (1)
src/mcp_agent/cli/core/utils.py (2)
  • detect_default_script (84-103)
  • select_servers_from_config (106-132)
src/mcp_agent/cli/main.py (3)
src/mcp_agent/cli/cloud/commands/auth/login/main.py (1)
  • login (57-103)
src/mcp_agent/cli/utils/typer_utils.py (1)
  • HelpfulTyperGroup (13-40)
src/mcp_agent/cli/commands/dev.py (1)
  • dev (26-136)
🔇 Additional comments (13)
src/mcp_agent/cli/commands/init.py (3)

227-228: LGTM: updated example uses uv run.


231-231: LGTM: factory example switched to uv run.


208-221: Add Python fallback to printed run instructions

Add a python fallback for users who may not have the 'uv' CLI.

File: src/mcp_agent/cli/commands/init.py (lines 208-221)

-            console.print(f"3. Run your agent: [cyan]uv run {run_file}[/cyan]")
+            console.print(f"3. Run your agent: [cyan]uv run {run_file}[/cyan]")
+            console.print(f"   (fallback) [cyan]python {run_file}[/cyan]")
src/mcp_agent/cli/commands/serve.py (2)

141-149: Good: default script auto-detection with clear guidance

Using detect_default_script and the improved error hint aligns UX across commands. LGTM.


384-391: Test command parity with serve: nice

Auto-detect + friendly missing-script message is consistent. LGTM.

src/mcp_agent/cli/commands/dev.py (1)

26-26: CLI default change to None is correct

Shifts responsibility to detect_default_script. Good.

src/mcp_agent/cli/core/utils.py (1)

84-104: Solid default script selection

Order and fallback are sensible and used consistently across commands. LGTM.

src/mcp_agent/cli/__main__.py (1)

46-57: Back-compat routing is clear and minimal

Nice injection strategy for go and chat-like options without impacting curated commands.

src/mcp_agent/cli/commands/chat.py (1)

148-152: Centralized server resolution is correct

Resolved list respects explicit > dynamic > config precedence. LGTM.

src/mcp_agent/cli/main.py (4)

146-151: Top-level curated surface looks good; doctor addition is clear.

The curated top-level keeps init/quickstart/config and adds doctor. Good separation between curated and dev/runtime.


152-173: Dev umbrella structure is coherent.

Subcommand set under dev (start, chat, invoke, serve, server, build, logs, check, go, keys, models, client) aligns with the PR’s goals. Nice consolidation.


174-175: Mounting the dev umbrella at top-level is appropriate.

This gives a clear entry for local workflows without polluting the top-level.


28-28: Exports present — verify Typer-compatible signatures for deploy_config and login.

  • Exports found: src/mcp_agent/cli/cloud/commands/init.py (includes deploy_config, login) and src/mcp_agent/cli/cloud/commands/deploy/init.py (all = ["deploy_config"]).
  • Definitions: src/mcp_agent/cli/cloud/commands/deploy/main.py -> def deploy_config(...); src/mcp_agent/cli/cloud/commands/auth/login/main.py -> def login(...).
  • Action: Confirm each function’s signature is Typer-compatible (typed parameters and defaults or use of typer.Option/Argument) so they can be used as CLI commands at runtime.

Comment on lines +126 to 156
# Determine entry script name and handle existing files
script_name = "main.py"
script_path = dir / script_name
agent_content = _load_template("basic_agent.py")
if agent_content and _write(agent_path, agent_content, force):
files_created.append("agent.py")
# Make executable
try:
agent_path.chmod(agent_path.stat().st_mode | 0o111)
except Exception:
pass

if agent_content:
write_force_flag = force
if script_path.exists() and not force:
if Confirm.ask(f"{script_path} exists. Overwrite?", default=False):
write_force_flag = True
else:
# Ask for an alternate filename and ensure it ends with .py
alt_name = Prompt.ask(
"Enter a filename to save the agent", default="agent.py"
)
if not alt_name.endswith(".py"):
alt_name += ".py"
script_name = alt_name
script_path = dir / script_name
# keep write_force_flag as-is to allow overwrite prompt if needed

if _write(script_path, agent_content, write_force_flag):
files_created.append(script_name)
entry_script_name = script_name
# Make executable
try:
script_path.chmod(script_path.stat().st_mode | 0o111)
except Exception:
pass

elif template == "server":
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Harden alt filename handling to prevent path escapes.

A user can enter an absolute path (e.g., “/tmp/x.py”) or include “../”, which would write outside the target dir. Constrain to a basename and ensure the resolved path remains within dir.

-                    alt_name = Prompt.ask(
-                        "Enter a filename to save the agent", default="agent.py"
-                    )
-                    if not alt_name.endswith(".py"):
-                        alt_name += ".py"
-                    script_name = alt_name
-                    script_path = dir / script_name
+                    alt_name = Prompt.ask(
+                        "Enter a filename to save the agent", default="agent.py"
+                    )
+                    if not alt_name.endswith(".py"):
+                        alt_name += ".py"
+                    base_dir = dir.resolve()
+                    # Keep only basename and ensure path stays within target dir
+                    script_name = Path(alt_name).name
+                    candidate_path = (base_dir / script_name).resolve()
+                    try:
+                        candidate_path.relative_to(base_dir)
+                    except ValueError:
+                        console.print("[red]Filename must be within the target directory[/red]")
+                        raise typer.Exit(1)
+                    script_path = candidate_path
+                    if script_path.exists() and script_path.is_dir():
+                        console.print(f"[red]{script_path} is a directory; choose a .py filename[/red]")
+                        raise typer.Exit(1)
📝 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.

Suggested change
# Determine entry script name and handle existing files
script_name = "main.py"
script_path = dir / script_name
agent_content = _load_template("basic_agent.py")
if agent_content and _write(agent_path, agent_content, force):
files_created.append("agent.py")
# Make executable
try:
agent_path.chmod(agent_path.stat().st_mode | 0o111)
except Exception:
pass
if agent_content:
write_force_flag = force
if script_path.exists() and not force:
if Confirm.ask(f"{script_path} exists. Overwrite?", default=False):
write_force_flag = True
else:
# Ask for an alternate filename and ensure it ends with .py
alt_name = Prompt.ask(
"Enter a filename to save the agent", default="agent.py"
)
if not alt_name.endswith(".py"):
alt_name += ".py"
script_name = alt_name
script_path = dir / script_name
# keep write_force_flag as-is to allow overwrite prompt if needed
if _write(script_path, agent_content, write_force_flag):
files_created.append(script_name)
entry_script_name = script_name
# Make executable
try:
script_path.chmod(script_path.stat().st_mode | 0o111)
except Exception:
pass
elif template == "server":
# Determine entry script name and handle existing files
script_name = "main.py"
script_path = dir / script_name
agent_content = _load_template("basic_agent.py")
if agent_content:
write_force_flag = force
if script_path.exists() and not force:
if Confirm.ask(f"{script_path} exists. Overwrite?", default=False):
write_force_flag = True
else:
# Ask for an alternate filename and ensure it ends with .py
alt_name = Prompt.ask(
"Enter a filename to save the agent", default="agent.py"
)
if not alt_name.endswith(".py"):
alt_name += ".py"
base_dir = dir.resolve()
# Keep only basename and ensure path stays within target dir
script_name = Path(alt_name).name
candidate_path = (base_dir / script_name).resolve()
try:
candidate_path.relative_to(base_dir)
except ValueError:
console.print("[red]Filename must be within the target directory[/red]")
raise typer.Exit(1)
script_path = candidate_path
if script_path.exists() and script_path.is_dir():
console.print(f"[red]{script_path} is a directory; choose a .py filename[/red]")
raise typer.Exit(1)
# keep write_force_flag as-is to allow overwrite prompt if needed
if _write(script_path, agent_content, write_force_flag):
files_created.append(script_name)
entry_script_name = script_name
# Make executable
try:
script_path.chmod(script_path.stat().st_mode | 0o111)
except Exception:
pass
elif template == "server":
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 126-156, the alternate
filename from Prompt.ask may contain absolute paths or path traversal (e.g.,
“/tmp/x.py” or “../escape.py”); sanitize this by taking only the basename (e.g.,
Path(alt_name).name), ensure it ends with “.py”, recompute script_path as dir /
sanitized_name, then verify the resolved script_path remains inside dir (e.g.,
compare dir.resolve() as a parent of script_path.resolve(), or fall back to a
safe default filename if the check fails); keep the existing write_force_flag
behavior and subsequent permission/chmod steps.

Comment on lines 222 to 225
console.print("3. Run the server: [cyan]uv run server.py[/cyan]")
console.print(
" Or serve: [cyan]mcp-agent serve --script server.py[/cyan]"
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Command mismatch with CLI reorg: use mcp-agent dev serve.

Runtime commands moved under dev. This line still suggests the old top-level serve.

-            console.print(
-                "   Or serve: [cyan]mcp-agent serve --script server.py[/cyan]"
-            )
+            console.print(
+                "   Or serve: [cyan]mcp-agent dev serve --script server.py[/cyan]"
+            )

Search for other stale references:


🏁 Script executed:

#!/bin/bash
rg -nP -C1 '\bmcp-agent\s+serve\b'

Length of output: 1811


Replace remaining mcp-agent serve usages with mcp-agent dev serve

Runtime commands were moved under the dev group — update CLI help/messages and docs.

  • src/mcp_agent/cli/commands/init.py (lines ~223-225): change the printed hint to mcp-agent dev serve.
-            console.print(
-                "   Or serve: [cyan]mcp-agent serve --script server.py[/cyan]"
-            )
+            console.print(
+                "   Or serve: [cyan]mcp-agent dev serve --script server.py[/cyan]"
+            )
  • src/mcp_agent/cli/commands/serve.py (examples & output: ~lines 121-123, 471-472, 533-539): update all example and status strings to use mcp-agent dev serve (and mcp-agent dev serve test where applicable).
  • docs/cloud/agent-server.mdx (lines ~140, 145): update uv run mcp-agent serve --app ... to uv run mcp-agent dev serve --app ....
📝 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.

Suggested change
console.print("3. Run the server: [cyan]uv run server.py[/cyan]")
console.print(
" Or serve: [cyan]mcp-agent serve --script server.py[/cyan]"
)
console.print("3. Run the server: [cyan]uv run server.py[/cyan]")
console.print(
" Or serve: [cyan]mcp-agent dev serve --script server.py[/cyan]"
)
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/init.py around lines 222 to 225, update the
printed CLI hint that currently suggests "mcp-agent serve" to the new runtime
command "mcp-agent dev serve"; replace both occurrences so the messages read "3.
Run the server: uv run server.py" and "Or serve: mcp-agent dev serve --script
server.py" (i.e., change the `mcp-agent serve` text to `mcp-agent dev serve`).

Comment on lines +77 to +87
@dev_group.callback(invoke_without_command=True)
def _dev_group_entry(
ctx: typer.Context,
script: Path = typer.Option(None, "--script", help="Entry script"),
):
"""If no subcommand is provided, behave like 'dev start'."""
if ctx.invoked_subcommand:
return
# Delegate to the existing dev implementation
dev_cmd.dev(script=script)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Make --script optional and avoid it being silently ignored with subcommands.

Two fixes:

  1. Type correctness: default None with type Path should be Optional[Path].
  2. UX: mcp-agent dev --script app.py start currently ignores the group-level --script. Warn users when a subcommand is present so intent isn’t lost.
 @dev_group.callback(invoke_without_command=True)
 def _dev_group_entry(
     ctx: typer.Context,
-    script: Path = typer.Option(None, "--script", help="Entry script"),
+    script: Optional[Path] = typer.Option(None, "--script", help="Entry script"),
 ):
     """If no subcommand is provided, behave like 'dev start'."""
-    if ctx.invoked_subcommand:
-        return
+    if ctx.invoked_subcommand:
+        if script is not None:
+            # Inform user that group-level --script is ignored for subcommands
+            err_console.print(
+                "[yellow]Note: --script passed to 'dev' is ignored when using a subcommand. "
+                "Pass --script after the subcommand instead (e.g., 'mcp-agent dev start --script app.py').[/yellow]"
+            )
+        return
     # Delegate to the existing dev implementation
     dev_cmd.dev(script=script)

Also add the missing import (outside this hunk):

from typing import Optional

Verification:

  • mcp-agent dev --script app.py → runs dev start with app.py.
  • mcp-agent dev --script app.py start → shows the warning; start proceeds with its own option parsing.

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Search for @dev_group.callback occurrences"
rg -n --hidden -S "@dev_group.callback" || true
echo

echo "2) Print src/mcp_agent/cli/main.py (first 240 lines) if it exists"
if [ -f "src/mcp_agent/cli/main.py" ]; then
  sed -n '1,240p' src/mcp_agent/cli/main.py || true
else
  echo "src/mcp_agent/cli/main.py not found"
fi
echo

echo "3) Search for def _dev_group_entry"
rg -n --hidden -S "def _dev_group_entry" || true
echo

echo "4) Search for dev_cmd references"
rg -n --hidden -S "dev_cmd" || true
echo

echo "5) Search for a 'dev' function definition"
rg -n --hidden -S "def dev\(" || true
echo

echo "6) Look for dev subcommands (decorators or defs named start)"
rg -n --hidden -S "@dev_group.command|def start\(" || true
echo

echo "7) Search for err_console / console.print / typer.secho usage"
rg -n --hidden -S "err_console|console\.print|typer\.secho|typer\.echo" || true
echo

echo "8) Search for typing imports or Optional usage"
rg -n --hidden -S "from typing import|Optional" || true

Length of output: 206664


Make --script optional and warn when a subcommand is present.

Verified: dev_cmd.dev also declares its own --script (src/mcp_agent/cli/commands/dev.py:26), so a group-level --script passed before a subcommand will be silently ignored — fix both typing and UX.

File: src/mcp_agent/cli/main.py (callback around lines 77–87)

 @dev_group.callback(invoke_without_command=True)
 def _dev_group_entry(
     ctx: typer.Context,
-    script: Path = typer.Option(None, "--script", help="Entry script"),
+    script: Optional[Path] = typer.Option(None, "--script", help="Entry script"),
 ):
     """If no subcommand is provided, behave like 'dev start'."""
-    if ctx.invoked_subcommand:
-        return
+    if ctx.invoked_subcommand:
+        if script is not None:
+            # Inform user that group-level --script is ignored for subcommands
+            err_console.print(
+                "[yellow]Note: --script passed to 'dev' is ignored when using a subcommand. "
+                "Pass --script after the subcommand instead (e.g., 'mcp-agent dev start --script app.py').[/yellow]"
+            )
+        return
     # Delegate to the existing dev implementation
     dev_cmd.dev(script=script)

Also add (near other typing imports):

from typing import Optional
🤖 Prompt for AI Agents
In src/mcp_agent/cli/main.py around lines 77–87, the group callback's script
parameter should be Optional[Path] and you must warn if a group-level --script
is provided but a subcommand is invoked (since subcommands have their own
--script). Add "from typing import Optional" near the other typing imports,
change the callback signature to use Optional[Path] for script, and inside the
ctx.invoked_subcommand branch, if script is not None emit a warning (e.g.,
typer.secho or typer.echo with a clear message) that the group-level --script
will be ignored, then return without delegating to dev_cmd.dev; keep the current
behavior of delegating to dev_cmd.dev only when no subcommand is invoked.

Copy link

@coderabbitai coderabbitai bot left a 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

♻️ Duplicate comments (1)
src/mcp_agent/cli/main.py (1)

77-86: Make script Optional and warn when group-level --script is ignored with subcommands.

Prevents silent confusion when users pass --script before a subcommand (previously flagged in review).

-@dev_group.callback(invoke_without_command=True)
-def _dev_group_entry(
-    ctx: typer.Context,
-    script: Path = typer.Option(None, "--script", help="Entry script"),
-):
+from typing import Optional
+
+@dev_group.callback(invoke_without_command=True)
+def _dev_group_entry(
+    ctx: typer.Context,
+    script: Optional[Path] = typer.Option(None, "--script", help="Entry script"),
+):
     """If no subcommand is provided, behave like 'dev start'."""
-    if ctx.invoked_subcommand:
-        return
+    if ctx.invoked_subcommand:
+        if script is not None:
+            err_console.print(
+                "[yellow]Note: --script passed to 'dev' is ignored when using a subcommand. "
+                "Pass --script after the subcommand instead (e.g., 'mcp-agent dev start --script app.py').[/yellow]"
+            )
+        return
     # Delegate to the existing dev implementation
     dev_cmd.dev(script=script)
🧹 Nitpick comments (5)
src/mcp_agent/cli/commands/keys.py (1)

47-49: Good endpoint switch; also handle rate limiting and tighten result messaging.

/v1/models is the right lightweight probe. Recommend treating HTTP 429 as “inconclusive/rate limited” instead of “Unexpected response”, so users aren’t told their key is invalid during transient throttling.

-            if response.status_code in [200, 401, 403]:
+            if response.status_code in [200, 401, 403, 429]:
                 if response.status_code == 200:
                     return True, "Key is valid"
-                else:
+                elif response.status_code in (401, 403):
                     return False, f"Invalid key (HTTP {response.status_code})"
+                else:  # 429
+                    return False, "Rate limited (HTTP 429) — try again shortly"
             else:
                 return False, f"Unexpected response (HTTP {response.status_code})"
src/mcp_agent/cli/commands/serve.py (1)

141-149: Nice: auto-detects main.py (preferred) with a clear missing-script hint.

Minor UX polish: when TLS is configured, print https:// in the Info panel and startup logs.

-            address = f"{host}:{port or 8000}"
-            info_table.add_row("Address", f"http://{address}")
+            address = f"{host}:{port or 8000}"
+            scheme = "https" if (ssl_certfile and ssl_keyfile) else "http"
+            info_table.add_row("Address", f"{scheme}://{address}")
             if transport == "sse":
-                info_table.add_row("SSE Endpoint", f"http://{address}/sse")
+                info_table.add_row("SSE Endpoint", f"{scheme}://{address}/sse")
             elif transport == "http":
-                info_table.add_row("HTTP Endpoint", f"http://{address}/mcp")
+                info_table.add_row("HTTP Endpoint", f"{scheme}://{address}/mcp")
-                console.print(f"[bold]URL:[/bold] http://{host}:{port or 8000}")
+                scheme = "https" if (ssl_certfile and ssl_keyfile) else "http"
+                console.print(f"[bold]URL:[/bold] {scheme}://{host}:{port or 8000}")
                 if transport == "sse":
-                    console.print(f"[bold]SSE:[/bold] http://{host}:{port or 8000}/sse")
+                    console.print(f"[bold]SSE:[/bold] {scheme}://{host}:{port or 8000}/sse")
                 elif transport == "http":
-                    console.print(f"[bold]HTTP:[/bold] http://{host}:{port or 8000}/mcp")
+                    console.print(f"[bold]HTTP:[/bold] {scheme}://{host}:{port or 8000}/mcp")
src/mcp_agent/cli/commands/chat.py (2)

113-115: Early script auto-detection is solid; consider friendlier error if missing.

Mirror serve.py’s message when neither main.py nor agent.py exists to reduce confusion before load_user_app raises.

 script = detect_default_script(script)
+if not script.exists():
+    typer.secho(
+        f"Script not found: {script}\nCreate a main.py (preferred) or agent.py, or pass --script.",
+        err=True,
+        fg=typer.colors.RED,
+    )
+    raise typer.Exit(1)

149-153: De-duplicate server names from multiple sources.

select_servers_from_config may return duplicates when URL and stdio names overlap. Prefer stable-order de-dupe in the utility.

Outside this file (src/mcp_agent/cli/core/utils.py):

 def select_servers_from_config(
@@
-    if url_servers:
-        names.extend(list(url_servers.keys()))
-    if stdio_servers:
-        names.extend(list(stdio_servers.keys()))
-    if names:
-        return names
+    if url_servers:
+        names.extend(list(url_servers.keys()))
+    if stdio_servers:
+        names.extend(list(stdio_servers.keys()))
+    if names:
+        # stable-order de-dupe
+        names = list(dict.fromkeys(names))
+        return names
src/mcp_agent/cli/main.py (1)

69-74: Minor help text nit: s/servers/server.

Subcommand mounted is “server”, not “servers”.

-dev_group = typer.Typer(
-    help="Local development: start app, chat, invoke, serve, servers, build, logs",
+dev_group = typer.Typer(
+    help="Local development: start app, chat, invoke, serve, server, build, logs",
     no_args_is_help=False,
     cls=HelpfulTyperGroup,
 )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f553b98 and e5623ef.

📒 Files selected for processing (6)
  • src/mcp_agent/cli/commands/chat.py (15 hunks)
  • src/mcp_agent/cli/commands/init.py (3 hunks)
  • src/mcp_agent/cli/commands/keys.py (1 hunks)
  • src/mcp_agent/cli/commands/serve.py (6 hunks)
  • src/mcp_agent/cli/core/utils.py (5 hunks)
  • src/mcp_agent/cli/main.py (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/mcp_agent/cli/commands/init.py
  • src/mcp_agent/cli/core/utils.py
🧰 Additional context used
🧬 Code graph analysis (3)
src/mcp_agent/cli/commands/chat.py (2)
src/mcp_agent/cli/core/utils.py (3)
  • detect_default_script (94-113)
  • select_servers_from_config (116-142)
  • load_user_app (30-82)
src/mcp_agent/config.py (1)
  • get_settings (727-826)
src/mcp_agent/cli/commands/serve.py (1)
src/mcp_agent/cli/core/utils.py (2)
  • load_user_app (30-82)
  • detect_default_script (94-113)
src/mcp_agent/cli/main.py (2)
src/mcp_agent/cli/utils/typer_utils.py (1)
  • HelpfulTyperGroup (13-40)
src/mcp_agent/cli/commands/dev.py (1)
  • dev (26-136)
🔇 Additional comments (12)
src/mcp_agent/cli/commands/serve.py (4)

22-23: Import of detect_default_script is appropriate and aligns with new defaults.


121-124: Docs/examples updated to mcp-agent dev serve — looks good.


384-391: Test path uses detect_default_script consistently — good.


534-541: “Next steps” messaging aligns with new dev namespace.

src/mcp_agent/cli/commands/chat.py (7)

15-21: Centralized imports (detect_default_script, select_servers_from_config, get_settings) — good cohesion.

Also applies to: 26-26


105-106: Optional script + Path typing is correct for auto-detection use.


159-164: Disabling progress + passing settings_override yields cleaner output.


248-253: Using resolved_server_list for fan-out is correct.


299-301: Interactive /tools and /resources respect resolved servers — good.

Also applies to: 319-321


393-395: One-shot paths correctly pass resolved servers.

Also applies to: 731-733


419-424: REPL paths: consistent resolved server usage and cleaner UX.

Also applies to: 445-449, 503-509, 531-535, 552-556

src/mcp_agent/cli/main.py (1)

146-176: CLI rewire under dev + top-level doctor/config/init/quickstart — solid.

Comment on lines +149 to +153
# Smart defaults for servers
resolved_server_list = select_servers_from_config(
servers_csv, url_servers, stdio_servers
)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Smart server defaults wired — good. One functional inconsistency remains.

/prompt still uses server_list instead of resolved_server_list, so dynamic/configured servers are ignored there.

-                                prompt_msgs = await ag.create_prompt(
+                                prompt_msgs = await ag.create_prompt(
                                     prompt_name=prompt_name,
                                     arguments=arguments,
-                                    server_names=server_list or [],
+                                    server_names=resolved_server_list or [],
                                 )
📝 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.

Suggested change
# Smart defaults for servers
resolved_server_list = select_servers_from_config(
servers_csv, url_servers, stdio_servers
)
# Smart defaults for servers
resolved_server_list = select_servers_from_config(
servers_csv, url_servers, stdio_servers
)
prompt_msgs = await ag.create_prompt(
prompt_name=prompt_name,
arguments=arguments,
server_names=resolved_server_list or [],
)
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/chat.py around lines 149-153, the code computes
resolved_server_list but the /prompt handler still references server_list,
causing dynamic/configured servers to be ignored; update the /prompt command
handler to use resolved_server_list everywhere server_list is currently used
(pass resolved_server_list into any function calls, closures or command
construction), and add a safe fallback to resolved_server_list if server_list
may be None so the dynamic/configured server selection is honored.

💡 Verification agent

🧩 Analysis chain

Quick sweep for any other legacy server_list usages.

Run this to ensure no other call paths still rely on server_list for server_names.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -nP --type=py -C2 '\bserver_names\s*=\s*server_list\b' || true
rg -nP --type=py -C2 '\bserver_names\s*=\s*server_list\s*\|\|\s*\[\]' || true
rg -nP --type=py -C2 'create_prompt\([^)]*server_names\s*=' || true

Length of output: 1248


Replace remaining legacy server_list usages with resolved_server_list.

rg found three call sites still passing server_list; update them to pass the resolved list (or call select_servers_from_config in that scope) and preserve or [] defaults where appropriate.

  • src/mcp_agent/cli/commands/invoke.py:65 — server_names=server_list
  • src/mcp_agent/cli/commands/go.py:113 — server_names=server_list or []
  • src/mcp_agent/cli/commands/chat.py:591 — server_names=server_list or []
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/chat.py around lines 149-153, you've already
assigned resolved_server_list from select_servers_from_config; replace the
remaining legacy server_list usages in the codebase to use that resolved list:
update src/mcp_agent/cli/commands/invoke.py at ~line 65 to pass
server_names=resolved_server_list (or call select_servers_from_config there to
obtain it), update src/mcp_agent/cli/commands/go.py at ~line 113 to pass
server_names=resolved_server_list or [], and update
src/mcp_agent/cli/commands/chat.py at ~line 591 to pass
server_names=resolved_server_list or []; preserve the existing "or []" defaults
where present.

Copy link
Collaborator

@StreetLamb StreetLamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/mcp_agent/cli/commands/chat.py (3)

105-105: Add a short alias for --script for ergonomics.

Apply:

-    script: Optional[Path] = typer.Option(None, "--script"),
+    script: Optional[Path] = typer.Option(None, "--script", "-s"),

113-115: Fail fast with helpful guidance when no script is found.

Currently a missing main.py/agent.py raises FileNotFoundError from load_user_app later; provide a clearer CLI message here.

Apply:

     # Resolve script with auto-detection
     script = detect_default_script(script)
+
+    # Fail fast with clear guidance
+    if not script.exists():
+        typer.secho(
+            f"Script not found: {script}. Run `mcp-agent init` to create main.py, "
+            "or pass --script <file>.",
+            err=True,
+            fg=typer.colors.RED,
+        )
+        raise typer.Exit(2)

116-147: Remove vestigial server_list accumulation.

server_list is built/extended here but no longer used after introducing select_servers_from_config; drop it to avoid confusion.

Apply:

-    server_list = servers_csv.split(",") if servers_csv else None
@@
-            url_servers = generate_server_configs(parsed)
-            if url_servers and not server_list:
-                server_list = list(url_servers.keys())
-            elif url_servers and server_list:
-                server_list.extend(list(url_servers.keys()))
+            url_servers = generate_server_configs(parsed)
@@
-        if stdio_servers:
-            if not server_list:
-                server_list = list(stdio_servers.keys())
-            else:
-                server_list.extend(list(stdio_servers.keys()))
+        # stdio_servers resolved; selection happens via select_servers_from_config
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5623ef and d983c65.

📒 Files selected for processing (1)
  • src/mcp_agent/cli/commands/chat.py (16 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/mcp_agent/cli/commands/chat.py (2)
src/mcp_agent/cli/core/utils.py (3)
  • detect_default_script (94-113)
  • select_servers_from_config (116-142)
  • load_user_app (30-82)
src/mcp_agent/config.py (1)
  • get_settings (727-826)
🔇 Additional comments (16)
src/mcp_agent/cli/commands/chat.py (16)

19-21: Centralized script/server utilities import — good alignment with the PR spec.

Brings detect_default_script and select_servers_from_config into chat, ensuring consistent defaults across commands.


25-25: Settings injection for cleaner UX — good.

Importing get_settings enables disabling progress display in REPL/listing paths.


149-153: Smart server defaults wired correctly.

select_servers_from_config honors --servers, then dynamic URL/stdio, then config — matches the PR policy.


159-164: Nice: progress display disabled in listing mode via settings override.


221-225: Consistent UX: progress off for multi-model REPL.


249-253: LLM creation uses resolved servers — good.


298-301: /tools (parallel REPL) now prefers resolved servers — good.


318-321: /resources (parallel REPL) now prefers resolved servers — good.


392-395: One-shot multi-model path passes resolved servers — good.


420-425: REPL: settings override + progress off + load_user_app — good pattern.


445-449: Single-model REPL wired to resolved servers — good.


503-509: /model hot-swap preserves resolved server selection — good.


529-535: /tools now uses resolved servers when no explicit server — good.


549-556: /resources now uses resolved servers when no explicit server — good.


586-592: Past inconsistency fixed: /prompt now uses resolved_server_list.

This addresses the previous review’s concern about ignoring dynamic/configured servers in /prompt.


729-733: One-shot single-model path passes resolved servers — good.

Comment on lines +181 to 183
server_names=resolved_server_list or target_servers,
context=app_obj.context,
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Honor --server filter in Agent.server_names.

If resolved_server_list is non-empty, it currently overrides a provided --server. Prefer the explicit filter.

Apply:

-                        server_names=resolved_server_list or target_servers,
+                        server_names=([server] if server else (resolved_server_list or target_servers)),
📝 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.

Suggested change
server_names=resolved_server_list or target_servers,
context=app_obj.context,
)
server_names=([server] if server else (resolved_server_list or target_servers)),
context=app_obj.context,
)
🤖 Prompt for AI Agents
In src/mcp_agent/cli/commands/chat.py around lines 181-183, the server_names
assignment currently uses "resolved_server_list or target_servers", which lets
the resolved list override an explicit --server filter; change the logic so the
explicit target_servers (the --server filter) takes precedence by using
"target_servers or resolved_server_list" (or equivalent truthy check), ensuring
that when a --server value is provided it is honoured, falling back to
resolved_server_list only when target_servers is empty/None.

@saqadri saqadri merged commit 83cd876 into main Sep 13, 2025
8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Sep 17, 2025
@coderabbitai coderabbitai bot mentioned this pull request Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants