# io.github.smeet666/mcp-stashbox (npm · mcp-stashbox)

Search scenes, performers, studios and tags across the public stash-box catalogues.

- Trust score: 89/100 (high trust)
- Change this week: 0
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-20

## Components

- mcpb · `mcp-stashbox-2.0.1.mcpb`: 49/100, [markdown](https://verifymcp.io/servers/smeet666-mcp-stashbox/https-github-com-smeet666-mcp-stashbox-releases-download-v2-0-1-mcp-stashbox-2-0.md), [page](https://verifymcp.io/servers/smeet666-mcp-stashbox/https-github-com-smeet666-mcp-stashbox-releases-download-v2-0-1-mcp-stashbox-2-0)
- npm · `mcp-stashbox`: 89/100 (this document), [markdown](https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox.md), [page](https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox)

## Channel facts

- Registry: `npm`
- Package: `mcp-stashbox`
- Version: `2.0.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-20.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 31 of 95 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to smeet666/mcp-stashbox).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 21 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 50/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 2578 tokens (~257/item across 10 items; 10 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 100/100
  - No destabilizing schema changes in the last 30 days.
- **Tool Coverage**: 82/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 38% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 10 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 11 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the io.github.smeet666/mcp-stashbox server?

io.github.smeet666/mcp-stashbox runs locally as an npm package, launched with npx -y mcp-stashbox. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add smeet666-mcp-stashbox -- npx -y mcp-stashbox
```

### Cursor

```json
{
  "mcpServers": {
    "smeet666-mcp-stashbox": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-stashbox"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "smeet666-mcp-stashbox": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-stashbox"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add smeet666-mcp-stashbox -- npx -y mcp-stashbox
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "smeet666-mcp-stashbox": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "mcp-stashbox"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add smeet666-mcp-stashbox --command npx --arg -y --arg mcp-stashbox
```

### Hermes

```yaml
mcp_servers:
  smeet666-mcp-stashbox:
    command: "npx"
    args: ["-y", "mcp-stashbox"]
```

### Netclaw

```json
{
  "McpServers": {
    "smeet666-mcp-stashbox": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "mcp-stashbox"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add smeet666-mcp-stashbox -t stdio -c npx -a -y mcp-stashbox
```

### Other

```json
{
  "mcpServers": {
    "smeet666-mcp-stashbox": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-stashbox"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-20 (score 89, 0)

- [security] Stability: 0.97 → pass

### 2026-09-19 (score 89, +1)

No change was recorded against any check on this day. Stability & Change Management went from 93 to 97. That category is still filling its 30-day observation window: 28 days of observed history at the previous scan, 29 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-17 (score 88, +1)

No change was recorded against any check on this day. Stability & Change Management went from 87 to 90. That category is still filling its 30-day observation window: 26 days of observed history at the previous scan, 27 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-15 (score 87, +1)

No change was recorded against any check on this day. Stability & Change Management went from 80 to 83. That category is still filling its 30-day observation window: 24 days of observed history at the previous scan, 25 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-14 (score 86, −3)

- [functional] Stability: pass → 0.80

### 2026-09-10 (score 89, 0)

- [security] Stability: 0.97 → pass

### 2026-09-09 (score 89, +1)

No change was recorded against any check on this day. Stability & Change Management went from 93 to 97. That category is still filling its 30-day observation window: 28 days of observed history at the previous scan, 29 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-07 (score 88, +1)

No change was recorded against any check on this day. Stability & Change Management went from 87 to 90. That category is still filling its 30-day observation window: 26 days of observed history at the previous scan, 27 at this one. The score rises as the window fills, whether or not the server changes.

## MCP tools (10)

### `get_sources` (~60 tokens)

What each catalogue answers

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.

Output parameters:

- `notes` (array)
- `sources` (array)

### `search_scenes` (~460 tokens)

Search scenes

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.

Input parameters:

- `alias` (string): No catalogue's faceted route applies it, though every faceted input declares it: a request carrying it answers as wide as one carrying none, so it is never sent and the answer names it as a narrowing…
- `code` (string)
- `date` (string)
- `date_compare` (string): These catalogues compare a date against one bound and answer no range, so the comparison is written rather than assumed.
- `direction` (string)
- `limit` (integer): How many rows one page of one catalogue carries. An answer holding several carries up to this many from each: their pages are their own and nothing here interleaves them into one.
- `match` (string): How performer_ids and tag_ids are read, which are the only arguments it governs. 'all', the default, asks for scenes carrying every identifier of a list; 'any' for scenes carrying at least one, which…
- `page` (integer): Which page of its own order every catalogue asked is read at, counted from 1. A search written with words alone reads the first rows each text index answers with, since those routes take no page.
- `parent_studio_id` (string)
- `performer_ids` (array)
- `query` (string): Words for the catalogue's own text index, which reads them as a union. It is exclusive with the typed arguments, which narrow as an intersection.
- `sort` (string)
- `sources` (array)
- `studio_ids` (array)
- `tag_ids` (array)
- `title` (string)

Output parameters:

- `cached` (boolean): Replayed from this client's store.
- `notes` (array)
- `ordering` (string): How the rows were laid out, which a reader needs before reading the first.
- `per_source` (array)
- `result_count` (number): How many rows this page carries.
- `results` (array)
- `window` (object): The page and the row limit this answer was read at, absent where no catalogue answered.

### `search_performers` (~454 tokens)

Search performers

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.

Input parameters:

- `alias` (string): No catalogue's faceted route applies it, though every faceted input declares it: a request carrying it answers as wide as one carrying none, so it is never sent and the answer names it as a narrowing…
- `birth_year` (integer)
- `career_end_year` (integer): No catalogue's faceted route applies it, though every faceted input declares it: a request carrying it answers as wide as one carrying none, so it is never sent and the answer names it as a narrowing…
- `career_start_year` (integer): No catalogue's faceted route applies it, though every faceted input declares it: a request carrying it answers as wide as one carrying none, so it is never sent and the answer names it as a narrowing…
- `country` (string)
- `direction` (string)
- `disambiguation` (string)
- `ethnicity` (string)
- `gender` (string)
- `limit` (integer): How many rows one page of one catalogue carries. An answer holding several carries up to this many from each: their pages are their own and nothing here interleaves them into one.
- `name` (string)
- `page` (integer): Which page of its own order every catalogue asked is read at, counted from 1. A search written with words alone reads the first rows each text index answers with, since those routes take no page.
- `performed_with` (string)
- `query` (string): Words for the catalogue's own text index, which reads them as a union. It is exclusive with the typed arguments, which narrow as an intersection.
- `sort` (string)
- `sources` (array)
- `studio_id` (string)

Output parameters:

- `cached` (boolean): Replayed from this client's store.
- `notes` (array)
- `ordering` (string): How the rows were laid out, which a reader needs before reading the first.
- `per_source` (array)
- `result_count` (number): How many rows this page carries.
- `results` (array)
- `window` (object): The page and the row limit this answer was read at, absent where no catalogue answered.

### `search_studios` (~258 tokens)

Search studios

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.

Input parameters:

- `direction` (string)
- `has_parent` (boolean)
- `limit` (integer): How many rows one page of one catalogue carries. An answer holding several carries up to this many from each: their pages are their own and nothing here interleaves them into one.
- `name` (string)
- `page` (integer): Which page of its own order every catalogue asked is read at, counted from 1. A search written with words alone reads the first rows each text index answers with, since those routes take no page.
- `parent_id` (string)
- `query` (string): Words for the catalogue's own text index, which reads them as a union. It is exclusive with the typed arguments, which narrow as an intersection.
- `sort` (string)
- `sources` (array)

Output parameters:

- `cached` (boolean): Replayed from this client's store.
- `notes` (array)
- `ordering` (string): How the rows were laid out, which a reader needs before reading the first.
- `per_source` (array)
- `result_count` (number): How many rows this page carries.
- `results` (array)
- `window` (object): The page and the row limit this answer was read at, absent where no catalogue answered.

### `search_tags` (~249 tokens)

Search tags

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.

Input parameters:

- `category_id` (string)
- `direction` (string)
- `limit` (integer): How many rows one page of one catalogue carries. An answer holding several carries up to this many from each: their pages are their own and nothing here interleaves them into one.
- `name` (string)
- `page` (integer): Which page of its own order every catalogue asked is read at, counted from 1. A search written with words alone reads the first rows each text index answers with, since those routes take no page.
- `query` (string): Words for the catalogue's own text index, which reads them as a union. It is exclusive with the typed arguments, which narrow as an intersection.
- `sort` (string)
- `sources` (array)

Output parameters:

- `cached` (boolean): Replayed from this client's store.
- `notes` (array)
- `ordering` (string): How the rows were laid out, which a reader needs before reading the first.
- `per_source` (array)
- `result_count` (number): How many rows this page carries.
- `results` (array)
- `window` (object): The page and the row limit this answer was read at, absent where no catalogue answered.

### `get_scene` (~181 tokens)

Get one scene

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.

Input parameters:

- `id` (string, required)
- `prefer` (array): 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.
- `sections` (array): 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.
- `sources` (array)

Output parameters:

- `cached` (boolean)
- `card` (object)

### `get_performer` (~204 tokens)

Get one performer

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.

Input parameters:

- `id` (string, required)
- `prefer` (array): 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.
- `sections` (array): 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. 'studios' is the whole table of studios they…
- `sources` (array)

Output parameters:

- `cached` (boolean)
- `card` (object)

### `get_studio` (~142 tokens)

Get one studio

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.

Input parameters:

- `id` (string, required)
- `prefer` (array): 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.
- `sources` (array)

Output parameters:

- `cached` (boolean)
- `card` (object)

### `get_tag` (~141 tokens)

Get one tag

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.

Input parameters:

- `id` (string, required)
- `prefer` (array): 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.
- `sources` (array)

Output parameters:

- `cached` (boolean)
- `card` (object)

### `find_by_fingerprint` (~170 tokens)

Find scenes by fingerprint

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 parameters:

- `fingerprints` (array, required)
- `prefer` (array): 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.
- `sections` (array): 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.
- `sources` (array)

Output parameters:

- `asked` (array)
- `cached` (boolean)
- `match_count` (number): 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…
- `matches` (array)
- `not_searched` (array): 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.
- `notes` (array)
- `per_source` (array)
- `records_named` (number): Distinct records an exact hash named. Two hashes reaching one record count once, and a perceptual match names no record.
- `resemblances` (number): Matches a perceptual hash reached, each a likeness and no claim about any file's bytes.
- `unattributed` (number): 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.
- `unmatched` (array): The hashes put to a catalogue that answered, which reached no record there. A catalogue named as unasked says nothing about them either way.

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox#diagnostics

## Score history

- 2026-09-20: 89
- 2026-09-19: 89
- 2026-09-18: 88
- 2026-09-17: 88
- 2026-09-16: 87
- 2026-09-15: 87
- 2026-09-14: 86
- 2026-09-13: 89
- 2026-09-12: 89
- 2026-09-11: 89
- 2026-09-10: 89
- 2026-09-09: 89
- 2026-09-08: 88
- 2026-09-07: 88
- 2026-09-06: 87
- 2026-09-05: 87
- 2026-09-04: 86
- 2026-09-03: 86
- 2026-09-02: 85
- 2026-09-01: 85
- 2026-08-31: 84
- 2026-08-30: 84
- 2026-08-29: 68
- 2026-08-28: 83
- 2026-08-27: 82
- 2026-08-26: 82
- 2026-08-25: 80
- 2026-08-24: 79
- 2026-08-23: 79
- 2026-08-22: 78

## Common questions

### What is the io.github.smeet666/mcp-stashbox server?

io.github.smeet666/mcp-stashbox is listed in the public MCP registry as io.github.smeet666/mcp-stashbox. Search scenes, performers, studios and tags across the public stash-box catalogues. This page covers its npm package (mcp-stashbox).

### Is the io.github.smeet666/mcp-stashbox server safe to use?

io.github.smeet666/mcp-stashbox scores 89 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the io.github.smeet666/mcp-stashbox server expose?

io.github.smeet666/mcp-stashbox exposes 10 tools: get_sources, search_scenes, search_performers, search_studios, search_tags, and 5 more. Their descriptions and schemas cost roughly 2,319 tokens of context every time the server is loaded.

### Is the io.github.smeet666/mcp-stashbox server still maintained?

io.github.smeet666/mcp-stashbox is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the io.github.smeet666/mcp-stashbox server under?

io.github.smeet666/mcp-stashbox declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/mcp-stashbox
- Socket report: https://socket.dev/npm/package/mcp-stashbox
- Repository: https://github.com/smeet666/mcp-stashbox
- Changelog RSS feed: https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox.xml
- Changelog JSON feed: https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox.json
- HTML version of this page: https://verifymcp.io/servers/smeet666-mcp-stashbox/mcp-stashbox
