Skip to main content
Glama
Stankye

AssemblyLine 4 MCP Server

by Stankye

al4_ingest_url

Ingest a URL into AssemblyLine for asynchronous malware analysis. Configure alerts, classification, notification queue, and services.

Instructions

Asynchronously ingest a URL into AssemblyLine.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYes
notification_queueNo
alertNo
descriptionNo
classificationNo
servicesNo
metadataNo

Implementation Reference

  • Input schema definition for the al4_ingest_url tool. Declares the tool name, description, and input properties (url required, plus optional notification_queue, alert, description, classification, services, metadata).
      name: "al4_ingest_url",
      description: "Asynchronously ingest a URL into AssemblyLine.",
      inputSchema: {
        type: "object",
        properties: {
          url: { type: "string" },
          notification_queue: { type: "string" },
          alert: { type: "boolean" },
          description: { type: "string" },
          classification: { type: "string" },
          services: { type: "array", items: { type: "string" } },
          metadata: { type: "object", additionalProperties: { type: "string" } },
        },
        required: ["url"],
      },
    },
  • Handler execution for al4_ingest_url. The switch case routes to client.ingestUrl with the URL from args and ingest options built by buildIngestOptions().
    case "al4_ingest_url":
      result = await client.ingestUrl(a.url as string, buildIngestOptions(a));
      break;
  • The AL4Client.ingestUrl() method that performs the actual API call. Validates the URL, constructs a JSON body with optional name/params/metadata/notification_queue/notification_threshold/alert fields, and POSTs to /api/v4/ingest/.
    ingestUrl(
      url: string,
      options: IngestOptions = {},
    ): Promise<Record<string, unknown>> {
      if (!url) throw new Error("url is required");
      const body: Record<string, unknown> = { url };
      if (options.name) body.name = options.name;
      if (options.params) body.params = options.params;
      if (options.metadata) body.metadata = options.metadata;
      if (options.notification_queue)
        body.notification_queue = options.notification_queue;
      if (options.notification_threshold !== undefined)
        body.notification_threshold = options.notification_threshold;
      if (options.alert !== undefined) body.generate_alert = options.alert;
      return this.requestJson("POST", "/api/v4/ingest/", body, options);
    }
  • buildIngestOptions() helper that transforms raw args into the IngestOptions object, merging submit options (description, classification, services, metadata) with ingest-specific fields (notification_queue, alert).
    function buildIngestOptions(args: Record<string, unknown>) {
      return {
        ...buildSubmitOptions(args),
        notification_queue: args.notification_queue as string | undefined,
        alert: args.alert as boolean | undefined,
      };
    }
  • src/index.ts:25-318 (registration)
    The TOOLS array that registers all MCP tools including al4_ingest_url. This array is passed to ListToolsRequestSchema handler at line 371.
    const TOOLS = [
      {
        name: "al4_whoami",
        description: "Return details about the currently authenticated AssemblyLine user.",
        inputSchema: { type: "object", properties: {}, required: [] },
      },
      // ── Submit (synchronous, quota-limited) ────────────────────────────────
      {
        name: "al4_submit_file",
        description:
          "Submit a local file to AssemblyLine for immediate synchronous analysis. Returns a submission ID. Limited to 5 concurrent submissions.",
        inputSchema: {
          type: "object",
          properties: {
            file_path: { type: "string", description: "Absolute path to the file to analyse" },
            name: { type: "string", description: "Override display name for the file" },
            description: { type: "string", description: "Human-readable description of the submission" },
            classification: { type: "string", description: "Classification label (e.g. TLP:CLEAR)" },
            services: {
              type: "array",
              items: { type: "string" },
              description: "Specific services to run (empty = all defaults)",
            },
            metadata: {
              type: "object",
              additionalProperties: { type: "string" },
              description: "Key/value metadata attached to the submission",
            },
          },
          required: ["file_path"],
        },
      },
      {
        name: "al4_submit_url",
        description:
          "Submit a URL to AssemblyLine for immediate synchronous analysis.",
        inputSchema: {
          type: "object",
          properties: {
            url: { type: "string", description: "URL to analyse" },
            description: { type: "string" },
            classification: { type: "string" },
            services: { type: "array", items: { type: "string" } },
            metadata: { type: "object", additionalProperties: { type: "string" } },
          },
          required: ["url"],
        },
      },
      {
        name: "al4_submit_sha256",
        description:
          "Submit a file by its SHA256 hash to AssemblyLine for immediate synchronous analysis. The file must already exist in the AL4 file store.",
        inputSchema: {
          type: "object",
          properties: {
            sha256: { type: "string", description: "SHA256 hash of the file" },
            description: { type: "string" },
            classification: { type: "string" },
            services: { type: "array", items: { type: "string" } },
            metadata: { type: "object", additionalProperties: { type: "string" } },
          },
          required: ["sha256"],
        },
      },
      // ── Ingest (asynchronous, high-volume) ─────────────────────────────────
      {
        name: "al4_ingest_file",
        description:
          "Asynchronously ingest a local file into AssemblyLine. Preferred for high-volume workflows. Returns an ingest ID. Results arrive on a notification queue.",
        inputSchema: {
          type: "object",
          properties: {
            file_path: { type: "string", description: "Absolute path to the file" },
            notification_queue: { type: "string", description: "Queue name for completion notifications" },
            alert: { type: "boolean", description: "Generate an alert if score exceeds threshold" },
            name: { type: "string" },
            description: { type: "string" },
            classification: { type: "string" },
            services: { type: "array", items: { type: "string" } },
            metadata: { type: "object", additionalProperties: { type: "string" } },
          },
          required: ["file_path"],
        },
      },
      {
        name: "al4_ingest_url",
        description: "Asynchronously ingest a URL into AssemblyLine.",
        inputSchema: {
          type: "object",
          properties: {
            url: { type: "string" },
            notification_queue: { type: "string" },
            alert: { type: "boolean" },
            description: { type: "string" },
            classification: { type: "string" },
            services: { type: "array", items: { type: "string" } },
            metadata: { type: "object", additionalProperties: { type: "string" } },
          },
          required: ["url"],
        },
      },
      {
        name: "al4_ingest_sha256",
        description:
          "Asynchronously ingest a file by SHA256 hash into AssemblyLine. The file must already exist in the AL4 file store.",
        inputSchema: {
          type: "object",
          properties: {
            sha256: { type: "string" },
            notification_queue: { type: "string" },
            alert: { type: "boolean" },
            description: { type: "string" },
            classification: { type: "string" },
            services: { type: "array", items: { type: "string" } },
            metadata: { type: "object", additionalProperties: { type: "string" } },
          },
          required: ["sha256"],
        },
      },
      // ── Submission tracking ─────────────────────────────────────────────────
      {
        name: "al4_submission_is_complete",
        description: "Check whether a submission has finished processing.",
        inputSchema: {
          type: "object",
          properties: {
            sid: { type: "string", description: "Submission ID" },
          },
          required: ["sid"],
        },
      },
      {
        name: "al4_submission_get",
        description: "Get metadata and status for a submission.",
        inputSchema: {
          type: "object",
          properties: {
            sid: { type: "string" },
          },
          required: ["sid"],
        },
      },
      {
        name: "al4_submission_full",
        description:
          "Get the complete results tree for a finished submission, including all service results and scores.",
        inputSchema: {
          type: "object",
          properties: {
            sid: { type: "string" },
          },
          required: ["sid"],
        },
      },
      {
        name: "al4_submission_summary",
        description: "Get a summarised view of a submission's results.",
        inputSchema: {
          type: "object",
          properties: {
            sid: { type: "string" },
          },
          required: ["sid"],
        },
      },
      {
        name: "al4_ingest_get_messages",
        description:
          "Retrieve completion notifications from an ingest notification queue.",
        inputSchema: {
          type: "object",
          properties: {
            notification_queue: {
              type: "string",
              description: "Queue name passed when ingesting",
            },
            count: {
              type: "number",
              description: "Max messages to retrieve (default 100)",
            },
          },
          required: ["notification_queue"],
        },
      },
      // ── Search ──────────────────────────────────────────────────────────────
      {
        name: "al4_search_submissions",
        description:
          "Search AssemblyLine submissions using Lucene query syntax (e.g. 'params.submitter:admin AND al_score:[500 TO *]').",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string", description: "Lucene query string" },
            fields: { type: "string", description: "Comma-separated fields to return" },
            rows: { type: "number", description: "Number of results (default 25)" },
            offset: { type: "number", description: "Pagination offset" },
            sort: { type: "string", description: "Sort field and direction, e.g. 'times.submitted desc'" },
          },
          required: ["query"],
        },
      },
      {
        name: "al4_search_alerts",
        description: "Search AssemblyLine alerts using Lucene query syntax.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            fields: { type: "string" },
            rows: { type: "number" },
            offset: { type: "number" },
            sort: { type: "string" },
          },
          required: ["query"],
        },
      },
      {
        name: "al4_search_files",
        description:
          "Search the AssemblyLine file store using Lucene query syntax (e.g. 'type:executable/windows AND seen.last:[now-7d TO now]').",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            fields: { type: "string" },
            rows: { type: "number" },
            offset: { type: "number" },
            sort: { type: "string" },
          },
          required: ["query"],
        },
      },
      {
        name: "al4_search_results",
        description: "Search AssemblyLine service results using Lucene query syntax.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string" },
            fields: { type: "string" },
            rows: { type: "number" },
            offset: { type: "number" },
            sort: { type: "string" },
          },
          required: ["query"],
        },
      },
      // ── Alerts ──────────────────────────────────────────────────────────────
      {
        name: "al4_alert_get",
        description: "Get a specific alert by its alert ID.",
        inputSchema: {
          type: "object",
          properties: {
            alert_id: { type: "string" },
          },
          required: ["alert_id"],
        },
      },
      // ── File / hash lookups ─────────────────────────────────────────────────
      {
        name: "al4_file_info",
        description: "Get metadata for a file by its SHA256 hash.",
        inputSchema: {
          type: "object",
          properties: {
            sha256: { type: "string" },
          },
          required: ["sha256"],
        },
      },
      {
        name: "al4_file_results",
        description: "Get all service analysis results for a file by SHA256.",
        inputSchema: {
          type: "object",
          properties: {
            sha256: { type: "string" },
          },
          required: ["sha256"],
        },
      },
      {
        name: "al4_file_score",
        description: "Get the highest score assigned to a file across all submissions.",
        inputSchema: {
          type: "object",
          properties: {
            sha256: { type: "string" },
          },
          required: ["sha256"],
        },
      },
    ] as const;
Behavior2/5

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

With no annotations, the description carries full burden but only mentions asynchronous behavior. It does not disclose side effects, authentication requirements, rate limits, or what happens to the URL after ingestion. This is insufficient for safe invocation.

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

Conciseness2/5

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

The description is extremely concise (one sentence) but at the cost of necessary information. For a tool with 7 parameters and no other documentation, it is under-specified.

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

Completeness1/5

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

Given the complexity (7 parameters, no annotations, no output schema), the description is critically incomplete. It fails to explain ingestion process, result handling, error conditions, or parameter usage.

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

Parameters1/5

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

The description adds no meaning to the 7 parameters beyond their names. Schema description coverage is 0%, and the description does not explain any parameter like 'notification_queue', 'classification', or 'services'.

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 action (asynchronously ingest) and the resource (a URL) and distinguishes from siblings that ingest files or hashes. However, it does not differentiate from similar sibling 'al4_submit_url', which may cause confusion.

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?

No guidance is provided on when to use this tool over alternatives like 'al4_submit_url' or 'al4_ingest_file'. The description lacks context for decision-making.

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/Stankye/vibe-assemblylinev4-mcp'

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