Connect an AI Agent with MCP
The short version
- The Delivr MCP server lets an AI agent work with your Delivr account through tools. Its URL is
https://api.delivr.ai/mcp. - It uses the Streamable HTTP transport. It keeps no session, so any request can reach any server.
- A person connects an agent with OAuth. The agent gets only the access the person approves, and never more than the person has.
- A backend job can use an organization API key instead. That path is read-only.
Connect with OAuth
OAuth is the normal way to connect an agent that acts for a person. The person signs in to Delivr and approves a list of permissions. The agent never sees the person's password.
Claude
- In Claude, add a custom connector.
- Enter the URL
https://api.delivr.ai/mcp. - Select Connect. Claude opens the Delivr sign-in page.
- Sign in, review the permissions on the consent page, and approve.
Claude Desktop and the Claude mobile apps use the same connector as claude.ai.
Claude Code
Run this command:
claude mcp add --transport http delivr https://api.delivr.ai/mcpThen run /mcp in Claude Code and select delivr to sign in. Claude Code opens a browser for the consent page.
Other clients
Any MCP client that supports OAuth 2.1 with PKCE can connect. The server does not offer dynamic client registration. A client identifies itself with a Client ID Metadata Document: its client_id is an HTTPS URL that returns the client's metadata. The server advertises this with client_id_metadata_document_supported.
A client finds the rest by itself:
- Send a request to
https://api.delivr.ai/mcpwithout a credential. The server answers401with aWWW-Authenticateheader. The header holds aresource_metadataURL. - Read the protected resource document at
https://api.delivr.ai/.well-known/oauth-protected-resource/mcp(RFC 9728). It names the authorization serverhttps://auth.delivr.aiand listsscopes_supported. - Read the authorization server document at
https://auth.delivr.ai/.well-known/oauth-authorization-server(RFC 8414). It lists the authorization, token, and revocation endpoints. - Send the person to the authorization endpoint with the
coderesponse type and a PKCE challenge. Only theS256method is accepted. Name the scopes you need inscope. A request with no scope is refused. - Exchange the code at the token endpoint. Send the PKCE verifier.
- Send the access token on each MCP request as
Authorization: Bearer <token>.
| Setting | Value |
|---|---|
| Issuer | https://auth.delivr.ai |
| Grant types | authorization_code, refresh_token |
| PKCE | S256 only |
| Token endpoint authentication | none, client_secret_basic, client_secret_post |
| Resource | https://api.delivr.ai/mcp |
Tokens
An access token lasts 15 minutes. It is a signed JWT. Use the refresh token to get a new access token without a new sign-in. Refresh tokens are opaque and can be revoked.
To end a grant from code, send the token to the revocation endpoint (RFC 7009). An access token that was already issued works until it expires.
Permissions
The consent page lists the permissions the agent asks for. Each permission is a scope, such as audiences:read or audiences:write. The scopes_supported list in the discovery documents is the full set.
- The agent can do only what the person approved. A tool the agent has no scope for is refused.
- The agent can never do more than the person can do in the dashboard. Delivr applies the person's own memberships to every call.
- The scopes are fixed when the person approves. If you add a tool that needs a new scope, the person must reconnect and approve again.
- Some actions are never open to an agent, such as launching a campaign or connecting a new destination. The person does these in the dashboard.
Disconnect an agent
- In the dashboard, open Account > Apps.
- Find the agent under Connected agents. The row shows what it can see and change, and when it was last used.
- Select Disconnect and confirm.
Connect with an API key
A backend job with no person present can send an organization API key in the X-Api-Key header. Do not send it as a bearer token.
If the key requires its secret, send the secret in the X-Api-Secret header too. New keys require it by default. A key that requires its secret and arrives without it gets a 401 with api secret is required for this key. A secret that does not match the key gets a 401 with api secret does not match this key, even when the key does not require one. See Authentication for the key and secret pair.
curl -sS https://api.delivr.ai/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "X-Api-Key: $DELIVR_API_KEY" \
-H "X-Api-Secret: $DELIVR_API_SECRET" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'An API key carries the identity:read and audiences:read scopes only. It cannot change anything. It cannot call a tool that needs another scope. Use OAuth for those tools.
A client must run the initialize handshake before any tools/call.
Start with these tools
After an OAuth connection:
- Call
whoamito see which identity the credential resolves to. - Call
list_workspacesto list the projects the person can reach. Most tools need aproject_id. - Call
list_audiencesorget_audienceto read audiences.
The server returns its full tool list in response to tools/list.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
401 with no credential presented | The request has no credential. Send a bearer token or the X-Api-Key header. |
401 and the X-Api-Key header "arrived empty" | The client sent the header with no value. Check the environment variable that fills it. |
401 and the Authorization header "did not carry a token" | The bearer value is not a Delivr access token. Do not put an API key in Authorization. |
| A tool is refused for a missing scope | The credential lacks the scope. Reconnect with OAuth and approve it. An API key cannot hold it. |
| A tool returns no data for a project | The person has no access to that project. Call list_workspaces to see the projects they can reach. |
| Access stops after 15 minutes | The client does not refresh its token. Make the client use the refresh token. |
Updated about 3 hours ago
