Skip to main content
Glama
README.md
# scentindex

A window onto a large fragrance index. scentindex queries
the public 10ml Fragrance Index — perfumes, the notes inside
them, the houses that make them, and the guides that explain
the vocabulary — and returns what the index returns,
unchanged. No account and no API key are involved; it is a
thin, honest client over a public API.

What you can do with it:

- Search perfumes by free text, house, notes included or
  excluded, accords, family, gender, season, occasion or
  style, and page through the results with a cursor.
- Open one perfume in full to see its notes, accords and
  metadata.
- Start from a perfume, a note set or an accord profile and
  find similar scents, or look for alternatives — the same
  scent profile from other houses.
- Browse perfumes by a single note, for example everything
  containing oud.
- Ask what a note actually smells like and where it tends
  to appear.
- List and open fragrance houses, filtered by type or
  country, and search the index's guides and glossary
  content.

Most tools accept a `locale` for the response language and,
where the underlying operation supports it, a
`response_format` of `concise` (the API's default) or
`detailed`. List tools page with `limit` (1–100) and an
opaque `cursor` taken from a previous response.

## Labelled subset: 9 of 15 tools

This rebuild implements **9 of the original tool set's 15
tools** — the nine that map onto operations published in
the upstream OpenAPI document:

`search_perfumes`, `get_perfume`, `find_similar_perfumes`,
`find_perfume_alternatives`, `perfumes_by_note`,
`explain_note`, `list_houses`, `get_house`, `search_guides`.

The remaining six are **omitted**, because they have no
operation in the published OpenAPI and their argument
shapes are not published anywhere reachable:

`compare_perfumes`, `recommend_perfumes`,
`explain_perfume_term`, `suggest_layering`,
`pick_for_occasion`, `find_gift`.

## Configuration

The API base defaults to `https://mcp.10ml.com/api/v1` and
can be overridden with the `PERFUME_API_BASE` environment
variable. No API key is required.

## CLI

Each tool is a subcommand taking one JSON argument string:

```bash
npx @reneturcios/scentindex search_perfumes '{"q":"oud","limit":10}'
npx @reneturcios/scentindex get_perfume '{"id":"<perfume id>"}'
npx @reneturcios/scentindex find_similar_perfumes '{"perfume":"<name>"}'
npx @reneturcios/scentindex find_perfume_alternatives '{"perfume":"<name>"}'
npx @reneturcios/scentindex perfumes_by_note '{"note":"oud"}'
npx @reneturcios/scentindex explain_note '{"id":"oud"}'
npx @reneturcios/scentindex list_houses '{"country":"FR"}'
npx @reneturcios/scentindex get_house '{"id":"<house id>"}'
npx @reneturcios/scentindex search_guides '{"q":"layering"}'
npx @reneturcios/scentindex --version
```

Output is the upstream JSON, verbatim. Exit codes: `0` on
success, `1` on a runtime error (including a validation or
upstream failure), `2` on a usage error.

## MCP server

```bash
npx -y @reneturcios/scentindex mcp
```

MCP client config:

```json
{
  "mcpServers": {
    "scentindex": {
      "command": "npx",
      "args": ["-y", "@reneturcios/scentindex", "mcp"]
    }
  }
}
```

## Docker

```bash
docker run -i ghcr.io/cloudcorprecords/scentindex
docker run --rm ghcr.io/cloudcorprecords/scentindex perfumes_by_note '{"note":"oud"}'
```

## Development

```bash
npm install
npm run build   # tsc -> dist/
npm test        # tsx --test test/*.test.ts (fake fetch only, no network)
npm run dev     # run the CLI from source
```

## License

MIT — Copyright (c) 2026 Rene Turcios