Fixed
-
An alias is no longer a hole in the flag-ownership check.
mcptoon list --verboseexited 2, whilemcptoon servers --verbose— the same command under its
short form — printed the server list and exited 0, dropping the flag in silence.
COMMAND_FLAGSis keyed by canonical name and the check looked the raw token up, so
all four aliases (servers,tools,qs,brief) were unmigrated by accident; the
"did you mean" hint was empty for them too. The alias now resolves to its canonical
command first, andtests/test_typo_and_flag_validation.pypins both the rejection
and the hint, plus a guard that every alias points at a registered command. -
A keyword after a garbage word no longer routes. The natural-language router
matched its keyword list against the whole line, so any unknown first token followed
by a keyword ran a command and exited 0:mcptoon whatever healthran the health
check,mcptoon garbage toolsran manifest,mcptoon asdf searchran search. This is
the same defect class asmcptoon lst list(fixed in 0.8.38) one token further out —
the guard rejected a near-command first word, but said nothing about an arbitrary
one. Keywords are now matched against the first token only, which is the whole
input for the phrase this feature exists for (mcptoon 有什么工具) because CJK does not
space its words. A non-ASCII first token still matches the whole line, so a CJK user
who does space them (mcptoon 列出 服务器) keeps working. Found 2026-11-13 while
closing #41; all five garbage-prefix shapes now exit 1 with a did-you-mean hint, and
the eight CJK phrases that motivated the router still route.
Changed
-
Flag ownership now covers the remaining commands whose flags can be enumerated
(issue #41, fifth batch). Measured 2026-11-13 on 0.8.39 by running every unregistered
command with--roots— a real flag that onlybenchowns, so the pre-pass tolerates
it everywhere and whatever the command does with it is its own answer:usage,
stats,status,credit,savings,report,mode,init,quickstart,off,
restore,uninstall,update,upgrade,import,select,bench,
footer-facts,demoanddemo-serverall printed their normal output and exited
0.doctorandhealthwere worse than silent — they exited 1 for an unrelated
reason (a failing check, a dead server), so a caller saw a failure and never learned
the flag was the problem. The registry now covers 46 commands.Four commands stay out on purpose, and the reason is a working invocation that a set
here would reject:add(everything after--stdio/--httpbelongs to the child
command —add foo --stdio node server.js --port 3000),exec(the code positional
may itself be a flag —exec bash --version— and it already rejects unknown options
itself, exit 1),config(config set <key> <value>, where a value may start with
--), and the delegated familiesauth/bake/openapi/graphql, whose sub-modules
own their tails.