Skip to content

Commit 83cd876

Browse files
authored
Refactor CLI: dev umbrella, default main.py, smart server defaults, clearer init (#469)
1 parent 4502f71 commit 83cd876

File tree

11 files changed

+263
-94
lines changed

11 files changed

+263
-94
lines changed

src/mcp_agent/cli/__main__.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,35 +25,35 @@
2525
}
2626

2727
KNOWN = {
28-
"go",
29-
"check",
30-
"chat",
31-
"dev",
32-
"invoke",
33-
"serve",
28+
# Curated top-level commands
3429
"init",
3530
"quickstart",
3631
"config",
37-
"keys",
38-
"models",
39-
"server",
40-
"build",
41-
"logs",
4232
"doctor",
43-
"configure",
33+
"deploy",
34+
"login",
35+
"whoami",
36+
"logout",
4437
"cloud",
38+
# Umbrella group
39+
"dev",
4540
}
4641

4742

4843
def main():
4944
if len(sys.argv) > 1:
5045
first = sys.argv[1]
51-
if first not in KNOWN:
46+
# Back-compat: allow `mcp-agent go ...`
47+
if first == "go":
48+
sys.argv.insert(1, "dev")
49+
elif first not in KNOWN:
5250
for i, arg in enumerate(sys.argv[1:], 1):
5351
if arg in GO_OPTIONS or any(
5452
arg.startswith(opt + "=") for opt in GO_OPTIONS
5553
):
56-
sys.argv.insert(i, "go")
54+
# Route bare chat-like invocations to dev go (legacy behavior)
55+
sys.argv.insert(i, "dev")
56+
sys.argv.insert(i + 1, "go")
5757
break
5858
app()
5959

src/mcp_agent/cli/commands/chat.py

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
attach_stdio_servers,
1717
attach_url_servers,
1818
load_user_app,
19+
detect_default_script,
20+
select_servers_from_config,
1921
)
2022
from mcp_agent.cli.utils.url_parser import generate_server_configs, parse_server_urls
2123
from mcp_agent.workflows.factory import create_llm
2224
from mcp_agent.agents.agent import Agent
25+
from mcp_agent.config import get_settings
2326

2427

2528
app = typer.Typer(help="Ephemeral REPL for quick iteration")
@@ -99,14 +102,17 @@ def chat(
99102
npx: Optional[str] = typer.Option(None, "--npx"),
100103
uvx: Optional[str] = typer.Option(None, "--uvx"),
101104
stdio: Optional[str] = typer.Option(None, "--stdio"),
102-
script: Optional[Path] = typer.Option(Path("agent.py"), "--script"),
105+
script: Optional[Path] = typer.Option(None, "--script"),
103106
list_servers: bool = typer.Option(False, "--list-servers"),
104107
list_tools: bool = typer.Option(False, "--list-tools"),
105108
list_resources: bool = typer.Option(False, "--list-resources"),
106109
server: Optional[str] = typer.Option(
107110
None, "--server", help="Filter to a single server"
108111
),
109112
) -> None:
113+
# Resolve script with auto-detection
114+
script = detect_default_script(script)
115+
110116
server_list = servers_csv.split(",") if servers_csv else None
111117

112118
url_servers = None
@@ -140,12 +146,21 @@ def chat(
140146
else:
141147
server_list.extend(list(stdio_servers.keys()))
142148

149+
# Smart defaults for servers
150+
resolved_server_list = select_servers_from_config(
151+
servers_csv, url_servers, stdio_servers
152+
)
153+
143154
# Listing mode (no generation)
144155
if list_servers or list_tools or list_resources:
145156
try:
146157

147158
async def _list():
148-
app_obj = load_user_app(script or Path("agent.py"))
159+
# Disable progress display for cleaner listing output
160+
settings = get_settings()
161+
if settings.logger:
162+
settings.logger.progress_display = False
163+
app_obj = load_user_app(script, settings_override=settings)
149164
await app_obj.initialize()
150165
attach_url_servers(app_obj, url_servers)
151166
attach_stdio_servers(app_obj, stdio_servers)
@@ -163,7 +178,7 @@ async def _list():
163178
agent = Agent(
164179
name="chat-lister",
165180
instruction="You list tools and resources",
166-
server_names=target_servers,
181+
server_names=resolved_server_list or target_servers,
167182
context=app_obj.context,
168183
)
169184
async with agent:
@@ -203,7 +218,11 @@ async def _list():
203218
):
204219

