mcp-stashbox
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| SB_LOG_LEVEL | No | Log level (default 'error'). | error |
| SB_TIMEOUT_MS | No | Timeout for requests in milliseconds (default 20000). | 20000 |
| SB_USER_AGENT | No | User-Agent string for HTTP requests. | |
| SB_MAX_RETRIES | No | Maximum number of retries (default 3). | 3 |
| SB_CACHE_TTL_MS | No | Cache TTL in milliseconds (default 900000). | 900000 |
| STASHBOX_PMV_KEY | No | API key for PMV Stash. | |
| STASHBOX_TPDB_KEY | No | API key for ThePornDB. | |
| SB_MIN_INTERVAL_MS | No | Minimum interval between requests in milliseconds (default and floor 1000). | 1000 |
| STASHBOX_FANSDB_KEY | No | API key for FansDB. | |
| SB_CACHE_MAX_ENTRIES | No | Maximum cache entries (default 200). | 200 |
| STASHBOX_STASHDB_KEY | No | API key for StashDB. | |
| STASHBOX_JAVSTASH_KEY | No | API key for JAVStash. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_sourcesA | What each configured stash-box catalogue was measured answering, and the day its surface was read from it. Whether a key is held for a catalogue is a fact about this install and changes nothing about what the catalogue does. Reaches no catalogue and takes no argument. |
| search_scenesA | Search scenes across every configured stash-box catalogue. Two exclusive paths: 'query' runs each catalogue's own text index, which reads the words as a union, and the typed arguments narrow as an intersection. Writing both is refused. The answer says per catalogue which of three it met: a failure, a catalogue nobody asked, and an emptiness it established. Counts are never added across them. |
| search_performersA | Search performers across every configured stash-box catalogue. Two exclusive paths: 'query' runs each catalogue's own text index, which reads the words as a union, and the typed arguments narrow as an intersection. Writing both is refused. The answer says per catalogue which of three it met: a failure, a catalogue nobody asked, and an emptiness it established. Counts are never added across them. |
| search_studiosA | Search studios across every configured stash-box catalogue. Two exclusive paths: 'query' runs each catalogue's own text index, which reads the words as a union, and the typed arguments narrow as an intersection. Writing both is refused. The answer says per catalogue which of three it met: a failure, a catalogue nobody asked, and an emptiness it established. Counts are never added across them. |
| search_tagsA | Search tags across every configured stash-box catalogue. Two exclusive paths: 'query' runs each catalogue's own text index, which reads the words as a union, and the typed arguments narrow as an intersection. Writing both is refused. The answer says per catalogue which of three it met: a failure, a catalogue nobody asked, and an emptiness it established. Counts are never added across them. |
| get_sceneA | Read one scene from the catalogue its identifier names, written instance:uuid. The answer is one card, read on every catalogue that holds the record and reached by the link each of them publishes to the same record elsewhere. Every value names the catalogues that said it, and where they disagree the reading nobody preferred is published beside the one that won. Name 'sources' to read one catalogue alone. |
| get_performerA | Read one performer from the catalogue its identifier names, written instance:uuid. The answer is one card, read on every catalogue that holds the record and reached by the link each of them publishes to the same record elsewhere. Every value names the catalogues that said it, and where they disagree the reading nobody preferred is published beside the one that won. Name 'sources' to read one catalogue alone. |
| get_studioA | Read one studio from the catalogue its identifier names, written instance:uuid. The answer is one card, read on every catalogue that holds the record and reached by the link each of them publishes to the same record elsewhere. Every value names the catalogues that said it, and where they disagree the reading nobody preferred is published beside the one that won. Name 'sources' to read one catalogue alone. |
| get_tagB | Read one tag from the catalogue its identifier names, written instance:uuid. The answer is one card, read on every catalogue that holds the record and reached by the link each of them publishes to the same record elsewhere. Every value names the catalogues that said it, and where they disagree the reading nobody preferred is published beside the one that won. Name 'sources' to read one catalogue alone. |
| find_by_fingerprintA | 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. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 10 tools
The set is neatly partitioned by verb (search_* vs get_*) and by entity type (scenes, performers, studios, tags), so selection is almost always obvious. The only soft edge is find_by_fingerprint, which reaches records that are then rendered like scene cards, making it slightly confusable with get_scene at the point of consumption; get_sources is clearly separate as install metadata.
Names are uniformly snake_case and verb-led, with a clean search_<entity> / get_<entity> symmetry across the four entity types. find_by_fingerprint and get_sources break the verb_noun shape slightly (prepositional compound, and a non-entity noun), which is a minor deviation rather than an inconsistency.
Ten tools is well within the ideal range and every tool earns its place: four entity searches, four entity reads, one hash lookup, and one configuration/health inspection. Nothing looks redundant or bolted on for a read-only cross-catalogue facade.
The read lifecycle is covered end to end for all four entity types: discover via search, resolve via get with cross-catalogue merge, plus fingerprint-based file identification and catalogue introspection. The main gap is the absence of an unfiltered browse/list operation — if a caller has no query terms or typed filters, there is no way to page through a catalogue's contents, and there are no tools for traversing relations (e.g. scenes by performer) beyond whatever filters the search schemas accept.