Skill240.2k repo starsupdated 3d ago
mcp-oauth-remote-gateway
Manual OAuth for remote MCP servers on headless gateways.
Install in Claude Code
Copygit clone --depth 1 https://github.com/NousResearch/hermes-agent /tmp/mcp-oauth-remote-gateway && cp -r /tmp/mcp-oauth-remote-gateway/optional-skills/mcp/mcp-oauth-remote-gateway ~/.claude/skills/mcp-oauth-remote-gatewayThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# MCP OAuth on a Remote Hermes Gateway ## Overview Hermes' built-in MCP OAuth client runs a one-shot HTTP listener on `127.0.0.1:<port>` inside the Hermes process and registers that loopback address as the OAuth `redirect_uri`. That works perfectly for a local CLI on the user's own machine. It breaks completely when Hermes runs as a remote gateway (container, VPS, messaging bot), because the user's browser resolves `127.0.0.1` to the user's own laptop, not the remote container — so the authorization code never reaches Hermes. This skill does the OAuth dance by hand and writes the resulting tokens into the exact files Hermes' token storage expects, so a subsequent `/reload-mcp` finds cached tokens and skips the browser flow entirely. ## When to Use Use this skill when **all** of the following are true: 1. The user wants to add a remote HTTP MCP server that requires OAuth (not a static Bearer token). 2. Hermes is running as a **remote gateway** (container, VPS, Docker, managed service) — NOT a local CLI on the user's laptop. 3. The server supports OAuth 2.1 with PKCE and RFC 7591 Dynamic Client Registration (most modern MCP servers do — Better Stack, Linear, Cloudflare, Datadog, etc.). If it doesn't support DCR (GitHub is the notable exception), this skill does not apply — use a pre-registered OAuth App or a Personal Access Token instead. Do NOT use this for: - **Local CLI Hermes** — just set `auth: oauth` in `mcp_servers.<name>` and `/reload-mcp`. The built-in flow opens a browser and captures the callback on localhost. Works perfectly. - **Servers that accept a static Bearer token (API key)** — always prefer `headers.Authorization: "Bearer <token>"` when the user is willing. Simpler, no refresh dance. - **GitHub Copilot MCP** (`api.githubcopilot.com/mcp/`) — GitHub does not expose DCR. Use a PAT or a pre-registered OAuth App (see pitfall 12). ## Why the Built-in OAuth Flow Fails on a Remote Gateway Hermes' native MCP OAuth client (`tools/mcp_oauth.py`): 1. Picks a free local port `P`. 2. Registers a dynamic OAuth client with the AS, sending `redirect_uri = http://127.0.0.1:P/callback`. 3. Starts an HTTP server on `127.0.0.1:P` **inside the Hermes process**. 4. Prints the authorize URL and waits for the code at its local endpoint. When Hermes runs remotely, the `127.0.0.1` in the `redirect_uri` is the remote container's loopback, not the user's. After authorizing, the user's browser 302s to `http://127.0.0.1:P/callback?code=...`, which resolves to the user's own laptop and fails to connect. The callback never reaches the Hermes process, the flow times out, and `/reload-mcp` returns "No MCP tools available" with no detail. Symptoms to recognize: `[xdg-open] <defunct>` processes under the hermes user, an empty or missing tokens directory (`$HERMES_HOME/mcp-tokens/`), and a reload that responds without any "Added/Reconnected: X" line in `change_detail`. ## Cheap First Fallbacks: the Built-in Flow's Own Escape Hatches Before any manual token surgery, check whether the built-in flow's fallbacks already cover the deployment. When Hermes detects a remote session it prints two options alongside the authorize URL (`tools/mcp_oauth.py`): 1. **Paste-back** — on an interactive TTY, a stdin reader races the HTTP listener. The user authorizes, the browser fails to connect to `127.0.0.1:<port>`, and they paste the full address-bar URL (`?code=...&state=...`) back at the prompt. Works for SSH'd-in CLI sessions. 2. **SSH port-forward** — `ssh -N -L <port>:127.0.0.1:<port> <user>@<host>` makes the redirect reach the remote listener normally. Both require an interactive terminal to the Hermes host. The rest of this skill is for when there is NO interactive TTY — Hermes running purely as a messaging gateway/bot where `/reload-mcp` triggers the flow with nobody at a prompt. ## Preferred Front Door: the Hermes Dashboard (try this BEFORE manual token surgery) A remote Hermes gateway often also runs the **dashboard** web UI as a SEPARATE process (e.g. `hermes dashboard --host 0.0.0.0 --port <port>`; check with `ps aux | grep 'hermes dashboard'`). It exposes a connector/MCP console — endpoints like `/api/mcp/servers`, `/api/mcp/status`, and `/connectors` (all login-gated; a cookieless curl returning 401/302 confirms they exist). **Why the dashboard solves the core problem:** when the user drives OAuth from the dashboard *in their own browser*, the redirect lands in a context the dashboard can capture — sidestepping the `127.0.0.1`-callback failure that breaks the CLI/manual flow. So the correct escalation order for "add or re-auth an OAuth MCP server on a remote gateway" is: 1. **Dashboard, in the user's browser** — the intended front door. Add servers, run OAuth, reload, all authenticated as the user. No copy-paste-callback dance, no hand-writing token files. 2. **Manual token surgery (the rest of this skill)** — the FALLBACK for when there's no browser session to the dashboard (pure-chat/headless context). **Finding the dashboard's PUBLIC URL.** The dashboard binds internally to `0.0.0.0:<port>`, but the user needs the externally-reachable URL. Most deploy platforms inject it into the environment — grep for it rather than making the user hunt: ```bash env | grep -iE "HERMES_DASHBOARD_PUBLIC_URL|RAILWAY_PUBLIC_DOMAIN|RAILWAY_STATIC_URL|RAILWAY_SERVICE_.*_URL|PUBLIC_URL|BASE_URL|DOMAIN" \ | sed -E 's/(TOKEN|SECRET|KEY|PASSWORD)=.*/\1=***REDACTED***/I' ``` `HERMES_DASHBOARD_PUBLIC_URL` is authoritative when present. On Railway also check `RAILWAY_PUBLIC_DOMAIN` / `RAILWAY_STATIC_URL` (the `*.up.railway.app` host) and `RAILWAY_SERVICE_*_URL` vars, which sometimes carry a friendlier custom domain. Hand the user the full `https://` URL and point them at the Connectors/MCP section. ALWAYS pipe through the `sed` redaction above — these env greps sit next to `*_TOKEN`/`*_SECRET` vars. **What the dashboard does NOT fix (still host-side / shell):** stdio servers that need shell auth
More from this repository
antigravity-cliSkill
Operate the Antigravity CLI (agy): plugins, auth, sandbox.
blackboxSkill
Delegate coding tasks to the Blackbox AI multi-model CLI.
grokSkill
Delegate coding to xAI Grok Build CLI (features, PRs).
honchoSkill
Configure and troubleshoot Honcho memory for Hermes.
openhandsSkill
Delegate coding to OpenHands CLI (model-agnostic, LiteLLM).
evmSkill
Read-only EVM client: wallets, tokens, gas across 8 chains.
hyperliquidSkill
Hyperliquid market data, account history, trade review.
solanaSkill
Query Solana wallets, tokens, txs, and NFTs in USD.