Skip to main content
Glama
Pexafy

Pexafy Stock Photos

Official

Find photos that look like an image or a Pexafy photo

search_photos_by_image
Read-only

Use this when the user wants photographs that look like a picture, rather than ones described in words: a picture they link to, one the host passes to the tool as a file, or a Pexafy photo already found.

Instructions

Use this when the user wants photographs that look like a picture, rather than ones described in words: a picture they link to, one the host passes to the tool as a file, or a Pexafy photo already found.

Call it for “find images like this”, “something similar to this photo”, “find a free alternative to this image”, “I need this but royalty-free”, “photos in this style”, “more like the second one”, whether or not they say “search by image”.

Give exactly one reference: photo_id for a Pexafy photo from an earlier result; image_url for a picture at a public URL, such as a link the user pasted; image_file when the host passes the user's uploaded image to the tool; image_base64 for image bytes a client already holds. Sending two is refused. A picture that is only visible in the conversation — not linked, not passed to the tool — is not a reference this tool can receive; its scene can be searched in words with search_photos. Words are optional, in english_search_sentence: with a photo_id, the words that photograph was found under; with an image, only what the user wants changed or kept (“like this but at night”).

It finds free stock photographs in Pexafy's index that visually match the reference. The reference image is sent to Pexafy only to run the search; it is not stored. Each result carries a rank, a photo_id, its licence, the credit line to display and an image link.

Input Schema

NameRequiredDescriptionDefault
photo_idNoThe photo_id of the Pexafy reference photo, copied from the result the user or assistant is referring to. It is a UUID such as `019e1ecb-0039-7da6-b1ca-987ee4d337c0`. Use it instead of an image when the reference is a Pexafy photo returned in an earlier search, and pass the words of that search in `english_search_sentence` if needed.
image_urlNoPublic http(s) URL pointing directly to the reference image file, including a URL the user pasted in the conversation. For a photograph Pexafy returned, send its `photo_id` instead.
image_fileNoThe user's uploaded image, as a host that passes uploads to tools provides it: the upload's `download_url` and `file_id`. A picture that is only visible in the conversation has neither.
image_base64NoReference image as base64-encoded bytes, optionally as a data: URL. Use for programmatic clients that already hold the image data.
english_search_sentenceNoOptional, and usable with any reference. Send the words that say what the user wants from the reference: with a `photo_id`, the words that photograph was found under, so the results stay on the subject they asked for; with an image, what they want changed or kept from it (“like this but at night”). The reference stays the main signal and these words adjust it. With an image, send the change alone (“at night”) rather than the whole scene rewritten, which would outweigh the picture instead of adjusting it; with a `photo_id`, the full sentence that photograph was found under is what to send. In English, like the sentence of a text search. The words a reference photograph was found under are the best ones. When it is unclear whether they want the same subject or simply the same look, send the words: staying on the subject is the safer default. Omit them only when they plainly want photographs that look like the picture itself.
explicit_orientation_filterNoOmit this parameter unless the user explicitly asks for a photo shape or orientation in their own words, or names a format whose shape is part of its definition — a vertical Short, a banner, a square post, a phone wallpaper. This is a hard filter, not a preference: it removes photos with other shapes before ranking, so using a shape the user did not request can exclude the best matches. Never infer the shape from the reference image the user gave — its shape is a property of the picture they had, not a constraint on the ones they want — nor from the subject, the composition, or a purpose that fixes no shape (“a photo for my blog post”, “something for my landing page”). If you are choosing a value rather than repeating one explicitly requested by the user, omit it. Allowed values: `landscape`, `portrait`, `square`. Multiple values are allowed: two shapes return more than one alone, though any filter still returns less than none. For example, “anything but portrait” means `['landscape', 'square']`.

Output Schema

NameRequiredDescriptionDefault
dataNo
errorNo
budgetNoPresent only when the caller is near the end of an allowance — the daily one without an account, the monthly one with. What is left of it, and, for a caller with no account, the one sentence that says what lifts the limit. Also carried by a refusal, where it describes the wall itself.
noticeNoWhy this answer is empty, when it is. A plan limit was reached: the allowance and when it returns. There is nothing to retry until then.
successNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed11 schema fields changedv1.0.1
    • addedOutput schema / properties / data / items / properties / alt_description / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / alt_description / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / height / anyOf
      Added value: +[
      +  {
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / height / type
      Removed value: -[
      -  "integer",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / photographer_full_name / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / photographer_full_name / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / source_image_url / anyOf
      Added value: +[
      +  {
      +    "format": "uri",
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / source_image_url / format
      Removed value: -"uri"
    • removedOutput schema / properties / data / items / properties / source_image_url / type
      Removed value: -[
      -  "string",
      -  "null"
      -]
    • addedOutput schema / properties / data / items / properties / width / anyOf
      Added value: +[
      +  {
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / data / items / properties / width / type
      Removed value: -[
      -  "integer",
      -  "null"
      -]
  2. Changed41 schema fields changedv1.0.0
    • removedInput schema / properties / after_date
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Only return photos published on or after this date, formatted YYYY-MM-DD."
      -}
    • removedInput schema / properties / color_name
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Keep only photos whose dominant color matches one of: red, orange, yellow, green, blue, purple, pink, brown, black, white, gray, teal, beige, gold, navy. Cannot be combined with color_hex."
      -}
    • removedInput schema / properties / cursor
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here — no need to re-upload the image. See the Pagination guide."
      -}
    • addedInput schema / properties / english_search_sentence
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 250,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Optional, and usable with any reference. Send the words that say what the user wants from the reference: with a `photo_id`, the words that photograph was found under, so the results stay on the subject they asked for; with an image, what they want changed or kept from it (“like this but at night”). The reference stays the main signal and these words adjust it. With an image, send the change alone (“at night”) rather than the whole scene rewritten, which would outweigh the picture instead of adjusting it; with a `photo_id`, the full sentence that photograph was found under is what to send. In English, like the sentence of a text search. The words a reference photograph was found under are the best ones. When it is unclear whether they want the same subject or simply the same look, send the words: staying on the subject is the safer default. Omit them only when they plainly want photographs that look like the picture itself."
      +}
    • addedInput schema / properties / explicit_orientation_filter
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "enum": [
      +          "landscape",
      +          "portrait",
      +          "square"
      +        ],
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Omit this parameter unless the user explicitly asks for a photo shape or orientation in their own words, or names a format whose shape is part of its definition — a vertical Short, a banner, a square post, a phone wallpaper.\n\nThis is a hard filter, not a preference: it removes photos with other shapes before ranking, so using a shape the user did not request can exclude the best matches.\n\nNever infer the shape from the reference image the user gave — its shape is a property of the picture they had, not a constraint on the ones they want — nor from the subject, the composition, or a purpose that fixes no shape (“a photo for my blog post”, “something for my landing page”). If you are choosing a value rather than repeating one explicitly requested by the user, omit it.\n\nAllowed values: `landscape`, `portrait`, `square`. Multiple values are allowed: two shapes return more than one alone, though any filter still returns less than none. For example, “anything but portrait” means `['landscape', 'square']`."
      +}
    • changedInput schema / properties / image_base64 / description
      Previous value: -"The reference image as base64 bytes, optionally as a `data:` URL. For a client that already holds the bytes; prefer `image_url` when a link exists."New value: +"Reference image as base64-encoded bytes, optionally as a data: URL. Use for programmatic clients that already hold the image data."
    • changedInput schema / properties / image_file / description
      Previous value: -"Filled in by the host when the user uploads an image, not by the caller. Carries the upload's `download_url` and `file_id`."New value: +"The user's uploaded image, as a host that passes uploads to tools provides it: the upload's `download_url` and `file_id`. A picture that is only visible in the conversation has neither."
    • changedInput schema / properties / image_url / description
      Previous value: -"Public http(s) URL of the reference image. Reuse the `image_url` of a photo from a previous search result, or any public URL the user provides."New value: +"Public http(s) URL pointing directly to the reference image file, including a URL the user pasted in the conversation. For a photograph Pexafy returned, send its `photo_id` instead."
    • removedInput schema / properties / license_type
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Keep only photos with these license types: free, cc0. 'free' means the photo can be used freely and attribution is appreciated. Repeat the parameter to pass several."
      -}
    • removedInput schema / properties / orientation
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Keep only photos with these shapes: landscape, portrait, square. Repeat the parameter to pass several."
      -}
    • addedInput schema / properties / photo_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "examples": [
      +        "019e1ecb-0039-7da6-b1ca-987ee4d337c0"
      +      ],
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "The photo_id of the Pexafy reference photo, copied from the result the user or assistant is referring to. It is a UUID such as `019e1ecb-0039-7da6-b1ca-987ee4d337c0`. Use it instead of an image when the reference is a Pexafy photo returned in an earlier search, and pass the words of that search in `english_search_sentence` if needed."
      +}
    • removedInput schema / properties / photographer
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Only return photos from this photographer's exact username."
      -}
    • removedInput schema / properties / q
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Your search query as a full natural-language sentence describing the scene you want — Pexafy is semantic, so sentences beat keywords. Up to 500 characters. Optional if you provide at least one filter instead. Example: 'an old man sitting at a café table he has visited every morning for thirty years'."
      -}
    • removedInput schema / properties / source
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Keep only photos from these providers: Unsplash, Pexels, Pixabay, Kaboompics, Burst, StockSnap, Picjumbo, Skitterphoto, NegativeSpace. Repeat the parameter to pass several."
      -}
    • removedInput schema / properties / text_alpha
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "number"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ],
      -  "default": null,
      -  "description": "Balance between your text and the image when both are provided, from `0` to `10`. `0` ignores the text (pure visual search), `1.7` (the default) is balanced, and higher values give your words more weight. Has no effect without `q`."
      -}
    • addedOutput schema / properties / budget
      Added value: +{
      +  "description": "Present only when the caller is near the end of an allowance — the daily one without an account, the monthly one with. What is left of it, and, for a caller with no account, the one sentence that says what lifts the limit. Also carried by a refusal, where it describes the wall itself.",
      +  "properties": {
      +    "limit": {
      +      "description": "Searches allowed in that period.",
      +      "type": "integer"
      +    },
      +    "message": {
      +      "description": "The whole notice in words, for a host with no UI.",
      +      "type": "string"
      +    },
      +    "remaining": {
      +      "description": "Searches left in that period.",
      +      "type": "integer"
      +    },
      +    "scope": {
      +      "description": "Which allowance this counts: the daily one or the monthly one. Both exist with or without an account, so `signed_in` does not tell them apart.",
      +      "enum": [
      +        "day",
      +        "month"
      +      ],
      +      "type": "string"
      +    },
      +    "signed_in": {
      +      "description": "Whether the caller has an account. False is the anonymous allowance.",
      +      "type": "boolean"
      +    },
      +    "state": {
      +      "description": "`warning` while there is room left, `exhausted` once there is none.",
      +      "enum": [
      +        "warning",
      +        "exhausted"
      +      ],
      +      "type": "string"
      +    },
      +    "used": {
      +      "description": "Searches spent in that period.",
      +      "type": "integer"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / data / items / description
      Previous value: -"A photo result. Fields returned can be narrowed with the `fields` parameter and may depend on your plan."New value: +"One photograph of this answer."
    • changedOutput schema / properties / data / items / properties / attribution / description
      Previous value: -"Ready-to-display credit for the photographer/source."New value: +"The credit line to display, already written."
    • removedOutput schema / properties / data / items / properties / attribution / properties / html
      Removed value: -{
      -  "description": "HTML attribution snippet.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / blur_hash
      Removed value: -{
      -  "description": "BlurHash placeholder string.",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / color_hex
      Removed value: -{
      -  "description": "Dominant color hex code.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / color_name
      Removed value: -{
      -  "description": "Dominant color name.",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / description
      Removed value: -{
      -  "description": "AI-generated caption.",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / image_url
      Removed value: -{
      -  "description": "Canonical source image URL.",
      -  "format": "uri",
      -  "type": "string"
      -}
    • addedOutput schema / properties / data / items / properties / orientation / description
      Added value: +"The shape of this photograph — `landscape`, `portrait` or `square`, the values `explicit_orientation_filter` takes."
    • removedOutput schema / properties / data / items / properties / photographer_url
      Removed value: -{
      -  "format": "uri",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / photographer_username
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / data / items / properties / rank
      Added value: +{
      +  "description": "This photograph's place in this answer, from 1. A person may name a result by position (“the second one”); the tools take that result's `photo_id`, not its rank.",
      +  "type": "integer"
      +}
    • removedOutput schema / properties / data / items / properties / relevance_score
      Removed value: -{
      -  "description": "Match score 0–1 (higher is better). Only on search results.",
      -  "type": [
      -    "number",
      -    "null"
      -  ]
      -}
    • removedOutput schema / properties / data / items / properties / source_description
      Removed value: -{
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • changedOutput schema / properties / data / items / properties / source_image_url / description
      Previous value: -"URL of the photo's page on the provider."New value: +"The photograph's page on the library it came from — where to send someone who wants the source."
    • removedOutput schema / properties / data / items / properties / uploaded_on
      Removed value: -{
      -  "description": "Publication date (YYYY-MM-DD).",
      -  "type": [
      -    "string",
      -    "null"
      -  ]
      -}
    • changedOutput schema / properties / data / items / properties / urls / description
      Previous value: -"Ready-to-use image links in five sizes."New value: +"The photograph's image file, 1280 pixels wide, for a page, a document or a download. `urls` carries this one variant and no other."
    • removedOutput schema / properties / data / items / properties / urls / properties / full
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / large
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / small
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • removedOutput schema / properties / data / items / properties / urls / properties / thumb
      Removed value: -{
      -  "format": "uri",
      -  "type": "string"
      -}
    • changedOutput schema / properties / error / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "code": {
      -        "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`).",
      -        "type": "string"
      -      },
      -      "message": {
      -        "description": "Human-readable error message.",
      -        "type": "string"
      -      },
      -      "request_id": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "code",
      -      "message"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "code": {
      +        "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`).",
      +        "type": "string"
      +      },
      +      "message": {
      +        "description": "Human-readable error message.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "code",
      +      "message"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / meta
      Removed value: -{
      -  "properties": {
      -    "request_id": {
      -      "description": "Unique id for this request (quote it in support tickets).",
      -      "type": "string"
      -    },
      -    "took_ms": {
      -      "description": "Server processing time in milliseconds.",
      -      "type": "number"
      -    }
      -  },
      -  "type": "object"
      -}
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Why this answer is empty, when it is. A plan limit was reached: the allowance and when it returns. There is nothing to retry until then.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / pagination
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "properties": {
      -        "has_more": {
      -          "description": "Whether another page exists.",
      -          "type": "boolean"
      -        },
      -        "next_cursor": {
      -          "description": "Pass back as `cursor` for the next page; `null` when `has_more` is false.",
      -          "type": [
      -            "string",
      -            "null"
      -          ]
      -        },
      -        "per_page": {
      -          "description": "Number of items per page.",
      -          "type": "integer"
      -        }
      -      },
      -      "type": "object"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
  3. Changed19 schema fields changedv0.4.9
    • addedInput schema / properties / after_date / description
      Added value: +"Only return photos published on or after this date, formatted YYYY-MM-DD."
    • addedInput schema / properties / color_name / description
      Added value: +"Keep only photos whose dominant color matches one of: red, orange, yellow, green, blue, purple, pink, brown, black, white, gray, teal, beige, gold, navy. Cannot be combined with color_hex."
    • addedInput schema / properties / cursor / description
      Added value: +"Token to fetch the next page. Take `pagination.next_cursor` from a previous response and pass it back here — no need to re-upload the image. See the Pagination guide."
    • addedInput schema / properties / image_base64 / description
      Added value: +"The reference image as base64 bytes, optionally as a `data:` URL. For a client that already holds the bytes; prefer `image_url` when a link exists."
    • addedInput schema / properties / image_file / additionalProperties
      Added value: +false
    • removedInput schema / properties / image_file / anyOf
      Removed value: -[
      -  {
      -    "additionalProperties": true,
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / image_file / default
      Removed value: -null
    • addedInput schema / properties / image_file / description
      Added value: +"Filled in by the host when the user uploads an image, not by the caller. Carries the upload's `download_url` and `file_id`."
    • addedInput schema / properties / image_file / properties
      Added value: +{
      +  "download_url": {
      +    "type": "string"
      +  },
      +  "file_id": {
      +    "type": "string"
      +  },
      +  "file_name": {
      +    "type": "string"
      +  },
      +  "mime_type": {
      +    "type": "string"
      +  }
      +}
    • addedInput schema / properties / image_file / required
      Added value: +[
      +  "download_url",
      +  "file_id"
      +]
    • addedInput schema / properties / image_file / type
      Added value: +"object"
    • addedInput schema / properties / image_url / description
      Added value: +"Public http(s) URL of the reference image. Reuse the `image_url` of a photo from a previous search result, or any public URL the user provides."
    • addedInput schema / properties / license_type / description
      Added value: +"Keep only photos with these license types: free, cc0. 'free' means the photo can be used freely and attribution is appreciated. Repeat the parameter to pass several."
    • addedInput schema / properties / orientation / description
      Added value: +"Keep only photos with these shapes: landscape, portrait, square. Repeat the parameter to pass several."
    • addedInput schema / properties / photographer / description
      Added value: +"Only return photos from this photographer's exact username."
    • addedInput schema / properties / q / description
      Added value: +"Your search query as a full natural-language sentence describing the scene you want — Pexafy is semantic, so sentences beat keywords. Up to 500 characters. Optional if you provide at least one filter instead. Example: 'an old man sitting at a café table he has visited every morning for thirty years'."
    • addedInput schema / properties / source / description
      Added value: +"Keep only photos from these providers: Unsplash, Pexels, Pixabay, Kaboompics, Burst, StockSnap, Picjumbo, Skitterphoto, NegativeSpace. Repeat the parameter to pass several."
    • addedInput schema / properties / text_alpha / description
      Added value: +"Balance between your text and the image when both are provided, from `0` to `10`. `0` ignores the text (pure visual search), `1.7` (the default) is balanced, and higher values give your words more weight. Has no effect without `q`."
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "data": {
      +      "items": {
      +        "description": "A photo result. Fields returned can be narrowed with the `fields` parameter and may depend on your plan.",
      +        "properties": {
      +          "alt_description": {
      +            "description": "Accessibility-friendly text.",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "attribution": {
      +            "description": "Ready-to-display credit for the photographer/source.",
      +            "properties": {
      +              "html": {
      +                "description": "HTML attribution snippet.",
      +                "type": "string"
      +              },
      +              "plain": {
      +                "description": "Plain-text attribution.",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "blur_hash": {
      +            "description": "BlurHash placeholder string.",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "color_hex": {
      +            "description": "Dominant color hex code.",
      +            "type": "string"
      +          },
      +          "color_name": {
      +            "description": "Dominant color name.",
      +            "type": "string"
      +          },
      +          "description": {
      +            "description": "AI-generated caption.",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "height": {
      +            "type": [
      +              "integer",
      +              "null"
      +            ]
      +          },
      +          "image_url": {
      +            "description": "Canonical source image URL.",
      +            "format": "uri",
      +            "type": "string"
      +          },
      +          "license_type": {
      +            "description": "License type (e.g. `free`).",
      +            "type": "string"
      +          },
      +          "orientation": {
      +            "enum": [
      +              "landscape",
      +              "portrait",
      +              "square"
      +            ],
      +            "type": "string"
      +          },
      +          "photo_id": {
      +            "description": "Unique Pexafy identifier (UUID).",
      +            "type": "string"
      +          },
      +          "photographer_full_name": {
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "photographer_url": {
      +            "format": "uri",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "photographer_username": {
      +            "type": "string"
      +          },
      +          "relevance_score": {
      +            "description": "Match score 0–1 (higher is better). Only on search results.",
      +            "type": [
      +              "number",
      +              "null"
      +            ]
      +          },
      +          "source": {
      +            "description": "Provider (e.g. `Pexels`, `Unsplash`, `Pixabay`).",
      +            "type": "string"
      +          },
      +          "source_description": {
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "source_image_url": {
      +            "description": "URL of the photo's page on the provider.",
      +            "format": "uri",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "uploaded_on": {
      +            "description": "Publication date (YYYY-MM-DD).",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "urls": {
      +            "description": "Ready-to-use image links in five sizes.",
      +            "properties": {
      +              "full": {
      +                "format": "uri",
      +                "type": "string"
      +              },
      +              "large": {
      +                "format": "uri",
      +                "type": "string"
      +              },
      +              "regular": {
      +                "format": "uri",
      +                "type": "string"
      +              },
      +              "small": {
      +                "format": "uri",
      +                "type": "string"
      +              },
      +              "thumb": {
      +                "format": "uri",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "width": {
      +            "type": [
      +              "integer",
      +              "null"
      +            ]
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "error": {
      +      "anyOf": [
      +        {
      +          "properties": {
      +            "code": {
      +              "description": "Machine-readable error code (e.g. `MISSING_PARAMS`, `PHOTO_NOT_FOUND`).",
      +              "type": "string"
      +            },
      +            "message": {
      +              "description": "Human-readable error message.",
      +              "type": "string"
      +            },
      +            "request_id": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "code",
      +            "message"
      +          ],
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "meta": {
      +      "properties": {
      +        "request_id": {
      +          "description": "Unique id for this request (quote it in support tickets).",
      +          "type": "string"
      +        },
      +        "took_ms": {
      +          "description": "Server processing time in milliseconds.",
      +          "type": "number"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "pagination": {
      +      "anyOf": [
      +        {
      +          "properties": {
      +            "has_more": {
      +              "description": "Whether another page exists.",
      +              "type": "boolean"
      +            },
      +            "next_cursor": {
      +              "description": "Pass back as `cursor` for the next page; `null` when `has_more` is false.",
      +              "type": [
      +                "string",
      +                "null"
      +              ]
      +            },
      +            "per_page": {
      +              "description": "Number of items per page.",
      +              "type": "integer"
      +            }
      +          },
      +          "type": "object"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "success": {
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object",
      +  "x-fastmcp-top-level-schema": "PhotoListResponse"
      +}
  4. First observedv0.2.0

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, non-idempotent and non-destructive, so the safety profile is covered. The description adds real value beyond that: exactly one reference is accepted and 'sending two is refused', and the reference image 'is sent to Pexafy only to run the search; it is not stored'. It stops short of describing ranking behaviour or failure modes for unreachable URLs, so not a full 5.

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

Conciseness3/5

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

Front-loading is excellent — the when-to-use triggers come first — but the body is roughly 400 words and the guidance for english_search_sentence and explicit_orientation_filter largely restates the schema descriptions almost verbatim, which is padding rather than added value. The orientation paragraph in particular repeats the schema's own caution about it being a hard filter.

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?

An output schema exists so return values need no explanation (the brief mention of rank/licence/credit is a bonus, not a requirement), and annotations carry the safety profile. The description still covers the privacy handling of the reference image and the single-reference constraint, so nothing an agent needs to invoke this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics the schema cannot express per-field: the mutually exclusive 'exactly one reference' rule across photo_id/image_url/image_file/image_base64, and the relationship between the reference and english_search_sentence ('the reference stays the main signal and these words adjust it', 'the full sentence that photograph was found under is what to send').

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 — finds free stock photographs in Pexafy's index that visually match a reference image — and explicitly distinguishes itself from the sibling search_photos by noting that an unlinked picture's scene 'can be searched in words with search_photos'. An agent can route between the two tools without opening either schema.

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 explicit trigger phrases ('find images like this', 'more like the second one'), the condition under which the tool is inapplicable (a picture only visible in the conversation, not linked or passed), and names the alternative tool for that case. When-to-use, when-not-to-use, and the alternative are all present.

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