Compare commits

...
6 Commits
11 changed files with 297 additions and 18 deletions
+4 -4
View File
@@ -1,8 +1,8 @@
# Optional: local Firecrawl endpoint for targeted botanical source search.
# Example: http://localhost:3002 or http://firecrawl:3002
FIRECRAWL_API_URL=
# Firecrawl endpoint for targeted botanical source search.
# Public Firecrawl API by default; replace with your self-hosted endpoint if needed.
FIRECRAWL_API_URL=https://api.firecrawl.dev
# Optional if your Firecrawl instance requires it.
# Required for the public Firecrawl API; optional for some self-hosted instances.
FIRECRAWL_API_KEY=
# Optional: comma-separated allow-list used by search_botanical_sources.
+144 -10
View File
@@ -105,7 +105,7 @@ Uses Wikimedia Commons to return:
### `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.
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
@@ -127,10 +127,137 @@ No paid API is required.
- Python 3.11+
- `uv` recommended, or any Python package installer capable of creating a virtual environment
### Local install with `uv`
### 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 <YOUR_GITEA_URL>/openherbarium-mcp.git
git clone https://git.home-deneuville.fr/Edern/openherbarium-mcp.git
cd openherbarium-mcp
uv sync --extra dev
```
@@ -141,15 +268,16 @@ Run tests:
uv run pytest
```
Run the MCP server over stdio:
Run the MCP server over stdio from the checked-out project:
```bash
uv run openherbarium-mcp
```
## Hermes Agent configuration
## Hermes Agent configuration for local development
Add the server to `~/.hermes/config.yaml`:
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:
@@ -162,6 +290,11 @@ mcp_servers:
- "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:
@@ -173,16 +306,17 @@ Restart Hermes Agent. Tools will be exposed with names similar to:
- `mcp_openherbarium_get_image_sources`
- `mcp_openherbarium_search_botanical_sources`
## Firecrawl configuration
## `.env` fallback for manual/local runs
Copy `.env.example` to `.env` and set:
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=http://localhost:3002
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.
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
+21
View File
@@ -0,0 +1,21 @@
{
"mcpServers": {
"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"
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"mcpServers": {
"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"
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"mcpServers": {
"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"
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"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"
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
# Drop this under ~/.hermes/config.yaml -> mcp_servers
# No manual clone is required: uvx installs/runs OpenHerbarium MCP from Gitea.
openherbarium:
command: "uvx"
args:
- "--quiet"
- "--from"
- "git+https://git.home-deneuville.fr/Edern/openherbarium-mcp.git"
- "openherbarium-mcp"
timeout: 120
connect_timeout: 60
env:
# Optional: enable targeted botanical source search through your local Firecrawl.
FIRECRAWL_API_URL: "https://api.firecrawl.dev"
FIRECRAWL_API_KEY: ""
# Optional: tune source filtering and HTTP timeout without editing code.
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"
+21
View File
@@ -0,0 +1,21 @@
{
"mcpServers": {
"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"
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"mcpServers": {
"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"
}
}
}
}
+3 -3
View File
@@ -40,9 +40,9 @@ dev = [
openherbarium-mcp = "openherbarium_mcp.server:main"
[project.urls]
Homepage = "https://example.invalid/openherbarium-mcp"
Repository = "https://example.invalid/openherbarium-mcp"
Issues = "https://example.invalid/openherbarium-mcp/issues"
Homepage = "https://git.home-deneuville.fr/Edern/openherbarium-mcp"
Repository = "https://git.home-deneuville.fr/Edern/openherbarium-mcp"
Issues = "https://git.home-deneuville.fr/Edern/openherbarium-mcp/issues"
[tool.hatch.build.targets.wheel]
packages = ["src/openherbarium_mcp"]
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import Any
import httpx
USER_AGENT = "OpenHerbarium-MCP/0.1 (+https://example.invalid/openherbarium-mcp)"
USER_AGENT = "OpenHerbarium-MCP/0.1 (+https://git.home-deneuville.fr/Edern/openherbarium-mcp)"
class BotanicalHTTPClient: