OAuth System Clarification: This document covers MCP Client → Satellite authentication (how VS Code/Cursor/Claude.ai authenticate to DeployStack).For User → MCP Server authentication (how users connect to Notion/Box/Linear), see:
- Backend Implementation: MCP Server OAuth
- Satellite Integration: OAuth Token Injection
Technical Overview
OAuth 2.1 Resource Server Architecture
The satellite operates as a multi-team OAuth 2.1 Resource Server that validates Bearer tokens via Backend introspection. The backend now uses database-backed storage for dynamic client registration, enabling persistent MCP client authentication:Core Components
Token Introspection Service:- Validates Bearer tokens via Backend introspection endpoint
- Implements 5-minute token caching for performance
- Supports multi-team authentication (any valid team)
- Extracts team context from token validation response
- Handles both static and dynamic client tokens
requireAuthentication()- Validates Bearer tokens for any teamrequireScope()- Enforces OAuth scope requirements- Proper WWW-Authenticate headers with OAuth 2.1 compliance
- JSON-RPC 2.0 compliant error responses
- Dynamic client registration guidance in error responses
- Filters tools based on team’s MCP server installations
- Team-aware
tools/list- only shows tools from team’s allowed servers - Team-aware
tools/call- validates team access before execution - Integrates with existing tool discovery and configuration systems
- Exposes
/.well-known/oauth-protected-resourceendpoint for MCP client discovery - Returns resource identifier:
${DEPLOYSTACK_SATELLITE_URL}/mcp(fixes Gemini CLI audience mismatch) - Advertises supported scopes:
["mcp:read", "mcp:tools:execute"] - Specifies bearer token methods:
["header"] - Provides documentation link for MCP clients
- Enables zero-configuration OAuth for compliant MCP clients
- Validates token
aud(audience) claim matches satellite URL - Prevents token reuse across different satellites
- Audience format:
https://satellite.deploystack.io/mcp - Backend generates
audclaim fromresourceparameter - Satellite validates via token introspection response
- Supports RFC 7591 dynamically registered clients
- Handles VS Code MCP extension client caching
- Supports Cursor, Claude.ai, and other MCP clients
- Persistent client storage survives backend restarts
Implementation Files
Core OAuth Services
Token Introspection Service:- File:
services/satellite/src/services/token-introspection-service.ts - Purpose: Backend token validation with 5-minute caching
- Dependencies: BackendClient for introspection calls
- File:
services/satellite/src/middleware/auth-middleware.ts - Purpose: Bearer token validation and scope enforcement
- Integration: Fastify preValidation hooks
- RFC 9728 Enhancements:
- WWW-Authenticate headers use
resource_metadatainstead of direct URIs - Includes OAuth error codes (
invalid_token,insufficient_scope) - Adds Link header for proactive discovery:
Link: </.well-known/oauth-protected-resource>; rel="oauth-protected-resource" - Error responses include
resource_metadata_urifor discovery starting point
- WWW-Authenticate headers use
- File:
services/satellite/src/services/team-aware-mcp-handler.ts - Purpose: Team-filtered tool discovery and execution
- Dependencies: DynamicConfigManager, RemoteToolDiscoveryManager
- File:
services/satellite/src/routes/oauth-discovery.ts - Purpose: RFC 9728 Protected Resource Metadata and RFC 8414 Authorization Server Metadata
- Endpoints:
GET /.well-known/oauth-protected-resource- Resource metadata with scopes and capabilitiesGET /.well-known/oauth-authorization-server- Proxy to backend authorization server metadataGET /.well-known/openid-configuration- VS Code compatibility endpoint
- Resource URL Format:
${DEPLOYSTACK_SATELLITE_URL}/mcp(fixes Gemini CLI audience mismatch) - Environment Variables:
DEPLOYSTACK_SATELLITE_URL- Base satellite URL (e.g.,https://satellite.deploystack.io)DEPLOYSTACK_RESOURCE_DOCUMENTATION- Documentation URL (defaults tohttps://docs.deploystack.io/)
Route Integration
Updated MCP Routes:- Files:
services/satellite/src/routes/mcp.ts,services/satellite/src/routes/sse.ts - Authentication: Bearer token required for all MCP endpoints
- Scopes:
mcp:readfor discovery,mcp:tools:executefor execution - CORS: OPTIONS endpoints remain unauthenticated
- File:
services/satellite/src/server.ts - Integration: OAuth services initialized after satellite registration
- Swagger: Updated with Bearer authentication security scheme
OAuth Scopes and Permissions
Supported OAuth Scopes
mcp:read:- Required for tool discovery (
tools/list) - Required for SSE connection establishment
- Required for MCP transport initialization
- Required for tool execution (
tools/call) - Required for MCP JSON-RPC message sending
- Includes read permissions implicitly
- Required for refresh token issuance
- Enables long-lived sessions for MCP clients
Default Scopes: The
scope parameter is optional in authorization requests. When not provided, the Backend defaults to mcp:read mcp:tools:execute offline_access. This allows MCP clients that don’t send scope (like Claude Code) to authenticate without errors.Team-Based Access Control
Team Resolution:- Team context extracted from validated OAuth token
- No hardcoded team configuration in satellite
- Dynamic team filtering based on token validation response
- Supports multiple teams per user
- Tools filtered based on team’s MCP server installations
- Team-MCP server mappings from Backend database (
mcpServerInstallationstable) - Access control enforced before tool execution
- Complete team isolation maintained
MCP Client Integration
Dynamic Client Registration Support
The satellite now supports MCP clients that use RFC 7591 Dynamic Client Registration: VS Code MCP Extension:- Automatic client registration via Backend
/api/oauth2/register - Client ID caching for improved user experience
- Persistent storage survives VS Code restarts
- Long-lived tokens (1-week access, 30-day refresh)
- Dynamic registration with
cursor://redirect URIs - Team-scoped tool access
- Automatic token refresh handling
- Registration with
https://claude.ai/mcp/auth/callback - OAuth 2.1 compliant authentication flow
- Team-aware tool discovery
- VS Code extension integration
- Shared client registration with VS Code patterns
- Consistent authentication experience
Client Authentication Flow
First-Time Authentication:- MCP client attempts to connect to satellite
- Satellite returns 401 with registration guidance
- Client registers via Backend
/api/oauth2/register - Client receives unique client_id (e.g.,
dyn_1757880447836_uvze3d0yc) - Client initiates OAuth flow with Backend
- User authorizes in browser with team selection
- Client receives Bearer token
- Client connects to satellite with token
- Satellite validates token and establishes SSE connection
- MCP client uses cached client_id
- Client uses stored refresh token if access token expired
- Client connects directly to satellite with valid token
- Satellite validates token via introspection (with caching)
- SSE connection established immediately
Development Setup
Environment Configuration
Required Environment Variables:DEPLOYSTACK_TEAM_ID- Team context comes from OAuth tokensDEPLOYSTACK_TEAM_NAME- Team context comes from OAuth tokens
Local Development Setup
Clone and Setup:Token Validation Implementation
Token Introspection Flow
Cache-First Validation:Backend Introspection Integration
Introspection Request:active: true- Token is valid, extract team contextactive: false- Token invalid, return authentication error- Team context includes: team_id, team_name, team_role, team_permissions
Session Management and Security Model
MCP Sessions vs OAuth Authentication
The satellite implements a two-layer security model that separates authentication from session management: Authentication Layer (OAuth Bearer Token):- Primary security mechanism for all requests
- Validates user identity, team membership, and permissions
- Enforced by authentication middleware before session handling
- Team isolation enforced at this layer via token introspection
- Transport-level identifier for HTTP/SSE connection routing
- NOT a security credential - purely for protocol state management
- Can be safely reused because security comes from Bearer token
- Managed by StreamableHTTPServerTransport from MCP SDK
Session Resurrection After Satellite Restart
When a satellite restarts (deployments, updates, crashes), MCP sessions are lost because they live in memory. The satellite implements transparent session resurrection to avoid forcing users to manually reconnect: How Session Resurrection Works:- Client sends request with old session ID (from before restart)
- Satellite validates Bearer token FIRST (authentication layer)
- If session ID is stale, satellite creates new Server + Transport with same session ID
- Bootstrap transport with synthetic
initializerequest - Process actual client request normally
- Client continues without reconnection
Team-Aware Tool Discovery
Tool Filtering Implementation
Team Server Access:Tool Execution Validation
Access Control Check:Authentication Middleware Integration
Fastify Route Protection
MCP Route Authentication:Authentication Context
Request Context Extension:Error Handling Implementation
Authentication Errors
401 Unauthorized Response:Scope Validation Errors
403 Insufficient Scope Response:Performance Characteristics
Token Validation Caching
Cache Configuration:- Cache TTL: 5 minutes
- Cache key: Hashed token (security)
- Memory usage: ~1KB per cached token
- Cleanup: Automatic expired token removal every 5 minutes
Multi-Team Scalability
Team Limits:- No hard limit on concurrent teams (memory-bound)
- Supports 100+ teams simultaneously
- Tool filtering: O(n) where n = team’s MCP servers
- Memory efficiency: Shared tool cache across all teams
- Connection pooling to Backend for introspection
- Async token validation pipeline
- Efficient team-server mapping lookups
Integration with Backend Systems
Backend Communication
Introspection Endpoint:- URL:
${DEPLOYSTACK_BACKEND_URL}/api/oauth2/introspect - Authentication: Satellite API key (Bearer token)
- Timeout: 10 seconds
- Retry: Handled by existing backend client
- Source: Backend database
mcpServerInstallationstable - Delivery: Via existing backend polling system
- Update: Dynamic configuration sync
- Storage: In-memory via DynamicConfigManager
Configuration Integration
Dynamic Configuration:Development Patterns
Service Initialization
Server Startup Integration:Logging Patterns
Authentication Events:Error Handling Patterns
Service Error Handling:Testing and Validation
Local Testing Setup
Backend OAuth Token Generation:Authentication Testing
Test Unauthenticated Access:Multi-Team Validation
Test Different Team Tokens:Security Implementation
Token Security
Token Handling:- Never log actual token values
- Use hashed tokens for cache keys
- Clear tokens from memory after use
- 10-second timeout for introspection requests
Team Isolation
Complete Separation:- Teams only see tools from their MCP server installations
- Access control enforced before tool execution
- Audit logging with team context
- No cross-team access possible
MCP Client Configuration
Claude.ai Custom Connector
Configuration Example:VS Code MCP Extension
Configuration Example:Troubleshooting
Common Issues
“Token introspection failed: HTTP 401”:- Check satellite API key is set correctly
- Verify backend is running and accessible
- Ensure satellite is registered with backend
- Check token format and expiry
- Verify token was issued by correct backend
- Ensure team exists in backend database
- Verify team has MCP server installations in backend
- Check team-MCP server mappings in database
- Ensure user is member of the team
- Check token hashing function
- Verify cache TTL settings (5 minutes)
- Monitor cache cleanup logs
Debug Logging
Enable Debug Logging:token_validation_cache_hit- Cache performanceauthentication_success- Successful token validationteam_tool_access_granted- Team access validationtoken_cache_cleanup- Cache maintenance
Integration Status
Current Implementation
Completed Features:- Multi-team token introspection with 5-minute caching
- Team-aware tool discovery and filtering
- OAuth 2.1 Resource Server with scope validation
- Authentication middleware with proper error handling
- Integration with existing backend polling system
- Swagger documentation with Bearer authentication
- RFC 7591 Dynamic Client Registration support
- Database-backed persistent client storage
- VS Code MCP extension authentication (tested and working)
- Support for Cursor, Claude.ai, and Cline MCP clients
- Uses existing satellite registration system
- Leverages existing backend polling for team-MCP server mappings
- Integrates with existing tool discovery and configuration systems
- Maintains all existing MCP transport functionality
- Database-backed client storage survives backend restarts
- Supports both static and dynamic OAuth clients
- VS Code MCP Extension: Full OAuth flow tested and working
- Dynamic client registration: RFC 7591 compliant implementation
- Client ID caching: Persistent across client restarts
- Token refresh: Long-lived access for MCP clients
- Team isolation: Complete separation of team resources
Implementation Status: OAuth authentication is fully implemented and operational with database-backed dynamic client registration. The system successfully authenticates MCP clients (including VS Code, Cursor, Claude.ai, and Cline) with team-aware access control, filters tools based on team permissions, and maintains complete team isolation while preserving all existing satellite functionality. Dynamic client registration enables seamless MCP client integration with persistent authentication.
Related Documentation
- OAuth2 Server - Backend OAuth server implementation
- MCP Server Token Injection - External MCP server OAuth
- MCP Server OAuth - Backend OAuth for MCP servers
- OAuth Providers - Social login

