Compare commits
6
Commits
26431a4e26
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c3c8de052 | ||
|
|
1bc3c6452f | ||
|
|
b812292d56 | ||
|
|
bb7ee08152 | ||
|
|
d6c1f9a280 | ||
|
|
490d8d27d5 |
+4
-4
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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"]
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user