# How to Connect Hermes Agent to MCP with Arcade.dev

> Source: <https://dev.to/arcade/secure-connect-hermes-mcp-1f7m>
> Published: 2026-06-29 06:12:33+00:00

For developers running Nous Research's Hermes Agent, connecting to a remote Model Context Protocol (MCP) server is straightforward. But as you add more services, you run into real problems: configuration sprawl, credential management, and raw API wrappers that cause the language model to hallucinate parameters and burn tokens.

Arcade.dev's MCP gateway gives your Hermes Agent access to thousands of agent-optimized tools through a single endpoint, with downstream credentials vaulted away from the agent process and native OAuth for gateway authentication.

**Scope note:** One person, one Hermes profile, one gateway process. A shared multi-user service needs per-user MCP connections and token storage, plus an appropriate isolation boundary (containers or OS-level separation, since [Hermes profiles are not sandboxes](https://hermes-agent.nousresearch.com/docs/user-guide/profiles#profiles-vs-workspaces-vs-sandboxing)). Arcade [User Sources](https://docs.arcade.dev/en/guides/user-sources) can provide external identity for production agents, but do not add per-user MCP isolation to Hermes by themselves. That architecture is a separate problem.

`uv pip install -e ".[mcp]"`

).`auth: oauth`

in `~/.hermes/config.yaml`

. Do not put a static `ARCADE_API_KEY`

in the config; Hermes's native OAuth flow establishes a user-bound session in Arcade.`tools.authorize`

API`tools.include`

/ `tools.exclude`

for least privilege.Before connecting to Arcade, make sure your base Hermes Agent installation supports the Model Context Protocol. The standard installer includes MCP support by default. If you're working from source or managing a custom environment, install the MCP extras from the repository root:

```
uv pip install -e ".[mcp]"
```

Once installed, Hermes routes connections through the `mcp_servers`

block in `config.yaml`

. For a basic test against a standard HTTP MCP server, define the connection and inject a static Bearer token:

```
mcp_servers:
  remote_test_api:
    url: "https://mcp.internal.example.com"
    headers:
      Authorization: "Bearer ${REMOTE_TEST_API_KEY}"
```

This pattern is fine for a single developer hitting an internal test server they control. For remote servers that support OAuth, prefer Hermes's native OAuth flow instead of static tokens.

The recommended way to connect Hermes to OAuth-protected remote MCP servers, including Arcade, is through its native OAuth 2.1 support. Set `auth: oauth`

in the configuration block. When configured, Hermes handles dynamic client registration, prints an authorization URL to the terminal, opens your browser, and waits for the callback on a local loopback port.

```
mcp_servers:
  my_server:
    url: "https://example.com/mcp"
    auth: oauth
```

After saving an OAuth configuration, run `hermes mcp login <server>`

from a fresh terminal. This provides enough time to complete browser authentication (five minutes, compared to the 30-second window during automatic config reload). Once authenticated, start or restart Hermes. Use `/reload-mcp`

in the chat interface when you need to refresh the registered tools after later configuration changes.

Verify the tools loaded successfully by running:

```
hermes mcp test <server>
```

You could wire Hermes to each service individually, one MCP server for Gmail, another for Slack, another for your CRM. That works until you're managing a dozen config blocks, each with its own credentials, timeouts, and failure modes. Arcade solves several problems at once.

The [Arcade MCP Gateway](https://docs.arcade.dev/en/guides/mcp-gateways/create-via-dashboard) gives your Hermes Agent access to [thousands of tools](https://www.arcade.dev/tools/) through a single URL. Instead of managing separate server connections and keeping track of which service lives where, your Hermes Agent talks to one gateway. Arcade handles routing and tool execution behind it.

Raw API wrappers hurt agent performance because they're built for deterministic software, not probabilistic language models.

When an agent receives a raw API definition, it frequently hallucinates required parameters, enters retry loops on malformed JSON payloads, and burns tokens trying to correct its own errors. Arcade's tools are designed at the intent level, translating natural language into precise API calls. In [published benchmarks](https://www.arcade.dev/blog/attio-mcp-toolkit-benchmark/), this approach has cut response token usage substantially compared to raw API passthrough, while also lowering parameter hallucination rates.

Storing API keys and OAuth tokens in environment files is a real risk, even for a single user. Recent reports from GitGuardian identified [tens of thousands of unique secrets exposed](https://www.gitguardian.com/state-of-secrets-sprawl-report-2026) in public MCP configuration files.

Arcade vaults downstream service tokens (Gmail, Slack, CRM, etc.) so they never reach Hermes or the model context. Refresh and revocation are centralized in Arcade rather than scattered across config files.

Define the gateway connection in `~/.hermes/config.yaml`

and set `auth: oauth`

. When you start Hermes, the native OAuth flow will prompt you to authenticate with your Arcade account in the browser.

```
mcp_servers:
  arcade_gateway:
    url: "https://api.arcade.dev/mcp/<YOUR-GATEWAY-SLUG>"
    auth: oauth
```

Replace `<YOUR-GATEWAY-SLUG>`

with the slug shown in your [Arcade dashboard](https://api.arcade.dev/dashboard) after creating a gateway. When setting up the gateway, select **Arcade Auth** as the authentication mode, which lets you sign in with your Arcade account.

**Do not use a static ARCADE_API_KEY in the headers.** Arcade's own documentation describes API keys as

You can optionally override `connect_timeout`

and `timeout`

in the config block if you need custom values, but Hermes ships with reasonable defaults.

After authenticating with `hermes mcp login arcade_gateway`

, verify the connection:

```
hermes mcp test arcade_gateway
```

With this configuration, Hermes no longer needs to manage credentials for the third-party services it calls. It formulates intent and sends the request to the Arcade gateway. Arcade resolves the authentication for the connected services and executes the underlying API call, returning only the result to Hermes.

Before your Hermes Agent can act on a downstream service like Gmail or a CRM, you need to authorize that service's connection through Arcade. Arcade's standard flow is just-in-time: when an agent calls a tool that requires a service the user hasn't connected yet, Arcade returns an authorization URL through [MCP URL-mode elicitation](https://www.arcade.dev/blog/mcp-server-authorization-guide). A client that supports elicitation surfaces this URL to the user, who completes the OAuth flow once. Arcade then vaults and automatically refreshes the resulting token.

As of June 2026, Hermes does not support URL-mode elicitation. Its handler explicitly declines URL-mode responses ([current implementation](https://github.com/NousResearch/hermes-agent/blob/a7983d5ad768551508667e8c708e13def7ee28ab/tools/mcp_tool.py#L1236-L1303)), so the authorization URL never reaches you. This limitation may change in a future release. Until then, authorize your service connections before running tool calls that require them.

Arcade provides a [ tools.authorize API](https://docs.arcade.dev/en/guides/tool-calling/custom-apps/auth-tool-calling) for this purpose. Install the SDK and set a temporary API key in a dedicated setup shell:

```
pip install arcadepy
export ARCADE_API_KEY="<your-api-key>"
```

Run preauthorization in this dedicated shell, separate from the one you use to launch Hermes.

Then run the following to authorize a tool's required scopes:

``` python
from arcadepy import Arcade

# For this personal Arcade Auth setup, use the email address
# associated with your Arcade account.
USER_ID = "you@example.com"

client = Arcade()  # Uses ARCADE_API_KEY from the environment

auth_response = client.tools.authorize(
    tool_name="Gmail.ListEmails",
    user_id=USER_ID,
)

if auth_response.status != "completed":
    print(f"Authorize Gmail: {auth_response.url}")
    client.auth.wait_for_completion(auth_response)
```

A few things to note about this setup step:

`Gmail.ListEmails`

) for `tools.authorize`

calls. Hermes `tools.include`

filters use the MCP wire names, which are underscore-separated (`Gmail_ListEmails`

).`user_id`

. If the `user_id`

doesn't match your gateway OAuth session identity, Arcade vaults the token under a different user and Hermes won't be able to use it.When your Hermes Agent calls a tool that interacts with an authorized service, the request goes to the Arcade gateway. Arcade checks that you have a valid, vaulted token for that service, makes the API call on your behalf, and returns the result to Hermes.

If a token has expired, Arcade handles the refresh automatically. If a service isn't authorized yet, the tool call will return an authorization error. Authorize the required tool scopes through the `tools.authorize`

API and retry.

Arcade keeps downstream service tokens out of Hermes and the model context. Hermes still stores its own MCP gateway OAuth token locally (under `~/.hermes/mcp-tokens/`

), so normal host and process security remain necessary. Vaulting prevents direct disclosure of downstream tokens and centralizes refresh and revocation, but it does not prevent a compromised Hermes process from invoking tools already authorized for its Arcade session.

Hermes provides native configuration semantics to restrict tool access, so your agent operates under the principle of least privilege. Use `tools.include`

and `tools.exclude`

in `config.yaml`

to filter Arcade's tool catalog down to what your use case actually needs. Restrict visibility to safe, read-only, or draft actions where possible:

```
mcp_servers:
  arcade_gateway:
    url: "https://api.arcade.dev/mcp/<YOUR-GATEWAY-SLUG>"
    auth: oauth
    tools:
      include:
        - Gmail_ListEmails
        - Gmail_WriteDraftEmail
```

Hermes compares `tools.include`

against the raw tool names returned by the MCP server. Arcade's MCP layer [converts canonical dotted names to underscores](https://github.com/ArcadeAI/arcade-mcp/blob/f537771f296c6cab91fe403964ce45b28357cd72/libs/arcade-mcp-server/arcade_mcp_server/convert.py#L40-L55) before sending them over the wire, so use underscore names in your filter (e.g. `Gmail_ListEmails`

, not `Gmail.ListEmails`

).

In this configuration, even though Arcade supports sending and deleting emails, the Hermes Agent can't see or invoke those capabilities. If you use an exclude block alongside an include block, the include rules take precedence.

A good starting pattern is to give the agent read and draft access only. Let it list emails, read calendar events, and write draft messages, but not send, delete, or modify anything irreversibly. You can widen the tool set incrementally as you build confidence in the agent's behavior.

| Symptom | Likely cause | Concrete fix |
|---|---|---|
| Expected tools are missing in chat | Gateway tool selection doesn't include that tool, overly restrictive `tools.include` filtering, or the MCP server failed discovery. |
Verify the tool is enabled in your Arcade gateway, review your Hermes include/exclude rules, and check `~/.hermes/logs/errors.log` for discovery errors. |
| OAuth flow times out during config reload | Hermes config auto-reload allows only 30 seconds for interactive OAuth, which may not be enough. | Run `hermes mcp login arcade_gateway` from a separate terminal, which allows five minutes. Then restart Hermes or use `/reload-mcp` to refresh tools. |
| Connection rejected after config change | OAuth flow not completed or incorrect gateway URL. | Check `~/.hermes/logs/errors.log` , confirm the gateway URL matches your Arcade dashboard, and re-run the OAuth flow. |
| OAuth flow fails in a headless environment | Hermes can't open a browser in a remote or containerized deployment. | See the
|

`tools.authorize`

APIWhen a tool call fails, start with `~/.hermes/logs/errors.log`

for connection-level issues (wrong URL, OAuth failures, timeouts). For tool execution failures (authorization errors, malformed requests, downstream API rejections), check Arcade's execution logs when available for your deployment.

Connecting Hermes Agent to MCP takes minimal effort in local development. Adding dozens of services, managing credentials for each, and keeping raw API wrappers from causing hallucinations is where the real time goes.

Arcade gives your Hermes Agent access to thousands of agent-optimized tools through one gateway, with downstream credentials vaulted away from the agent process and the language model. You focus on building the agent logic that matters.

[Create a free Arcade.dev account](https://app.arcade.dev/register), configure your first gateway, and connect your Hermes Agent today.

Use native OAuth (`auth: oauth`

). A static `ARCADE_API_KEY`

is an [administrator credential](https://docs.arcade.dev/en/get-started/setup/api-keys) that lets anyone who has the key make requests as you. The OAuth flow gives you a user-bound session instead.

Add an `mcp_servers`

entry with your gateway `url`

(format: `https://api.arcade.dev/mcp/<YOUR-GATEWAY-SLUG>`

) and set `auth: oauth`

. Optionally add `tools.include`

/ `tools.exclude`

to restrict the visible tool set. Timeout overrides are available but Hermes ships with reasonable defaults.

Use Arcade's [ tools.authorize API](https://docs.arcade.dev/en/guides/tool-calling/custom-apps/auth-tool-calling) to authorize each required tool or provider scope set before running tool calls that need them. Hermes does not currently support MCP URL-mode elicitation, so authorization must happen out of band. Make sure the

`user_id`

you pass matches the identity from your gateway OAuth session. Once authorized, Arcade vaults the tokens and your agent can call the corresponding tools.Use `auth: oauth`

to connect to Arcade, and authorize downstream services through the `tools.authorize`

API. Arcade vaults all downstream tokens and returns only tool results to Hermes. Note that Hermes still stores its own gateway OAuth token locally under `~/.hermes/mcp-tokens/`

, so host-level security practices still apply.

Common causes: the tool isn't included in your Arcade gateway configuration, your `tools.include`

filter is too restrictive, or MCP server discovery failed. Verify the tool is enabled in your gateway, check your Hermes include/exclude rules, and review `~/.hermes/logs/errors.log`

for discovery errors.

Use `/reload-mcp`

in Hermes for local iteration. If the OAuth flow times out during a config reload (the auto-reload window is 30 seconds), run `hermes mcp login arcade_gateway`

from a separate terminal, then restart Hermes or use `/reload-mcp`

.

Not with a single Hermes process. Hermes shares its MCP server connections and OAuth token store at the process level, so all users of one process share the same identity. For multi-user setups, you need per-user [Hermes profiles](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) running as separate processes, with appropriate OS-level or container isolation (profiles alone [are not sandboxes](https://hermes-agent.nousresearch.com/docs/user-guide/profiles#profiles-vs-workspaces-vs-sandboxing)). Arcade [User Sources](https://docs.arcade.dev/en/guides/user-sources) can provide external identity for production agents, but do not add per-user MCP isolation to Hermes by themselves.

Create an Arcade account and gateway, authorize the required tool scopes through `tools.authorize`

, add the gateway to `config.yaml`

with `auth: oauth`

, and optionally restrict tools with `include`

/`exclude`

.
