Skip to main content

M2M tokens

Authenticate an agent to its Virtual MCP with short-lived access tokens minted through the OAuth 2.0 client-credentials grant. Machine-to-machine (M2M) tokens are the more secure alternative to a bearer key: the agent holds a client ID and secret, exchanges them for a short-lived access token, and sends that token, not the long-lived secret, on each MCP request.

M2M tokens apply to agent identities only. A Virtual MCP offered to human members uses interactive OAuth; a Virtual MCP scoped to an agent can authenticate with a bearer key, an M2M token, or both.

How it works

MintMCP provisions a client for the agent's Virtual MCP, and the agent runs a standard client-credentials exchange:

  1. An admin opens the agent Virtual MCP's settings and clicks Create M2M client. MintMCP mints a client ID and a client secret scoped to that one Virtual MCP and shows the secret once.
  2. The runtime stores the client ID and secret in its secret manager.
  3. On startup, and whenever its token is close to expiry, the agent POSTs the credentials to the Virtual MCP's token endpoint and receives a short-lived access token.
  4. The agent sends the access token as Authorization: Bearer <access_token> on every request to the MCP endpoint. When the token expires, it exchanges the credentials again.

Both endpoints come from the Virtual MCP's settings, and the exchange looks like this:

# Exchange client credentials for an access token
curl -X POST "https://app.mintmcp.com/o/<org-slug>/s/<server-slug>/m2m/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "grant_type=client_credentials&client_id=<client_id>&client_secret=<client_secret>"

# => {"access_token": "...", "expires_in": 3600, "token_type": "bearer"}

# Call the agent's MCP with the returned token
# Authorization: Bearer <access_token>
# https://app.mintmcp.com/o/<org-slug>/s/<server-slug>/mcp

The token endpoint comes in two shapes, .../o/<org-slug>/s/<server-slug>/m2m/token and .../s/<gateway-id>/m2m/token, so copy the exact one shown alongside the client credentials in the admin UI rather than deriving it from the MCP URL. The runtime reuses the access token until the expires_in window the endpoint returns elapses (the sample above shows 3600 seconds), then exchanges the credentials again. Only grant_type=client_credentials is accepted, and the presented client_id must match the one bound to the Virtual MCP, so a token minted for one agent can't be replayed against another.

Why M2M over a bearer key

Both mechanisms land on the same gateway as the same agent principal and inherit the same tool curation and rules. They differ in what the agent holds and what travels on each request:

PropertyBearer keyM2M token
What each request carriesThe long-lived secret itselfA short-lived access token; the client secret only appears during the token exchange
Default lifetimeNo expiry unless you set one (up to 1 year)Access tokens are short-lived and re-minted on demand
RotationMint a new key, then delete the old oneAdd a new client secret while the old one still works, then revoke the old one
ContainmentRevoke the keyThe token expires on its own, or revoke a client secret
Per-use auditCreate and delete events, plus a last-used timestampEvery token exchange is a discrete audit event

The credential the agent handles on each request is disposable: the access token turns over on its own, and the client secret stays out of the request path, appearing only during the token exchange. You rotate the client secret on your own schedule.

Client secrets and rotation

Each agent Virtual MCP has one M2M client and can hold more than one client secret at a time:

  • One-time display. MintMCP shows a new secret once, in a copy panel, and stores only an encrypted form. Copy it into your secret manager then, or mint a new one.
  • Overlapping secrets. Click Create new secret to add a second live secret. Creating a secret does not revoke existing secrets or already-issued access tokens, so you can roll the runtime onto the new secret with no cutover window.
  • Independent revocation. Revoke secret invalidates one secret. New token exchanges with it fail immediately; tokens already issued from it keep working until they expire.

Scoping

M2M tokens carry the same tight scope as any agent credential:

ScopeWhat it means
VMCP-boundThe token authenticates against one Virtual MCP; the gateway checks both the client ID and the organization on every request
Principal-boundThe token acts as exactly one agent identity, never a human user
Policy-boundThe token inherits the Virtual MCP's tool curation, rules, and middleware; it authenticates the agent, it doesn't elevate it
Org-scopedTokens never cross organizations

For how access policies shape what any agent credential can reach, see role-based access control.

Audit

M2M authentication is auditable at a finer grain than a static key, because the token exchange itself is logged:

  • Token exchange writes a discrete event on every attempt: agent_m2m_token_issued on success, agent_m2m_token_denied when the client ID is wrong or the grant is unsupported, and agent_m2m_token_failed on an upstream error. Each records the client ID, response status, request ID, and user agent.
  • Lifecycle events cover the client and its secrets: agent_m2m_client_created, agent_m2m_secret_created, and agent_m2m_secret_revoked.
  • Tool calls made with the token attribute to the agent identity, the same as any other agent traffic, so agent activity stays distinguishable from human activity in the gateway audit log.

Together these show not just what the agent did, but when and how it authenticated. A bearer key records its creation and deletion and a last-used timestamp, so you can see that a key exists and when it was last used, but not each time it authenticated.

When to use M2M tokens

  • Sandboxed and ephemeral runs are the strongest fit. When an agent calls MCP from a throwaway sandbox (a background coding agent, a CI job, a scheduled run on compute that's torn down afterward), the credential on each request is a short-lived token the run mints at startup, not a durable key baked into the environment. The token expires on its own, so the sandbox never has to hold a long-lived key that outlives the run.
  • Reach for M2M tokens whenever the runtime can run a client-credentials exchange (most CI platforms and standing services can) and you want short-lived credentials with per-exchange audit. This is the more secure option for agents that can support it.
  • Use a bearer key when the client can only send a static Authorization: Bearer header and can't manage a token exchange, or when you want the simplest possible setup.