{
  "id": "image.add_text",
  "object": "tool",
  "name": "Add text to image",
  "summary": "Captions, labels and memes.",
  "description": "Draws text on an image: one or more items, each anchored to one of nine points (plus an offset) or placed at x/y, with a font size in px or as a share of the image height, colour, outline, font and an optional wrap width. The meme shortcut adds classic white Anton captions with a black outline at the top and bottom.",
  "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_add_text",
  "input_schema": {
    "type": "object",
    "properties": {
      "file": {
        "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": "The image"
      },
      "texts": {
        "description": "Text items, drawn in order",
        "maxItems": 20,
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "text": {
              "type": "string",
              "minLength": 1,
              "maxLength": 2000,
              "description": "The text. Use \\n for line breaks."
            },
            "anchor": {
              "default": "center",
              "description": "Which point of the image the text is anchored to",
              "type": "string",
              "enum": [
                "top-left",
                "top",
                "top-right",
                "left",
                "center",
                "right",
                "bottom-left",
                "bottom",
                "bottom-right"
              ]
            },
            "offset_x": {
              "default": 0,
              "description": "Pixels from the anchor: inward from a side edge, rightward from the centre",
              "type": "integer",
              "minimum": -12000,
              "maximum": 12000
            },
            "offset_y": {
              "default": 0,
              "description": "Pixels from the anchor: inward from the top or bottom edge, downward from the centre",
              "type": "integer",
              "minimum": -12000,
              "maximum": 12000
            },
            "x": {
              "description": "Absolute left position in px (with y, replaces anchor and offsets)",
              "type": "integer",
              "minimum": 0,
              "maximum": 12000
            },
            "y": {
              "description": "Absolute top position in px",
              "type": "integer",
              "minimum": 0,
              "maximum": 12000
            },
            "size": {
              "description": "Font size in px. Overrides size_percent.",
              "type": "number",
              "minimum": 4,
              "maximum": 2000
            },
            "size_percent": {
              "default": 6,
              "description": "Font size as a percentage of the image height",
              "type": "number",
              "minimum": 0.5,
              "maximum": 50
            },
            "font": {
              "default": "Noto Sans",
              "description": "Font. Noto Sans CJK for Chinese, Japanese or Korean.",
              "type": "string",
              "enum": [
                "Noto Sans",
                "Noto Sans Bold",
                "Noto Serif",
                "Noto Serif Bold",
                "Noto Sans CJK",
                "DejaVu Sans",
                "DejaVu Sans Bold",
                "DejaVu Sans Mono",
                "Liberation Sans",
                "Liberation Serif",
                "Anton"
              ]
            },
            "color": {
              "default": "#FFFFFF",
              "description": "Text colour like #FFFFFF",
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "stroke_color": {
              "default": "#000000",
              "description": "Outline colour",
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "stroke_width": {
              "default": 0,
              "description": "Outline width in px (0 for none)",
              "type": "number",
              "minimum": 0,
              "maximum": 50
            },
            "max_width": {
              "description": "Wrap lines at this width in px",
              "type": "integer",
              "minimum": 16,
              "maximum": 12000
            },
            "max_width_percent": {
              "description": "Wrap lines at this percentage of the image width",
              "type": "number",
              "minimum": 1,
              "maximum": 100
            }
          },
          "required": [
            "text"
          ]
        }
      },
      "meme": {
        "description": "Meme shortcut: white text with a black outline, wrapped to the image width",
        "type": "object",
        "properties": {
          "top": {
            "description": "Top caption (upper-cased)",
            "type": "string",
            "maxLength": 500
          },
          "bottom": {
            "description": "Bottom caption (upper-cased)",
            "type": "string",
            "maxLength": 500
          },
          "font": {
            "default": "Anton",
            "description": "Font",
            "type": "string",
            "enum": [
              "Noto Sans",
              "Noto Sans Bold",
              "Noto Serif",
              "Noto Serif Bold",
              "Noto Sans CJK",
              "DejaVu Sans",
              "DejaVu Sans Bold",
              "DejaVu Sans Mono",
              "Liberation Sans",
              "Liberation Serif",
              "Anton"
            ]
          },
          "size_percent": {
            "default": 10,
            "description": "Font size as a percentage of the image height",
            "type": "number",
            "minimum": 2,
            "maximum": 30
          }
        }
      },
      "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": [
      "file"
    ]
  },
  "kind": "tool"
}