Skip to main content
Glama
REMnux

REMnux MCP Server

Official
by REMnux

get_file_info

Extract file type, cryptographic hashes, and basic metadata from files for malware analysis and security investigations.

Instructions

Get file type, hashes, and basic metadata

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fileYesFile path relative to samples directory, or absolute path in local mode

Implementation Reference

  • Main handler function handleGetFileInfo that executes file analysis commands (file, sha256sum, md5sum, sha1sum, stat) to gather metadata including file type, cryptographic hashes, and size. Includes path validation, error handling, and returns standardized MCP response.
    export async function handleGetFileInfo(
      deps: HandlerDeps,
      args: GetFileInfoArgs
    ) {
      const startTime = Date.now();
      try {
      const { connector, config } = deps;
    
      // Validate file path (skip unless --sandbox)
      if (!config.noSandbox) {
        const validation = validateFilePath(args.file, config.samplesDir);
        if (!validation.safe) {
          return formatError("get_file_info", new REMnuxError(
            validation.error || "Invalid file path",
            "INVALID_PATH",
            "validation",
            "Use a relative path within the samples directory",
          ), startTime);
        }
      }
    
      const filePath = (config.mode === "local" && args.file.startsWith("/")) ? args.file : `${config.samplesDir}/${args.file}`;
      let fileType = "";
      let sha256 = "";
      let md5 = "";
      let sizeBytes: number | null = null;
    
      // file command
      try {
        const result = await connector.execute(["file", filePath], { timeout: 30000 });
        if (result.stdout) fileType = result.stdout.trim();
      } catch (error) {
        const mapped = toREMnuxError(error, config.mode);
        if (mapped.code === "CONNECTION_FAILED") {
          return formatError("get_file_info", mapped, startTime);
        }
        // Non-connection errors: continue (file command failure is non-fatal)
      }
    
      // sha256sum
      try {
        const result = await connector.execute(["sha256sum", filePath], { timeout: 30000 });
        if (result.stdout) sha256 = result.stdout.trim().split(/\s+/)[0] || "";
      } catch { /* skip */ }
    
      // md5sum
      try {
        const result = await connector.execute(["md5sum", filePath], { timeout: 30000 });
        if (result.stdout) md5 = result.stdout.trim().split(/\s+/)[0] || "";
      } catch { /* skip */ }
    
      // sha1sum
      let sha1 = "";
      try {
        const result = await connector.execute(["sha1sum", filePath], { timeout: 30000 });
        if (result.stdout) sha1 = result.stdout.trim().split(/\s+/)[0] || "";
      } catch { /* skip */ }
    
      // file size (stat -c works on Linux/REMnux; wc -c as fallback)
      try {
        const result = await connector.execute(["stat", "-c", "%s", filePath], { timeout: 30000 });
        if (result.stdout && result.exitCode === 0) {
          sizeBytes = parseInt(result.stdout.trim(), 10);
        }
      } catch { /* skip */ }
      if (sizeBytes === null) {
        try {
          const result = await connector.execute(["wc", "-c", filePath], { timeout: 30000 });
          if (result.stdout && result.exitCode === 0) {
            sizeBytes = parseInt(result.stdout.trim().split(/\s+/)[0] || "0", 10);
          }
        } catch { /* skip */ }
      }
    
      if (!fileType && !sha256 && !md5) {
        return formatError("get_file_info", new REMnuxError(
          "Could not get file info",
          "EMPTY_OUTPUT",
          "tool_failure",
          "Check that the file exists and is readable",
        ), startTime);
      }
    
      return formatResponse("get_file_info", {
        file: args.file,
        file_type: fileType,
        sha256,
        sha1,
        md5,
        ...(sizeBytes !== null ? { size_bytes: sizeBytes } : {}),
      }, startTime);
      } catch (error) {
        return formatError("get_file_info", toREMnuxError(error, deps.config.mode), startTime);
      }
    }
  • Zod schema definition for getFileInfoSchema and its inferred type GetFileInfoArgs. Validates input with a single 'file' parameter that accepts a file path relative to samples directory or absolute path in local mode.
    export const getFileInfoSchema = z.object({
      file: z.string().describe("File path relative to samples directory, or absolute path in local mode"),
    });
    export type GetFileInfoArgs = z.infer<typeof getFileInfoSchema>;
  • src/index.ts:104-109 (registration)
    MCP server tool registration for get_file_info. Registers the tool with its name 'get_file_info', description 'Get file type, hashes, and basic metadata', schema shape, and handler function bound with dependencies.
    server.tool(
      "get_file_info",
      "Get file type, hashes, and basic metadata",
      getFileInfoSchema.shape,
      (args) => handleGetFileInfo(deps, args)
    );
  • formatResponse helper function that creates standardized success response envelopes with tool name, data, and elapsed time metadata. Used by get_file_info handler to return results.
    export function formatResponse(
      tool: string,
      data: Record<string, unknown>,
      startTime: number,
    ): { content: Array<{ type: "text"; text: string }>; isError?: boolean } {
      const envelope: ToolResponse = {
        success: true,
        tool,
        data,
        metadata: { elapsed_ms: Date.now() - startTime },
      };
      const COMPACT_THRESHOLD = 50 * 1024;
      const compact = JSON.stringify(envelope);
      const text = compact.length > COMPACT_THRESHOLD ? compact : JSON.stringify(envelope, null, 2);
      return {
        content: [{ type: "text", text }],
      };
    }
  • formatError helper function that creates standardized error response envelopes with structured error fields (code, category, remediation) when error is a REMnuxError instance. Used by get_file_info handler for error reporting.
    export function formatError(
      tool: string,
      error: string | REMnuxError,
      startTime: number,
    ): { content: Array<{ type: "text"; text: string }>; isError: true } {
      const envelope: ToolResponse = {
        success: false,
        tool,
        data: {},
        error: error instanceof REMnuxError ? error.message : error,
        metadata: { elapsed_ms: Date.now() - startTime },
      };
    
      if (error instanceof REMnuxError) {
        envelope.error_code = error.code;
        envelope.error_category = error.category;
        if (error.remediation) {
          envelope.remediation = error.remediation;
        }
      }
    
      return {
        content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
        isError: true,
      };
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions what information is retrieved but lacks details on permissions, rate limits, error handling, or whether this is a read-only operation. For a tool with no annotations, this leaves significant gaps in understanding its behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise and front-loaded, consisting of a single, clear sentence that directly states the tool's purpose without any unnecessary words. Every part of the sentence earns its place by specifying what is retrieved.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of annotations and output schema, the description is incomplete. It doesn't cover behavioral aspects like safety, permissions, or output format, which are crucial for a tool that retrieves file metadata. This leaves the agent with insufficient context for reliable use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, with the 'file' parameter clearly documented in the schema. The description adds no additional parameter semantics beyond what's in the schema, so it meets the baseline of 3 for adequate but not enhanced parameter explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('Get') and resources ('file type, hashes, and basic metadata'), making it easy to understand what it does. However, it doesn't explicitly differentiate from sibling tools like 'analyze_file' or 'list_files', which might offer overlapping functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With siblings like 'analyze_file' and 'list_files' available, there's no indication of the specific context or scenarios where 'get_file_info' is preferred, leaving the agent to guess based on the tool name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/REMnux/remnux-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server