Skip to content

fix(mcp): wire Authorization header for http catalog MCPs using api_key auth - #51100

Closed
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/mcp-catalog-http-api-key-header
Closed

fix(mcp): wire Authorization header for http catalog MCPs using api_key auth#51100
briandevans wants to merge 1 commit into
NousResearch:mainfrom
briandevans:fix/mcp-catalog-http-api-key-header

Conversation

@briandevans

Copy link
Copy Markdown
Contributor

What does this PR do?

Installing an http-transport catalog MCP that authenticates with an API key (hermes mcp install <name>, or the interactive picker) prompts for and saves the key to ~/.hermes/.env, but the generated mcp_servers.<name> block contained only a url — no Authorization header. The saved key was never referenced, so the server was contacted unauthenticated and every tool call failed (401 / hang) with no obvious cause.

The manual path (hermes mcp add) already does this correctly (hermes_cli/mcp_config.py), writing headers: {"Authorization": "Bearer ${VAR}"}. Only the catalog install path (_build_server_config in hermes_cli/mcp_catalog.py) was missing it — it handled the oauth auth shape for http but silently dropped api_key. http+api_key is a valid, documented manifest combination (the docs describe http auth as an Authorization: Bearer ${VAR} header), so this was a latent correctness gap that triggered the moment such a manifest was installed.

Related Issue

No filed issue — code-originated correctness fix (path-to-path asymmetry between the catalog install path and the manual hermes mcp add path).

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • hermes_cli/mcp_catalog.py: in the http branch of _build_server_config, wire the Authorization header for api_key auth, mirroring the manual-add format. The env-var name comes from auth.env_var when set, else the first declared auth.env entry (which also gives the parsed-but-unused AuthSpec.env_var field a consumer). Guarded so an api_key entry with no declared env var writes no unresolvable Bearer ${} placeholder.
  • tests/hermes_cli/test_mcp_catalog.py: add test_install_http_api_key_writes_authorization_header.

How to Test

  1. Add a catalog manifest with transport.type: http and auth.type: api_key declaring an env var (e.g. DEMO_API_KEY).
  2. Run hermes mcp install <name> and enter the key when prompted.
  3. Inspect ~/.hermes/config.yaml: mcp_servers.<name> now contains headers.Authorization: "Bearer ${DEMO_API_KEY}" (previously absent). The key in .env is now actually used at connect time.

The regression test test_install_http_api_key_writes_authorization_header builds an http+api_key manifest, installs it, and asserts the persisted server config carries headers.Authorization == "Bearer ${DEMO_API_KEY}". It fails before the fix (no headers key) and passes after. It reads the raw config file rather than load_config() so it asserts the persisted ${VAR} placeholder, not the env-expanded value.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/hermes_cli/test_mcp_catalog.py -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15 (Python 3.11)

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A (no doc change; the http+api_key header shape is already documented)
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A (pure string/dict config wiring, no platform-specific paths)
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

…ey auth

Installing an http-transport catalog MCP that authenticates with an API
key prompts for and saves the key to ~/.hermes/.env, but the generated
mcp_servers.<name> block contained only a `url` — no Authorization
header. The saved key was never referenced, so the server was contacted
unauthenticated and every tool call failed (401 / hang) with no obvious
cause.

The manual `hermes mcp add` path (hermes_cli/mcp_config.py) already writes
headers: {"Authorization": "Bearer ${VAR}"} for this case. Only the
catalog install path (_build_server_config) was missing it — it handled
the oauth auth shape for http but silently dropped api_key, even though
http+api_key is a valid, documented manifest combination.

Mirror the manual-add format in the http branch: take the env-var name
from auth.env_var when set (previously parsed but unused), else the first
declared auth.env entry, and guard so an api_key entry with no declared
env var writes no unresolvable Bearer ${} placeholder.
Copilot AI review requested due to automatic review settings June 22, 2026 23:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a catalog-install gap for HTTP-transport MCP servers using auth.type: api_key by ensuring the generated mcp_servers.<name> config includes an Authorization: Bearer ${ENV_VAR} header, matching the behavior of the manual hermes mcp add flow and making the saved .env key actually used during connections.

Changes:

  • Update hermes_cli/mcp_catalog.py to emit headers.Authorization = "Bearer ${<env var>}" for http + api_key catalog entries (preferring auth.env_var, else the first auth.env name).
  • Add a regression test asserting the persisted config contains the Authorization header placeholder and that the key is saved to .env.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
hermes_cli/mcp_catalog.py Wires Authorization header into generated server config for catalog-installed HTTP MCPs using api_key auth.
tests/hermes_cli/test_mcp_catalog.py Adds coverage for the http + api_key install path to prevent regressions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard tool/mcp MCP client and OAuth labels Jun 23, 2026
@briandevans

Copy link
Copy Markdown
Contributor Author

Closing to keep the queue clean — this has sat ~13 days without a review. The catalog-install Authorization-header gap is a real fix; happy to reopen if maintainers want it picked up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants