Tencent/WeKnora · error

principal context is required to connect to OAuth MCP…

Error message

principal context is required to connect to OAuth MCP service %s

What it means

For OAuth-enabled MCP services, GetOrCreateClient requires a valid principal in the request context (from types.PrincipalFromContext / MCPOAuthPrincipalFromContext) so each identity can use its own token. If the principal is missing or invalid (Principal.Valid() == false), it returns "principal context is required to connect to OAuth MCP service %s".

Solutions

  1. Ensure the request context passes through the auth middleware that injects the principal before MCP calls
  2. Use types.WithPrincipal (or the equivalent context helper) to attach a valid types.Principal to the context
  3. If no user context exists (system job), connect as a designated service principal instead

Example fix

// before
client, err := manager.GetOrCreateClient(context.Background(), oauthSvc)
// after
ctx := types.WithPrincipal(context.Background(), principal) // principal from auth/session
client, err := manager.GetOrCreateClient(ctx, oauthSvc)
Defensive patterns

Strategy: validation

Validate before calling

principal, _ := types.PrincipalFromContext(ctx)
if !principal.Valid() {
    return errors.New("request context lacks a valid principal; required for OAuth MCP services")
}

Type guard

func hasPrincipal(ctx context.Context) bool {
    p, _ := types.PrincipalFromContext(ctx)
    return p.Valid()
}

Try / catch

client, err := manager.GetOrCreateClient(ctx, svc)
if err != nil && strings.Contains(err.Error(), "principal context is required") {
    return fmt.Errorf("attach authenticated principal to ctx before using OAuth service %q", svc.Name)
}

Prevention

When it happens

Trigger: Calling GetOrCreateClient (or GetMCPServiceTools/Resources) with a context lacking the principal when service.AuthConfig.IsOAuth() is true — e.g. background jobs, webhook handlers, or code paths that build a bare context.Background() without auth middleware.

Common situations: Calling MCP tools from a cron/worker goroutine where auth middleware never ran; forgetting to inject the principal after extracting a tenant ID; a test constructing ctx without the principal helper.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/cfaf527efb468da3. Report an issue: GitHub.

Appendix: source

Thrown at internal/mcp/manager.go:76

func (m *MCPManager) GetOrCreateClient(ctx context.Context, service *types.MCPService) (MCPClient, error) {
	// Check if service is enabled
	if !service.Enabled {
		return nil, fmt.Errorf("MCP service %s is not enabled", service.Name)
	}

	// Stdio transport is disabled for security reasons
	if service.TransportType == types.MCPTransportStdio {
		return nil, fmt.Errorf("stdio transport is disabled for security reasons; please use SSE or HTTP Streamable transport instead")
	}

	var tenantID uint64
	var principal types.Principal
	if service.AuthConfig.IsOAuth() {
		tenantID, _ = types.TenantIDFromContext(ctx)
		principal, _ = types.PrincipalFromContext(ctx)
		principal = types.MCPOAuthPrincipalFromContext(ctx)
		if !principal.Valid() {
			return nil, fmt.Errorf("principal context is required to connect to OAuth MCP service %s", service.Name)
		}
	}
	key := cacheKey(service, principal)

	// For SSE/HTTP Streamable, check if client already exists and reuse
	m.clientsMu.RLock()
	client, exists := m.clients[key]
	m.clientsMu.RUnlock()

	if exists && client.IsConnected() {
		return client, nil
	}

	// Create new client
	m.clientsMu.Lock()
	defer m.clientsMu.Unlock()

	// Double check after acquiring write lock

View on GitHub (pinned to 988cbb0330)