Hermes Agent Deep Cuts: `-t` Can Stop MCP Servers Before They Start
$ python - <<'PY'
from hermes_cli.mcp_startup import set_mcp_server_filter
for value in ("terminal", "terminal,mcp-github", "all", None):
print(f"filter({value!r}) -> {set_mcp_server_filter(value)!r}")
PY
filter('terminal') -> ['terminal']
filter('terminal,mcp-github') -> ['terminal', 'mcp-github']
filter('all') -> None
filter(None) -> None
That last None is the surprise. With -t all, Hermes does not pass an allowlist to MCP discovery. It starts discovery without a server-name filter. A narrow toolset can keep unrelated MCP subprocesses out of a one-shot run; all and an omitted selection take the broad path.
One flag, two filters
--toolsets has two jobs in a CLI run. First, it selects the tools the agent can call. A toolset can be a core group such as file, a composite such as debugging, or a configured server name such as mcp-github. Hermes resolves composite definitions recursively into tool names. In this checkout, debugging resolved to eight tools: patch, process_manage, read_file, search_files, terminal, web_extract, web_search, and write_file.
Second, the CLI uses the same argument to decide which configured MCP servers to discover. The startup path sets a process-wide server filter before discovery. Built-in names like terminal do not match MCP server keys, so they do not start any configured MCP server. An explicit server name does match, if that server exists in mcp_servers and is enabled.
That is why this is more than prompt trimming. An MCP server can be a child process with its own import cost, connection handshake, and remote service dependency. If the task only needs local files and a shell, bringing up every server first spends time initializing capabilities the model cannot use anyway.
Make the invocation match the task
The current CLI accepts -t at the global level, and hermes chat also has its own --toolsets option. Both take comma-separated names. This profile has a configured MCP server named firecrawl, so a narrow research request can be launched like this:
hermes -z -t web,firecrawl "Extract the title and main point from https://example.com/report"
firecrawl is the MCP server key in this profile’s config. Or use the chat form:
hermes chat --oneshot --query "Extract the title and main point from https://example.com/report" --toolsets web,firecrawl
For your own setup, pass the actual key under mcp_servers. The name is not a URL or a tool name. It is the configured server’s key.
The resolver accepts repeated and comma-separated values, trims whitespace, and ignores empty entries. Unknown names are not fatal for hermes -z: Hermes writes a warning and continues with the valid toolsets. A disabled MCP server is also ignored with a distinct message telling you to set enabled: true. That partial-success behavior is convenient interactively, but dangerous in a pipeline if you interpret a completed answer as proof that the requested integration ran.
For a recurring CLI profile, save the same choice under platform_toolsets in config.yaml:
platform_toolsets:
cli:
- web
- firecrawl
The profile selection controls the normal CLI tool surface. For cron jobs, set the job’s enabled_toolsets to the names required for that job. The task’s prompt and tool selection should agree. A prompt that asks an agent to edit files while its only enabled toolset is web has no way to complete the request.
The trap: all is the expensive choice
The filter treats either all or * as a request to clear the MCP allowlist. That preserves the full discovery behavior, but it also means -t all defeats the startup optimization. The flag is not a denylist with exclusions: if all appears, extra names are ignored by the one-shot validator, and MCP discovery is unfiltered.
There is another easy-to-miss distinction. Selecting a toolset is not always enough to make every tool available. Some tools have a separate runtime prerequisite, such as a configured browser backend or credentials. The all wildcard does not override those checks, and it does not opt in to workflow-gated Kanban. Toolset resolution and runtime availability are separate checks.
Also, the MCP filter only narrows server discovery. It is not a sandbox or an authorization boundary. If an enabled server exposes powerful methods, include it only when the run has a reason to use it, and enforce real permissions at the server and account level.
Verify both sides
Start with the CLI’s actual option surface:
hermes chat --help | rg -A2 -- '--toolsets'
Then inspect a saved MCP server key without printing its environment values. In YAML, the names immediately under mcp_servers: are the names to pass after -t. If a requested name is being ignored, check for three separate causes: a typo, a missing key, or enabled: false.
For a one-shot run, capture stderr as well as stdout. Hermes reports unknown names and disabled server names on stderr, while a valid request can still produce a normal answer with only the remaining tools. To test an MCP server’s connection independently, run hermes mcp test firecrawl. That confirms the server can connect at test time, not that a previous agent turn actually called it. A valid name accepted by the filter proves only selection, not a successful connection.
The useful default for automation is not all. Name the small set of toolsets the task needs, then add only the MCP server keys it must call. That saves startup work and makes the task’s capability envelope visible in the command that launched it.
Sources
- Hermes CLI commands reference, global options and one-shot command behavior.
- Toolsets reference, composites, wildcards, and runtime-gated toolsets.
- Tools and toolsets guide, terminal backends and tool availability.
hermes_cli/main.py, startup sets the MCP server filter from--toolsetsbefore discovery.hermes_cli/mcp_startup.py,set_mcp_server_filterclears the filter forall,*, or an empty selection, then passes the allowlist into MCP discovery.hermes_cli/oneshot.py, normalizes comma-separated toolsets and warns on unknown or disabled server names.toolsets.py, recursively resolves composites into tool names.
The resolver and filter output in the opening block came from Hermes Agent v0.21.5+5778.g0a374d1, local source commit 0a374d1674, on 2026-10-04. The toolset resolution made no model request and started no MCP server.