326 lines
8.6 KiB
Markdown
326 lines
8.6 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 a local Firecrawl instance if `FIRECRAWL_API_URL` is configured. If 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:
|
|
- "--from"
|
|
- "git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git"
|
|
- "openherbarium-mcp"
|
|
timeout: 120
|
|
connect_timeout: 60
|
|
```
|
|
|
|
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": [
|
|
"--from",
|
|
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
|
|
"openherbarium-mcp"
|
|
],
|
|
"timeout": 120,
|
|
"connect_timeout": 60
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Generic `mcp.json` snippet used by many MCP clients:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"openherbarium": {
|
|
"command": "uvx",
|
|
"args": [
|
|
"--from",
|
|
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
|
|
"openherbarium-mcp"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
If your client supports environment variables in MCP server definitions, you can
|
|
enable targeted Firecrawl search like this:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"openherbarium": {
|
|
"command": "uvx",
|
|
"args": [
|
|
"--from",
|
|
"git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git",
|
|
"openherbarium-mcp"
|
|
],
|
|
"env": {
|
|
"FIRECRAWL_API_URL": "http://localhost:3002",
|
|
"FIRECRAWL_API_KEY": ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
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
|
|
```
|
|
|
|
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`
|
|
|
|
## Firecrawl configuration
|
|
|
|
Copy `.env.example` to `.env` and set:
|
|
|
|
```bash
|
|
FIRECRAWL_API_URL=http://localhost:3002
|
|
FIRECRAWL_API_KEY=
|
|
```
|
|
|
|
If Firecrawl is not configured, source-search tools return explicit suggested queries and a `not_configured` status.
|
|
|
|
## 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
|