Tencent/WeKnora · error
principal context is required to connect to an OAuth MCP ser
Error message
principal context is required to connect to an OAuth MCP service
What it means
OAuth token storage is keyed by a principal (user identity). buildOAuthConfig requires a valid Principal after normalization, optionally falling back to config.UserID as a web-user principal. If neither yields a valid principal, the client cannot know whose OAuth token to load/refresh, so it fails before connecting.
Source
Thrown at internal/mcp/client.go:266
// buildOAuthConfig returns the OAuth configuration for an OAuth-enabled MCP
// service, or (_, false, nil) when the service does not use OAuth. It loads
// the dynamically-registered client_id and wires a per-user token store so
// the transport injects the invoking user's bearer token and refreshes it.
func buildOAuthConfig(config *ClientConfig, httpClient *http.Client) (transport.OAuthConfig, bool, error) {
svc := config.Service
if !svc.AuthConfig.IsOAuth() {
return transport.OAuthConfig{}, false, nil
}
if config.OAuthRepo == nil {
return transport.OAuthConfig{}, false, fmt.Errorf("OAuth repository is required for OAuth MCP services")
}
principal := config.Principal.Normalize()
if !principal.Valid() && config.UserID != "" {
principal = types.Principal{Type: types.PrincipalWebUser, ID: config.UserID}.Normalize()
}
if !principal.Valid() {
return transport.OAuthConfig{}, false, fmt.Errorf("principal context is required to connect to an OAuth MCP service")
}
config.Principal = principal
oauthCfg := transport.OAuthConfig{
Scopes: svc.AuthConfig.Scopes,
TokenStore: newManagedTokenStore(config.OAuthRepo, config.TenantID, principal, svc.ID),
PKCEEnabled: true,
AuthServerMetadataURL: svc.AuthConfig.AuthServerMetadataURL,
HTTPClient: httpClient,
}
if regClient, err := config.OAuthRepo.GetClient(context.Background(), config.TenantID, svc.ID); err == nil && regClient != nil {
oauthCfg.ClientID = regClient.ClientID
oauthCfg.ClientSecret = regClient.ClientSecret
oauthCfg.RedirectURI = regClient.RedirectURI
}
return oauthCfg, true, nil
}
View on GitHub (pinned to 988cbb0330)
Solutions
- Set config.Principal to the authenticated user's principal (type + ID) before creating the client
- Or set config.UserID; it is converted to a PrincipalWebUser principal automatically
- For non-interactive jobs, use a dedicated service-account principal or switch the service to a non-OAuth auth strategy
- Propagate the user ID from the request context through to the MCP client config
Example fix
// before
cfg := &ClientConfig{Service: svc, OAuthRepo: repo, TenantID: tid} // no principal/user
// after
cfg := &ClientConfig{Service: svc, OAuthRepo: repo, TenantID: tid,
Principal: types.Principal{Type: types.PrincipalWebUser, ID: userID}.Normalize()} Defensive patterns
Strategy: validation
Validate before calling
func requirePrincipal(cfg *ClientConfig) error {
if cfg.Service == nil || !cfg.Service.AuthConfig.IsOAuth() { return nil }
p := cfg.Principal.Normalize()
if !p.Valid() && cfg.UserID != "" {
p = types.Principal{Type: types.PrincipalWebUser, ID: cfg.UserID}.Normalize()
}
if !p.Valid() { return errors.New("valid principal or UserID required for OAuth MCP service") }
return nil
} Type guard
func hasPrincipalContext(cfg *ClientConfig) bool {
return cfg.Principal.Normalize().Valid() || cfg.UserID != ""
} Try / catch
_, err := NewMCPClient(cfg)
if err != nil && strings.Contains(err.Error(), "principal context is required") {
return fmt.Errorf("no user context available for OAuth service %s; cannot authorize", cfg.Service.ID)
} Prevention
- Always thread the authenticated user (principal or UserID) from the HTTP request into MCP client configs
- For background jobs, configure a service-account principal or non-OAuth auth
- Add a middleware that rejects MCP calls lacking user context for OAuth services
When it happens
Trigger: NewMCPClient for an OAuth service where config.Principal is zero/invalid AND config.UserID is empty, or config.UserID is set but still produces an invalid normalized principal (e.g. empty ID).
Common situations: Background/system jobs calling the MCP client without a user context; request context lost between service layers so UserID was never propagated; machine-to-machine calls to a per-user OAuth service that has no service-account principal.
Related errors
- OAuth repository is required for OAuth MCP services
- URL is required for HTTP Streamable transport
- stdio transport is disabled for security reasons; please use
- principal context is required to connect to OAuth MCP servic
- custom agent configuration is required for agent QA
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/2fddea188e8798b8.
Report an issue: GitHub.