{
  "id": "image.collage",
  "object": "tool",
  "name": "Photo collage",
  "summary": "Grid collage of photos.",
  "description": "Lays out up to 100 images in a grid: choose the columns, the cell size, the gap and margin, the background colour (or transparent), whether photos fill their cell (cover, cropped) or fit inside it (contain), and an optional corner radius for rounded cells.",
  "category": "images",
  "hosted_by": "Opentools",
  "runtime": "container",
  "side_effects": false,
  "status": "live",
  "credits": 2,
  "price": "$0.0020",
  "providers": [
    {
      "id": "opentools",
      "name": "Opentools",
      "price": "$0.0020"
    }
  ],
  "mcp_name": "image_collage",
  "input_schema": {
    "type": "object",
    "properties": {
      "files": {
        "minItems": 1,
        "maxItems": 100,
        "type": "array",
        "items": {
          "anyOf": [
            {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri",
                  "description": "Public http(s) URL of the file"
                }
              },
              "required": [
                "url"
              ]
            },
            {
              "type": "object",
              "properties": {
                "file_id": {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                  "description": "An id returned by POST /v1/files"
                }
              },
              "required": [
                "file_id"
              ]
            },
            {
              "type": "object",
              "properties": {
                "base64": {
                  "type": "string",
                  "description": "Base64-encoded file bytes (up to 10 MB)"
                },
                "name": {
                  "type": "string",
                  "description": "File name, e.g. invoice.pdf"
                },
                "content_type": {
                  "type": "string"
                }
              },
              "required": [
                "base64",
                "name"
              ]
            },
            {
              "type": "object",
              "properties": {
                "connection": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64,
                  "description": "A storage connection id or name (see storage.connections)"
                },
                "path": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 1024,
                  "description": "Path of the file in that connection, e.g. reports/q3.pdf"
                }
              },
              "required": [
                "connection",
                "path"
              ]
            }
          ],
          "x-file": true,
          "description": "A file: { url }, { file_id }, { base64, name } or { connection, path } from connected storage"
        },
        "description": "1 to 100 images (PNG, JPEG, WebP, GIF, TIFF, HEIC, AVIF…)"
      },
      "columns": {
        "description": "Columns. Defaults to a square-ish grid for the number of images.",
        "type": "integer",
        "minimum": 1,
        "maximum": 20
      },
      "cell_width": {
        "default": 600,
        "description": "Cell width in px",
        "type": "integer",
        "minimum": 16,
        "maximum": 4000
      },
      "cell_height": {
        "description": "Cell height in px (defaults to cell_width)",
        "type": "integer",
        "minimum": 16,
        "maximum": 4000
      },
      "gap": {
        "default": 10,
        "description": "Space between cells in px",
        "type": "integer",
        "minimum": 0,
        "maximum": 500
      },
      "margin": {
        "description": "Outer margin in px (defaults to gap)",
        "type": "integer",
        "minimum": 0,
        "maximum": 500
      },
      "background": {
        "default": "#FFFFFF",
        "description": "Background colour like #FFFFFF, or \"transparent\" (PNG/WebP output)",
        "anyOf": [
          {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          {
            "type": "string",
            "const": "transparent"
          }
        ]
      },
      "fit": {
        "default": "cover",
        "description": "cover fills each cell (cropping), contain fits the whole photo inside",
        "type": "string",
        "enum": [
          "cover",
          "contain"
        ]
      },
      "radius": {
        "default": 0,
        "description": "Corner radius of each cell in px (0 = square)",
        "type": "integer",
        "minimum": 0,
        "maximum": 2000
      },
      "format": {
        "default": "auto",
        "description": "Output format. auto keeps JPEG, PNG or WebP inputs as they are, uses PNG otherwise or when transparent",
        "type": "string",
        "enum": [
          "auto",
          "png",
          "jpg",
          "webp"
        ]
      },
      "quality": {
        "default": 90,
        "description": "Quality for lossy formats, 1-100",
        "type": "integer",
        "minimum": 1,
        "maximum": 100
      }
    },
    "required": [
      "files"
    ]
  },
  "kind": "tool"
}