Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,15 @@ export const createCli = (
// Incur's `mcp add` silently skips a valued option with no value and
// swallows the next flag as the value: the registration succeeds without
// the requested agent or command. Reject a trailing --agent/--command/-c,
// a value position occupied by another flag, and an empty `--flag=` form
// up front.
// a value position occupied by another flag, an empty `--flag=` form,
// and a separate empty-string value up front.
const valued = ["--agent", "--command", "-c"];
let missingValue: string | undefined;
for (let index = 0; index < command.length; index += 1) {
const next = command[index + 1];
if (
valued.includes(command[index]!) &&
(next === undefined || next.startsWith("-"))
(next === undefined || next === "" || next.startsWith("-"))
) {
missingValue = command[index];
break;
Expand Down
24 changes: 24 additions & 0 deletions tests/boundary/cli/mcpAddOptionValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ cliTest("mcp add rejects valued options without a value", async ({ cli }) => {
});
}

// A separate empty string is not a value either; without this check Incur
// silently registers with defaults. REA rejects it before registration.
for (const [flag, field] of [
["--agent", "agent"],
["--command", "command"],
["-c", "command"],
] as const) {
const result = await run(["mcp", "add", flag, ""]);
expect(result.exitCode, result.stderr).toBe(1);
expect(result.json).toMatchObject({
code: "VALIDATION_ERROR",
fieldErrors: expect.arrayContaining([
expect.objectContaining({
code: "invalid_value",
missing: false,
path: field,
}),
]),
});
await expect(access(settingsPath(home))).rejects.toMatchObject({
code: "ENOENT",
});
}

// Incur would swallow the following flag as the option value; REA rejects it.
const swallowed = await run(["mcp", "add", "--command", "--agent", "amp"]);
expect(swallowed.exitCode, swallowed.stderr).toBe(1);
Expand Down
Loading