Skip to main content
Glama

scaffold_transform

Generate a Maltego transform module from a cURL command or OpenAPI spec, mapping API response fields to entities and properties for data enrichment.

Instructions

Scaffold a new Maltego transform module from a cURL command or OpenAPI specification.

The output lists each transform by the id the server registers it under, its sample input, a ready-made run command, and a field inventory: every leaf path seen in the sample response or schema, its sample value, and what happened to it (mapped to an entity, attached as a property, or dropped and why). Read the inventory and the notes: data an investigator needs is often nested deeper than the scaffolder follows by default. Preview with dry_run=True, adjust records/mappings/primary until the inventory maps what matters, then call again without dry_run. Restart the server, then call run_transform with the transform id exactly as listed (it includes the namespace).

Args: service: Optional service name slug (e.g. 'greynoise', 'threatfox'). curl: A full cURL command string demonstrating an API request. openapi: An OpenAPI/Swagger spec in JSON or YAML: a URL, a file path, or the document itself (as text or as an object). Use list_operations first to pick operation_ids. sample_response: A real JSON response (as text or as the parsed value), to map outputs from. Works with curl, and with openapi when exactly one operation is scaffolded (name it in operation_ids); without it a spec with no response schema maps nothing. operation_ids: OpenAPI operation ids to scaffold. Without it every GET operation is scaffolded; POST operations are only scaffolded when named here. force: Replace an existing service: its whole directory and its project.py imports. name: Transform name for a curl scaffold (default '_lookup'), so one service can grow endpoint by endpoint. records: Dotted path to the list of records in the response, e.g. 'data' or 'containers.cna.references'. Each element becomes one record to map. mappings: Per-field overrides as 'dotted.path[].field=EntityType', e.g. 'containers.cna.affected[].vendor=Company'. EntityType 'Property' attaches the field to the record's entity as a property; 'Drop' ignores it. dry_run: Parse and report the plan (transforms, field inventory, notes, auth, and the files that would be written) without writing anything. sample_input: An input value the API answers for, e.g. the hash or id the sample_response came from. The generated transform skips the input when the response echoes it back (so the other fields enrich the input instead of a copy of it), and samples.json records it so the smoke test sends a value the endpoint accepts. A curl scaffold defaults to the value in the request; give it for an openapi scaffold, which otherwise only has the spec's example, if any. primary: Path of the field to use as each record's primary entity, the one every other field attaches to as a property, written like a mappings path (e.g. 'SHA-1' or 'hits.hits[]._id'). It must map to an entity type; the error names the valid candidates.

Input Schema

NameRequiredDescriptionDefault
curlNo
nameNo
forceNo
dry_runNo
openapiNo
primaryNo
recordsNo
serviceNo
mappingsNo
sample_inputNo
operation_idsNo
sample_responseNo

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed10 schema fields changed
    • addedInput schema / properties / dry_run
      Added value: +{
      +  "default": false,
      +  "title": "Dry Run",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / force
      Added value: +{
      +  "default": false,
      +  "title": "Force",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / mappings
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Mappings"
      +}
    • addedInput schema / properties / name
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Name"
      +}
    • changedInput schema / properties / openapi / anyOf
      Previous value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / operation_ids
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Operation Ids"
      +}
    • addedInput schema / properties / primary
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Primary"
      +}
    • addedInput schema / properties / records
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Records"
      +}
    • addedInput schema / properties / sample_input
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Sample Input"
      +}
    • changedInput schema / properties / sample_response / anyOf
      Previous value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  {
      +    "items": {},
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  2. First observedv0.1.0

TDQS

A4.7/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does so well: force is disclosed as destroying 'its whole directory and its project.py imports', dry_run is described as writing nothing but reporting 'the files that would be written', and the generated transform's echo-skipping and error behavior for primary are explained. It stops short of stating permission or rate-limit requirements outright, though it notes auth is surfaced in the dry-run report.

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

Conciseness4/5

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

Front-loaded with purpose, then workflow, then a per-argument glossary, which is the right ordering for a 12-parameter tool. The opening paragraph on the output inventory is somewhat long given an output schema exists, but it explains the decision-critical inventory semantics, so it mostly earns its space.

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

Completeness5/5

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

For a 12-parameter, zero-required, no-annotation scaffold tool, the description supplies the full selection workflow, the side effects of force and dry_run, the sequence to run_transform, and complete per-parameter semantics. An agent could drive this tool end-to-end from the description alone.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate entirely, and it does: every one of the 12 parameters is documented with type, default, and format examples (e.g. records as a dotted path, mappings as 'dotted.path[].field=EntityType', operation_ids defaulting to all GETs). This is far more than the bare-typed schema conveys.

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

Purpose5/5

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

States a specific verb and resource ('Scaffold a new Maltego transform module') plus the two concrete input sources (cURL command or OpenAPI spec). It is immediately distinguishable from siblings like run_transform, list_operations, and remove_scaffold, going so far as to name list_operations as a prerequisite and run_transform as the follow-up step.

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

Usage Guidelines5/5

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

Gives an explicit workflow ('Preview with dry_run=True, adjust records/mappings/primary until the inventory maps what matters, then call again without dry_run. Restart the server, then call run_transform...'). It also states selection conditions per input mode: 'Use list_operations first to pick operation_ids', operation_ids needed for POST, sample_response needed for openapi with no response schema.

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