POST https://appconnecthq.vercel.app/api/mcp/unified is a single Streamable HTTP MCP endpoint (JSON-RPC 2.0) exposing every tool from a user's connected services. There are two ways to authenticate against it, depending on what kind of MCP client you're connecting.
headers field.access_token the normal way — complete a /connect/[service] flow and exchange the resulting code at POST /api/oauth/token (see the Getting Started section on the main API Reference), or read one out of the admin dashboard for testing..mcp.json for Claude Code or Cursor:{
"mcpServers": {
"appconnect": {
"type": "http",
"url": "https://appconnecthq.vercel.app/api/mcp/unified",
"headers": {
"Authorization": "Bearer <YOUR_ACCESS_TOKEN>"
}
}
}
}Known limitation: a static access_token is short-lived (1 hour) and refreshing it requires your partner client_id/client_secret, which an individual end user typically doesn't have — this method is best for development/testing or first-party tooling, not for distributing to end users. For a long-lived, self-refreshing connection, use Method 2.
AppConnectHQ has no first-party login of its own, so the flow's human-facing step is bootstrapped by your app (the partner) rather than a password:
https://appconnecthq.vercel.app as a custom connector in Claude.ai/ChatGPT. The client hits /api/mcp/unified unauthenticated, gets a 401 with a WWW-Authenticate header, and follows the discovery chain (/.well-known/oauth-protected-resource → /.well-known/oauth-authorization-server) and dynamic client registration entirely on its own — nothing for you to configure here./api/mcp/oauth/authorize, which lands on AppConnectHQ's consent page. Since there's no login, the consent page asks for a short-lived connection code instead.POST /api/mcp/oauth/sessions with your partner client_id/client_secret and the same user_idyou used for that user's /connect flow, and shows the returned session_tokento the user in your own UI (it's only valid for 10 minutes and single-use)./api/mcp/oauth/token for an access token and a refresh token, and calls /api/mcp/unified from then on with Authorization: Bearer <access_token>.Access tokens expire after 1 hour; the client refreshes automatically with the refresh token, which rotates on every use (the old refresh token is invalidated the instant a new one is issued — replaying a stolen one fails):
curl -X POST https://appconnecthq.vercel.app/api/mcp/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=<REFRESH_TOKEN>" \
-d "client_id=<CLIENT_ID>"A client (or a user disconnecting from their client's UI) can also proactively kill a token via POST /api/mcp/oauth/revoke (RFC 7009) with token and an optional token_type_hint (access_token or refresh_token).
| Endpoint | Purpose | Caller |
|---|---|---|
| POST /api/mcp/unified | The MCP server itself (JSON-RPC 2.0) | Any MCP client |
| GET /.well-known/oauth-protected-resource | RFC 9728 protected-resource metadata | OAuth-capable clients (auto) |
| GET /.well-known/oauth-authorization-server | RFC 8414 authorization-server metadata | OAuth-capable clients (auto) |
| POST /api/mcp/oauth/register | RFC 7591 dynamic client registration | OAuth-capable clients (auto) |
| GET /api/mcp/oauth/authorize | Authorization endpoint (PKCE) | OAuth-capable clients (auto) |
| POST /api/mcp/oauth/token | Code/refresh-token exchange | OAuth-capable clients (auto) |
| POST /api/mcp/oauth/revoke | RFC 7009 token revocation | OAuth-capable clients (optional) |
| POST /api/mcp/oauth/sessions | Mint a consent-page connection code for a user | Your app (partner SDK) |