RevenueHogdocs
AI and MCP

MCP server

The RevenueHog MCP endpoint, its transport, the three ways to authenticate (OAuth, MCP tokens, sessions), token lifetimes, scoping rules and error responses.

The RevenueHog MCP server answers questions about one workspace's revenue, subscriptions, store analytics, ads, reviews, feedback, experiments and payouts. It speaks the Model Context Protocol over streamable HTTP.

Endpoint

PropertyValue
URLhttps://revenuehog.dev/api/mcp
TransportStreamable HTTP, stateless JSON mode (no session ID, no SSE stream)
MethodsPOST for MCP messages. GET returns 405 with the message "Only POST requests are accepted for MCP." OPTIONS answers CORS preflight.
Server namerevenuehog
CORSAny origin. Allowed headers: Authorization, Content-Type, mcp-protocol-version. WWW-Authenticate is exposed so browser clients can read the OAuth pointer.

Each request builds a fresh server bound to the caller's workspace, so no server state is shared between workspaces or requests.

Authentication

Every POST must carry a credential. The server accepts three kinds and routes a bearer token by its prefix.

CredentialShapeBest forHow to get it
OAuth access tokenmcp_at_...claude.ai, Claude Desktop, Cursor, VS Code, any client with remote-connector OAuthThe client runs the OAuth flow when you add the server
MCP token (personal access token)rh_mcp_...Claude Code, Codex, CI, scripts, any headless clientDashboard, Settings → MCP, Create token
Dashboard sessionSession cookie or session bearer tokenThe RevenueHog mobile app and the terminal device-flow login used by the experiments skillSigning in

Send a token as a header:

Authorization: Bearer rh_mcp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A token with the rh_mcp_ or mcp_at_ prefix is checked only as that kind. An invalid MCP token fails; it is never retried as a session.

Unauthenticated requests

A request without a valid credential gets HTTP 401 and a JSON-RPC error:

{ "jsonrpc": "2.0", "error": { "code": -32001, "message": "Unauthorized" }, "id": null }

The response carries WWW-Authenticate: Bearer resource_metadata="https://app.revenuehog.dev/.well-known/oauth-protected-resource/api/mcp". OAuth-capable clients follow that pointer and start the sign-in flow on their own.

OAuth 2.1

RevenueHog runs a small OAuth 2.1 authorization server for MCP clients.

EndpointPurpose
/.well-known/oauth-protected-resource/api/mcpProtected resource metadata for the MCP endpoint. Resource .../api/mcp, scope mcp, bearer in header. The root /.well-known/oauth-protected-resource names the bare origin, per RFC 9728.
/.well-known/oauth-authorization-serverAuthorization server metadata.
/oauth/registerDynamic client registration (RFC 7591). Open: any client may register.
/oauth/authorizeApproval page for a signed-in RevenueHog user.
/oauth/tokenExchanges a code, or a refresh token, for tokens.

Supported options:

  • Response type code, grant types authorization_code and refresh_token.
  • PKCE is required, method S256 only.
  • Token endpoint auth method none (public clients).
  • redirect_uri must be an http or https URL.

The approval page

When you add the server to an OAuth client, your browser opens Connect an MCP client on RevenueHog. If you are not signed in, you are sent to the login page first and returned afterwards. The page names the workspace and says the client will "Read your revenue, subscriptions, reviews, experiments, and payouts, and create feedback API keys for this workspace. It cannot see other workspaces." It shows the email you are signed in as. Select Approve and connect to finish.

The connection is bound to the workspace that is active in your session at that moment.

Token lifetimes

TokenPrefixLifetime
Authorization codemcp_code_5 minutes
Access tokenmcp_at_7 days
Refresh tokenmcp_rt_90 days. Each refresh returns a new access token and a new refresh token.

