# 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