inspector/clients/cli/__tests__/headers.test.ts
Bob Dickinson 2488ca5e38
feat: port CLI, TUI, and launcher from v1.5 into v2 (#1452)
Ports the CLI, TUI, and launcher from v1.5 into v2 behind a single
`mcp-inspector` entrypoint (launcher → web/cli/tui). Includes the
`mcp-inspector --web --dev` launcher fix (Vite alias resolution + prod-server
double-start), the root `postinstall` install cascade with simplified CI, and
spec/AGENTS docs (no-workspaces rationale, Development setup).

Closes #1246.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 20:27:49 -04:00

202 lines
5.6 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { runCli } from "./helpers/cli-runner.js";
import {
expectCliFailure,
expectOutputContains,
expectCliSuccess,
} from "./helpers/assertions.js";
import {
createTestServerHttp,
createEchoTool,
createTestServerInfo,
} from "@modelcontextprotocol/inspector-test-server";
describe("Header Parsing and Validation", () => {
describe("Valid Headers", () => {
it("should parse valid single header and send it to server", async () => {
const server = createTestServerHttp({
serverInfo: createTestServerInfo(),
tools: [createEchoTool()],
});
try {
await server.start();
const result = await runCli([
server.url,
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
"Authorization: Bearer token123",
]);
expectCliSuccess(result);
// Check that the server received the request with the correct headers
const recordedRequests = server.getRecordedRequests();
expect(recordedRequests.length).toBeGreaterThan(0);
// Find the tools/list request (should be the last one)
const toolsListRequest = recordedRequests[recordedRequests.length - 1];
expect(toolsListRequest).toBeDefined();
expect(toolsListRequest.method).toBe("tools/list");
// Express normalizes headers to lowercase
expect(toolsListRequest.headers).toHaveProperty("authorization");
expect(toolsListRequest.headers?.authorization).toBe("Bearer token123");
} finally {
await server.stop();
}
});
it("should parse multiple headers", async () => {
const server = createTestServerHttp({
serverInfo: createTestServerInfo(),
tools: [createEchoTool()],
});
try {
await server.start();
const result = await runCli([
server.url,
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
"Authorization: Bearer token123",
"--header",
"X-API-Key: secret123",
]);
expectCliSuccess(result);
const recordedRequests = server.getRecordedRequests();
const toolsListRequest = recordedRequests[recordedRequests.length - 1];
expect(toolsListRequest.method).toBe("tools/list");
expect(toolsListRequest.headers?.authorization).toBe("Bearer token123");
expect(toolsListRequest.headers?.["x-api-key"]).toBe("secret123");
} finally {
await server.stop();
}
});
it("should handle header with colons in value", async () => {
const server = createTestServerHttp({
serverInfo: createTestServerInfo(),
tools: [createEchoTool()],
});
try {
await server.start();
const result = await runCli([
server.url,
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
"X-Time: 2023:12:25:10:30:45",
]);
expectCliSuccess(result);
const recordedRequests = server.getRecordedRequests();
const toolsListRequest = recordedRequests[recordedRequests.length - 1];
expect(toolsListRequest.method).toBe("tools/list");
expect(toolsListRequest.headers?.["x-time"]).toBe(
"2023:12:25:10:30:45",
);
} finally {
await server.stop();
}
});
it("should handle whitespace in headers", async () => {
const server = createTestServerHttp({
serverInfo: createTestServerInfo(),
tools: [createEchoTool()],
});
try {
await server.start();
const result = await runCli([
server.url,
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
" X-Header : value with spaces ",
]);
expectCliSuccess(result);
const recordedRequests = server.getRecordedRequests();
const toolsListRequest = recordedRequests[recordedRequests.length - 1];
expect(toolsListRequest.method).toBe("tools/list");
// Header values should be trimmed by the CLI parser
expect(toolsListRequest.headers?.["x-header"]).toBe(
"value with spaces",
);
} finally {
await server.stop();
}
});
});
describe("Invalid Header Formats", () => {
it("should reject header format without colon", async () => {
const result = await runCli([
"https://example.com",
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
"InvalidHeader",
]);
expectCliFailure(result);
expectOutputContains(result, "Invalid header format");
});
it("should reject header format with empty name", async () => {
const result = await runCli([
"https://example.com",
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
": value",
]);
expectCliFailure(result);
expectOutputContains(result, "Invalid header format");
});
it("should reject header format with empty value", async () => {
const result = await runCli([
"https://example.com",
"--cli",
"--method",
"tools/list",
"--transport",
"http",
"--header",
"Header:",
]);
expectCliFailure(result);
expectOutputContains(result, "Invalid header format");
});
});
});