# MCP Authentication

The Resolve MCP supports two authentication paths. Choose based on who is connecting:

|  | Web App Authentication | Machine-to-Machine (M2M) |
|  --- | --- | --- |
| **Who it's for** | A person using a native AI assistant (Claude, ChatGPT) | Automation: custom MCP clients, headless agents, server-side jobs |
| **How it works** | Interactive OAuth 2.0 sign-in with your Resolve dashboard login, including Google login | OAuth 2.0 Client Credentials — exchange an MCP access key for a bearer token |
| **Login required** | Every individual must have their own Resolve account and sign in to connect | Never interactive — the token impersonates the account owner on every call, with no additional auth |
| **Identity & scope** | The signed-in user's dashboard roles and permissions | The merchant that owns the access key, limited by the key's scopes |
| **Revoke** | Disconnect the connector in the AI assistant | Revoke the key in Merchant Dashboard |


## Which one should I use?

- **A person working in Claude or ChatGPT** → Web App Authentication. Each person signs in with their own Resolve account, so permissions follow the individual user.
- **Automation — an unattended agent, backend service, or custom MCP client** → M2M. Only use it if the credential is protected behind your own gated access (secrets manager, permissioned CI, locked-down service account) — remember, anyone holding the token can act as the account owner with no further auth.
- **Both at once is fine** — for example, your AR team uses Claude via Web App Authentication while a nightly automation reconciles invoices with an M2M token.


## Web App Authentication

Use this path when a person connects Resolve inside Claude, ChatGPT, or another OAuth-capable MCP client.

This still requires each individual to have their own Resolve account. When you add `https://mcp.resolvepay.com/mcp` as a connector, the client discovers Resolve's authorization server and redirects you to the Resolve dashboard login, including Google login. After you sign in and approve access, the client receives an access token tied to **your user identity**. Every tool call is checked against your dashboard role, so a read-only dashboard login gets read-only MCP tools.

No credentials to copy, no keys to manage — and access follows your dashboard user. Deactivating the user in the dashboard cuts off their MCP access too.

### OAuth callback URLs for common LLM clients

During the sign-in flow, the client redirects back to itself using an OAuth callback (redirect) URL. For reference, these are the callback URLs used by common LLM clients:

| Client | Callback URL |
|  --- | --- |
| Claude (claude.ai) | `https://claude.ai/api/mcp/auth_callback` |
| Claude (claude.com) | `https://claude.com/api/mcp/auth_callback` |
| ChatGPT | Generated per connector — see below |


Some LLMs, like ChatGPT, might have dynamic callback URLs that are generated per connector. In ChatGPT, when you create the connector (**New App**), enter the MCP server URL, then under **Advanced OAuth settings** choose **User-Defined OAuth Client** as the registration method — ChatGPT then displays the callback URL for that connector (e.g. `https://chatgpt.com/connector/oauth/<connector-id>`).

## Machine-to-Machine (M2M) Authentication

Use this path for automation: custom MCP clients, scheduled agents, CI jobs, or backends that call the MCP on your behalf. There is no login screen and no OAuth redirect — the client presents a bearer token on every request, and the MCP server simply validates it.

**The token impersonates the account owner every time it's used, with no additional authentication.** Whoever created the access key is the identity every M2M call runs as — there's no per-call sign-in, no MFA, and no way to distinguish which person or job triggered a given request beyond what you log yourself. Because of this, we recommend only using M2M when access to the credential itself is gated behind your own authentication and authorization controls (a secrets manager, a permissioned CI system, a locked-down service account) — not stored somewhere any team member can read and reuse it.

### 1. Generate an MCP access key

In Merchant Dashboard, navigate to `Settings > Integrations > Direct API` and create an access key of type **MCP**. Choose the scopes:

- `merchant:read` — read tools only
- `merchant:write` — read and write tools


Copy the `client_id` and `client_secret` immediately — the secret is shown once. MCP keys are distinct from standard API keys: a standard v3 API key cannot be used with the MCP, and an MCP key cannot call the REST API.

### 2. Exchange the key for a bearer token

Send a `POST` request to `/api/access-keys/token` with `audience` set to `mcp`:

```bash
curl https://app.resolvepay.com/api/access-keys/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "<client_id>",
    "client_secret": "<client_secret>",
    "audience": "mcp"
  }'
```

Example response:

```json
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 86400
}
```

The returned token is a JWT with `aud = https://mcp.resolvepay.com/mcp`, scoped to your merchant account.

### 3. Configure your MCP client

Point your client at the MCP URL and send the token as a bearer header. Example configuration (Claude Code / any `mcpServers`-style client):

```json
{
  "mcpServers": {
    "resolve": {
      "type": "http",
      "url": "https://mcp.resolvepay.com/mcp",
      "headers": {
        "Authorization": "Bearer <access_token>"
      }
    }
  }
}
```

Tokens expire (`expires_in` is in seconds) — mint a new one from the same key when needed. Revoked or expired keys cannot mint tokens.