205220
async def _parallel_repl():
206-
app_obj = load_user_app(script or Path("agent.py"))
221+
# Disable progress display for cleaner multi-model REPL
222+
settings = get_settings()
223+
if settings.logger:
224+
settings.logger.progress_display = False
225+
app_obj = load_user_app(script, settings_override=settings)
207226
await app_obj.initialize()
208227
attach_url_servers(app_obj, url_servers)
209228
attach_stdio_servers(app_obj, stdio_servers)
@@ -227,7 +246,7 @@ async def _parallel_repl():
227246
provider = prov_guess
228247
llm = create_llm(
229248
agent_name=m,
230-
server_names=server_list or [],
249+
server_names=resolved_server_list or [],
231250
provider=(provider or "openai"),
232251
model=m,
233252
context=app_obj.context,
@@ -276,7 +295,9 @@ async def _parallel_repl():
276295
ag = _Agent(
277296
name="chat-lister",
278297
instruction="list tools",
279-
server_names=[srv] if srv else (server_list or []),
298+
server_names=[srv]
299+
if srv
300+
else (resolved_server_list or []),
280301
context=app_obj.context,
281302
)
282303
async with ag:
@@ -294,7 +315,9 @@ async def _parallel_repl():
294315
ag = _Agent(
295316
name="chat-lister",
296317
instruction="list resources",
297-
server_names=[srv] if srv else (server_list or []),
318+
server_names=[srv]
319+
if srv
320+
else (resolved_server_list or []),
298321
context=app_obj.context,
299322
)
300323
async with ag:
@@ -367,8 +390,8 @@ async def _gen(llm_instance):
367390
try:
368391
out = asyncio.run(
369392
_run_single_model(
370-
script=script or Path("agent.py"),
371-
servers=server_list,
393+
script=script,
394+
servers=resolved_server_list,
372395
url_servers=url_servers,
373396
stdio_servers=stdio_servers,
374397
model=m,
@@ -392,9 +415,12 @@ async def _gen(llm_instance):
392415
and not models
393416
and not (list_servers or list_tools or list_resources)
394417
):
395-
# Interactive loop
418+
# Interactive loop - disable progress display for cleaner REPL experience
396419
async def _repl():
397-
app_obj = load_user_app(script or Path("agent.py"))
420+
settings = get_settings()
421+
if settings.logger:
422+
settings.logger.progress_display = False
423+
app_obj = load_user_app(script, settings_override=settings)
398424
await app_obj.initialize()
399425
attach_url_servers(app_obj, url_servers)
400426
attach_stdio_servers(app_obj, stdio_servers)
@@ -416,7 +442,7 @@ async def _repl():
416442
provider = model_id.split(":", 1)[0]
417443
llm = create_llm(
418444
agent_name=(name or "chat"),
419-
server_names=server_list or [],
445+
server_names=resolved_server_list or [],
420446
provider=(provider or "openai"),
421447
model=model_id,
422448
context=app_obj.context,
@@ -476,7 +502,7 @@ async def _repl():
476502
# Recreate LLM with new model
477503
llm_local = create_llm(
478504
agent_name=(name or "chat"),
479-
server_names=server_list or [],
505+
server_names=resolved_server_list or [],
480506
provider=(prov or "openai"),
481507
model=model_id,
482508
context=app_obj.context,
@@ -502,7 +528,9 @@ async def _repl():
502528
ag = Agent(
503529
name="chat-lister",
504530
instruction="list tools",
505-
server_names=[srv] if srv else (server_list or []),
531+
server_names=[srv]
532+
if srv
533+
else (resolved_server_list or []),
506534
context=app_obj.context,
507535
)
508536
async with ag:
@@ -521,7 +549,9 @@ async def _repl():
521549
ag = Agent(
522550
name="chat-lister",
523551
instruction="list resources",
524-
server_names=[srv] if srv else (server_list or []),
552+
server_names=[srv]
553+
if srv
554+
else (resolved_server_list or []),
525555
context=app_obj.context,
526556
)
527557
async with ag:
@@ -558,7 +588,7 @@ async def _repl():
558588
prompt_msgs = await ag.create_prompt(
559589
prompt_name=prompt_name,
560590
arguments=arguments,
561-
server_names=server_list or [],
591+
server_names=resolved_server_list or [],
562592
)
563593
# Generate with prompt messages
564594
out = await llm.generate_str(prompt_msgs)
@@ -698,8 +728,8 @@ async def _repl():
698728
else:
699729
out = asyncio.run(
700730
_run_single_model(
701-
script=script or Path("agent.py"),
702-
servers=server_list,
731+
script=script,
732+
servers=resolved_server_list,
703733
url_servers=url_servers,
704734
stdio_servers=stdio_servers,
705735
model=model,

src/mcp_agent/cli/commands/dev.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
from rich.console import Console
1616

1717
from mcp_agent.config import get_settings
18+
from mcp_agent.cli.core.utils import detect_default_script
1819

1920

2021
app = typer.Typer(help="Run app locally with diagnostics")
2122
console = Console()
2223

2324

2425
@app.callback(invoke_without_command=True)
25-
def dev(script: Path = typer.Option(Path("agent.py"), "--script")) -> None:
26+
def dev(script: Path = typer.Option(None, "--script")) -> None:
2627
"""Run the user's app script with optional live reload and preflight checks."""
2728

2829
def _preflight_ok() -> bool:
@@ -49,6 +50,9 @@ def _run_script() -> subprocess.Popen:
4950
stdin=None, # Inherit stdin
5051
)
5152

53+
# Resolve script path with auto-detection (main.py preferred)
54+
script = detect_default_script(script)
55+
5256
# Simple preflight
5357
_ = _preflight_ok()
5458

src/mcp_agent/cli/commands/doctor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ def doctor() -> None:
412412
"• Add API key: [cyan]mcp-agent keys set <provider> <key>[/cyan]\n"
413413
"• Add server: [cyan]mcp-agent server add recipe filesystem[/cyan]\n"
414414
"• Start chat: [cyan]mcp-agent chat --model anthropic.haiku[/cyan]\n"
415-
"• Run agent: [cyan]mcp-agent dev --script agent.py[/cyan]",
415+
"• Run agent: [cyan]mcp-agent dev start --script main.py[/cyan]",
416416
title="Getting Started",
417417
border_style="dim",
418418
)

src/mcp_agent/cli/commands/go.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
attach_stdio_servers,
1919
attach_url_servers,
2020
load_user_app,
21+
detect_default_script,
22+
select_servers_from_config,
2123
)
2224
from mcp_agent.cli.utils.url_parser import generate_server_configs, parse_server_urls
2325
from mcp_agent.workflows.factory import create_llm
@@ -268,8 +270,11 @@ def go(
268270
npx: Optional[str] = typer.Option(None, "--npx"),
269271
uvx: Optional[str] = typer.Option(None, "--uvx"),
270272
stdio: Optional[str] = typer.Option(None, "--stdio"),
271-
script: Optional[Path] = typer.Option(Path("agent.py"), "--script"),
273+
script: Optional[Path] = typer.Option(None, "--script"),
272274
) -> None:
275+
# Resolve script with auto-detection
276+
script = detect_default_script(script)
277+
273278
# Parse server names from config if provided
274279
server_list = servers.split(",") if servers else None
275280

@@ -302,6 +307,11 @@ def go(
302307
else:
303308
server_list.extend(list(stdio_servers.keys()))
304309

310+
# Smart defaults from config if still unspecified
311+
resolved_server_list = select_servers_from_config(
312+
",".join(server_list) if server_list else None, url_servers, stdio_servers
313+
)
314+
305315
# Multi-model support if comma-separated
306316
if model and "," in model:
307317
models = [m.strip() for m in model.split(",") if m.strip()]
@@ -311,7 +321,7 @@ def go(
311321
asyncio.run(
312322
_run_agent(
313323
app_script=script,
314-
server_list=server_list,
324+
server_list=resolved_server_list,
315325
model=m,
316326
message=message,
317327
prompt_file=prompt_file,
@@ -331,7 +341,7 @@ def go(
331341
asyncio.run(
332342
_run_agent(
333343
app_script=script,
334-
server_list=server_list,
344+
server_list=resolved_server_list,
335345
model=model,
336346
message=message,
337347
prompt_file=prompt_file,

0 commit comments

Comments
 (0)