Problem
parseArgs in src/cli.ts is 20 lines of hand-rolled parsing, and it has three defects that matter for a tool whose main job is to be a CI gate.
1. Unknown flags are silently accepted and ignored. Anything starting with -- becomes a key in flags, and nothing ever validates the key set. So:
mcp-audit static manifest.json --failon critical
does not error. flags["failon"] is set, flags["fail-on"] is not, and the audit silently runs with the default failOn: "high". A typo in the flag that controls the exit code changes the gate and says nothing. The same applies to --jsn (you get terminal output while expecting JSON) and --saarif.
2. Flags cannot repeat. flags is a flat Record<string, string | boolean>, so the second --header overwrites the first. This is open issue #3, and the fix belongs here rather than in collectHeaders.
3. There is dead code that documents the intent. collectHeaders contains:
const values = Array.isArray(raw) ? raw : raw ? [raw] : [];
raw can never be an array, because parseArgs cannot produce one. That branch was written for the parser this should have been.
A fourth, smaller one: if (next !== undefined && !next.startsWith("--")) means a flag value that legitimately starts with -- cannot be passed, and there is no -- end-of-flags terminator.
Suggested approach
- Change
flags to Record<string, Array<string | boolean>>, or keep a separate repeatable set. Either way, --header must accumulate.
- Declare the known flags per command, with their arity, in one table. Reject unknown flags with a clear message and exit 2, which the usage text already documents as the code for usage errors. Suggest the closest known flag if you want to be kind.
- Support
-- as the end-of-flags marker.
- Delete the dead
Array.isArray branch once the parser can actually produce arrays, or keep it and make it reachable.
- Consider
node:util's parseArgs, which is available on Node 18 and would remove most of this code. It supports multiple: true and strict: true, which are exactly the two things missing. The dependency cost is zero.
- Add tests. There are none for the CLI layer today, so please add
test/cli.test.ts covering: unknown flag rejected, repeated --header collected, --fail-on validated, -- terminator, and a value beginning with --.
Done when
If you want to take this on, comment on the issue to claim it and it will be assigned. Please keep to a maximum of 2 open claims per person at a time so other contributors get a chance.
Problem
parseArgsinsrc/cli.tsis 20 lines of hand-rolled parsing, and it has three defects that matter for a tool whose main job is to be a CI gate.1. Unknown flags are silently accepted and ignored. Anything starting with
--becomes a key inflags, and nothing ever validates the key set. So:does not error.
flags["failon"]is set,flags["fail-on"]is not, and the audit silently runs with the defaultfailOn: "high". A typo in the flag that controls the exit code changes the gate and says nothing. The same applies to--jsn(you get terminal output while expecting JSON) and--saarif.2. Flags cannot repeat.
flagsis a flatRecord<string, string | boolean>, so the second--headeroverwrites the first. This is open issue #3, and the fix belongs here rather than incollectHeaders.3. There is dead code that documents the intent.
collectHeaderscontains:rawcan never be an array, becauseparseArgscannot produce one. That branch was written for the parser this should have been.A fourth, smaller one:
if (next !== undefined && !next.startsWith("--"))means a flag value that legitimately starts with--cannot be passed, and there is no--end-of-flags terminator.Suggested approach
flagstoRecord<string, Array<string | boolean>>, or keep a separaterepeatableset. Either way,--headermust accumulate.--as the end-of-flags marker.Array.isArraybranch once the parser can actually produce arrays, or keep it and make it reachable.node:util'sparseArgs, which is available on Node 18 and would remove most of this code. It supportsmultiple: trueandstrict: true, which are exactly the two things missing. The dependency cost is zero.test/cli.test.tscovering: unknown flag rejected, repeated--headercollected,--fail-onvalidated,--terminator, and a value beginning with--.Done when
--headeris genuinely repeatable, closing Bug: --header is documented as repeatable but only the last one is sent #3.collectHeaders.If you want to take this on, comment on the issue to claim it and it will be assigned. Please keep to a maximum of 2 open claims per person at a time so other contributors get a chance.