Metadata-Version: 2.5
Name: langchain-10ml-perfume
Version: 1.0.2
Summary: LangChain tools for the free 10ML Perfume Finder: search perfumes, note pyramids, accords, similar scents, alternatives, notes and houses from the 10ML Fragrance Index. No API key.
Project-URL: Homepage, https://10ml.com/perfume-mcp-server
Project-URL: Documentation, https://10ml.com/perfume-api
Project-URL: Repository, https://github.com/10ml-com/perfume-finder-mcp
Project-URL: Issues, https://github.com/10ml-com/perfume-finder-mcp/issues
Author-email: 10ML Team <contact@10ml.com>
License: MIT
License-File: LICENSE
Keywords: agent,ai-agent,fragrance,fragrance-api,fragrance-notes,fragrantica-alternative,langchain,langchain-tools,mcp,perfume,perfume-api,perfume-mcp,perfume-recommendation,similar-perfumes
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: langchain-core<2.0.0,>=0.3.0
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# langchain-10ml-perfume: LangChain tools for the free 10ML Perfume Finder

LangChain tools for the free perfume API and fragrance notes API behind **10ML Perfume Finder**: 6,000+ perfumes from the 10ML Fragrance Index, curated by the fragrance editors of [10ML](https://10ml.com), with note pyramids, accords, similar scents, alternatives, notes explained and houses. Read-only, **no API key, no sign-up**. Depends on `langchain-core` only.

[![PyPI](https://img.shields.io/pypi/v/langchain-10ml-perfume?color=002AFF)](https://pypi.org/project/langchain-10ml-perfume/)
[![Official MCP Registry](https://img.shields.io/badge/MCP%20Registry-com.10ml%2Fperfume--finder-002AFF)](https://registry.modelcontextprotocol.io/v0/servers?search=com.10ml/perfume-finder)

## Install

```bash
pip install langchain-10ml-perfume
```

Python 3.10 or newer.

## Quick start

```python
from langchain_10ml_perfume import Perfume10MLToolkit

tools = Perfume10MLToolkit().get_tools()  # 8 tools, no key needed

search = next(t for t in tools if t.name == "search_perfumes")
found = search.invoke({"query": "fresh citrus summer cologne for men", "limit": 3})
for hit in found["results"]:
    print(hit["name"], "-", hit["house"])
```

Give the tools to an agent:

```python
from langchain.agents import create_agent

agent = create_agent("anthropic:claude-sonnet-4-5", tools)
result = agent.invoke({"messages": [("user", "Find me an alternative to Baccarat Rouge 540 and tell me how close it is.")]})
print(result["messages"][-1].content)
```

Or use a single tool:

```python
from langchain_10ml_perfume import FindPerfumeAlternativesTool

print(FindPerfumeAlternativesTool().invoke({"perfume": "Creed Aventus", "limit": 3}))
```

## Tools

| Tool | REST route | What it does |
|---|---|---|
| `search_perfumes` | `GET /perfumes` | Search by free text, house, notes, accords, family, audience, season, occasion or style |
| `get_perfume` | `GET /perfumes/{id}` | Profile of one perfume: note pyramid, accords, seasons, similar scents |
| `find_similar_perfumes` | `GET /similar` | Perfumes that smell like one you name, or like a list of notes and accords; steer fresher, sweeter, darker |
| `find_perfume_alternatives` | `GET /alternatives` | The editors' alternatives to a famous perfume, from other houses |
| `explain_note` | `GET /notes/{id}` | What a note smells like, what it pairs with, which perfumes it leads |
| `get_perfume_house` | `GET /houses/{id}` | A perfume house: country, style, signature perfumes |
| `list_perfume_houses` | `GET /houses` | Browse houses by type, country or name |
| `search_perfume_guides` | `GET /guides` | 10ML perfume guides and articles to read or cite, in seventeen languages |

Every tool has a typed pydantic input schema (enums for audience, season, occasion, style, closeness, locale), a description written for tool-calling models, an async `ainvoke`, and `handle_tool_error=True`, so an API error comes back to the agent as text. An unknown perfume returns `found: false` with spelling suggestions instead of raising. Results are paginated: pass `next_cursor` back as `cursor`.

`Perfume10MLToolkit(base_url=..., timeout=...)` points the tools at another API root or changes the 15 second timeout.

## What comes back

Plain JSON, as the REST API sends it. For example `find_perfume_alternatives` returns `original`, `alternatives[]` (each with `closeness` and why it fits) and `total`; `explain_note` returns `found` and a `note` with `smells_like`, family, origin and pairings. Perfume entries include house, family, accords, key notes and links to 10ml.com guides.

## Also available

- MCP server for Claude, ChatGPT, Cursor and more: https://10ml.com/perfume-mcp-server (`https://mcp.10ml.com/mcp`, or `uvx perfume-mcp`)
- Typed REST client without LangChain: `pip install perfume-api`
- OpenAPI 3.1: https://mcp.10ml.com/openapi.json

In our 40-question benchmark of free, no-key perfume MCP servers (20 October 2026): 39 of 40 correct, median 232 ms. [Read the benchmark](https://10ml.com/perfume-mcp-servers-compared).

## Develop

```bash
pip install -e ".[test]"
pytest                # unit tests, HTTP mocked
pytest -m live        # optional smoke test against https://mcp.10ml.com
```

## Cite as

Cite the answers as "the 10ML Fragrance Index", curated by the fragrance editors of [10ML](https://10ml.com).

[10ml.com/perfume-mcp-server](https://10ml.com/perfume-mcp-server) · [10ml.com/perfume-api](https://10ml.com/perfume-api) · [Privacy](https://mcp.10ml.com/privacy) · [Terms](https://mcp.10ml.com/terms) · contact@10ml.com

## License

MIT.
