hermosodocs

MCP server

The MCP server is the programmatic interface to Hermoso. Two transports expose the identical toolset from the identical source file, so nothing is available on one and missing from the other.

Hosted (Streamable HTTP)

https://app.hermoso.ai/mcp — a remote MCP server with OAuth 2.0. The client registers dynamically, the user approves on a Hermoso consent page, and no key is ever created or pasted.

In Claude on the web or desktop: Settings → Connectors → Add custom connector, paste the URL, approve. ChatGPT takes the same URL under its own Connectors settings.

Claude Code accepts claude mcp add --transport http hermoso https://app.hermoso.ai/mcp, but it will not start the OAuth flow by itself: claude mcp list then reports ! Needs authentication, and the user has to open a session, run /mcp, find the server and press Authenticate. The challenge is served correctly (an unauthenticated call answers 401 with a WWW-Authenticate header naming the protected-resource document, and dynamic client registration is live), so this is client behaviour rather than a gap on our side. In Claude Code, use the stdio line below. Measured against Claude Code 2.1.241 on 2026-08-23.

Sessions

The transport is session-based; the server returns an mcp-session-id on initialize and expects it on subsequent requests. Two behaviours are worth knowing because they affect how you write a long-lived client:

stdio

For Claude Code, Cursor, Codex and anything that launches a subprocess. The published hermoso npm package means there is nothing to clone.

Sign in once with the CLI and the stdio server needs no key in any client config, because hermoso mcp reads the bearer stored by hermoso auth login before it hands stdout to the JSON-RPC channel. In Claude Code that is one line, and it reports Connected on the spot:

npm install -g hermoso && hermoso auth login && claude mcp add hermoso -- npx -y hermoso mcp
{ "mcpServers": { "hermoso": { "command": "npx", "args": ["-y", "hermoso", "mcp"] } } }

Pass the key explicitly instead when the process cannot read your home directory, for example in CI:

claude mcp add hermoso -e HERMOSO_TOKEN=hmk_… -- npx -y hermoso mcp

The mcp subcommand is required. Running npx -y hermoso with no subcommand prints the CLI help and exits, so a client configured without it spawns a process that writes usage text to the JSON-RPC channel and dies.

Environment

VariableMeaning
HERMOSO_TOKENYour agent key (hmk_…). Required against the hosted app.
HERMOSO_API_BASEAPI origin. Defaults to https://app.hermoso.ai; set http://localhost:3000 to run against your own server.
HERMOSO_PROFILEBrand workspace to act in. stdio only — see below.
HERMOSO_OWNEROwning account, for a brand another account shared with you. stdio only.

Authentication

A Hermoso agent key, sent as a bearer token:

Authorization: Bearer hmk_…

There is no x-api-key header. If you have seen one referenced, it is the header we send to a third-party data provider, not one we accept.

Key properties, all deliberate:

Workspace scoping

One account holds many brand workspaces. Which one a call acts in is resolved on the server, every request, from three inputs in order:

  1. The workspace pinned to the key by use_brand.
  2. On stdio only, HERMOSO_PROFILE / HERMOSO_OWNER.
  3. Otherwise the account's default brand.

A pin is not a grant. Membership is re-checked on every single request, and it fails closed: an unreadable membership record denies rather than falling back to your own account. Access revoked after a pin was written stops working on the next call, not at the next login.

On the hosted transport the environment variables are not consulted at all — a hosted connector has no environment of yours, and honouring the server's would scope your call to whatever workspace our host happens to name.

Discovery: never hard-code the roster

tools/list is always authoritative. Beyond that, two free calls tell an agent what is true right now:

Both exist because a roster written into a prompt goes stale. Our own marketing pages have done exactly that, which is why the tool reference on this site is generated rather than typed.

Registry

WhereIdentifier
Official MCP registryio.github.hermoso-ai/hermoso
npmhermoso
Server card/.well-known/mcp.json

Spend safety

Worth knowing before you let an agent loose on an ad account, because it changes how much supervision the loop needs: