Skip to main content
Glama
smeet666

mcp-stashbox

Find scenes by fingerprint

find_by_fingerprint
Read-only

Match file hashes (MD5, OSHASH, PHASH) against stash-box catalogues to identify scenes and return detailed records from every catalogue holding the fingerprint.

Instructions

Identify a file from the hashes held for it, across every configured stash-box catalogue. MD5 and OSHASH name the bytes of a file; PHASH states a likeness a re-encode, a crop or another scene from one shoot can satisfy. Each record reached is answered as one card, read on every catalogue that holds it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
preferNoThe order the catalogues are preferred in where they disagree on a field. Left out, the registry's own order stands, and every card states the order applied.
sourcesNo
sectionsNoThe blocks read beside the record's own fields, which come back whatever is written here. Each name adds a block, and 'basic' asks for those fields alone.
fingerprintsYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
askedYes
notesYes
cachedNo
matchesYes
unmatchedYesThe hashes put to a catalogue that answered, which reached no record there. A catalogue named as unasked says nothing about them either way.
per_sourceYes
match_countYesOne per card here. Every hash that reached a record names it on one card, and a record reached both by an exact hash and by a perceptual one stands as two, since the two claim different things about it. Read records_named for how many files were named, which counts each once.
not_searchedYesHashes and the catalogues that answered without searching their algorithm, so they were never put to those. Nobody looked there, which is no evidence about the files behind them.
resemblancesYesMatches a perceptual hash reached, each a likeness and no claim about any file's bytes.
unattributedYesRecords the catalogues answered with that carry none of the hashes asked. Which hash reached them is unknown, so they stand as no match and are counted apart.
records_namedYesDistinct records an exact hash named. Two hashes reaching one record count once, and a perceptual match names no record.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changedv1.0.0
    • changedInput schema / properties / prefer / description
      Previous value: -"The order the catalogues are preferred in where they disagree on a field. Left out, the order the registry declares stands. Every card states the order that was applied."New value: +"The order the catalogues are preferred in where they disagree on a field. Left out, the registry's own order stands, and every card states the order applied."
    • changedOutput schema / properties / match_count / description
      Previous value: -"One per record reached, whatever number of hashes reached it."New value: +"One per card here. Every hash that reached a record names it on one card, and a record reached both by an exact hash and by a perceptual one stands as two, since the two claim different things about it. Read records_named for how many files were named, which counts each once."
    • changedOutput schema / properties / matches / items / properties / scene / properties / held_by / description
      Previous value: -"Every catalogue asked, with the identifier the record carries there."New value: +"Every catalogue asked, with the identifier the record carries there. This is where what each of them did with the record is read: the state says which of the three it met, and the reason says why it was not asked or what went wrong."
    • changedOutput schema / properties / per_source / items / properties / index_total / description
      Previous value: -"What its own index holds for this question, the rows on this page included."New value: +"What its own index holds for the question it received, the rows on this page included. A narrowing it could not receive, or received in part, leaves that question wider than the one written."
    • changedOutput schema / properties / per_source / items / properties / narrowings_not_received / description
      Previous value: -"Narrowings this catalogue cannot receive. This is the one field that says a catalogue cannot do something."New value: +"Narrowings that shaped no part of the request this catalogue received, whether its route declares no field for one or nothing written was left for one to decide."
    • addedOutput schema / properties / per_source / items / properties / narrowings_received_in_part / description
      Added value: +"Narrowings it received short of what was written, the rest of the list naming records another catalogue minted. It answered a wider question than the one asked."
  2. Changed57 schema fields changedv0.9.0
    • removedInput schema / properties / fingerprints / description
      Removed value: -"Every fingerprint held for one file. A file carries one hash per algorithm, so a longer list is an inventory rather than a question."
    • addedInput schema / properties / fingerprints / items / additionalProperties
      Added value: +false
    • removedInput schema / properties / fingerprints / items / properties / hash / description
      Removed value: -"The fingerprint as the hashing tool produced it."
    • addedInput schema / properties / fingerprints / items / properties / hash / minLength
      Added value: +1
    • changedInput schema / properties / fingerprints / maxItems
      Previous value: -10New value: +25
    • addedInput schema / properties / prefer
      Added value: +{
      +  "description": "The order the catalogues are preferred in where they disagree on a field. Left out, the order the registry declares stands. Every card states the order that was applied.",
      +  "items": {
      +    "enum": [
      +      "stashdb",
      +      "tpdb",
      +      "fansdb",
      +      "pmv",
      +      "javstash"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 5,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • addedInput schema / properties / sections
      Added value: +{
      +  "description": "The blocks read beside the record's own fields, which come back whatever is written here. Each name adds a block, and 'basic' asks for those fields alone.",
      +  "items": {
      +    "enum": [
      +      "basic",
      +      "fingerprints",
      +      "images"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 3,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • removedInput schema / properties / sources / description
      Removed value: -"Narrow to named catalogues. Every configured catalogue is asked by default."
    • addedInput schema / properties / sources / items / enum
      Added value: +[
      +  "stashdb",
      +  "tpdb",
      +  "fansdb",
      +  "pmv",
      +  "javstash"
      +]
    • addedInput schema / properties / sources / maxItems
      Added value: +5
    • addedInput schema / properties / sources / minItems
      Added value: +1
    • addedOutput schema / properties / cached
      Added value: +{
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / match_count / description
      Previous value: -"Matches returned: one per scene per fingerprint it carries."New value: +"One per record reached, whatever number of hashes reached it."
    • removedOutput schema / properties / matches / items / properties / algorithm
      Removed value: -{
      -  "enum": [
      -    "MD5",
      -    "OSHASH",
      -    "PHASH"
      -  ],
      -  "type": "string"
      -}
    • removedOutput schema / properties / matches / items / properties / fingerprint
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "additionalProperties": false,
      -      "properties": {
      -        "algorithm": {
      -          "enum": [
      -            "MD5",
      -            "OSHASH",
      -            "PHASH"
      -          ],
      -          "type": "string"
      -        },
      -        "contested": {
      -          "anyOf": [
      -            {
      -              "type": "boolean"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ],
      -          "description": "Whether the reports reach the submissions. Null where the catalogue publishes no report count: a fingerprint nobody has disputed and one on a catalogue that counts no disputes are different things."
      -        },
      -        "duration_seconds": {
      -          "anyOf": [
      -            {
      -              "type": "number"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ]
      -        },
      -        "hash": {
      -          "type": "string"
      -        },
      -        "reports": {
      -          "anyOf": [
      -            {
      -              "type": "number"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ],
      -          "description": "How many people reported against it. Null on a catalogue that records no reports, which is an unknown contest and never an absence of one."
      -        },
      -        "submissions": {
      -          "anyOf": [
      -            {
      -              "type": "number"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ],
      -          "description": "How many people entered this fingerprint. Null where the catalogue counts none."
      -        }
      -      },
      -      "required": [
      -        "algorithm",
      -        "hash",
      -        "duration_seconds",
      -        "submissions",
      -        "reports",
      -        "contested"
      -      ],
      -      "type": "object"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
    • changedOutput schema / properties / matches / items / properties / match_kind / description
      Previous value: -"'exact_file' means the same file, byte for byte. 'perceptual_similarity' means images that resemble each other, which covers a re-encode, a crop and a different scene from one shoot, and is no evidence that two files are the same."New value: +"'exact_file' names the same bytes. 'perceptual_similarity' covers a re-encode, a crop and another scene from one shoot, and is no evidence that two files are the same."
    • addedOutput schema / properties / matches / items / properties / matched_by
      Added value: +{
      +  "description": "Every hash that reached this record, each naming the catalogues it reached it on. A hash a catalogue does not search reached nothing there.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "algorithm": {
      +        "enum": [
      +          "MD5",
      +          "OSHASH",
      +          "PHASH"
      +        ],
      +        "type": "string"
      +      },
      +      "hash": {
      +        "type": "string"
      +      },
      +      "sources": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "hash",
      +      "algorithm",
      +      "sources"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / matches / items / properties / scene / properties / counts
      Added value: +{
      +  "additionalProperties": {
      +    "items": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "source": {
      +          "type": "string"
      +        },
      +        "state": {
      +          "enum": [
      +            "answered",
      +            "failed",
      +            "absent"
      +          ],
      +          "type": "string"
      +        },
      +        "value": {
      +          "anyOf": [
      +            {
      +              "type": "number"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        }
      +      },
      +      "required": [
      +        "source",
      +        "value",
      +        "state"
      +      ],
      +      "type": "object"
      +    },
      +    "type": "array"
      +  },
      +  "description": "Counts, one entry per catalogue asked and never added together. A null is read with the state beside it: a catalogue that publishes no such count, one that could not answer, and one nobody asked are three different facts.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / matches / items / properties / scene / properties / fields
      Added value: +{
      +  "additionalProperties": {
      +    "anyOf": [
      +      {
      +        "additionalProperties": false,
      +        "properties": {
      +          "agreed_by": {
      +            "description": "The catalogues that published this reading. Two agreeing is evidence of its own.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "disagreed": {
      +            "description": "The readings nobody preferred, published rather than dropped: choosing between them is a policy, and a policy applied in silence is a claim nobody can check.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "source": {
      +                  "type": "string"
      +                },
      +                "value": {}
      +              },
      +              "required": [
      +                "source",
      +                "value"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "value": {
      +            "description": "The reading the preference named, null where none published one."
      +          }
      +        },
      +        "required": [
      +          "value",
      +          "agreed_by"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "items": {
      +          "additionalProperties": false,
      +          "properties": {
      +            "also_at": {
      +              "description": "What this same record is called on another catalogue, from a link joining the two.",
      +              "items": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "id": {
      +                    "type": "string"
      +                  },
      +                  "source": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "source",
      +                  "id"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "published_by": {
      +              "description": "Every catalogue that published this very record. A shared name is no join, so an entry one catalogue minted names that one.",
      +              "items": {
      +                "type": "string"
      +              },
      +              "type": "array"
      +            },
      +            "same_name_as": {
      +              "description": "A record another catalogue published under a matching name. A resemblance, never a join.",
      +              "items": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "id": {
      +                    "type": "string"
      +                  },
      +                  "source": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "source",
      +                  "id"
      +                ],
      +                "type": "object"
      +              },
      +              "type": "array"
      +            },
      +            "value": {}
      +          },
      +          "required": [
      +            "value",
      +            "published_by"
      +          ],
      +          "type": "object"
      +        },
      +        "type": "array"
      +      }
      +    ]
      +  },
      +  "description": "Each field of the record. A scalar carries the catalogues that said it; a list is the union, each entry naming who published it.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / matches / items / properties / scene / properties / held_by
      Added value: +{
      +  "description": "Every catalogue asked, with the identifier the record carries there.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "error": {
      +        "type": "string"
      +      },
      +      "id": {
      +        "type": "string"
      +      },
      +      "reason": {
      +        "type": "string"
      +      },
      +      "retrieved_at": {
      +        "description": "The moment this client read it there.",
      +        "type": "string"
      +      },
      +      "source": {
      +        "type": "string"
      +      },
      +      "source_url": {
      +        "description": "The address it was read at, which credits it.",
      +        "type": "string"
      +      },
      +      "state": {
      +        "enum": [
      +          "answered",
      +          "failed",
      +          "absent"
      +        ],
      +        "type": "string"
      +      },
      +      "status": {
      +        "description": "What the identifier addresses there now. A folded record is held elsewhere.",
      +        "enum": [
      +          "established",
      +          "merged",
      +          "deleted"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "source",
      +      "state"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • removedOutput schema / properties / matches / items / properties / scene / properties / id
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / matches / items / properties / scene / properties / kind
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / matches / items / properties / scene / properties / notes
      Added value: +{
      +  "description": "What this answer does not establish, which is what makes it safe to act on.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • removedOutput schema / properties / matches / items / properties / scene / properties / performers
      Removed value: -{
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • addedOutput schema / properties / matches / items / properties / scene / properties / preferred
      Added value: +{
      +  "description": "The order the readings were preferred in. This is the policy that was applied, whether or not every catalogue in it answered.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / matches / items / properties / scene / properties / read_from
      Added value: +{
      +  "description": "The catalogues that answered, in the order they were preferred. A policy and an outcome are two facts, and a reader deciding whether to change the policy needs both.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • removedOutput schema / properties / matches / items / properties / scene / properties / release_date
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "additionalProperties": false,
      -      "properties": {
      -        "precision": {
      -          "description": "How much of the date a cataloguer entered. A value recorded to the year carries no month and no day, and reading it as one would claim a precision nobody entered.",
      -          "enum": [
      -            "day",
      -            "month",
      -            "year"
      -          ],
      -          "type": "string"
      -        },
      -        "value": {
      -          "description": "The date exactly as the catalogue publishes it.",
      -          "type": "string"
      -        }
      -      },
      -      "required": [
      -        "value",
      -        "precision"
      -      ],
      -      "type": "object"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
    • removedOutput schema / properties / matches / items / properties / scene / properties / source
      Removed value: -{
      -  "type": "string"
      -}
    • removedOutput schema / properties / matches / items / properties / scene / properties / source_url
      Removed value: -{
      -  "type": "string"
      -}
    • removedOutput schema / properties / matches / items / properties / scene / properties / studio
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
    • removedOutput schema / properties / matches / items / properties / scene / properties / title
      Removed value: -{
      -  "anyOf": [
      -    {
      -      "type": "string"
      -    },
      -    {
      -      "type": "null"
      -    }
      -  ]
      -}
    • changedOutput schema / properties / matches / items / properties / scene / required
      Previous value: -[
      -  "id",
      -  "source",
      -  "title",
      -  "release_date",
      -  "studio",
      -  "performers",
      -  "source_url"
      -]New value: +[
      +  "kind",
      +  "fields",
      +  "counts",
      +  "held_by",
      +  "preferred",
      +  "read_from",
      +  "notes"
      +]
    • changedOutput schema / properties / matches / items / required
      Previous value: -[
      -  "algorithm",
      -  "match_kind",
      -  "scene",
      -  "fingerprint"
      -]New value: +[
      +  "scene",
      +  "matched_by",
      +  "match_kind"
      +]
    • addedOutput schema / properties / not_searched
      Added value: +{
      +  "description": "Hashes and the catalogues that answered without searching their algorithm, so they were never put to those. Nobody looked there, which is no evidence about the files behind them.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "algorithm": {
      +        "type": "string"
      +      },
      +      "hash": {
      +        "type": "string"
      +      },
      +      "sources": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "hash",
      +      "algorithm",
      +      "sources"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / per_source / items / properties / algorithms_not_searched
      Added value: +{
      +  "description": "Fingerprint algorithms its lookup does not search, so they were never put to it.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / per_source / items / properties / count / description
      Previous value: -"Rows this catalogue contributed to this page."New value: +"Rows it contributed. Never added to another catalogue's: they index corpora that overlap by an amount none of them publishes."
    • addedOutput schema / properties / per_source / items / properties / error / enum
      Added value: +[
      +  "not_found",
      +  "invalid_input",
      +  "rate_limited",
      +  "parse_failure",
      +  "network_error",
      +  "timeout"
      +]
    • removedOutput schema / properties / per_source / items / properties / fields_searched
      Removed value: -{
      -  "description": "The fields the text index read. Absent where no text index was consulted.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • changedOutput schema / properties / per_source / items / properties / index_total / description
      Previous value: -"What this catalogue's index holds for the question, beyond the page returned."New value: +"What its own index holds for this question, the rows on this page included."
    • addedOutput schema / properties / per_source / items / properties / index_total_over_any_word
      Added value: +{
      +  "description": "The total counts rows carrying any word of the query, its text index reading them apart.",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / per_source / items / properties / moment / description
      Previous value: -"Which step failed, for a catalogue that failed."New value: +"Which moment failed."
    • addedOutput schema / properties / per_source / items / properties / name / description
      Added value: +"The name that catalogue calls itself."
    • addedOutput schema / properties / per_source / items / properties / narrowings_naming_no_record
      Added value: +{
      +  "description": "Narrowings written only with identifiers another catalogue minted.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / per_source / items / properties / narrowings_not_received / description
      Previous value: -"Narrowings this catalogue could not receive. A row of its satisfying one of them does so by chance."New value: +"Narrowings this catalogue cannot receive. This is the one field that says a catalogue cannot do something."
    • addedOutput schema / properties / per_source / items / properties / narrowings_received_in_part
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / per_source / items / properties / reason / description
      Added value: +"Why it was not asked, or what went wrong."
    • addedOutput schema / properties / per_source / items / properties / records
      Added value: +{
      +  "description": "Distinct records behind its rows.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / per_source / items / properties / skipped / description
      Added value: +"Rows it answered with that this client could not read and left out."
    • addedOutput schema / properties / per_source / items / properties / source / description
      Added value: +"The catalogue this row is about."
    • changedOutput schema / properties / per_source / items / properties / state / description
      Previous value: -"'answered' is a catalogue that looked, and a count of zero there means it found nothing. 'failed' could not answer. 'absent' was never asked. An answer holding rows from some catalogues is no evidence about the others."New value: +"'answered' looked, and a count of zero means it found nothing. 'failed' could not answer, and states nothing about what it holds. 'absent' was never asked. Only the first is evidence about the world."
    • addedOutput schema / properties / per_source / items / properties / unattributed / description
      Added value: +"Records it answered with while carrying none of what was asked about."
    • addedOutput schema / properties / records_named
      Added value: +{
      +  "description": "Distinct records an exact hash named. Two hashes reaching one record count once, and a perceptual match names no record.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / resemblances
      Added value: +{
      +  "description": "Matches a perceptual hash reached, each a likeness and no claim about any file's bytes.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / scenes_matched
      Removed value: -{
      -  "description": "Distinct scenes behind those matches.",
      -  "type": "number"
      -}
    • changedOutput schema / properties / unattributed / description
      Previous value: -"Scenes a catalogue answered with while returning none of the fingerprints asked for. Which hash reached them is unknown, which is kept apart from a catalogue that found nothing."New value: +"Records the catalogues answered with that carry none of the hashes asked. Which hash reached them is unknown, so they stand as no match and are counted apart."
    • addedOutput schema / properties / unmatched
      Added value: +{
      +  "description": "The hashes put to a catalogue that answered, which reached no record there. A catalogue named as unasked says nothing about them either way.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "algorithm": {
      +        "type": "string"
      +      },
      +      "hash": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "hash",
      +      "algorithm"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "asked",
      -  "matches",
      -  "match_count",
      -  "scenes_matched",
      -  "unattributed",
      -  "per_source",
      -  "notes"
      -]New value: +[
      +  "matches",
      +  "match_count",
      +  "records_named",
      +  "resemblances",
      +  "unattributed",
      +  "unmatched",
      +  "not_searched",
      +  "asked",
      +  "per_source",
      +  "notes"
      +]
  3. Changed5 schema fields changedv0.2.1
    • addedOutput schema / properties / match_count / description
      Added value: +"Matches returned: one per scene per fingerprint it carries."
    • addedOutput schema / properties / per_source / items / properties / skipped
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / per_source / items / properties / unattributed
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / scenes_matched
      Added value: +{
      +  "description": "Distinct scenes behind those matches.",
      +  "type": "number"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "asked",
      -  "matches",
      -  "match_count",
      -  "unattributed",
      -  "per_source",
      -  "notes"
      -]New value: +[
      +  "asked",
      +  "matches",
      +  "match_count",
      +  "scenes_matched",
      +  "unattributed",
      +  "per_source",
      +  "notes"
      +]
  4. First observedv0.1.1

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already disclose readOnlyHint and openWorldHint, so the description needs less safety disclosure. It adds behavioral value by stating the search spans every configured catalogue and that each matched record is returned as one card per catalogue that holds it, and it explains the semantic distinction between byte-exact and likeness hashes.

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?

The description is compact and front-loaded with the main action, and it packs useful hash semantics into just three sentences. The wording is somewhat stylized and roundabout ('answered as one card, read on every catalogue that holds it'), but it remains appropriately sized and readable.

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

Completeness4/5

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

Given the output schema exists, the description does not need to detail return record shapes, and it addresses the central behaviors: catalogue-wide scanning, hash algorithm meanings, and per-catalogue cards. It leaves some nuance about the 'sources' parameter implicit, yet the parseable schema descriptions and annotation still make this tool usable without large gaps.

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?

The schema covers about half of the parameters with descriptions, and the description adds meaning beyond it—especially the algorithm semantics: MD5/OSHASH name file bytes, while PHASH captures a re-encode/crop similarity. This helps an agent choose correct fingerprint values, though sources and sections still rely heavily on schema names and the existing descriptions.

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?

Description clearly states the tool's function: identify a file/scene from hashes across every configured stash-box catalogue. It uses a specific verb and resource ('identify a file', 'hashes', 'catalogue'), and the fingerprint-based scope distinguishes it from siblings like search_scenes and get_scene.

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

Usage Guidelines4/5

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

The description creates clear context: use this when you have hashes and want to identify a matching file across catalogues, with MD5/OSHASH for byte-exact matches and PHASH for likeness. It does not explicitly name alternatives or say 'use search_scenes instead', so it falls short of a perfect score, but the intended usage is unmistakable.

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