Each OAuth connection is recorded when the client first exchanges its code. It appears in Settings → MCP tokens with an OAUTH tag, labelled with the client's host (for example OAuth: claude.ai). Every access token and refresh token names its connection, and RevenueHog checks it on each request:

  • Revoke the connection in Settings and the client is cut off on its next request. Its refresh token stops working too, so it cannot mint new tokens.
  • If the person who approved the connection is removed from the workspace, the connection stops working.
  • If that person deletes their account, the connection is deleted with it.

Owners and admins can revoke any connection. A member can revoke only a connection they approved.

Reconnect after this change

Tokens issued before connections were recorded (before October 2026) carry no connection and are refused. The client sees invalid_grant on its next refresh and runs the OAuth flow again.

OAuth errors

ErrorDescriptionFix
invalid_requestresponse_type must be "code", redirect_uri must be an http(s) URL, code_challenge is required (PKCE), Only the S256 code_challenge_method is supported, or Expected a form-encoded request body.A client configuration problem. Update the client, or use an MCP token instead.
invalid_grantUnrecognized authorization code., The authorization code is invalid or expired., PKCE verification failed., redirect_uri does not match the authorization request., Unrecognized refresh token., This connection was revoked. Connect again., The refresh token is invalid or expired.Remove and re-add the connector to start a fresh flow. Codes last 5 minutes.
unsupported_grant_typeUnsupported grant_type "..."The client must use authorization_code or refresh_token.

MCP tokens

MCP tokens are personal access tokens for clients that cannot run OAuth.

Open Settings → MCP

In the dashboard, open Settings and select the MCP tab. If the tab is not shown, go to /settings/mcp directly.

Name the token

Type a label in Token label, e.g. Claude desktop (up to 80 characters) and select Create token.

Copy the secret

A Copy your token now box shows the secret once. Select Copy and store it. "This is the only time the secret is shown." RevenueHog keeps only a SHA-256 hash.

The list shows each token's label, creation date, and either used with a relative time or never used. The card header counts tokens ("None yet" or "N active"). Select Revoke to delete a token; it stops working on the next request. used reflects the last time RevenueHog looked the token up in its database. Lookups are cached for up to 12 hours (revoking clears the cache at once), so an active token can show a use time up to 12 hours old.

Facts about MCP tokens:

  • A token belongs to the workspace, not to the person who created it. It keeps working if its creator leaves the workspace. Revoke tokens you no longer need.
  • Only workspace owners and admins can create MCP tokens or revoke them. Members see the list, and the create form is replaced by "Only workspace owners and admins can create tokens." The API answers 403 with Only workspace owners and admins can manage tokens and API keys.
  • The secret is rh_mcp_ followed by 32 URL-safe characters.
  • Last used is updated on a best-effort basis on each request.
  • The settings list shows up to 200 tokens.

Token management API

The card calls /api/settings/mcp-tokens, which also accepts a session bearer token.

MethodBodyResponseErrors
GETnone{ "tokens": [{ "id", "label", "createdAt", "lastUsedAt" }] }401
POST{ "label": "CI" }{ "token": "rh_mcp_...", "summary": { ... } }400 invalid JSON, 400 missing label, 400 label too long, 401
DELETE{ "id": "..." }{ "ok": true }400 missing id, 404 not found, 401

Scoping and safety

  • Every tool reads only the workspace the credential is bound to. A tool given an ID from another workspace answers "not found".
  • To query a different workspace, connect again while that workspace is active, or create an MCP token while in it.
  • Analytics tools are read-only. The only write is rh_create_api_key, which creates a feedback API key in the same workspace.
  • All money values are USD.

Tool results and errors

Every tool returns one text content block containing pretty-printed JSON. A failed call returns {"error": "<message>"} with isError: true, for example Unknown measure "mmr". Valid measures: .... See MCP tools for each tool's messages.

Test with curl

List the tools
curl -s https://revenuehog.dev/api/mcp \
  -H "Authorization: Bearer $REVENUEHOG_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Call rh_meta
curl -s https://revenuehog.dev/api/mcp \
  -H "Authorization: Bearer $REVENUEHOG_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"rh_meta","arguments":{"topic":"freshness"}}}'

Last updated on

On this page