Skip to content

RBAC ConfigurationΒΆ

Role-based access control (RBAC) defines which actions users or teams can perform in MCP Gateway. This document covers the security model, token scoping semantics, and best practices for access control.


OverviewΒΆ

MCP Gateway implements a multi-layered access control system:

  1. Authentication: Verify user identity via JWT, SSO, or API tokens
  2. Team Membership: Group users for collective access policies
  3. Token Scoping: Restrict token capabilities to specific resources
  4. Visibility Filtering: Control which resources users can discover
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Access Control Layers                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚   Request β†’ Authentication β†’ Team Resolution β†’ Token Scoping β†’ Visibility  β”‚
β”‚                                                                             β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚   β”‚   JWT    β”‚   β”‚  User    β”‚   β”‚  Token   β”‚   β”‚ Resource β”‚   β”‚ Filtered β”‚ β”‚
β”‚   β”‚  Token   │──▢│ Identity │──▢│  Teams   │──▢│  Access  │──▢│  Results β”‚ β”‚
β”‚   β”‚          β”‚   β”‚          β”‚   β”‚          β”‚   β”‚          β”‚   β”‚          β”‚ β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core ConceptsΒΆ

SubjectsΒΆ

Users authenticated via: - JWT tokens (session or API) - SSO providers (OAuth 2.0/OIDC) - Basic authentication (development only)

TeamsΒΆ

Logical groups that: - Organize users for access boundaries - Own resources (tools, prompts, resources) - Map from external identity providers (SSO groups)

RolesΒΆ

Current role types: - Admin: Full management access, can bypass team restrictions - Maintainer: Manage servers, tools, prompts, configurations - Viewer: Read-only access and metrics

ResourcesΒΆ

Protected entities: - Servers (MCP gateways and virtual servers) - Tools, Prompts, Resources (MCP primitives) - System configuration and audit logs


Token Scoping ModelΒΆ

Token scoping controls what resources a token can access based on the teams claim in the JWT payload. This provides fine-grained access control for automation tokens, service accounts, and restricted user sessions.

Teams Claim SemanticsΒΆ

The teams claim in JWT tokens determines resource visibility:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Token Teams Claim Handling                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  JWT Claim State          β”‚  Admin User           β”‚  Non-Admin User         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  No "teams" key           β”‚  UNRESTRICTED         β”‚  PUBLIC-ONLY (secure)   β”‚
β”‚  teams: null              β”‚  UNRESTRICTED         β”‚  PUBLIC-ONLY (secure)   β”‚
β”‚  teams: []                β”‚  PUBLIC-ONLY          β”‚  PUBLIC-ONLY            β”‚
β”‚  teams: ["team-id"]       β”‚  Team + Public        β”‚  Team + Public          β”‚
β”‚  teams: ["t1", "t2"]      β”‚  Both Teams + Public  β”‚  Both Teams + Public    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Security Design PrinciplesΒΆ

  1. Principle of Least Privilege
  2. Non-admin tokens without explicit team scope default to public-only access
  3. This prevents accidental exposure of team resources

  4. Scoped Automation Tokens

  5. Admin tokens with teams: [] are intentionally restricted to public resources
  6. Use case: CI/CD pipelines, monitoring systems, public API clients

  7. Backward Compatible Admin Access

  8. Admin session tokens (from UI login) omit the teams claim entirely
  9. This grants unrestricted access for administrative operations

Token Scoping FlowΒΆ

                                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                 β”‚   JWT Token      β”‚
                                 β”‚   Received       β”‚
                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚  Extract "teams"      β”‚
                              β”‚  claim from JWT       β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚                               β”‚
                          β–Ό                               β–Ό
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚ "teams" key exists  β”‚       β”‚ "teams" key missing β”‚
               β”‚ with non-null value β”‚       β”‚ OR teams: null      β”‚
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚                             β”‚
                          β–Ό                             β–Ό
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚ Use explicit scope  β”‚       β”‚ Check is_admin flag β”‚
               β”‚ teams = [...] or [] β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
                          β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚                 β”‚                       β”‚
                          β”‚                 β–Ό                       β–Ό
                          β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚      β”‚ Admin: teams =   β”‚   β”‚ Non-Admin:       β”‚
                          β”‚      β”‚ None (bypass)    β”‚   β”‚ teams = []       β”‚
                          β”‚      β”‚ UNRESTRICTED     β”‚   β”‚ PUBLIC-ONLY      β”‚
                          β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚               β”‚                      β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          β–Ό
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚   Apply visibility    β”‚
                              β”‚   filter to query     β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Visibility LevelsΒΆ

Resources in MCP Gateway have three visibility levels:

Visibility Description Who Can See
public Accessible to all authenticated users Everyone with valid token
team Accessible to team members only Team members + admins (unrestricted)
private Accessible to owner only Resource owner + admins (unrestricted)

