Authentication & RBAC
How authentication and role-based access control work in the MCP server
The hosted Metadot MCP endpoint at https://metadot.net/api/mcp/{workspace-slug} authenticates every request via OAuth 2.1 with PKCE. When you add the URL to your AI tool, your browser opens a consent page — you sign in with your existing Metadot account and your client receives a short-lived bearer token. Refreshes happen silently in the background.
Every tool call then passes through three layers of authorization before any data is read or modified.
OAuth Flow
On first connection your MCP client performs these steps automatically:
- Discovery — client fetches
https://metadot.net/.well-known/oauth-authorization-serverfor endpoint metadata - Dynamic client registration (RFC 7591) — client registers itself with Metadot's OAuth server
- Authorization — your browser opens to a Metadot consent page; you sign in and approve
- Token exchange — client exchanges the authorization code for a 24-hour access token + refresh token
- Subsequent calls — every MCP request sends
Authorization: Bearer <access_token>; the access token refreshes silently via the refresh token
No API keys, no database credentials, no manual token paste. Access tokens expire after 24 hours and refresh automatically.
RBAC (Three Layers)
Every tool call passes through three authorization layers:
| Layer | Check | Example |
|---|---|---|
| 1. Workspace Scope | Does the token match this connection's workspace? | You must be a member of the workspace |
| 2. Workspace Role | Is the user a member? Owners/admins receive the admin app role. | App-role promotion applies to enabled apps |
| 3. App-Level Role | Does the user have a role for this specific app? | crm.contact:manage permission required for writes |
Read vs Write Permissions
- Read tools (search, list, get) require any app role
- Write tools (create, update, delete) require a specific permission such as
crm.contact:manageortickets.ticket:manage
What Happens When Access Is Denied
If any layer denies access, the tool returns a clear error message explaining which permission is missing. The AI agent will relay this to you so you can ask your workspace admin for the appropriate role.
Workspace Resolution
Each connection targets one workspace. OAuth binds it at consent; a PAT is bound to its workspace at creation, and the endpoint slug must match. Tools need no workspace_id parameter. Call current_workspace to inspect the binding; current membership, credential restrictions and resource grants still apply.
The hosted endpoint revalidates identity, workspace membership, roles and enabled apps on every HTTP request. A standalone stdio server may reuse workspace resolution for five minutes; native writes still recheck current authority on their owning transaction.
Personal Access Token (PAT) Authentication
For agents, scripts, CI pipelines, and tools that cannot open a browser for OAuth, authenticate with a Personal Access Token instead.
How It Works
- Generate a PAT from Account → API Keys in any workspace
- Pass it as a Bearer token:
Authorization: Bearer mk_your_token_here - The MCP endpoint validates the token and builds the same auth context as OAuth — same RBAC, same tool access
No browser, no redirect, no client registration. Just a single header.
OAuth vs PAT
| OAuth 2.1 | Personal Access Token | |
|---|---|---|
| Auth flow | Browser-based consent | No browser needed |
| Token lifetime | 24 hours (auto-refresh) | Never expires (until revoked) |
| Scopes | Full access (*) | Per-module (e.g. crm:*, tickets:*) |
| Best for | Humans using AI tools | Agents, scripts, CI pipelines |
| Workspace scope | One workspace, selected at consent | One workspace, selected at creation |
Scope Enforcement
PATs have per-module scopes. If your PAT has scopes: ["crm:*", "tickets:*"], only CRM and Tickets tools will be available via MCP. Tools for other modules will return a clear scope error. Generate a PAT with * scope for full access.
Generating a PAT
Go to Account → API Keys → Generate token. Choose your scopes and copy the token — it is shown only once.
Was this page helpful?