mirror of
https://github.com/morluto/rea
synced 2026-10-28 23:11:11 -04:00
b675073b73
Scope MCP discovery, setup, doctor, status and recovery guidance by selected tool families using one contract inventory and shared catalog identity. Preserve default discovery, canonical validation and complete Evidence. Fixes #3246. Builds on #3026. Real libcrypto workflow verifies all 5,367 exports and identical complete Evidence. Static/source/build/docs/Windows/package/Greptile checks pass; ten assertions reproduced identically on clean main and feature across Node 24/22, with cancelled coverage explicitly unverified. Merge uses the user-authorized bypass for baseline failures and unchecked human-readiness declarations, without attesting human review. Co-authored-by: 0xLLVEL <fakhrezan1@gmail.com> Co-authored-by: Codebuff <noreply@codebuff.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1337 lines
46 KiB
TypeScript
1337 lines
46 KiB
TypeScript
import { AnalysisSettings } from "../application/AnalysisSettings.js";
|
|
import { registerAnalysisSettingsTools } from "./registerAnalysisSettingsTools.js";
|
|
import type { DevicetreeService } from "../application/binaryDiagnostics/DevicetreeService.js";
|
|
import { registerDevicetreeTool } from "./registerDevicetreeTool.js";
|
|
import { pcapCaptureHostSupported } from "../domain/pcap/pcapAnalysis.js";
|
|
import { createGpuCodeObjectsService } from "../composition/gpu.js";
|
|
import { registerGpuCodeObjectsTools } from "./registerGpuCodeObjectsTools.js";
|
|
import type { PacketCaptureService } from "../application/captures/PacketCaptureService.js";
|
|
import { serverInstructions } from "./serverInstructions.js";
|
|
import {
|
|
createPacketCaptureService,
|
|
tsharkHostSupported,
|
|
} from "../composition/captures.js";
|
|
import { registerCaptureTools } from "./registerCaptureTools.js";
|
|
import type { SignalRecordingService } from "../application/signals/SignalRecordingService.js";
|
|
import {
|
|
createSignalRecordingService,
|
|
sigrokHostSupported,
|
|
} from "../composition/signals.js";
|
|
import { registerSignalTools } from "./registerSignalTools.js";
|
|
import type { WasmArtifactService } from "../application/wasm/WasmArtifactService.js";
|
|
import { wasmArtifactModule } from "../composition/wasm.js";
|
|
import { registerWasmTools } from "./registerWasmTools.js";
|
|
import type { ApkSignatureService } from "../application/apkSignature/ApkSignatureService.js";
|
|
import { apkSignatureModule } from "../composition/apkSignature.js";
|
|
import { registerApkSignatureTools } from "./registerApkSignatureTools.js";
|
|
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
import { captureProviderEnvironment } from "./providerEnvironment.js";
|
|
import {
|
|
createElfNotesService,
|
|
createAppleIpsService,
|
|
createDevicetreeService,
|
|
createKernelModuleService,
|
|
createPeLoadConfigService,
|
|
createPeCertificatesService,
|
|
createPeImportsService,
|
|
createNativeExportsService,
|
|
createPeResourcesService,
|
|
createRecordedCrashService,
|
|
createByteEntropyService,
|
|
createBinaryLayoutService,
|
|
pwntoolsHostSupported,
|
|
} from "../composition/binaryDiagnostics.js";
|
|
import type { ElfNotesService } from "../application/binaryDiagnostics/ElfNotesService.js";
|
|
import type { AppleIpsService } from "../application/binaryDiagnostics/AppleIpsService.js";
|
|
import type { KernelModuleService } from "../application/binaryDiagnostics/KernelModuleService.js";
|
|
import type { PeLoadConfigService } from "../application/binaryDiagnostics/PeLoadConfigService.js";
|
|
import type { PeCertificatesService } from "../application/binaryDiagnostics/PeCertificatesService.js";
|
|
import type { PeImportsService } from "../application/binaryDiagnostics/PeImportsService.js";
|
|
import type { PeResourcesService } from "../application/binaryDiagnostics/PeResourcesService.js";
|
|
import type { NativeExportsService } from "../application/binaryDiagnostics/NativeExportsService.js";
|
|
import { registerElfNotesTool } from "./registerElfNotesTool.js";
|
|
import { registerAppleIpsTool } from "./registerAppleIpsTool.js";
|
|
import { registerKernelModuleTool } from "./registerKernelModuleTool.js";
|
|
import { registerPeLoadConfigTool } from "./registerPeLoadConfigTool.js";
|
|
import { registerPeCertificatesTool } from "./registerPeCertificatesTool.js";
|
|
import { registerPeImportsTool } from "./registerPeImportsTool.js";
|
|
import { registerPeResourcesTool } from "./registerPeResourcesTool.js";
|
|
import { registerNativeExportsTool } from "./registerNativeExportsTool.js";
|
|
import type { EvmInterfaceService } from "../application/evm/EvmInterfaceService.js";
|
|
import {
|
|
evmHostSupported,
|
|
evmInterfaceModule,
|
|
evmLimiterAvailability,
|
|
} from "../composition/evm.js";
|
|
import { registerEvmTools } from "./registerEvmTools.js";
|
|
import type { SqliteDatabaseService } from "../application/sqlite/SqliteDatabaseService.js";
|
|
import { createSqliteDatabaseService } from "../composition/sqlite.js";
|
|
import { registerSqliteTools } from "./registerSqliteTools.js";
|
|
import { registerRecordedCrashTools } from "./registerRecordedCrashTools.js";
|
|
import { createDesktopApplicationService } from "../composition/desktop.js";
|
|
import { registerDesktopApplicationTool } from "./registerDesktopApplicationTool.js";
|
|
import { createGoBinaryService } from "../composition/go.js";
|
|
import { createModelArtifactService } from "../composition/model.js";
|
|
import { registerModelArtifactTools } from "./registerModelArtifactTools.js";
|
|
import { createIl2cppMetadataService } from "../composition/il2cpp.js";
|
|
import type { Il2cppMetadataService } from "../application/il2cpp/Il2cppMetadataService.js";
|
|
import type { GoBinaryService } from "../application/go/GoBinaryService.js";
|
|
import { createElectronFuseService } from "../composition/electronFuses.js";
|
|
import type { ElectronFuseService } from "../application/electron/ElectronFuseService.js";
|
|
import { registerGoTools } from "./registerGoTools.js";
|
|
import { registerIl2cppTools } from "./registerIl2cppTools.js";
|
|
import { createRustBinaryService } from "../composition/rust.js";
|
|
import type { RustBinaryService } from "../application/rust/RustBinaryService.js";
|
|
import { registerRustTools } from "./registerRustTools.js";
|
|
import { createPythonPycService } from "../composition/pythonPyc.js";
|
|
import type { PythonPycService } from "../application/python/PythonPycService.js";
|
|
import { registerPythonPycTool } from "./registerPythonPycTool.js";
|
|
import { createBeamService } from "../composition/erlang.js";
|
|
import type { BeamService } from "../application/erlang/BeamService.js";
|
|
import { registerErlangTools } from "./registerErlangTools.js";
|
|
import type { RecordedCrashService } from "../application/binaryDiagnostics/RecordedCrashService.js";
|
|
import { registerAnalysisViewTool } from "./registerAnalysisViewTool.js";
|
|
import { registerBinaryDiagnosticsTools } from "./registerBinaryDiagnosticsTools.js";
|
|
import { FridaInstrumentationManager } from "../frida/FridaInstrumentationManager.js";
|
|
import { registerFridaTools } from "./registerFridaTools.js";
|
|
import type { BinaryLayoutService } from "../application/binaryDiagnostics/BinaryLayoutService.js";
|
|
import { EvidenceMcpServer } from "./EvidenceMcpServer.js";
|
|
import { catalogIdentityForToolFamilies } from "../catalogIdentity.js";
|
|
import { parseMcpToolFamilies } from "../config/mcpToolFamilies.js";
|
|
import { createToolResultDelivery } from "./toolResult.js";
|
|
import type { ToolResultDelivery } from "./ToolResultDelivery.js";
|
|
import { parseMcpResponseBudget } from "../config/mcpResponseBudget.js";
|
|
import {
|
|
parseMcpOutputSchemaProfile,
|
|
type McpOutputSchemaProfile,
|
|
} from "../config/mcpOutputSchemaProfile.js";
|
|
import {
|
|
compactPresentationForMcpInputSchemaProfile,
|
|
parseMcpInputSchemaProfile,
|
|
} from "../config/mcpInputSchemaProfile.js";
|
|
import type { CompactInputSchemaPresentation } from "./EvidenceMcpServer.js";
|
|
import { isAbsolute } from "node:path";
|
|
|
|
import type { BinarySessionPort } from "../application/binary/BinarySessionPort.js";
|
|
import type { BrowserObservationPort } from "../application/BrowserObservationPort.js";
|
|
import type { BrowserScenarioCapturePort } from "../application/BrowserScenarioCapturePort.js";
|
|
import type { ElectronActiveObservationPort } from "../application/javascript/ElectronActiveObservationPort.js";
|
|
import type { ElectronObservationPort } from "../application/javascript/ElectronObservationPort.js";
|
|
import type { JavaScriptRuntimeObservationPort } from "../application/javascript/JavaScriptRuntimeObservationPort.js";
|
|
import type { FridaInstrumentationPort } from "../application/frida/FridaInstrumentationPort.js";
|
|
import type { OptionalProviderLoadFailures } from "../application/OptionalObservationProviders.js";
|
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
import { silentLogger } from "../logger.js";
|
|
import type { Logger } from "pino";
|
|
import { registerApplicationTools } from "./registerApplicationTools.js";
|
|
import { registerArtifactTools } from "./registerArtifactTools.js";
|
|
import { registerNativeTools } from "./registerNativeTools.js";
|
|
import { registerBrowserScenarioTool } from "./registerBrowserScenarioTool.js";
|
|
import { registerBrowserTools } from "./registerBrowserTools.js";
|
|
import { registerWebScriptTool } from "./registerWebScriptTool.js";
|
|
import { registerWebModuleTool } from "./registerWebModuleTool.js";
|
|
import type { WebModuleTraceService } from "../application/WebModuleTraceService.js";
|
|
import { createWebModuleTraceService } from "../composition/webModules.js";
|
|
import { createWebSourceLocationService } from "../composition/webSourceLocations.js";
|
|
import { registerWebSourceLocationTool } from "./registerWebSourceLocationTool.js";
|
|
import type { WebSourceLocationService } from "../application/WebSourceLocationService.js";
|
|
import type { WebRuntimeService } from "../application/WebRuntimeService.js";
|
|
import { createWebRuntimeService } from "../composition/webRuntime.js";
|
|
import { registerWebRuntimeTools } from "./registerWebRuntimeTools.js";
|
|
import type { WebNetworkCaptureService } from "../application/WebNetworkCaptureService.js";
|
|
import { createWebNetworkCaptureService } from "../composition/webNetworkCaptures.js";
|
|
import { registerWebNetworkCaptureTool } from "./registerWebNetworkCaptureTool.js";
|
|
import { registerJavaScriptRecoveryTool } from "./registerJavaScriptRecoveryTool.js";
|
|
import { JavaScriptRecoveryService } from "../application/javascript/JavaScriptRecoveryService.js";
|
|
import type { JavaScriptRecoveryPort } from "../application/javascript/JavaScriptRecoveryPort.js";
|
|
import {
|
|
createJavaScriptRecoveryProvider,
|
|
wakaruHostSupported,
|
|
} from "../composition/javascriptRecovery.js";
|
|
import { registerElectronTools } from "./registerElectronTools.js";
|
|
import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js";
|
|
import { registerEnhancedTools } from "./registerEnhancedTools.js";
|
|
import { registerJavaScriptRuntimeObservationTools } from "./registerJavaScriptRuntimeObservationTools.js";
|
|
import { registerManagedTools } from "./registerManagedTools.js";
|
|
import { registerFirmwareTools } from "./registerFirmwareTools.js";
|
|
import { FirmwareAnalysisService } from "../application/firmware/FirmwareAnalysisService.js";
|
|
import type { FirmwareAnalysisPort } from "../application/firmware/FirmwareAnalysisPort.js";
|
|
import {
|
|
createFirmwareAnalysisProvider,
|
|
firmwareHostSupported,
|
|
} from "../composition/firmware.js";
|
|
import { registerAndroidTools } from "./registerAndroidTools.js";
|
|
import { registerApktoolTools } from "./registerApktoolTools.js";
|
|
import { registerPcapTools } from "./registerPcapTools.js";
|
|
import { registerFlutterTools } from "./registerFlutterTools.js";
|
|
import { registerJebTools } from "./registerJebTools.js";
|
|
import { registerAdbTools } from "./registerAdbTools.js";
|
|
import { AndroidAnalysisService } from "../application/android/AndroidAnalysisService.js";
|
|
import { JebAnalysisService } from "../application/jeb/JebAnalysisService.js";
|
|
import type { AndroidAnalysisPort } from "../application/android/AndroidAnalysisPort.js";
|
|
import type { ApktoolResourceAnalysisPort } from "../application/apktool/ApktoolResourceAnalysisPort.js";
|
|
import type { PcapAnalysisPort } from "../application/pcap/PcapAnalysisPort.js";
|
|
import { PcapAnalysisService } from "../application/pcap/PcapAnalysisService.js";
|
|
import {
|
|
locateWiresharkTool,
|
|
selectWiresharkTool,
|
|
} from "../pcap/PcapConfiguration.js";
|
|
import { ApktoolResourceAnalysisService } from "../application/apktool/ApktoolResourceAnalysisService.js";
|
|
import type { FlutterBuildAnalysisPort } from "../application/flutter/FlutterBuildAnalysisPort.js";
|
|
import { FlutterBuildAnalysisService } from "../application/flutter/FlutterBuildAnalysisService.js";
|
|
import { createAndroidAnalysisProvider } from "../composition/android.js";
|
|
import { createApktoolResourceAnalysisProvider } from "../composition/apktool.js";
|
|
import { createPcapAnalysisProvider } from "../composition/pcap.js";
|
|
import { createFlutterBuildAnalysisProvider } from "../composition/flutter.js";
|
|
import type { JebAnalysisPort } from "../application/jeb/JebAnalysisPort.js";
|
|
import { createJebAnalysisProvider } from "../composition/jeb.js";
|
|
import type { AdbDeviceAnalysisPort } from "../application/adb/AdbDeviceAnalysisPort.js";
|
|
import { AdbDeviceAnalysisService } from "../application/adb/AdbDeviceAnalysisService.js";
|
|
import { createAdbDeviceAnalysisProvider } from "../composition/adb.js";
|
|
import { registerManagedWorkflowTools } from "./registerManagedWorkflowTools.js";
|
|
import { registerOfficialTools } from "./registerOfficialTools.js";
|
|
import { registerGuidedPrompts } from "./registerPrompts.js";
|
|
import { registerSessionTools } from "./registerSessionTools.js";
|
|
import type { AvailabilityPolicy } from "../application/CapabilityInventory.js";
|
|
import { sessionAvailabilityPolicy } from "./sessionAvailabilityPolicy.js";
|
|
import {
|
|
withAdmittedAnalysis,
|
|
type ServerAnalysisSource,
|
|
type WithAdmittedAnalysis,
|
|
} from "./analysisAdmission.js";
|
|
import { createReverseEngineeringService } from "../composition/reverseEngineering.js";
|
|
import { registerReverseEngineeringTools } from "./registerReverseEngineeringTools.js";
|
|
import { CutterBridgeClient } from "../cutter/CutterBridgeClient.js";
|
|
import { CutterBridgeService } from "../cutter/CutterBridgeService.js";
|
|
import { registerCutterTools } from "./registerCutterTools.js";
|
|
import { GdbSessionManager } from "../gdb/GdbSessionManager.js";
|
|
import { registerGdbTools } from "./registerGdbTools.js";
|
|
import { RizinDebugSessionManager } from "../rizin/RizinDebugSessionManager.js";
|
|
import { registerRizinDebugTools } from "./registerRizinDebugTools.js";
|
|
|
|
export interface CreateServerOptions {
|
|
readonly analysisSettings?: AnalysisSettings;
|
|
/** Preserve the connection's creation time when materializing its runtime. */
|
|
readonly startedAt?: string;
|
|
/** Existing SDK server whose deferred registrations are being materialized. */
|
|
readonly mcpServer?: EvidenceMcpServer;
|
|
readonly environment?: Readonly<NodeJS.ProcessEnv>;
|
|
readonly delivery?: ToolResultDelivery;
|
|
readonly packetCapture?: PacketCaptureService;
|
|
readonly signalRecording?: SignalRecordingService;
|
|
readonly wasmArtifact?: WasmArtifactService;
|
|
readonly apkSignature?: ApkSignatureService;
|
|
readonly providerEnvironment?: Readonly<NodeJS.ProcessEnv>;
|
|
readonly evmInterface?: EvmInterfaceService;
|
|
readonly sqliteDatabase?: SqliteDatabaseService;
|
|
readonly logger?: Logger;
|
|
readonly binaryLayout?: BinaryLayoutService;
|
|
readonly goBinary?: GoBinaryService;
|
|
readonly il2cppMetadata?: Il2cppMetadataService;
|
|
readonly rustBinary?: RustBinaryService;
|
|
readonly pythonPyc?: PythonPycService;
|
|
readonly erlangBeam?: BeamService;
|
|
readonly electronFuses?: ElectronFuseService;
|
|
readonly recordedCrash?: RecordedCrashService;
|
|
readonly firmwareAnalysis?: FirmwareAnalysisPort;
|
|
readonly javascriptRecovery?: JavaScriptRecoveryPort;
|
|
readonly webModuleTrace?: WebModuleTraceService;
|
|
readonly webSourceLocation?: WebSourceLocationService;
|
|
readonly webRuntime?: WebRuntimeService;
|
|
readonly webNetworkCapture?: WebNetworkCaptureService;
|
|
readonly androidAnalysis?: AndroidAnalysisPort;
|
|
readonly apktoolAnalysis?: ApktoolResourceAnalysisPort;
|
|
readonly pcapAnalysis?: PcapAnalysisPort;
|
|
readonly flutterAnalysis?: FlutterBuildAnalysisPort;
|
|
readonly jebAnalysis?: JebAnalysisPort;
|
|
readonly adbDeviceAnalysis?: AdbDeviceAnalysisPort;
|
|
readonly browserObservation?: BrowserObservationPort;
|
|
readonly browserScenarioCapture?: BrowserScenarioCapturePort;
|
|
readonly electronObservation?: ElectronObservationPort;
|
|
/** Selects who closes the shared optional observation providers. */
|
|
readonly optionalObservationProviderOwner?: "server" | "caller";
|
|
readonly electronActiveObservation?: ElectronActiveObservationPort;
|
|
readonly javascriptRuntimeObservation?: JavaScriptRuntimeObservationPort;
|
|
readonly fridaInstrumentation?: FridaInstrumentationPort;
|
|
readonly availabilityPolicy?: () => AvailabilityPolicy;
|
|
readonly optionalProviderLoadFailures?: OptionalProviderLoadFailures;
|
|
}
|
|
|
|
/** Apply the shared TShark selection rule without starting the tool. */
|
|
const tsharkLocatable = (environment: Readonly<NodeJS.ProcessEnv>): boolean => {
|
|
try {
|
|
return (
|
|
locateWiresharkTool(
|
|
selectWiresharkTool(environment, "tshark"),
|
|
environment,
|
|
) !== undefined
|
|
);
|
|
} catch {
|
|
// A relative REA_TSHARK_COMMAND is configuration the tool reports at execution.
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const installSessionToolAvailability = (
|
|
session: BinarySessionPort | undefined,
|
|
options: CreateServerOptions,
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
fridaInstrumentation: FridaInstrumentationPort,
|
|
) => {
|
|
if (session === undefined) return undefined;
|
|
const { platform, arch } = process;
|
|
// Each provider owns its verified host; discovery and execution share it.
|
|
const verifiedHost = {
|
|
packetCapture: tsharkHostSupported(platform),
|
|
pcapCapture: pcapCaptureHostSupported(platform),
|
|
signalRecording: sigrokHostSupported(platform),
|
|
evmInterface: evmHostSupported(platform, arch),
|
|
pwntools: pwntoolsHostSupported(platform, arch),
|
|
firmware: firmwareHostSupported(platform),
|
|
javascriptRecovery: wakaruHostSupported(platform, arch),
|
|
};
|
|
const pwntools =
|
|
verifiedHost.pwntools && isAbsolute(environment.REA_PWNTOOLS_PYTHON ?? "");
|
|
// Injected services own their availability on any host. Otherwise no
|
|
// configuration lets an integration pass its execution host check.
|
|
const outsideVerifiedHost = (injected: unknown, supported: boolean) =>
|
|
injected === undefined && !supported;
|
|
const basePolicy = sessionAvailabilityPolicy(options.availabilityPolicy, {
|
|
optionalProviderLoadFailures: options.optionalProviderLoadFailures,
|
|
hostUnsupported: {
|
|
pcapCapture: outsideVerifiedHost(
|
|
options.pcapAnalysis,
|
|
verifiedHost.pcapCapture,
|
|
),
|
|
packetCapture: outsideVerifiedHost(
|
|
options.packetCapture,
|
|
verifiedHost.packetCapture,
|
|
),
|
|
signalRecording: outsideVerifiedHost(
|
|
options.signalRecording,
|
|
verifiedHost.signalRecording,
|
|
),
|
|
evmInterface: outsideVerifiedHost(
|
|
options.evmInterface,
|
|
verifiedHost.evmInterface,
|
|
),
|
|
binaryLayout: outsideVerifiedHost(
|
|
options.binaryLayout,
|
|
verifiedHost.pwntools,
|
|
),
|
|
recordedCrash: outsideVerifiedHost(
|
|
options.recordedCrash,
|
|
verifiedHost.pwntools,
|
|
),
|
|
firmwareInspection: outsideVerifiedHost(
|
|
options.firmwareAnalysis,
|
|
verifiedHost.firmware,
|
|
),
|
|
firmwareExtraction: outsideVerifiedHost(
|
|
options.firmwareAnalysis,
|
|
verifiedHost.firmware,
|
|
),
|
|
javascriptRecovery: outsideVerifiedHost(
|
|
options.javascriptRecovery,
|
|
verifiedHost.javascriptRecovery,
|
|
),
|
|
},
|
|
optionalFeatures: {
|
|
packetCaptureEnabled:
|
|
options.packetCapture !== undefined ||
|
|
(verifiedHost.packetCapture && tsharkLocatable(environment)),
|
|
signalRecordingEnabled:
|
|
options.signalRecording !== undefined ||
|
|
(verifiedHost.signalRecording &&
|
|
isAbsolute(environment.REA_SIGROK_COMMAND ?? "")),
|
|
wasmArtifactEnabled:
|
|
options.wasmArtifact !== undefined ||
|
|
isAbsolute(environment.REA_WABT_BIN_DIRECTORY ?? ""),
|
|
evmInterfaceEnabled:
|
|
options.evmInterface !== undefined || verifiedHost.evmInterface,
|
|
webModuleResolutionEnabled:
|
|
options.webModuleTrace !== undefined ||
|
|
isAbsolute(environment.REA_BROWSER_EXECUTABLE ?? ""),
|
|
recordedCrashEnabled: options.recordedCrash !== undefined || pwntools,
|
|
binaryLayoutEnabled: options.binaryLayout !== undefined || pwntools,
|
|
firmwareInspectionEnabled:
|
|
options.firmwareAnalysis !== undefined ||
|
|
(verifiedHost.firmware &&
|
|
isAbsolute(environment.REA_BINWALK_COMMAND ?? "")),
|
|
firmwareExtractionEnabled:
|
|
options.firmwareAnalysis !== undefined ||
|
|
(verifiedHost.firmware &&
|
|
isAbsolute(environment.REA_UNBLOB_COMMAND ?? "")),
|
|
browserObservationEnabled: options.browserObservation !== undefined,
|
|
javascriptRecoveryEnabled:
|
|
options.javascriptRecovery !== undefined ||
|
|
(verifiedHost.javascriptRecovery &&
|
|
isAbsolute(environment.REA_WAKARU_COMMAND ?? "")),
|
|
browserScenarioEnabled: options.browserScenarioCapture !== undefined,
|
|
electronObservationEnabled: options.electronObservation !== undefined,
|
|
electronAutomationEnabled:
|
|
options.electronActiveObservation !== undefined,
|
|
v8InspectorObservationEnabled:
|
|
options.javascriptRuntimeObservation !== undefined,
|
|
},
|
|
});
|
|
const policy = (): AvailabilityPolicy => {
|
|
const value = basePolicy();
|
|
const fridaFailure =
|
|
options.optionalProviderLoadFailures?.fridaInstrumentation ??
|
|
fridaInstrumentation.availabilityFailure?.();
|
|
return fridaFailure === undefined
|
|
? value
|
|
: {
|
|
...value,
|
|
optionalProviderLoadFailures: {
|
|
...value.optionalProviderLoadFailures,
|
|
fridaInstrumentation: fridaFailure,
|
|
},
|
|
};
|
|
};
|
|
return {
|
|
policy,
|
|
...(options.evmInterface !== undefined || !verifiedHost.evmInterface
|
|
? {}
|
|
: {
|
|
evmLimiterAvailability: (signal: AbortSignal) =>
|
|
evmLimiterAvailability(environment, { signal }),
|
|
}),
|
|
};
|
|
};
|
|
|
|
const createMcpServer = (
|
|
session: BinarySessionPort | undefined,
|
|
delivery: ToolResultDelivery,
|
|
compactPresentation: CompactInputSchemaPresentation | undefined,
|
|
outputSchemaProfile: McpOutputSchemaProfile,
|
|
advertisedToolFamilies: ReadonlySet<string> | undefined,
|
|
): EvidenceMcpServer =>
|
|
new EvidenceMcpServer(
|
|
{
|
|
name: PRODUCT_IDENTITY.mcpServerKey,
|
|
version: PRODUCT_IDENTITY.packageVersion,
|
|
},
|
|
{
|
|
capabilities: {},
|
|
instructions: serverInstructions(
|
|
session !== undefined,
|
|
advertisedToolFamilies,
|
|
),
|
|
},
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
delivery,
|
|
compactPresentation,
|
|
outputSchemaProfile,
|
|
catalogIdentityForToolFamilies(
|
|
compactPresentation,
|
|
outputSchemaProfile,
|
|
advertisedToolFamilies,
|
|
),
|
|
advertisedToolFamilies,
|
|
);
|
|
|
|
/**
|
|
* Construct one MCP server without acquiring subprocess resources.
|
|
* Supplying a session adds target lifecycle tools; omitting it retains the
|
|
* fixed-target seam used by focused tests and embedders.
|
|
*/
|
|
export const createServer = (
|
|
source: ServerAnalysisSource,
|
|
options: CreateServerOptions = {},
|
|
): EvidenceMcpServer => {
|
|
const session = source.kind === "session" ? source.session : undefined;
|
|
const analysis = source.kind === "session" ? source.session : source.analysis;
|
|
const environment = snapshotEnvironment(options.environment ?? process.env);
|
|
const analysisSettings =
|
|
options.analysisSettings ?? new AnalysisSettings(environment);
|
|
const compactInputPresentation =
|
|
selectCompactInputSchemaPresentation(environment);
|
|
const selectedOutputSchemaProfile = outputSchemaProfile(environment);
|
|
const advertisedToolFamilies = selectAdvertisedToolFamilies(environment);
|
|
const providerEnvironment = captureProviderEnvironment(
|
|
options.providerEnvironment,
|
|
environment,
|
|
);
|
|
const delivery = selectToolResultDelivery(environment, options.delivery);
|
|
const evmInterface =
|
|
options.evmInterface ?? evmInterfaceModule.create(environment);
|
|
const sqliteDatabase =
|
|
options.sqliteDatabase ?? createSqliteDatabaseService(environment);
|
|
const binaryLayout =
|
|
options.binaryLayout ?? createBinaryLayoutService(environment);
|
|
const recordedCrash =
|
|
options.recordedCrash ?? createRecordedCrashService(environment);
|
|
const webSourceLocation =
|
|
options.webSourceLocation ?? createWebSourceLocationService(environment);
|
|
const webModuleTrace =
|
|
options.webModuleTrace ?? createWebModuleTraceService(environment);
|
|
const desktopApplication = createDesktopApplicationService();
|
|
const goBinary = options.goBinary ?? createGoBinaryService();
|
|
const rustBinary = options.rustBinary ?? createRustBinaryService();
|
|
const erlangBeam = options.erlangBeam ?? createBeamService();
|
|
const modelArtifact = createModelArtifactService();
|
|
const gpuCodeObjects = createGpuCodeObjectsService();
|
|
const il2cppMetadata =
|
|
options.il2cppMetadata ?? createIl2cppMetadataService();
|
|
const peResources = createPeResourcesService();
|
|
const nativeExports = createNativeExportsService();
|
|
const devicetree = createDevicetreeService();
|
|
const elfNotes = createElfNotesService();
|
|
const appleIps = createAppleIpsService();
|
|
const kernelModule = createKernelModuleService();
|
|
const peLoadConfig = createPeLoadConfigService();
|
|
const peCertificates = createPeCertificatesService();
|
|
const peImports = createPeImportsService();
|
|
const electronFuses = options.electronFuses ?? createElectronFuseService();
|
|
const pythonPyc = options.pythonPyc ?? createPythonPycService();
|
|
const webNetworkCapture =
|
|
options.webNetworkCapture ??
|
|
createWebNetworkCaptureService(environment, analysisSettings.read);
|
|
const javascriptRecovery =
|
|
options.javascriptRecovery ?? createJavaScriptRecoveryProvider(environment);
|
|
const artifactResources = new ArtifactResourceScope();
|
|
const reverseEngineering =
|
|
createReverseEngineeringService(providerEnvironment);
|
|
const firmwareAnalysis = new FirmwareAnalysisService(
|
|
options.firmwareAnalysis ?? createFirmwareAnalysisProvider(environment),
|
|
);
|
|
const selectedOptions = {
|
|
...options,
|
|
environment,
|
|
delivery,
|
|
evmInterface,
|
|
sqliteDatabase,
|
|
binaryLayout,
|
|
recordedCrash,
|
|
webSourceLocation,
|
|
webModuleTrace,
|
|
javascriptRecovery,
|
|
};
|
|
const startedAt = options.startedAt ?? new Date().toISOString();
|
|
const logger = options.logger ?? silentLogger;
|
|
const server =
|
|
options.mcpServer ??
|
|
createMcpServer(
|
|
session,
|
|
delivery,
|
|
compactInputPresentation,
|
|
selectedOutputSchemaProfile,
|
|
advertisedToolFamilies,
|
|
);
|
|
server.analysisSettings = analysisSettings;
|
|
registerAnalysisSettingsTools(server, analysisSettings);
|
|
if (options.mcpServer !== undefined) {
|
|
server.attachRuntime(
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
delivery,
|
|
catalogIdentityForToolFamilies(
|
|
compactInputPresentation,
|
|
selectedOutputSchemaProfile,
|
|
advertisedToolFamilies,
|
|
),
|
|
);
|
|
}
|
|
const gdbSessions = new GdbSessionManager({
|
|
environment: providerEnvironment,
|
|
});
|
|
const rizinDebugSessions = new RizinDebugSessionManager(providerEnvironment);
|
|
const android =
|
|
options.androidAnalysis ??
|
|
createAndroidAnalysisProvider(
|
|
environment,
|
|
undefined,
|
|
analysisSettings.read,
|
|
);
|
|
const pcap = options.pcapAnalysis ?? createPcapAnalysisProvider(environment);
|
|
const flutter =
|
|
options.flutterAnalysis ?? createFlutterBuildAnalysisProvider();
|
|
const fridaInstrumentation =
|
|
options.fridaInstrumentation ?? new FridaInstrumentationManager();
|
|
const wasmArtifact = wasmArtifactModule.create(
|
|
environment,
|
|
options.wasmArtifact,
|
|
analysisSettings.read,
|
|
);
|
|
const apkSignature = apkSignatureModule.create(
|
|
environment,
|
|
options.apkSignature,
|
|
);
|
|
const packetCapture =
|
|
options.packetCapture ?? createPacketCaptureService(environment);
|
|
const signalRecording =
|
|
options.signalRecording ?? createSignalRecordingService(environment);
|
|
const webRuntime = options.webRuntime ?? createWebRuntimeService();
|
|
const apktool =
|
|
options.apktoolAnalysis ??
|
|
createApktoolResourceAnalysisProvider(environment);
|
|
const jeb = options.jebAnalysis ?? createJebAnalysisProvider(environment);
|
|
const adbDevice =
|
|
options.adbDeviceAnalysis ?? createAdbDeviceAnalysisProvider(environment);
|
|
const cutter = new CutterBridgeService(
|
|
new CutterBridgeClient(providerEnvironment),
|
|
);
|
|
let providerClose: Promise<void> | undefined;
|
|
const closeProviders = (): Promise<void> => {
|
|
providerClose ??= Promise.allSettled([
|
|
android.close(),
|
|
cutter.close(),
|
|
fridaInstrumentation.closeAll(),
|
|
wasmArtifact.close(),
|
|
apkSignature.close(),
|
|
packetCapture.close(),
|
|
signalRecording.close(),
|
|
apktool.close(),
|
|
jeb.close(),
|
|
adbDevice.close(),
|
|
flutter.close(),
|
|
pcap.close(),
|
|
evmInterface.close(),
|
|
sqliteDatabase.close(),
|
|
binaryLayout.close(),
|
|
recordedCrash.close(),
|
|
webSourceLocation.close(),
|
|
webModuleTrace.close(),
|
|
desktopApplication.close(),
|
|
goBinary.close(),
|
|
rustBinary.close(),
|
|
erlangBeam.close(),
|
|
il2cppMetadata.close(),
|
|
modelArtifact.close(),
|
|
gpuCodeObjects.close(),
|
|
peResources.close(),
|
|
nativeExports.close(),
|
|
devicetree.close(),
|
|
elfNotes.close(),
|
|
appleIps.close(),
|
|
kernelModule.close(),
|
|
peLoadConfig.close(),
|
|
peCertificates.close(),
|
|
peImports.close(),
|
|
electronFuses.close(),
|
|
pythonPyc.close(),
|
|
webNetworkCapture.close(),
|
|
javascriptRecovery.close?.() ?? Promise.resolve(),
|
|
...(options.optionalObservationProviderOwner === "caller"
|
|
? []
|
|
: [
|
|
options.browserObservation?.close?.() ?? Promise.resolve(),
|
|
options.browserScenarioCapture?.close?.() ?? Promise.resolve(),
|
|
options.electronObservation?.close?.() ?? Promise.resolve(),
|
|
options.electronActiveObservation?.close?.() ?? Promise.resolve(),
|
|
options.javascriptRuntimeObservation?.close?.() ??
|
|
Promise.resolve(),
|
|
]),
|
|
webRuntime.provider.close?.() ?? Promise.resolve(),
|
|
artifactResources.close(),
|
|
reverseEngineering.close(),
|
|
firmwareAnalysis.close(),
|
|
gdbSessions.closeAll(),
|
|
rizinDebugSessions.closeAll(),
|
|
])
|
|
.then((results) => {
|
|
const failures = results.flatMap((result) =>
|
|
result.status === "rejected" ? [result.reason] : [],
|
|
);
|
|
if (failures.length > 0)
|
|
throw new AggregateError(failures, "REA provider cleanup failed");
|
|
})
|
|
.catch((cause: unknown) => {
|
|
providerClose = undefined;
|
|
throw cause;
|
|
});
|
|
return providerClose;
|
|
};
|
|
const availability = installSessionToolAvailability(
|
|
session,
|
|
options,
|
|
environment,
|
|
fridaInstrumentation,
|
|
);
|
|
const toolLogger = logger.child({ layer: "server" });
|
|
const {
|
|
evidenceById,
|
|
activeTarget,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
} = createSessionRecorders(server, session);
|
|
const analysisAdmission = withAdmittedAnalysis(source);
|
|
const toolContext: ServerToolContext = {
|
|
server,
|
|
session,
|
|
options: selectedOptions,
|
|
environment,
|
|
logger: toolLogger,
|
|
evidenceById,
|
|
activeTarget,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
withAdmittedAnalysis: analysisAdmission,
|
|
artifactResources,
|
|
goBinary,
|
|
rustBinary,
|
|
erlangBeam,
|
|
il2cppMetadata,
|
|
peResources,
|
|
nativeExports,
|
|
devicetree,
|
|
elfNotes,
|
|
appleIps,
|
|
kernelModule,
|
|
peLoadConfig,
|
|
peCertificates,
|
|
peImports,
|
|
electronFuses,
|
|
pythonPyc,
|
|
webNetworkCapture,
|
|
};
|
|
registerDesktopApplicationTool(
|
|
server,
|
|
desktopApplication,
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
evidenceById,
|
|
);
|
|
registerModelArtifactTools(
|
|
server,
|
|
modelArtifact,
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
evidenceById,
|
|
);
|
|
registerGpuCodeObjectsTools(
|
|
server,
|
|
gpuCodeObjects,
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
evidenceById,
|
|
);
|
|
registerBinaryAnalysisTools(toolContext);
|
|
registerReverseEngineeringTools(
|
|
server,
|
|
reverseEngineering,
|
|
toolLogger,
|
|
delivery,
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
analysisAdmission,
|
|
session === undefined
|
|
? undefined
|
|
: () => session.invalidateSnapshotForExternalMutation(),
|
|
session === undefined
|
|
? undefined
|
|
: (path, signal, operation, rebindFailure) =>
|
|
session.withAdmittedExternalMutation(
|
|
path,
|
|
signal,
|
|
operation,
|
|
rebindFailure,
|
|
),
|
|
evidenceById,
|
|
);
|
|
registerFridaTools(
|
|
server,
|
|
fridaInstrumentation,
|
|
toolLogger,
|
|
delivery,
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
evidenceById,
|
|
);
|
|
registerCutterTools(
|
|
server,
|
|
cutter,
|
|
toolLogger,
|
|
delivery,
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
session,
|
|
);
|
|
registerGdbTools(
|
|
server,
|
|
gdbSessions,
|
|
toolLogger,
|
|
delivery,
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
session,
|
|
evidenceById,
|
|
);
|
|
registerRizinDebugTools(
|
|
server,
|
|
rizinDebugSessions,
|
|
toolLogger,
|
|
delivery,
|
|
session === undefined
|
|
? undefined
|
|
: (evidence) => session.recordEvidence(evidence),
|
|
session,
|
|
);
|
|
const previousOnclose = server.server.onclose;
|
|
server.server.onclose = () => {
|
|
previousOnclose?.();
|
|
void closeProviders().catch((cause: unknown) => {
|
|
logger.error(
|
|
{ error: cause instanceof Error ? cause.message : String(cause) },
|
|
"Provider cleanup failed during server shutdown",
|
|
);
|
|
});
|
|
};
|
|
const closeServer = server.close.bind(server);
|
|
server.close = async () => {
|
|
const results = await Promise.allSettled([closeServer(), closeProviders()]);
|
|
for (const result of results)
|
|
if (result.status === "rejected") throw result.reason;
|
|
};
|
|
registerCaptureTools(
|
|
server,
|
|
packetCapture,
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
);
|
|
registerSignalTools(
|
|
server,
|
|
signalRecording,
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
);
|
|
registerConfiguredAnalysisTools(
|
|
toolContext,
|
|
android,
|
|
wasmArtifact,
|
|
apkSignature,
|
|
evmInterface,
|
|
jeb,
|
|
firmwareAnalysis,
|
|
webRuntime,
|
|
);
|
|
registerAdbTools(
|
|
server,
|
|
new AdbDeviceAnalysisService(adbDevice),
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
);
|
|
registerPcapTools(
|
|
server,
|
|
new PcapAnalysisService(pcap),
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
evidenceById,
|
|
);
|
|
registerFlutterTools(
|
|
server,
|
|
new FlutterBuildAnalysisService(flutter),
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
evidenceById,
|
|
);
|
|
registerApktoolTools(
|
|
server,
|
|
new ApktoolResourceAnalysisService(apktool),
|
|
toolLogger,
|
|
recordEvidence,
|
|
analysisAdmission,
|
|
);
|
|
registerObservationTools(toolContext);
|
|
registerGuidedPrompts(server, analysis, session);
|
|
if (session !== undefined) {
|
|
registerSessionTools(server, session, toolLogger, {
|
|
...selectedOptions,
|
|
artifactResources,
|
|
...(availability === undefined
|
|
? {}
|
|
: { availabilityPolicy: availability.policy }),
|
|
...(availability?.evmLimiterAvailability === undefined
|
|
? {}
|
|
: { evmLimiterAvailability: availability.evmLimiterAvailability }),
|
|
androidAnalysisAvailability: (signal) =>
|
|
android.inspectAvailability(signal),
|
|
adbAnalysisAvailability: (signal) =>
|
|
adbDevice.inspectAvailability(signal),
|
|
apktoolAnalysisAvailability: (signal) =>
|
|
apktool.inspectAvailability(signal),
|
|
jebAnalysisAvailability: (signal) => jeb.inspectAvailability(signal),
|
|
startedAt,
|
|
});
|
|
}
|
|
return server;
|
|
};
|
|
|
|
const selectToolResultDelivery = (
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
selected: ToolResultDelivery | undefined,
|
|
): ToolResultDelivery => {
|
|
if (selected !== undefined) return selected;
|
|
const configured = parseMcpResponseBudget(
|
|
environment.REA_MCP_MAX_RESPONSE_BYTES,
|
|
);
|
|
if (!configured.ok) throw configured.error;
|
|
return createToolResultDelivery(configured.value);
|
|
};
|
|
|
|
const outputSchemaProfile = (
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
): McpOutputSchemaProfile => {
|
|
const configured = parseMcpOutputSchemaProfile(
|
|
environment.REA_MCP_OUTPUT_SCHEMA_PROFILE,
|
|
);
|
|
if (!configured.ok) throw configured.error;
|
|
return configured.value ?? "full";
|
|
};
|
|
|
|
const selectCompactInputSchemaPresentation = (
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
): CompactInputSchemaPresentation | undefined => {
|
|
const configured = parseMcpInputSchemaProfile(
|
|
environment.REA_MCP_INPUT_SCHEMA_PROFILE,
|
|
);
|
|
if (!configured.ok) throw configured.error;
|
|
return compactPresentationForMcpInputSchemaProfile(configured.value);
|
|
};
|
|
|
|
const registerConfiguredAnalysisTools = (
|
|
{
|
|
server,
|
|
options,
|
|
environment,
|
|
logger: toolLogger,
|
|
evidenceById,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
goBinary,
|
|
rustBinary,
|
|
erlangBeam,
|
|
il2cppMetadata,
|
|
peResources,
|
|
nativeExports,
|
|
devicetree,
|
|
elfNotes,
|
|
appleIps,
|
|
kernelModule,
|
|
peLoadConfig,
|
|
peCertificates,
|
|
peImports,
|
|
pythonPyc,
|
|
webNetworkCapture,
|
|
artifactResources,
|
|
}: ServerToolContext,
|
|
android: AndroidAnalysisPort,
|
|
wasmArtifact: Pick<WasmArtifactService, "inspect" | "close">,
|
|
apkSignature: Pick<ApkSignatureService, "inspect" | "close">,
|
|
evmInterface: EvmInterfaceService,
|
|
jeb: JebAnalysisPort,
|
|
firmwareAnalysis: FirmwareAnalysisService,
|
|
webRuntime: WebRuntimeService,
|
|
): void => {
|
|
registerAndroidTools(
|
|
server,
|
|
new AndroidAnalysisService(android, recordEvidence),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerJebTools(
|
|
server,
|
|
new JebAnalysisService(jeb),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerBinaryDiagnosticsTools(
|
|
server,
|
|
options.binaryLayout ?? createBinaryLayoutService(environment),
|
|
createByteEntropyService(artifactResources),
|
|
toolLogger,
|
|
recordEvidence,
|
|
evidenceById,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerAnalysisViewTool(
|
|
server,
|
|
toolLogger,
|
|
evidenceById,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
artifactResources,
|
|
);
|
|
registerPeResourcesTool(
|
|
server,
|
|
peResources,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerNativeExportsTool(
|
|
server,
|
|
nativeExports,
|
|
toolLogger,
|
|
recordEvidence,
|
|
evidenceById,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerDevicetreeTool(
|
|
server,
|
|
devicetree,
|
|
toolLogger,
|
|
recordEvidence,
|
|
evidenceById,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerElfNotesTool(
|
|
server,
|
|
elfNotes,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerAppleIpsTool(
|
|
server,
|
|
appleIps,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerKernelModuleTool(
|
|
server,
|
|
kernelModule,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerPeLoadConfigTool(
|
|
server,
|
|
peLoadConfig,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerPeCertificatesTool(
|
|
server,
|
|
peCertificates,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerPeImportsTool(
|
|
server,
|
|
peImports,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerGoTools(
|
|
server,
|
|
goBinary,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerIl2cppTools(
|
|
server,
|
|
il2cppMetadata,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerRustTools(
|
|
server,
|
|
rustBinary,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerPythonPycTool(
|
|
server,
|
|
pythonPyc,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerErlangTools(
|
|
server,
|
|
erlangBeam,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerWasmTools(
|
|
server,
|
|
wasmArtifact,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerApkSignatureTools(
|
|
server,
|
|
apkSignature,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerEvmTools(
|
|
server,
|
|
evmInterface,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerSqliteTools(
|
|
server,
|
|
options.sqliteDatabase ?? createSqliteDatabaseService(environment),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerRecordedCrashTools(
|
|
server,
|
|
options.recordedCrash ?? createRecordedCrashService(environment),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerFirmwareTools(
|
|
server,
|
|
firmwareAnalysis,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerWebModuleTool(
|
|
server,
|
|
options.webModuleTrace ?? createWebModuleTraceService(environment),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerWebSourceLocationTool(
|
|
server,
|
|
options.webSourceLocation ?? createWebSourceLocationService(environment),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerWebRuntimeTools(
|
|
server,
|
|
webRuntime,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
registerWebNetworkCaptureTool(
|
|
server,
|
|
webNetworkCapture,
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
evidenceById,
|
|
);
|
|
registerJavaScriptRecoveryTool(
|
|
server,
|
|
new JavaScriptRecoveryService(
|
|
options.javascriptRecovery ??
|
|
createJavaScriptRecoveryProvider(environment),
|
|
),
|
|
toolLogger,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
);
|
|
};
|
|
|
|
const createSessionRecorders = (
|
|
server: EvidenceMcpServer,
|
|
session: BinarySessionPort | undefined,
|
|
) => ({
|
|
evidenceById:
|
|
session === undefined
|
|
? undefined
|
|
: session.evidenceForAnalysis.bind(session),
|
|
activeTarget:
|
|
session === undefined ? undefined : () => session.activeTarget(),
|
|
recordEvidence:
|
|
session === undefined
|
|
? undefined
|
|
: (evidence: Parameters<typeof session.recordEvidence>[0]) =>
|
|
session.recordEvidence(evidence),
|
|
recordEvidenceWithUnknown:
|
|
session === undefined
|
|
? undefined
|
|
: (
|
|
evidence: Parameters<typeof session.recordEvidenceWithUnknown>[0],
|
|
input: Parameters<typeof session.recordEvidenceWithUnknown>[1],
|
|
) => session.recordEvidenceWithUnknown(evidence, input),
|
|
});
|
|
|
|
interface ServerToolContext extends ReturnType<typeof createSessionRecorders> {
|
|
readonly goBinary: GoBinaryService;
|
|
readonly rustBinary: RustBinaryService;
|
|
readonly erlangBeam: BeamService;
|
|
readonly il2cppMetadata: Il2cppMetadataService;
|
|
readonly peResources: PeResourcesService;
|
|
readonly nativeExports: NativeExportsService;
|
|
readonly devicetree: DevicetreeService;
|
|
readonly elfNotes: ElfNotesService;
|
|
readonly appleIps: AppleIpsService;
|
|
readonly kernelModule: KernelModuleService;
|
|
readonly peLoadConfig: PeLoadConfigService;
|
|
readonly peCertificates: PeCertificatesService;
|
|
readonly peImports: PeImportsService;
|
|
readonly electronFuses: ElectronFuseService;
|
|
readonly pythonPyc: PythonPycService;
|
|
readonly webNetworkCapture: WebNetworkCaptureService;
|
|
readonly artifactResources: ArtifactResourceScope;
|
|
readonly server: EvidenceMcpServer;
|
|
readonly session: BinarySessionPort | undefined;
|
|
readonly options: CreateServerOptions;
|
|
readonly environment: Readonly<NodeJS.ProcessEnv>;
|
|
readonly logger: Logger;
|
|
readonly withAdmittedAnalysis: WithAdmittedAnalysis;
|
|
}
|
|
|
|
const registerBinaryAnalysisTools = ({
|
|
server,
|
|
session,
|
|
logger,
|
|
activeTarget,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
evidenceById,
|
|
withAdmittedAnalysis,
|
|
}: ServerToolContext): void => {
|
|
const recordUnknown =
|
|
session === undefined
|
|
? undefined
|
|
: (input: Parameters<typeof session.recordUnknown>[0]) =>
|
|
session.recordUnknown(input);
|
|
const analysisOptions = {
|
|
logger,
|
|
activeTarget,
|
|
recordEvidence,
|
|
recordUnknown,
|
|
evidenceById,
|
|
withAdmittedAnalysis,
|
|
};
|
|
registerOfficialTools(server, analysisOptions);
|
|
registerEnhancedTools(server, {
|
|
...analysisOptions,
|
|
analysisProfile:
|
|
session === undefined
|
|
? undefined
|
|
: (operation) =>
|
|
session.analysisProfile() ?? session.analysisProfile(operation),
|
|
allowsSnapshotReplay:
|
|
session === undefined
|
|
? undefined
|
|
: (operation) => session.allowsSnapshotReplay(operation),
|
|
recordWorkflowSnapshot:
|
|
session === undefined
|
|
? undefined
|
|
: (input) => session.recordWorkflowSnapshot(input),
|
|
});
|
|
const evidenceOptions = {
|
|
logger,
|
|
activeTarget,
|
|
recordEvidence,
|
|
withAdmittedAnalysis,
|
|
};
|
|
registerNativeTools(server, { ...evidenceOptions, evidenceById });
|
|
registerArtifactTools(server, { ...evidenceOptions, evidenceById });
|
|
registerManagedTools(server, { ...evidenceOptions, evidenceById });
|
|
if (session !== undefined)
|
|
registerManagedWorkflowTools(server, {
|
|
logger,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
session,
|
|
withAdmittedAnalysis,
|
|
});
|
|
};
|
|
|
|
const registerObservationTools = ({
|
|
electronFuses,
|
|
evidenceById,
|
|
server,
|
|
options,
|
|
logger,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
withAdmittedAnalysis,
|
|
artifactResources,
|
|
environment,
|
|
}: ServerToolContext): void => {
|
|
const common = { logger, recordEvidence, withAdmittedAnalysis };
|
|
registerWebScriptTool(server, { ...common, artifactResources });
|
|
registerBrowserTools(server, {
|
|
...common,
|
|
evidenceById,
|
|
browser: options.browserObservation,
|
|
loadFailure: options.optionalProviderLoadFailures?.browserObservation,
|
|
});
|
|
registerBrowserScenarioTool(server, {
|
|
...common,
|
|
evidenceById,
|
|
provider: options.browserScenarioCapture,
|
|
loadFailure: options.optionalProviderLoadFailures?.browserScenarioCapture,
|
|
});
|
|
registerElectronTools(server, {
|
|
...common,
|
|
artifactResources,
|
|
environment,
|
|
evidenceById,
|
|
electron: options.electronObservation,
|
|
electronActive: options.electronActiveObservation,
|
|
electronFuses,
|
|
observationLoadFailure:
|
|
options.optionalProviderLoadFailures?.electronObservation,
|
|
activeLoadFailure:
|
|
options.optionalProviderLoadFailures?.electronActiveObservation,
|
|
});
|
|
registerJavaScriptRuntimeObservationTools(server, {
|
|
...common,
|
|
runtime: options.javascriptRuntimeObservation,
|
|
loadFailure:
|
|
options.optionalProviderLoadFailures?.javascriptRuntimeObservation,
|
|
});
|
|
registerApplicationTools(server, {
|
|
artifactResources,
|
|
evidenceById,
|
|
logger,
|
|
recordEvidence,
|
|
recordEvidenceWithUnknown,
|
|
withAdmittedAnalysis,
|
|
});
|
|
};
|
|
|
|
const selectAdvertisedToolFamilies = (
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
): ReadonlySet<string> | undefined => {
|
|
const configured = parseMcpToolFamilies(environment.REA_MCP_TOOL_FAMILIES);
|
|
if (!configured.ok) throw configured.error;
|
|
return configured.value === undefined ? undefined : new Set(configured.value);
|
|
};
|