Hermes Agent with Frihet
The job: run your ERP from Hermes Agent, the open-source agent by Nous Research, with a human-confirmation guard before actions that cannot be undone.
The Frihet plugin is in the Hermes plugin catalog. It does not duplicate tools: data operations go through the Frihet MCP server (@frihet/mcp-server locally, or the remote endpoint https://mcp.frihet.io/mcp). The plugin adds three things:
- The
/frihetcommand with three actions:status,setupanddoctor. - A
pre_tool_callfilter that detects Frihet writes that cannot be undone and asks for your confirmation before they run. - A skill that teaches Hermes how to work with Frihet: read before writing, create as draft, and reuse the
Idempotency-Keywhen retrying.
1. Install the plugin
hermes plugins search frihet
hermes plugins install frihet --enable
Hermes installs plugins disabled by default: --enable turns it on in the same step. If you already installed it without that option, run hermes plugins enable frihet. Then restart Hermes or start a new chat (/reset) so it loads the plugin. The code is public: github.com/Frihet-io/hermes-frihet.
2. Connect the MCP server
Generate an API key at app.frihet.io → Integrations → API Keys tab (it starts with fri_) and add the server to ~/.hermes/config.yaml.
Remote endpoint with OAuth (browser sign-in):
mcp_servers:
frihet:
url: https://mcp.frihet.io/mcp
auth: oauth
oauth:
flow: browser
trust: untrusted
Remote endpoint with an API key (Authorization header):
mcp_servers:
frihet:
url: https://mcp.frihet.io/mcp
headers:
Authorization: "Bearer ${FRIHET_API_KEY}"
trust: untrusted
Store FRIHET_API_KEY in ~/.hermes/.env. On a remote server, auth only accepts the plain text oauth (not a nested block) and env only applies to local servers: the key goes in headers. If the connection stays on "Connecting…", Hermes is not sending credentials.
The block must be named frihet: under any other name, the confirmation filter is not applied.
Local server with the @frihet/mcp-server npm package:
mcp_servers:
frihet:
command: npx
args: ["-y", "@frihet/mcp-server"]
env:
FRIHET_API_KEY: "${FRIHET_API_KEY}"
To sign in with OAuth use hermes mcp login frihet. /frihet setup does not accept keys, so they never end up in the chat transcript. More about the server on the MCP server page.
3. Check the connection
In any Hermes chat:
/frihet status # local state, no network
/frihet setup # authentication guidance; does not accept credentials
/frihet doctor # live check of the MCP server
Then ask something real:
Show me my overdue invoices from the last 30 days
Confirmation before irreversible writes
The pre_tool_call filter reviews every call to Frihet operations:
- Reads go through without asking.
- Creating invoices, quotes, clients, expenses or products, and irreversible operations (send, mark as paid, register in VeriFactu, delete, create a payment) ask for your approval before running. Some lookups that contact external services ask too.
- If the plugin does not recognize an operation, it also asks for confirmation.
Without a person to approve, those operations do not run.
With trust: untrusted in the server block, as in the examples, Hermes also asks for approval on any operation not marked read-only. Reads still go through without asking.
Troubleshooting
/frihet doctor reports four states separately:
| State | What it means | If it fails |
|---|---|---|
endpoint_reachable | The server responds. | Check your connection and that the remote endpoint is reachable from your network. |
mcp_configured_in_hermes | The mcp_servers.frihet block exists in ~/.hermes/config.yaml. | Add the block from step 2, named frihet. |
authenticated | The server accepted your credential. An anonymous response counts as reachable, not as authenticated. | Run hermes mcp login frihet, or check the Authorization header if you use an API key. |
tools_available | The initialization response is valid. | Run /frihet doctor again and check the endpoint. |
/frihet doctor sends an MCP initialization without credentials to mcp.frihet.io and makes one invoice read through the Hermes MCP client when you grant the plugins.entries.frihet.mcp_allowlist permission. It does not contact any other service.