mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
feat(mcp): Nous-approved MCP catalog with interactive picker (#30870)
* feat(mcp): Nous-approved MCP catalog with interactive picker
Adds an optional-mcps/ directory mirroring optional-skills/: curated,
Nous-approved MCP servers shipped with the repo but disabled by default.
Presence in optional-mcps/ = approval. No community tier, no trust signals.
Entries are added by merging a PR.
New surface:
hermes mcp Interactive catalog picker (default)
hermes mcp catalog Plain-text list, scriptable
hermes mcp install <name> Install a catalog entry
Picker behavior:
not installed -> install (clone/bootstrap if needed, prompt for creds)
installed/off -> enable
installed/on -> menu (disable / uninstall / reinstall)
Manifest schema (manifest_version: 1) supports:
- transport: stdio (command/args, ${INSTALL_DIR} substitution) or http (url)
- install: optional git clone + bootstrap commands (for repos that need
local venv setup, like the n8n bridge); omit for npx/uvx servers
- auth: api_key (prompts -> ~/.hermes/.env), oauth (provider-mediated
or native MCP), or none
Catalog entries are never auto-updated. Users re-run `hermes mcp install`
to refresh. Credentials always go to ~/.hermes/.env (the .env-is-for-secrets
rule), never to per-server env blocks.
Ships n8n as the reference manifest (https://github.com/CyberSamuraiX/hermes-n8n-mcp).
Tests: 19 catalog tests + E2E install/uninstall round-trip via the shipped
manifest.
* feat(mcp): tool-selection checklist + Linear catalog entry
Adds install-time tool selection so users only enable the MCP tools they
actually want, and ships Linear as a second reference catalog entry to
demonstrate the http+oauth path alongside n8n's stdio+api_key+git-bootstrap.
Tool selection flow:
install (clone/auth/credentials) ->
probe server for available tools ->
curses checklist with pre-checked rows ->
write mcp_servers.<name>.tools.include
Pre-check priority:
1. user's prior tools.include (reinstall preserves selection)
2. manifest's tools.default_enabled (curated subset)
3. all probed tools (default)
Probe-failure fallback (server unreachable, OAuth not yet complete,
backing service offline):
- manifest declared default_enabled -> applied directly
- no default declared -> no filter written (all-on when reachable)
- both cases point user at hermes mcp configure <name>
Manifest schema additions:
tools:
default_enabled: [list, of, tool, names] # optional
Updates:
- optional-mcps/linear/manifest.yaml -- new reference entry (http+oauth)
- optional-mcps/n8n/manifest.yaml -- tools.default_enabled set to the
8 read-mostly tools; mutating tools (activate/deactivate, container_logs)
pruned by default
- docs: new 'Tool selection at install time' section in features/mcp.md
Tests: 7 new tests in TestToolSelection covering probe-success / probe-fail
matrix, manifest-default filtering, reinstall-preserves-selection, and
invalid-default-enabled rejection. 26 catalog tests + 32 existing
mcp_config tests passing.
* feat(mcp): polish — picker unification, include-mode convergence, hardening
Addresses review findings on PR #30870. Lands all improvements that
belong in this PR before merge; defers separate cleanup (consolidating
two probe implementations, change-detector tests) to follow-ups.
Picker UX (mcp_picker.py)
- Unifies catalog + custom (user-added) MCPs in one view with distinct
status badges (available / enabled / installed (disabled) /
custom — enabled / custom — disabled)
- Adds 'Configure tools (probe server + re-pick)' action to both the
catalog-installed and custom-row submenus — the existing
hermes mcp configure flow was previously unreachable from the picker
- Loops until ESC/q so the user can manage several entries in one
session instead of having to re-launch
- Uninstall message now mentions .env credentials are preserved with a
pointer to clean them up manually if no longer needed
- Surfaces a 'requires a newer Hermes' warning per future-manifest
entry instead of silently hiding it
Catalog (mcp_catalog.py)
- catalog_diagnostics() exposes which manifests were skipped and why
(future_manifest vs invalid) so UIs can give actionable feedback
- _do_git_install detects SHA-shaped refs (regex /[0-9a-f]{7,40}/)
and skips the doomed 'git clone --branch <sha>' attempt — clone --branch
only accepts branches/tags, so SHAs always failed noisily before
falling back to the full-clone path
- Probe-success all-tools-enabled message now mentions that new tools
the server adds later will be auto-enabled (no-filter mode)
Convergence (tools_config.py)
- _configure_mcp_tools_interactive now writes tools.include (whitelist)
instead of tools.exclude (blacklist), matching the catalog flow and
hermes mcp configure. The on-disk config shape no longer depends on
which UI the user touched last
- Two existing tests updated to assert the new include-mode contract
Discoverability
- Setup wizard final step now prints 'Browse curated MCPs: hermes mcp'
- Three tip-corpus entries pointing at the new catalog
- Docs updated with: trust model (manifests run code locally, gated by
PR review, but read before installing), runtime ${ENV_VAR} substitution
semantics, and the manifest_version forward-compat behavior
Tests
- 7 new tests covering future-manifest diagnostics, custom MCP picker
rows, SHA-ref git-install path, branch-ref git-install path, and the
tools_config include-mode write contract
- 80 MCP-related tests passing across test_mcp_catalog.py,
test_mcp_config.py, test_mcp_tools_config.py
* fix(mcp): drop setup-wizard catalog hint to satisfy supply-chain scanner
The wizard line 'Browse curated MCPs: hermes mcp' triggered the
CI supply-chain scanner because it pattern-matches on edits to any
file named hermes_cli/setup.py — that filename matches the Python
'install-hook file' heuristic even though this setup.py is the
user-facing 'hermes setup' wizard, not a packaging install hook.
The catalog is already surfaced via three tip-corpus entries in
hermes_cli/tips.py (which the scanner doesn't flag), so dropping the
wizard mention loses no discoverability. Worth revisiting after a
scanner allowlist for this specific file lands.
This commit is contained in:
parent
2517917de3
commit
8b69ec03af
13 changed files with 2226 additions and 23 deletions
|
|
@ -52,6 +52,126 @@ List the files in /home/user/projects and summarize the repo structure.
|
|||
|
||||
Hermes will discover the MCP server's tools and use them like any other tool.
|
||||
|
||||
## Catalog: one-click install for Nous-approved MCPs
|
||||
|
||||
Hermes ships a curated catalog of MCP servers that Nous staff has reviewed
|
||||
and merged. They're disabled by default — install only what you actually
|
||||
want.
|
||||
|
||||
```bash
|
||||
hermes mcp # interactive picker (default)
|
||||
hermes mcp catalog # plain-text list, scriptable
|
||||
hermes mcp install n8n # install a catalog entry by name
|
||||
```
|
||||
|
||||
The picker shows each entry with its current status:
|
||||
|
||||
```
|
||||
n8n available Manage and inspect n8n workflows from Hermes
|
||||
linear enabled Linear issue/project management (remote OAuth)
|
||||
github installed (disabled) GitHub repo + PR tools
|
||||
```
|
||||
|
||||
Hit `Enter` on a row to install (and walk through any required credentials),
|
||||
enable, disable, or uninstall. Catalog entries are stored under
|
||||
`optional-mcps/` in the hermes-agent repo — presence in that directory means
|
||||
Nous approval. There is no community submission tier; entries are added by
|
||||
merging a PR.
|
||||
|
||||
Catalog entries can require:
|
||||
|
||||
- **API key** — Hermes prompts at install time and writes the value to
|
||||
`~/.hermes/.env`. Non-secret values (base URLs) go to the same file.
|
||||
- **OAuth** (remote MCP) — written as `auth: oauth` in your config; the MCP
|
||||
client opens a browser on first connection.
|
||||
- **OAuth** (third-party provider like Google/GitHub) — Hermes points you at
|
||||
`hermes auth <provider>` if you haven't authenticated already.
|
||||
|
||||
### Tool selection at install time
|
||||
|
||||
After credentials are configured, Hermes probes the MCP server to list every
|
||||
tool it exposes and presents a checklist:
|
||||
|
||||
```
|
||||
Select tools for 'linear' (SPACE toggle, ENTER confirm)
|
||||
[x] find_issues Find issues matching a query
|
||||
[x] get_issue Get a single issue
|
||||
[x] create_issue Create a new issue
|
||||
[ ] delete_workspace Delete a Linear workspace
|
||||
...
|
||||
```
|
||||
|
||||
The pre-checked rows come from:
|
||||
|
||||
1. **Your prior selection** if you've installed this entry before (reinstalls
|
||||
preserve what you had — the manifest's defaults don't override it)
|
||||
2. **The manifest's `tools.default_enabled`** if the entry declares one (some
|
||||
catalog entries pre-prune mutating or rarely-useful tools)
|
||||
3. **Everything** if neither applies
|
||||
|
||||
Submit the checklist with ENTER. Only the checked tools end up in
|
||||
`mcp_servers.<name>.tools.include`. If you select everything, no filter is
|
||||
written (cleanest config shape, identical behavior).
|
||||
|
||||
**If the probe fails** (server unreachable, OAuth not yet completed,
|
||||
backing service not running), the install still succeeds: the manifest's
|
||||
`tools.default_enabled` is applied directly (if declared), or no filter is
|
||||
written (if not). Re-run `hermes mcp configure <name>` once the server is
|
||||
reachable to refine.
|
||||
|
||||
### Trust model
|
||||
|
||||
Installing a catalog entry runs whatever the manifest specifies — `git clone`,
|
||||
the entry's `bootstrap` commands (`pip install`, `npm install`, etc.), and
|
||||
ultimately the MCP server's own code. Manifests are gated by PR review into
|
||||
the hermes-agent repo, so Nous has reviewed each entry before it shipped —
|
||||
**but you should still read the manifest before installing**, especially the
|
||||
`source:` field's repository, the `install.bootstrap:` commands, and any
|
||||
`transport.command:` invocation.
|
||||
|
||||
Manifests live at
|
||||
[`optional-mcps/<name>/manifest.yaml`](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps)
|
||||
on GitHub. The picker also prints the manifest's `source:` URL at install
|
||||
time so you can quickly verify the upstream repo.
|
||||
|
||||
### Manifest version compatibility
|
||||
|
||||
Manifests pin a `manifest_version`. The catalog is forward-compatible: if a
|
||||
PR adds an entry with a newer `manifest_version` than your installed Hermes
|
||||
understands, the picker will surface a warning (`⚠ '<name>' requires a newer
|
||||
Hermes`) for that entry instead of silently hiding it. Run `hermes update`
|
||||
to install the latest Hermes when you see that.
|
||||
|
||||
### Runtime `${ENV_VAR}` substitution
|
||||
|
||||
Inside an entry's `transport.command`, `transport.args`, `transport.url`,
|
||||
and `headers`, `${VAR}` placeholders are resolved at server-connect time
|
||||
from environment variables (which include everything in `~/.hermes/.env`).
|
||||
This is useful when a catalog entry wants to reference a value the user
|
||||
configured elsewhere — e.g. `${HOME}/foo` or `${MY_PROVIDER_TOKEN}`.
|
||||
|
||||
Note this is distinct from `${INSTALL_DIR}` in catalog manifests, which is
|
||||
substituted at install-time with the path the catalog cloned the entry's
|
||||
repo into.
|
||||
|
||||
### Updating tool selection later
|
||||
|
||||
```bash
|
||||
hermes mcp configure linear
|
||||
```
|
||||
|
||||
Reopens the same checklist with your current selection pre-checked. Use this
|
||||
when you want more tools enabled, or when the server has added new tools that
|
||||
you want to opt into.
|
||||
|
||||
### Updating the catalog manifest
|
||||
|
||||
MCPs are never auto-updated. Re-run `hermes mcp install <name>` to refresh
|
||||
after a Hermes update if a manifest version changed.
|
||||
|
||||
To add an MCP to the catalog, open a PR against
|
||||
[`optional-mcps/`](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps).
|
||||
|
||||
## Two kinds of MCP servers
|
||||
|
||||
### Stdio servers
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue