Authentication
Related Topics: Policies (use user context for access control) | Configuration (secrets management) | Common Tasks (quick setup)
MXCP supports OAuth 2.0 authentication to control who can access your MCP server. This guide covers configuring various OAuth providers.
How It Works
Section titled “How It Works”When authentication is enabled:
- Client connects to your MCP server
- Server redirects to OAuth provider (GitHub, Google, etc.)
- User authenticates with the provider
- Provider redirects back with authorization code
- Server exchanges code for access token
- User context becomes available in policies and SQL
All tools, resources, and prompts require valid authentication tokens when auth is enabled.
Protected Features
Section titled “Protected Features”When authentication is enabled, these features require valid tokens:
- Custom Endpoints: All tools, resources, and prompts defined in your YAML files
- SQL Tools: Built-in DuckDB querying and schema exploration tools
User Information Logging
Section titled “User Information Logging”MXCP automatically logs user information for each authenticated request:
- Username and user ID
- OAuth provider (GitHub, Google, etc.)
- User’s display name and email (when available)
Supported Providers
Section titled “Supported Providers”| Provider | Use Case |
|---|---|
| GitHub | Developer teams, open source projects |
| Atlassian | Enterprise teams using Jira/Confluence |
| Salesforce | CRM integrations, enterprise apps |
| Google Workspace organizations | |
| Keycloak | Self-hosted identity management |
Configuration Overview
Section titled “Configuration Overview”Authentication is configured in your user configuration file (~/.mxcp/config.yml):
mxcp: 1projects: my-project: profiles: default: auth: provider: github github: client_id: "${GITHUB_CLIENT_ID}" client_secret: "${GITHUB_CLIENT_SECRET}" callback_path: /callback auth_url: https://github.com/login/oauth/authorize token_url: https://github.com/login/oauth/access_tokenDisable Authentication
Section titled “Disable Authentication”By default, authentication is disabled (provider: none):
mxcp: 1projects: my-project: profiles: default: auth: provider: none # No authentication requiredUse this for:
- Local development
- Internal tools with network-level security
- Read-only public APIs
GitHub Authentication
Section titled “GitHub Authentication”1. Create OAuth App
Section titled “1. Create OAuth App”- Go to GitHub Settings → Developer settings → OAuth Apps
- Click New OAuth App
- Configure:
- Application name: Your MCP Server
- Homepage URL:
http://localhost:8000 - Authorization callback URL:
http://localhost:8000/callback
- Copy the Client ID and Client Secret
2. Configure MXCP
Section titled “2. Configure MXCP”mxcp: 1projects: my-project: profiles: default: auth: provider: github github: client_id: "${GITHUB_CLIENT_ID}" client_secret: "${GITHUB_CLIENT_SECRET}" callback_path: /callback auth_url: https://github.com/login/oauth/authorize token_url: https://github.com/login/oauth/access_token scope: "read:user user:email"Note: The examples below for other providers show just the auth block for brevity. Place them at the same location: projects.{project}.profiles.{profile}.auth.
3. Available Scopes
Section titled “3. Available Scopes”| Scope | Access |
|---|---|
read:user | User profile information |
user:email | User email addresses |
read:org | Organization membership |
repo | Repository access (if needed) |
Atlassian Authentication
Section titled “Atlassian Authentication”For Jira and Confluence integration.
1. Create OAuth 2.0 App
Section titled “1. Create OAuth 2.0 App”- Go to Atlassian Developer Console
- Create a new OAuth 2.0 integration
- Configure:
- Name: Your MCP Server
- Callback URL:
http://localhost:8000/callback
- Enable required API scopes
- Copy credentials
2. Configure MXCP
Section titled “2. Configure MXCP”# In ~/.mxcp/config.ymlauth: provider: atlassian atlassian: client_id: "${ATLASSIAN_CLIENT_ID}" client_secret: "${ATLASSIAN_CLIENT_SECRET}" callback_path: /callback auth_url: https://auth.atlassian.com/authorize token_url: https://auth.atlassian.com/oauth/token scope: "read:me read:jira-work write:jira-work"3. Available Scopes
Section titled “3. Available Scopes”| Scope | Access |
|---|---|
read:me | User profile |
read:jira-work | Read Jira issues |
write:jira-work | Create/update issues |
read:confluence-content.all | Read Confluence pages |
offline_access | Enable refresh tokens |
4. Accessing Multiple Sites
Section titled “4. Accessing Multiple Sites”Atlassian OAuth grants access to all sites where your app is installed. To work with specific sites:
-
Get accessible resources (returns cloud IDs):
Terminal window curl -H "Authorization: Bearer ACCESS_TOKEN" \https://api.atlassian.com/oauth/token/accessible-resources -
Use the cloud ID in API requests:
Terminal window # JIRA APIcurl -H "Authorization: Bearer ACCESS_TOKEN" \https://api.atlassian.com/ex/jira/{cloudid}/rest/api/2/project# Confluence APIcurl -H "Authorization: Bearer ACCESS_TOKEN" \https://api.atlassian.com/ex/confluence/{cloudid}/rest/api/space
Salesforce Authentication
Section titled “Salesforce Authentication”For CRM and enterprise integrations.
1. Create Connected App
Section titled “1. Create Connected App”- Go to Salesforce Setup → App Manager
- Click New Connected App
- Enable OAuth Settings:
- Callback URL:
http://localhost:8000/callback - Select required OAuth Scopes
- Callback URL:
- Copy Consumer Key and Consumer Secret
2. Configure MXCP
Section titled “2. Configure MXCP”# In ~/.mxcp/config.ymlauth: provider: salesforce salesforce: client_id: "${SALESFORCE_CLIENT_ID}" client_secret: "${SALESFORCE_CLIENT_SECRET}" callback_path: /callback auth_url: https://login.salesforce.com/services/oauth2/authorize token_url: https://login.salesforce.com/services/oauth2/token scope: "openid profile email api"3. Available Scopes
Section titled “3. Available Scopes”| Scope | Access |
|---|---|
openid | OpenID Connect authentication |
profile | User profile information |
email | User email address |
api | Access to Salesforce APIs |
refresh_token | Enable token refresh |
4. Sandbox Environment
Section titled “4. Sandbox Environment”For sandbox/test environments:
auth_url: https://test.salesforce.com/services/oauth2/authorizetoken_url: https://test.salesforce.com/services/oauth2/tokenGoogle Authentication
Section titled “Google Authentication”For Google Workspace organizations.
1. Create OAuth Client
Section titled “1. Create OAuth Client”- Go to Google Cloud Console
- Create or select a project
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Configure:
- Application type: Web application
- Authorized redirect URIs:
http://localhost:8000/callback
- Copy credentials
2. Configure MXCP
Section titled “2. Configure MXCP”# In ~/.mxcp/config.ymlauth: provider: google google: client_id: "${GOOGLE_CLIENT_ID}" client_secret: "${GOOGLE_CLIENT_SECRET}" callback_path: /callback auth_url: https://accounts.google.com/o/oauth2/v2/auth token_url: https://oauth2.googleapis.com/token scope: "openid email profile"3. Available Scopes
Section titled “3. Available Scopes”| Scope | Access |
|---|---|
openid | OpenID Connect authentication |
email | User email address |
profile | User profile information |
https://www.googleapis.com/auth/calendar.readonly | Read calendar events |
https://www.googleapis.com/auth/drive.readonly | Read Drive files |
4. Domain Restriction
Section titled “4. Domain Restriction”To restrict to a specific Google Workspace domain, validate the user’s email domain in your policies:
policies: input: - condition: "!user.email.endsWith('@yourcompany.com')" action: deny reason: "Access restricted to company domain"5. Working with Google APIs
Section titled “5. Working with Google APIs”Once authenticated, use the user’s token to access Google services from SQL:
-- List Google Calendar eventsSELECT *FROM read_json_auto( 'https://www.googleapis.com/calendar/v3/calendars/primary/events', headers = MAP { 'Authorization': 'Bearer ' || get_user_external_token() });
-- Search Google Drive filesSELECT *FROM read_json_auto( 'https://www.googleapis.com/drive/v3/files?q=name+contains+''report''', headers = MAP { 'Authorization': 'Bearer ' || get_user_external_token() });Keycloak Authentication
Section titled “Keycloak Authentication”For self-hosted identity management.
1. Create Client
Section titled “1. Create Client”- Go to your Keycloak Admin Console
- Select your realm
- Go to Clients → Create
- Configure:
- Client ID: mxcp-server
- Client Protocol: openid-connect
- Access Type: confidential
- Valid Redirect URIs:
http://localhost:8000/callback
- Go to Credentials tab for Client Secret
2. Configure MXCP
Section titled “2. Configure MXCP”# In ~/.mxcp/config.ymlauth: provider: keycloak keycloak: client_id: "${KEYCLOAK_CLIENT_ID}" client_secret: "${KEYCLOAK_CLIENT_SECRET}" realm: myrealm server_url: https://keycloak.example.com callback_path: /callback scope: "openid profile email"Note: MXCP auto-constructs the OAuth URLs from server_url and realm:
- Authorization:
{server_url}/realms/{realm}/protocol/openid-connect/auth - Token:
{server_url}/realms/{realm}/protocol/openid-connect/token
3. Available Scopes
Section titled “3. Available Scopes”| Scope | Access |
|---|---|
openid | OpenID Connect authentication |
profile | User profile information |
email | User email address |
roles | User roles from Keycloak |
offline_access | Enable refresh tokens |
Token Persistence
Section titled “Token Persistence”MXCP stores OAuth tokens for session continuity:
auth: provider: github persistence: type: sqlite path: ~/.mxcp/oauth.dbTokens are:
- Stored securely in SQLite
- Refreshed automatically when expired
- Cleared on logout
User Context
Section titled “User Context”After authentication, user information is available in policies:
policies: input: - condition: "!user.email.endsWith('@yourcompany.com')" action: deny reason: "Only company emails allowed"
- condition: "user.role != 'admin'" action: deny reason: "Admin role required"Available User Fields
Section titled “Available User Fields”| Field | Source | Description |
|---|---|---|
user.id | OAuth provider | Unique user identifier |
user.email | OAuth provider | User’s email address |
user.name | OAuth provider | Display name |
user.role | --user-context or custom mapping | User role for access control |
user.permissions | --user-context or custom mapping | List of permissions |
user.groups | OAuth provider (if supported) | Group memberships |
Note: Fields like role and permissions are not provided by most OAuth providers. Use --user-context for testing or implement custom role mapping in your application.
Stateless Mode
Section titled “Stateless Mode”For serverless deployments without session state:
transport: http: stateless: true # No session storageIn stateless mode:
- Each request must include auth token
- No session cookies
- Tokens validated on every request
Reverse Proxy Configuration
Section titled “Reverse Proxy Configuration”When running behind a reverse proxy, configure MXCP to trust forwarded headers.
Transport Configuration
Section titled “Transport Configuration”Configure trust_proxy in your transport settings:
transport: http: host: 0.0.0.0 port: 8000 trust_proxy: true # Trust X-Forwarded-Proto headersWhen trust_proxy: true:
- OAuth callback URLs use the scheme from
X-Forwarded-Proto - Redirect URIs are constructed correctly for HTTPS
- Required when running behind load balancers or reverse proxies
Basic configuration:
location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;}Complete SSL configuration:
server { listen 80; server_name api.example.com; return 301 https://$server_name$request_uri;}
server { listen 443 ssl http2; server_name api.example.com;
ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private.key;
# Security headers add_header Strict-Transport-Security "max-age=31536000" always;
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }}Traefik
Section titled “Traefik”http: routers: mxcp: rule: "Host(`mxcp.example.com`)" service: mxcp tls: certResolver: letsencrypt services: mxcp: loadBalancer: servers: - url: "http://localhost:8000"Testing Authentication
Section titled “Testing Authentication”Without Authentication
Section titled “Without Authentication”Test endpoints without auth:
mxcp run tool my_tool --param key=valueWith User Context
Section titled “With User Context”Test with simulated user:
mxcp run tool my_tool \ --param key=value \ --user-context '{"role": "admin", "email": "admin@example.com"}'HTTP Testing
Section titled “HTTP Testing”Start authenticated server:
mxcp serve --transport streamable-http --port 8000Visit http://localhost:8000 to trigger OAuth flow.
Troubleshooting
Section titled “Troubleshooting””Invalid redirect_uri”
Section titled “”Invalid redirect_uri””- Ensure callback URL matches exactly in provider settings
- Check for trailing slashes
”Token expired”
Section titled “”Token expired””- Enable token persistence for auto-refresh
- Check token expiration settings
”User not authorized”
Section titled “”User not authorized””- Verify scopes include required permissions
- Check policy conditions
”Connection refused to provider”
Section titled “”Connection refused to provider””- Verify auth_url and token_url are correct
- Check network connectivity
Security Best Practices
Section titled “Security Best Practices”1. Use HTTPS in Production
Section titled “1. Use HTTPS in Production”transport: http: host: 0.0.0.0 port: 4432. Secure Client Secrets
Section titled “2. Secure Client Secrets”client_secret: "vault://secret/oauth#github_secret"3. Limit Scopes
Section titled “3. Limit Scopes”Request only necessary scopes.
4. Rotate Secrets
Section titled “4. Rotate Secrets”Regularly rotate OAuth client secrets.
5. Monitor Auth Logs
Section titled “5. Monitor Auth Logs”mxcp log --since 24h | grep -i authAdvanced Features
Section titled “Advanced Features”Dynamic Client Registration (RFC 7591)
Section titled “Dynamic Client Registration (RFC 7591)”MXCP implements RFC 7591 Dynamic Client Registration. Clients can register themselves at runtime:
curl -X POST http://localhost:8000/register \ -H "Content-Type: application/json" \ -d '{ "client_name": "My Application", "redirect_uris": ["https://myapp.example.com/oauth/callback"], "grant_types": ["authorization_code"], "scope": "mxcp:access" }'Response:
{ "client_id": "generated-client-id", "client_secret": "generated-client-secret", "client_id_issued_at": 1640995200, "client_secret_expires_at": 0, "redirect_uris": ["https://myapp.example.com/oauth/callback"], "grant_types": ["authorization_code"], "scope": "mxcp:access"}Authorization Configuration
Section titled “Authorization Configuration”Configure scope-based authorization to control endpoint access:
auth: provider: github authorization: required_scopes: - "mxcp:access" - "mxcp:admin"Configuration Options:
required_scopes: []- Authentication only (no scope requirements)required_scopes: ["mxcp:access"]- Require basic access- Multiple scopes - User must have ALL listed scopes
User Token Access in SQL
Section titled “User Token Access in SQL”When authentication is enabled, SQL queries can access user information:
-- Get the user's OAuth provider tokenSELECT get_user_external_token() as token;
-- Get user informationSELECT get_username() as username;SELECT get_user_provider() as provider;SELECT get_user_email() as email;
-- Access request headersSELECT get_request_header('X-Custom-Header') as custom_header;SELECT get_request_headers_json() as all_headers;Use Cases:
Making authenticated API calls from SQL:
SELECT *FROM read_json_auto( 'https://api.github.com/user/repos', headers = MAP { 'Authorization': 'Bearer ' || get_user_external_token(), 'User-Agent': 'MXCP' });User-specific data filtering:
SELECT *FROM user_documentsWHERE created_by = get_username();Function Behavior:
- When authentication is disabled: Functions return NULL
- When user is not authenticated: Functions return NULL
- When user is authenticated: Functions return actual user data
Note: These functions only work when running through mxcp serve. Direct CLI execution via mxcp run does not have access to these functions.
Pre-Configured OAuth Clients
Section titled “Pre-Configured OAuth Clients”Define static clients in configuration:
auth: provider: github clients: - client_id: "my-app-client" client_secret: "${CLIENT_SECRET}" name: "My Application" redirect_uris: - "https://myapp.example.com/callback" scopes: - "mxcp:access"Client Configuration Options:
client_id(required): Unique identifiername(required): Human-readable nameclient_secret(optional): Secret for confidential clientsredirect_uris(optional): Allowed redirect URIsgrant_types(optional): Allowed grant types (default:["authorization_code"])scopes(optional): Allowed scopes (default:["mxcp:access"])
Production Checklist
Section titled “Production Checklist”- Enable OAuth persistence for session continuity
- Set file permissions (600) on OAuth database
- Use environment variables for secrets
- Configure HTTPS for all redirect URIs
- Limit OAuth scopes to minimum required
- Remove development clients from production config
- Enable audit logging for authentication events
- Set up monitoring for auth-related errors
Next Steps
Section titled “Next Steps”- Policies - Configure access control
- Auditing - Track authentication events
- Configuration - More configuration options