Files
openherbarium-mcp/README.md
T

361 lines
11 KiB
Markdown

# OpenHerbarium MCP
**Botanical Knowledge MCP Server** — a Model Context Protocol server that gives AI agents structured, sourced botanical data from free/open sources.
OpenHerbarium MCP is designed for a downstream agent such as **Hermes Agent Botaniste**. It is deliberately a knowledge-access layer only: it fetches, normalizes and cites botanical evidence, then lets the client agent reason, write, format and publish.
## What this MCP does
It exposes MCP tools for:
- plant lookup by common or scientific name;
- taxonomic information;
- species information such as distribution, habitat and botanical descriptions;
- horticultural care-source discovery;
- image-source discovery with licence and author metadata;
- targeted botanical source search through a local Firecrawl instance when configured.
Every returned data point is wrapped with provenance:
```json
{
"value": "Marantaceae",
"source": "GBIF Backbone Taxonomy",
"url": "https://www.gbif.org/species/8184122",
"retrieved_at": "2026-08-02T12:00:00+00:00",
"confidence": "high"
}
```
## What this MCP does **not** do
OpenHerbarium MCP never:
- creates final Markdown plant sheets;
- writes to Outline;
- manages Outline collections;
- creates care calendars;
- decides final horticultural recommendations;
- replaces the reasoning/presentation layer of Hermes Agent.
## MCP tools
### `search_plant(name: str)`
Returns:
- accepted scientific name;
- canonical name;
- common/vernacular names when available;
- synonyms;
- family, genus, species and rank;
- external identifiers such as GBIF keys and GBIF species URL;
- best-effort Kew/POWO results when accessible.
### `get_taxonomy(name: str)`
Returns sourced taxonomy:
- kingdom;
- phylum/class/order when available;
- family;
- genus;
- species;
- scientific name;
- botanical authorship;
- taxonomic status;
- synonyms.
Priority sources:
- GBIF Backbone Taxonomy;
- Plants of the World Online, Kew, best-effort.
### `get_species_information(name: str)`
Returns raw evidence for:
- botanical descriptions;
- known distribution;
- natural habitat where available;
- additional source-search records when Firecrawl is configured.
### `get_care_sources(name: str)`
Returns raw source candidates for:
- light;
- temperature;
- humidity;
- watering;
- substrate;
- fertilisation;
- repotting.
It does **not** transform those sources into final care advice.
### `get_image_sources(name: str, limit: int = 10)`
Uses Wikimedia Commons to return:
- image URL;
- licence;
- author;
- source page.
### `search_botanical_sources(query: str, limit: int = 5)`
Uses the configured Firecrawl endpoint if `FIRECRAWL_API_URL` is configured. The examples default to the public Firecrawl API (`https://api.firecrawl.dev`), and you can replace it with a self-hosted endpoint if preferred. If Firecrawl is not configured, the tool returns source-constrained suggested queries rather than pretending to have scraped content.
## Sources
Implemented/targeted sources:
- [GBIF](https://www.gbif.org/)
- [Plants of the World Online, Kew](https://powo.science.kew.org/) best-effort connector
- [Wikimedia Commons](https://commons.wikimedia.org/)
- [Royal Horticultural Society](https://www.rhs.org.uk/) source candidates / Firecrawl search
- [Tela Botanica](https://www.tela-botanica.org/) source candidates / Firecrawl search
- public university horticultural resources via targeted Firecrawl search
No paid API is required.
## Installation
### Requirements
- Python 3.11+
- `uv` recommended, or any Python package installer capable of creating a virtual environment
### Simplest install: run directly with `uvx`
You do not need to clone the repository manually. Hermes can let `uvx` install
and run the MCP server directly from Gitea:
```yaml
mcp_servers:
openherbarium:
command: "uvx"
args:
- "--quiet"
- "--from"
- "git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git"
- "openherbarium-mcp"
timeout: 120
connect_timeout: 60
env:
FIRECRAWL_API_URL: "https://api.firecrawl.dev"
FIRECRAWL_API_KEY: ""
BOTANICAL_ALLOWED_DOMAINS: "gbif.org,powo.science.kew.org,missouribotanicalgarden.org,tela-botanica.org,inpn.mnhn.fr,rhs.org.uk,edu,wikimedia.org,wikipedia.org"
OPENHERBARIUM_TIMEOUT: "20"
```
Restart Hermes Agent after editing `~/.hermes/config.yaml`.
An equivalent ready-to-copy snippet is available at
[`examples/hermes-openherbarium-uvx.yaml`](examples/hermes-openherbarium-uvx.yaml).
### JSON setup examples
Some MCP clients use a JSON config file instead of YAML. Ready-to-copy JSON
examples are provided in [`examples/`](examples/):
| Client / use case | Example file | Notes |
|---|---|---|
| Hermes-style JSON | [`examples/hermes-mcp.json`](examples/hermes-mcp.json) | Same structure as Hermes `mcp_servers`, but JSON. Useful if you keep MCP snippets in a separate `mcp.json` before converting/merging into `config.yaml`. |
| Generic MCP clients | [`examples/generic-mcp.json`](examples/generic-mcp.json) | Uses the common `mcpServers` JSON key. |
| Claude Desktop / Claude Code-style configs | [`examples/claude-desktop-mcp.json`](examples/claude-desktop-mcp.json) | Copy the `openherbarium` entry under your existing `mcpServers`. |
| Cursor | [`examples/cursor-mcp.json`](examples/cursor-mcp.json) | Copy into Cursor's MCP configuration when it expects `mcpServers`. |
| Windsurf | [`examples/windsurf-mcp.json`](examples/windsurf-mcp.json) | Copy into Windsurf's MCP configuration when it expects `mcpServers`. |
| Local development checkout | [`examples/local-dev-mcp.json`](examples/local-dev-mcp.json) | Uses `uv --directory /absolute/path/to/openherbarium-mcp run openherbarium-mcp`. |
Hermes JSON-style snippet:
```json
{
"mcp_servers": {
"openherbarium": {
"command": "uvx",
"args": [
"--quiet",
"--from",
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
"openherbarium-mcp"
],
"timeout": 120,
"connect_timeout": 60,
"env": {
"FIRECRAWL_API_URL": "https://api.firecrawl.dev",
"FIRECRAWL_API_KEY": "",
"BOTANICAL_ALLOWED_DOMAINS": "gbif.org,powo.science.kew.org,missouribotanicalgarden.org,tela-botanica.org,inpn.mnhn.fr,rhs.org.uk,edu,wikimedia.org,wikipedia.org",
"OPENHERBARIUM_TIMEOUT": "20"
}
}
}
}
```
Generic `mcp.json` snippet used by many MCP clients:
```json
{
"mcpServers": {
"openherbarium": {
"command": "uvx",
"args": [
"--quiet",
"--from",
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
"openherbarium-mcp"
]
}
}
}
```
The MCP is configured through environment variables passed by the MCP client.
This lets you change endpoints and timeouts directly in `config.yaml`, `mcp.json`
or your client's MCP settings screen, without modifying the repository.
Available parameters:
| Environment variable | Required | Default | Purpose |
|---|---:|---|---|
| `FIRECRAWL_API_URL` | No | unset | Firecrawl base URL. The examples use the public API `https://api.firecrawl.dev`; replace it with your self-hosted endpoint if preferred. Enables `search_botanical_sources` and richer source search in care/species tools. |
| `FIRECRAWL_API_KEY` | No | unset | Bearer token for the public Firecrawl API, or for any self-hosted instance that requires authentication. |
| `BOTANICAL_ALLOWED_DOMAINS` | No | built-in allow-list | Comma-separated source domains used to constrain targeted botanical searches. |
| `OPENHERBARIUM_TIMEOUT` | No | `20` | HTTP timeout in seconds for public APIs and Firecrawl calls. |
Generic JSON example with all configurable parameters:
```json
{
"mcpServers": {
"openherbarium": {
"command": "uvx",
"args": [
"--quiet",
"--from",
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
"openherbarium-mcp"
],
"env": {
"FIRECRAWL_API_URL": "https://api.firecrawl.dev",
"FIRECRAWL_API_KEY": "",
"BOTANICAL_ALLOWED_DOMAINS": "gbif.org,powo.science.kew.org,missouribotanicalgarden.org,tela-botanica.org,inpn.mnhn.fr,rhs.org.uk,edu,wikimedia.org,wikipedia.org",
"OPENHERBARIUM_TIMEOUT": "20"
}
}
}
}
```
Client-specific file locations change between applications and versions. When in
doubt, use the app's MCP settings screen and paste the `openherbarium` server
entry under its existing `mcpServers` object.
### Development install with `uv`
```bash
git clone https://git.home-deneuville.fr/Edern/openherbarium-mcp.git
cd openherbarium-mcp
uv sync --extra dev
```
Run tests:
```bash
uv run pytest
```
Run the MCP server over stdio from the checked-out project:
```bash
uv run openherbarium-mcp
```
## Hermes Agent configuration for local development
If you want to work on the source code locally instead of using the `uvx` setup,
add the checked-out server to `~/.hermes/config.yaml`:
```yaml
mcp_servers:
openherbarium:
command: "uv"
args:
- "--directory"
- "/absolute/path/to/openherbarium-mcp"
- "run"
- "openherbarium-mcp"
timeout: 120
connect_timeout: 60
env:
FIRECRAWL_API_URL: "https://api.firecrawl.dev"
FIRECRAWL_API_KEY: ""
BOTANICAL_ALLOWED_DOMAINS: "gbif.org,powo.science.kew.org,missouribotanicalgarden.org,tela-botanica.org,inpn.mnhn.fr,rhs.org.uk,edu,wikimedia.org,wikipedia.org"
OPENHERBARIUM_TIMEOUT: "20"
```
Restart Hermes Agent. Tools will be exposed with names similar to:
- `mcp_openherbarium_search_plant`
- `mcp_openherbarium_get_taxonomy`
- `mcp_openherbarium_get_species_information`
- `mcp_openherbarium_get_care_sources`
- `mcp_openherbarium_get_image_sources`
- `mcp_openherbarium_search_botanical_sources`
## `.env` fallback for manual/local runs
For direct local execution outside an MCP client, you can also copy `.env.example`
to `.env` and set the same parameters there:
```bash
FIRECRAWL_API_URL=https://api.firecrawl.dev
FIRECRAWL_API_KEY=
```
If Firecrawl is not configured, source-search tools return explicit suggested queries and a `not_configured` status. With the public API URL, set `FIRECRAWL_API_KEY` to your Firecrawl key.
## Development
```bash
uv sync --extra dev
uv run pytest
```
Project layout:
```text
openherbarium-mcp/
├── src/
│ └── openherbarium_mcp/
│ ├── server.py
│ ├── gbif.py
│ ├── kew.py
│ ├── rhs.py
│ ├── tela_botanica.py
│ ├── wikimedia.py
│ └── firecrawl.py
├── tests/
├── README.md
├── pyproject.toml
├── LICENSE
└── .env.example
```
## Reliability model
The server distinguishes between:
- **high confidence**: exact/high-confidence API matches, mostly GBIF taxonomic matches;
- **medium confidence**: sourced API records that still require interpretation;
- **low confidence**: source candidates or search results that must be manually/agent verified.
OpenHerbarium MCP prefers returning `status: unavailable`, `status: not_configured` or empty records over inventing missing data.
## License
MIT