Skip to content
Merged
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
27 changes: 19 additions & 8 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,33 @@ import { ALL_SEVERITIES } from "./types.js";

const VERSION = "0.1.0";

type CliFlag = string | boolean | string[];

interface CliArgs {
command?: string;
positional: string[];
flags: Record<string, string | boolean>;
flags: Record<string, CliFlag>;
}

function parseArgs(argv: string[]): CliArgs {
export function parseArgs(argv: string[]): CliArgs {
const positional: string[] = [];
const flags: Record<string, string | boolean> = {};
const flags: Record<string, CliFlag> = {};
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];
if (arg.startsWith("--")) {
const key = arg.slice(2);
const next = argv[i + 1];
if (next !== undefined && !next.startsWith("--")) {
flags[key] = next;
if (key === "header" && flags[key] !== undefined) {
const previous = flags[key];
flags[key] = Array.isArray(previous)
? [...previous, next]
: typeof previous === "string"
? [previous, next]
: next;
} else {
flags[key] = next;
}
i++;
} else {
flags[key] = true;
Expand Down Expand Up @@ -73,7 +84,7 @@ EXIT CODES
`;
}

function csv(value: string | boolean | undefined): string[] {
function csv(value: CliFlag | undefined): string[] {
if (typeof value !== "string") return [];
return value
.split(",")
Expand All @@ -83,7 +94,7 @@ function csv(value: string | boolean | undefined): string[] {

function overlayFlags(
base: McpAuditConfig,
flags: Record<string, string | boolean>,
flags: Record<string, CliFlag>,
): McpAuditConfig {
const overlay: Record<string, unknown> = {};
if (flags["fail-on"]) {
Expand All @@ -100,8 +111,8 @@ function overlayFlags(
return normalizeConfig(overlay, base);
}

function collectHeaders(
flags: Record<string, string | boolean>,
export function collectHeaders(
flags: Record<string, CliFlag>,
): Record<string, string> {
const headers: Record<string, string> = {};
const raw = flags["header"];
Expand Down
44 changes: 44 additions & 0 deletions test/cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, expect, it } from "vitest";
import { collectHeaders, parseArgs } from "../src/cli.js";

describe("HTTP headers", () => {
it("collects every repeated --header flag", () => {
const { flags } = parseArgs([
"http",
"https://example.com/mcp",
"--header",
"X-Tenant: acme",
"--header",
"X-Env: prod",
]);

expect(collectHeaders(flags)).toEqual({
"X-Tenant": "acme",
"X-Env": "prod",
});
});

it("preserves colons in header values", () => {
const { flags } = parseArgs([
"http",
"https://example.com/mcp",
"--header",
"Authorization: Bearer a:b",
]);

expect(collectHeaders(flags)).toEqual({ Authorization: "Bearer a:b" });
});

it("keeps last-wins behavior for repeated non-header flags", () => {
const { flags } = parseArgs([
"http",
"https://example.com/mcp",
"--config",
"one.json",
"--config",
"two.json",
]);

expect(flags.config).toBe("two.json");
});
});
Loading