Enforcement PointsΒΆ

Token scoping is enforced consistently across all access paths:

Layer Location Description
Middleware token_scoping.py Request-level access control
REST API main.py /tools, /resources, /prompts endpoints
RPC Handler main.py tools/list, resources/list, prompts/list
MCP Transport streamablehttp_transport.py Streamable HTTP protocol filtering
Service Layer *_service.py Database query filtering

Token Types and Use CasesΒΆ

Session Tokens (UI Login)ΒΆ

Generated when users log in via the Admin UI:

{
  "sub": "user@example.com",
  "is_admin": true,
  "iss": "mcpgateway",
  "aud": "mcpgateway-api",
  "exp": 1234567890
  // Note: No "teams" key for admin users = unrestricted access
}

Behavior: Admin session tokens omit the teams claim, granting unrestricted access to all resources.

API Tokens (Programmatic Access)ΒΆ

Generated via the Admin UI or API for automation:

{
  "sub": "service-account@example.com",
  "is_admin": false,
  "teams": ["team-uuid-1", "team-uuid-2"],
  "iss": "mcpgateway",
  "aud": "mcpgateway-api",
  "exp": 1234567890
}

Behavior: Access restricted to public resources plus resources owned by specified teams.

Scoped Automation TokensΒΆ

For CI/CD, monitoring, or public API access:

{
  "sub": "ci-pipeline@example.com",
  "is_admin": true,
  "teams": [],  // Explicitly empty = public-only
  "iss": "mcpgateway",
  "aud": "mcpgateway-api",
  "exp": 1234567890
}

Behavior: Even admin tokens with teams: [] are restricted to public resources only. This enables creating limited-scope tokens for automation that shouldn't access team-internal resources.


Generating Scoped TokensΒΆ

Using the CLI ToolΒΆ

# Unrestricted admin token (no teams key)
python3 -m mcpgateway.utils.create_jwt_token \
  --username admin@example.com \
  --exp 60 \
  --secret $JWT_SECRET_KEY

# Team-scoped token
python3 -m mcpgateway.utils.create_jwt_token \
  --username user@example.com \
  --exp 60 \
  --secret $JWT_SECRET_KEY \
  --teams '["team-uuid-1"]'

# Public-only scoped token (for automation)
python3 -m mcpgateway.utils.create_jwt_token \
  --username ci@example.com \
  --exp 60 \
  --secret $JWT_SECRET_KEY \
  --teams '[]'

Using the Admin UIΒΆ

  1. Navigate to Admin UI β†’ Tokens
  2. Click Create Token
  3. Select team scope:
  4. No team selected: Public resources only (secure default)
  5. Specific team(s): Team + public resources
  6. Configure additional restrictions (IP, permissions, expiry)

Token Scope Warning

Tokens created without selecting a team will have access to public resources only. This is the secure default to prevent accidental exposure of team resources.


Best PracticesΒΆ

Token LifecycleΒΆ

  1. Use short expiration times for interactive sessions (hours)
  2. Use longer expiration for service accounts with IP restrictions
  3. Rotate tokens regularly (recommended: 90 days for long-lived tokens)
  4. Revoke tokens immediately when access should be removed

Team OrganizationΒΆ

  1. Create purpose-specific teams:
  2. platform-admins - Full administrative access
  3. developers - Development and testing resources
  4. ci-automation - CI/CD pipeline access
  5. monitoring - Read-only observability access

  6. Map SSO groups to teams for automatic membership management

  7. Use personal teams for individual resource ownership

Scoping StrategyΒΆ

Use Case Recommended Token Scope
Admin UI access Session token (no teams key)
CI/CD pipeline teams: [] (public-only)
Service integration Specific team(s)
Developer access Personal team + project teams
Monitoring/alerting teams: [] with read permissions

TroubleshootingΒΆ

Token Not Seeing Expected ResourcesΒΆ

  1. Check token claims: Decode the JWT to verify teams claim

    # Decode JWT payload (middle section)
    echo "$TOKEN" | cut -d. -f2 | base64 -d | jq .
    

  2. Verify resource visibility: Check the resource's visibility and team_id

    curl -H "Authorization: Bearer $ADMIN_TOKEN" /tools/{id} | jq '{visibility, teamId}'
    

  3. Check user admin status: Non-admin users without teams get public-only access

Admin Token Being RestrictedΒΆ

If an admin token is unexpectedly restricted:

  1. Check for explicit teams claim: teams: [] restricts even admins
  2. Verify is_admin flag: Must be true in JWT or database user
  3. Check middleware logs: Look for "token_teams" in debug output

Inconsistent Results Between EndpointsΒΆ

If REST and RPC endpoints return different results:

  1. Check for caching: REST list endpoints may have cached data
  2. Wait for cache TTL: Default is 60 seconds for registry cache
  3. Use direct GET: /tools/{id} bypasses list cache