Files
reverse-engineering-anything/tests/boundary/mcp/packetCaptureAvailability.test.ts
T
Lewis WangandClaude Opus 5.5 5a311d8afe fix(mcp): report Linux-only integrations as unsupported_host off their hosts (#5793)
* fix(mcp): report Linux-only integrations as unsupported_host off their hosts

Session discovery folded the host check into each optional integration's
enabled flag, so on macOS or Windows the Linux-only packet, signal,
firmware, pwntools, EVM and Wakaru tools reported provider_missing.
Their execution guards refuse those hosts whatever is configured, so
installing a provider there could never make them available.

The server now records, per integration, when the host is outside its
verified host and no service is injected. Discovery checks that before
configuration and reports unsupported_host with the existing
remediation. Injected services and supported hosts behave as before.

Fixes #5730

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(mcp): share provider host checks with session discovery

Discovery restated each Linux-only integration's host rule in
createServer while its provider kept a separate execution check, so the
two could drift apart again. Each provider now exports its host
predicate, uses it in its execution guard, and composition hands the
same predicate to createServer for both the host restriction and the
enabled flag.

Observed host restrictions now also apply when an embedder supplies its
own availability policy, as provider load failures already do, because
no policy lets the default providers pass their host checks.

The MCP regression moves to tests/process-global and emulates darwin
arm64, linux arm64 and linux x64 through the real createServer, so CI on
Linux x64 exercises the unsupported-host branch. It also covers a
configured policy and the matching execution refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mcp): keep caller host restrictions beside observed ones

The observed host restriction replaced a configured policy's whole
hostUnsupported map. For an injected service the observed value is
false, so a caller's own restriction was lost and the tool was reported
available. Combine both per integration: either the caller or the
observed host can mark it unsupported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(pcap): expect unsupported_host for packet tools off Linux

The host-independent PATH case asserted provider_missing on every host.
Off Linux the packet tools are unavailable because of the host, so
discovery now reports unsupported_host there; Linux still reports
provider_missing for an unusable PATH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 05:14:26 +08:00

109 lines
3.6 KiB
TypeScript

import { chmod, mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { Client, InMemoryTransport } from "@modelcontextprotocol/client";
import { expect, it } from "vitest";
import { z } from "zod";
import {
expandToolAvailability,
sessionProvider,
} from "../../../src/contracts/toolOutputSchemaPrimitives.js";
import { createServer } from "../../../src/server/createServer.js";
import { createTestBinarySession } from "../../fixtures/binarySession.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
// The server enables default packet tools only on Linux, where they can run.
const linux = process.platform === "linux";
const packetCaptureAvailability = async (
environment: Readonly<Record<string, string | undefined>>,
): Promise<Record<string, unknown> | undefined> => {
const session = createTestBinarySession(() => {
throw new Error("binary analysis must not start during status discovery");
});
const server = createServer(
{ kind: "session", session },
{ environment: { ...environment, REA_MCP_OUTPUT_SCHEMA_PROFILE: "off" } },
);
const client = new Client({
name: "packet-capture-availability",
version: "1",
});
const [clientTransport, serverTransport] =
InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
await client.connect(clientTransport);
try {
const response = await client.callTool({
name: "binary_session",
arguments: {},
});
if (response.isError === true) throw new Error("binary_session failed");
const parsed = z
.object({ result: sessionProvider })
.parse(response.structuredContent).result;
return expandToolAvailability(parsed.tool_availability).find(
({ name }) => name === "inspect_packet_capture",
);
} finally {
await Promise.allSettled([client.close(), server.close(), session.close()]);
}
};
const executableTshark = async (prefix: string): Promise<string> => {
const directory = await createTestTempDirectory(prefix);
await mkdir(join(directory, "bin"));
const tshark = join(directory, "bin", "tshark");
await writeFile(tshark, "");
await chmod(tshark, 0o700);
return join(directory, "bin");
};
it.runIf(linux)(
"reports packet tools available for a PATH-only TShark install",
async () => {
const bin = await executableTshark("rea-packet-path-only-");
expect(await packetCaptureAvailability({ PATH: bin })).toMatchObject({
available: true,
reason: "available",
});
},
);
it.runIf(linux)(
"reports packet tools available for an absolute REA_TSHARK_COMMAND",
async () => {
const bin = await executableTshark("rea-packet-absolute-");
expect(
await packetCaptureAvailability({
PATH: "",
REA_TSHARK_COMMAND: join(bin, "tshark"),
}),
).toMatchObject({ available: true, reason: "available" });
},
);
it.runIf(linux)(
"reports packet tools missing for a relative REA_TSHARK_COMMAND even when PATH holds TShark",
async () => {
const bin = await executableTshark("rea-packet-relative-");
expect(
await packetCaptureAvailability({
PATH: bin,
REA_TSHARK_COMMAND: "bin/tshark",
}),
).toMatchObject({ available: false, reason: "provider_missing" });
},
);
it("reports packet tools unavailable when no absolute PATH entry holds TShark", async () => {
// Off Linux the host, not the missing tool, keeps packet tools unavailable.
expect(
await packetCaptureAvailability({ PATH: "relative-entry" }),
).toMatchObject({
available: false,
reason: linux ? "provider_missing" : "unsupported_host",
});
});