UNPKG

@coretext-ai/public-looker-mcp-b5c6d7e8-f9a0-4123-a456-567890123456

Version:

MCP server with full looker capabilities (35 endpoints)

3,707 lines 178 kB
import axios from 'axios';
import { Logger } from '../services/logger.js';
export class LookerClient {
    constructor(config) {
        this.config = config;
        // Generate unique session ID for this client instance
        this.sessionId = `looker-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
        // Initialize logger (fallback to console if not provided)
        this.logger = config.logger || new Logger({
            logLevel: 'ERROR',
            component: 'client',
            enableConsole: true,
            enableShipping: false,
            serverName: 'public-looker-mcp'
        });
        this.logger.info('CLIENT_INIT', 'Client instance created', {
            baseUrl: this.resolveBaseUrl(),
            timeout: this.config.timeout || 30000,
            hasRateLimit: !!this.config.rateLimit,
            configKeys: Object.keys(config)
        });
        this.httpClient = axios.create({
            baseURL: this.resolveBaseUrl(),
            timeout: this.config.timeout || 30000,
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'User-Agent': 'public-looker-mcp/1.0.0',
                ...this.getAuthHeaders()
            },
        });
        // Add request interceptor for rate limiting
        if (this.config.rateLimit) {
            this.setupRateLimit(this.config.rateLimit);
        }
        // Add request interceptor for logging
        this.httpClient.interceptors.request.use((config) => {
            this.logger.logRequestStart(config.method?.toUpperCase() || 'GET', `${config.baseURL}${config.url}`, {
                hasData: !!config.data,
                hasParams: !!(config.params && Object.keys(config.params).length > 0),
                headers: Object.keys(config.headers || {})
            });
            if (config.data) {
                this.logger.debug('HTTP_REQUEST_BODY', 'Request body data', {
                    dataType: typeof config.data,
                    dataSize: JSON.stringify(config.data).length
                });
            }
            if (config.params && Object.keys(config.params).length > 0) {
                this.logger.debug('HTTP_REQUEST_PARAMS', 'Query parameters', {
                    paramCount: Object.keys(config.params).length,
                    paramKeys: Object.keys(config.params)
                });
            }
            return config;
        }, (error) => {
            this.logger.error('HTTP_REQUEST_ERROR', 'Request interceptor error', {
                error: error.message,
                code: error.code
            });
            return Promise.reject(error);
        });
        // Add response interceptor for logging and error handling
        this.httpClient.interceptors.response.use((response) => {
            this.logger.logRequestSuccess(response.config?.method?.toUpperCase() || 'GET', `${response.config?.baseURL}${response.config?.url}`, response.status, 0, // Duration will be calculated in endpoint methods
            {
                statusText: response.statusText,
                responseSize: JSON.stringify(response.data).length,
                headers: Object.keys(response.headers || {})
            });
            return response;
        }, (error) => {
            this.logger.logRequestError(error.config?.method?.toUpperCase() || 'GET', `${error.config?.baseURL}${error.config?.url}`, error, 0, // Duration will be calculated in endpoint methods
            {
                hasResponseData: !!error.response?.data
            });
            throw error;
        });
    }
    setupRateLimit(requestsPerMinute) {
        const interval = 60000 / requestsPerMinute; // ms between requests
        let lastRequestTime = 0;
        this.logger.info('RATE_LIMIT_SETUP', 'Rate limiting configured', {
            requestsPerMinute,
            intervalMs: interval
        });
        this.httpClient.interceptors.request.use(async (config) => {
            const now = Date.now();
            const timeSinceLastRequest = now - lastRequestTime;
            if (timeSinceLastRequest < interval) {
                const delayMs = interval - timeSinceLastRequest;
                this.logger.logRateLimit('HTTP_REQUEST', delayMs, {
                    timeSinceLastRequest,
                    requiredInterval: interval
                });
                await new Promise(resolve => setTimeout(resolve, delayMs));
            }
            lastRequestTime = Date.now();
            return config;
        });
    }
    resolveBaseUrl() {
        let baseUrl = 'https://{instance_name}.looker.com';
        // Handle dynamic domain replacement (e.g., YOUR_DOMAIN placeholder)
        if (baseUrl.includes('YOUR_DOMAIN')) {
            const domainEnvVar = `LOOKER_DOMAIN`;
            const domain = process.env[domainEnvVar];
            if (!domain) {
                throw new Error(`Missing domain configuration. Please set ${domainEnvVar} environment variable.`);
            }
            baseUrl = baseUrl.replace('YOUR_DOMAIN', domain);
            console.error(`[LOOKER] Resolved base URL: ${baseUrl}`);
        }
        return baseUrl;
    }
    getAuthHeaders() {
        // Bearer/API key authentication (static tokens)
        const token = this.config.authToken || this.config['lOOKERCLIENTCREDENTIALS'] || process.env.LOOKER_CLIENT_CREDENTIALS;
        if (token) {
            this.logger.logAuthEvent('static_token_auth_setup', true, {
                authType: 'client_credentials',
                tokenPreview: token.substring(0, 8) + '...',
                header: 'Authorization',
                source: 'static_configuration'
            });
            return {
                'Authorization': `Bearer ${token}`
            };
        }
        this.logger.warn('AUTH_WARNING', 'No authentication token found', {
            authType: 'client_credentials',
            warning: 'API calls may be rate limited',
            checkedSources: ['config.authToken', 'environment variables']
        });
        return {};
    }
    /**
     * Initialize the client (for OAuth clients that need initialization)
     */
    async initialize() {
        this.logger.debug('CLIENT_INITIALIZE', 'No initialization required for this auth type');
    }
    /**
     * Get the session ID for this client instance
     */
    getSessionId() {
        return this.sessionId;
    }
    /**
     * Make an authenticated request with proper headers
     */
    async makeAuthenticatedRequest(config) {
        // For non-OAuth requests, log what auth headers are being used
        this.logger.info('REQUEST_AUTH', 'Using pre-configured authentication headers', {
            authType: 'static',
            requestUrl: config.url,
            authHeaders: config.headers?.Authorization ? 'present' : 'missing',
            headerKeys: Object.keys(config.headers || {})
        });
        return this.httpClient.request(config);
    }
    buildPath(template, params) {
        let path = template;
        // Custom encoding that preserves forward slashes for API paths
        const encodePathComponent = (value) => {
            // For Google API resource names like "people/c123", preserve the forward slash
            return encodeURIComponent(value).replace(/%2F/g, '/');
        };
        // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
        const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
        let match;
        const processedParams = [];
        while ((match = googlePathTemplateRegex.exec(template)) !== null) {
            const fullMatch = match[0]; // e.g., "{resourceName=people/*}"
            const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
            if (paramName && params[paramName] !== undefined) {
                path = path.replace(fullMatch, encodePathComponent(String(params[paramName])));
                processedParams.push(paramName);
            }
        }
        // Handle standard path templates: {resourceName}
        for (const [key, value] of Object.entries(params)) {
            if (!processedParams.includes(key)) {
                const standardTemplate = `{${key}}`;
                if (path.includes(standardTemplate)) {
                    path = path.replace(standardTemplate, encodePathComponent(String(value)));
                    processedParams.push(key);
                }
            }
        }
        this.logger.debug('PATH_BUILD', 'Built API path from template', {
            template,
            resultPath: path,
            paramCount: Object.keys(params).length,
            paramKeys: Object.keys(params),
            processedParams,
            hasGoogleTemplates: googlePathTemplateRegex.test(template)
        });
        return path;
    }
    async login(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'login',
            method: 'POST',
            path: '/api/4.0/login',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/login';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["client_id"] !== undefined) {
                bodyParams["client_id"] = params["client_id"];
                extractedParams.push("client_id");
            }
            if (params["client_secret"] !== undefined) {
                bodyParams["client_secret"] = params["client_secret"];
                extractedParams.push("client_secret");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.client_id) {
                throw new Error(`Missing required parameter: client_id`);
            }
            if (!params.client_secret) {
                throw new Error(`Missing required parameter: client_secret`);
            }
            const path = this.buildPath('/api/4.0/login', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'login',
                method: 'POST',
                path: '/api/4.0/login',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'login',
                method: 'POST',
                path: '/api/4.0/login',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute login: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async logout(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'logout',
            method: 'DELETE',
            path: '/api/4.0/logout',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/logout';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            const path = this.buildPath('/api/4.0/logout', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.delete(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'logout',
                method: 'DELETE',
                path: '/api/4.0/logout',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'logout',
                method: 'DELETE',
                path: '/api/4.0/logout',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute logout: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async me(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'me',
            method: 'GET',
            path: '/api/4.0/user',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/user';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/user', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'me',
                method: 'GET',
                path: '/api/4.0/user',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'me',
                method: 'GET',
                path: '/api/4.0/user',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute me: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listUsers(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_users',
            method: 'GET',
            path: '/api/4.0/users',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/users';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["sorts"] !== undefined) {
                queryParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/users', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_users',
                method: 'GET',
                path: '/api/4.0/users',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_users',
                method: 'GET',
                path: '/api/4.0/users',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_users: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createUser(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_user',
            method: 'POST',
            path: '/api/4.0/users',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/users';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["first_name"] !== undefined) {
                bodyParams["first_name"] = params["first_name"];
                extractedParams.push("first_name");
            }
            if (params["last_name"] !== undefined) {
                bodyParams["last_name"] = params["last_name"];
                extractedParams.push("last_name");
            }
            if (params["email"] !== undefined) {
                bodyParams["email"] = params["email"];
                extractedParams.push("email");
            }
            if (params["is_disabled"] !== undefined) {
                bodyParams["is_disabled"] = params["is_disabled"];
                extractedParams.push("is_disabled");
            }
            if (params["models_dir_validated"] !== undefined) {
                bodyParams["models_dir_validated"] = params["models_dir_validated"];
                extractedParams.push("models_dir_validated");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.first_name) {
                throw new Error(`Missing required parameter: first_name`);
            }
            if (!params.last_name) {
                throw new Error(`Missing required parameter: last_name`);
            }
            if (!params.email) {
                throw new Error(`Missing required parameter: email`);
            }
            const path = this.buildPath('/api/4.0/users', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_user',
                method: 'POST',
                path: '/api/4.0/users',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_user',
                method: 'POST',
                path: '/api/4.0/users',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_user: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async updateUser(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'update_user',
            method: 'PATCH',
            path: '/api/4.0/users/{user_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/users/{user_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["first_name"] !== undefined) {
                bodyParams["first_name"] = params["first_name"];
                extractedParams.push("first_name");
            }
            if (params["last_name"] !== undefined) {
                bodyParams["last_name"] = params["last_name"];
                extractedParams.push("last_name");
            }
            if (params["email"] !== undefined) {
                bodyParams["email"] = params["email"];
                extractedParams.push("email");
            }
            if (params["is_disabled"] !== undefined) {
                bodyParams["is_disabled"] = params["is_disabled"];
                extractedParams.push("is_disabled");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.user_id) {
                throw new Error(`Missing required parameter: user_id`);
            }
            const path = this.buildPath('/api/4.0/users/{user_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.patch(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'update_user',
                method: 'PATCH',
                path: '/api/4.0/users/{user_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'update_user',
                method: 'PATCH',
                path: '/api/4.0/users/{user_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute update_user: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listDashboards(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_dashboards',
            method: 'GET',
            path: '/api/4.0/dashboards',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["sorts"] !== undefined) {
                queryParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/dashboards', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_dashboards',
                method: 'GET',
                path: '/api/4.0/dashboards',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_dashboards',
                method: 'GET',
                path: '/api/4.0/dashboards',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_dashboards: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getDashboard(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_dashboard',
            method: 'GET',
            path: '/api/4.0/dashboards/{dashboard_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards/{dashboard_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.dashboard_id) {
                throw new Error(`Missing required parameter: dashboard_id`);
            }
            const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_dashboard',
                method: 'GET',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_dashboard',
                method: 'GET',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_dashboard: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createDashboard(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_dashboard',
            method: 'POST',
            path: '/api/4.0/dashboards',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["title"] !== undefined) {
                bodyParams["title"] = params["title"];
                extractedParams.push("title");
            }
            if (params["description"] !== undefined) {
                bodyParams["description"] = params["description"];
                extractedParams.push("description");
            }
            if (params["hidden"] !== undefined) {
                bodyParams["hidden"] = params["hidden"];
                extractedParams.push("hidden");
            }
            if (params["refresh_interval"] !== undefined) {
                bodyParams["refresh_interval"] = params["refresh_interval"];
                extractedParams.push("refresh_interval");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.title) {
                throw new Error(`Missing required parameter: title`);
            }
            const path = this.buildPath('/api/4.0/dashboards', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_dashboard',
                method: 'POST',
                path: '/api/4.0/dashboards',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_dashboard',
                method: 'POST',
                path: '/api/4.0/dashboards',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_dashboard: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async updateDashboard(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'update_dashboard',
            method: 'PATCH',
            path: '/api/4.0/dashboards/{dashboard_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards/{dashboard_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["title"] !== undefined) {
                bodyParams["title"] = params["title"];
                extractedParams.push("title");
            }
            if (params["description"] !== undefined) {
                bodyParams["description"] = params["description"];
                extractedParams.push("description");
            }
            if (params["hidden"] !== undefined) {
                bodyParams["hidden"] = params["hidden"];
                extractedParams.push("hidden");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.dashboard_id) {
                throw new Error(`Missing required parameter: dashboard_id`);
            }
            const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.patch(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'update_dashboard',
                method: 'PATCH',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'update_dashboard',
                method: 'PATCH',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute update_dashboard: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async deleteDashboard(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'delete_dashboard',
            method: 'DELETE',
            path: '/api/4.0/dashboards/{dashboard_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards/{dashboard_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.dashboard_id) {
                throw new Error(`Missing required parameter: dashboard_id`);
            }
            const path = this.buildPath('/api/4.0/dashboards/{dashboard_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.delete(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'delete_dashboard',
                method: 'DELETE',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'delete_dashboard',
                method: 'DELETE',
                path: '/api/4.0/dashboards/{dashboard_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute delete_dashboard: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listLooks(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_looks',
            method: 'GET',
            path: '/api/4.0/looks',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/looks';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["sorts"] !== undefined) {
                queryParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/looks', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_looks',
                method: 'GET',
                path: '/api/4.0/looks',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_looks',
                method: 'GET',
                path: '/api/4.0/looks',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_looks: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getLook(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_look',
            method: 'GET',
            path: '/api/4.0/looks/{look_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/looks/{look_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.look_id) {
                throw new Error(`Missing required parameter: look_id`);
            }
            const path = this.buildPath('/api/4.0/looks/{look_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_look',
                method: 'GET',
                path: '/api/4.0/looks/{look_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_look',
                method: 'GET',
                path: '/api/4.0/looks/{look_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_look: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async runLook(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'run_look',
            method: 'GET',
            path: '/api/4.0/looks/{look_id}/run/{result_format}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/looks/{look_id}/run/{result_format}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["limit"] !== undefined) {
                queryParams["limit"] = params["limit"];
                extractedParams.push("limit");
            }
            if (params["apply_formatting"] !== undefined) {
                queryParams["apply_formatting"] = params["apply_formatting"];
                extractedParams.push("apply_formatting");
            }
            if (params["apply_vis"] !== undefined) {
                queryParams["apply_vis"] = params["apply_vis"];
                extractedParams.push("apply_vis");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.look_id) {
                throw new Error(`Missing required parameter: look_id`);
            }
            if (!params.result_format) {
                throw new Error(`Missing required parameter: result_format`);
            }
            const path = this.buildPath('/api/4.0/looks/{look_id}/run/{result_format}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'run_look',
                method: 'GET',
                path: '/api/4.0/looks/{look_id}/run/{result_format}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'run_look',
                method: 'GET',
                path: '/api/4.0/looks/{look_id}/run/{result_format}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute run_look: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createLook(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_look',
            method: 'POST',
            path: '/api/4.0/looks',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/looks';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["title"] !== undefined) {
                bodyParams["title"] = params["title"];
                extractedParams.push("title");
            }
            if (params["description"] !== undefined) {
                bodyParams["description"] = params["description"];
                extractedParams.push("description");
            }
            if (params["public"] !== undefined) {
                bodyParams["public"] = params["public"];
                extractedParams.push("public");
            }
            if (params["query_id"] !== undefined) {
                bodyParams["query_id"] = params["query_id"];
                extractedParams.push("query_id");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.title) {
                throw new Error(`Missing required parameter: title`);
            }
            if (!params.query_id) {
                throw new Error(`Missing required parameter: query_id`);
            }
            const path = this.buildPath('/api/4.0/looks', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_look',
                method: 'POST',
                path: '/api/4.0/looks',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_look',
                method: 'POST',
                path: '/api/4.0/looks',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_look: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listQueries(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_queries',
            method: 'GET',
            path: '/api/4.0/queries',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/queries';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["sorts"] !== undefined) {
                queryParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/queries', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_queries',
                method: 'GET',
                path: '/api/4.0/queries',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_queries',
                method: 'GET',
                path: '/api/4.0/queries',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_queries: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getQuery(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_query',
            method: 'GET',
            path: '/api/4.0/queries/{query_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/queries/{query_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.query_id) {
                throw new Error(`Missing required parameter: query_id`);
            }
            const path = this.buildPath('/api/4.0/queries/{query_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_query',
                method: 'GET',
                path: '/api/4.0/queries/{query_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_query',
                method: 'GET',
                path: '/api/4.0/queries/{query_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_query: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createQuery(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_query',
            method: 'POST',
            path: '/api/4.0/queries',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/queries';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["model"] !== undefined) {
                bodyParams["model"] = params["model"];
                extractedParams.push("model");
            }
            if (params["explore"] !== undefined) {
                bodyParams["explore"] = params["explore"];
                extractedParams.push("explore");
            }
            if (params["dimensions"] !== undefined) {
                bodyParams["dimensions"] = params["dimensions"];
                extractedParams.push("dimensions");
            }
            if (params["measures"] !== undefined) {
                bodyParams["measures"] = params["measures"];
                extractedParams.push("measures");
            }
            if (params["filters"] !== undefined) {
                bodyParams["filters"] = params["filters"];
                extractedParams.push("filters");
            }
            if (params["sorts"] !== undefined) {
                bodyParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            if (params["limit"] !== undefined) {
                bodyParams["limit"] = params["limit"];
                extractedParams.push("limit");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.model) {
                throw new Error(`Missing required parameter: model`);
            }
            if (!params.explore) {
                throw new Error(`Missing required parameter: explore`);
            }
            const path = this.buildPath('/api/4.0/queries', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_query',
                method: 'POST',
                path: '/api/4.0/queries',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_query',
                method: 'POST',
                path: '/api/4.0/queries',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_query: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async runQuery(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'run_query',
            method: 'GET',
            path: '/api/4.0/queries/{query_id}/run/{result_format}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/queries/{query_id}/run/{result_format}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["limit"] !== undefined) {
                queryParams["limit"] = params["limit"];
                extractedParams.push("limit");
            }
            if (params["apply_formatting"] !== undefined) {
                queryParams["apply_formatting"] = params["apply_formatting"];
                extractedParams.push("apply_formatting");
            }
            if (params["apply_vis"] !== undefined) {
                queryParams["apply_vis"] = params["apply_vis"];
                extractedParams.push("apply_vis");
            }
            if (params["cache"] !== undefined) {
                queryParams["cache"] = params["cache"];
                extractedParams.push("cache");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.query_id) {
                throw new Error(`Missing required parameter: query_id`);
            }
            if (!params.result_format) {
                throw new Error(`Missing required parameter: result_format`);
            }
            const path = this.buildPath('/api/4.0/queries/{query_id}/run/{result_format}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'run_query',
                method: 'GET',
                path: '/api/4.0/queries/{query_id}/run/{result_format}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'run_query',
                method: 'GET',
                path: '/api/4.0/queries/{query_id}/run/{result_format}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute run_query: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async runInlineQuery(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'run_inline_query',
            method: 'POST',
            path: '/api/4.0/queries/run/{result_format}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/queries/run/{result_format}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["model"] !== undefined) {
                bodyParams["model"] = params["model"];
                extractedParams.push("model");
            }
            if (params["explore"] !== undefined) {
                bodyParams["explore"] = params["explore"];
                extractedParams.push("explore");
            }
            if (params["dimensions"] !== undefined) {
                bodyParams["dimensions"] = params["dimensions"];
                extractedParams.push("dimensions");
            }
            if (params["measures"] !== undefined) {
                bodyParams["measures"] = params["measures"];
                extractedParams.push("measures");
            }
            if (params["filters"] !== undefined) {
                bodyParams["filters"] = params["filters"];
                extractedParams.push("filters");
            }
            if (params["sorts"] !== undefined) {
                bodyParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            if (params["limit"] !== undefined) {
                bodyParams["limit"] = params["limit"];
                extractedParams.push("limit");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.result_format) {
                throw new Error(`Missing required parameter: result_format`);
            }
            if (!params.model) {
                throw new Error(`Missing required parameter: model`);
            }
            if (!params.explore) {
                throw new Error(`Missing required parameter: explore`);
            }
            const path = this.buildPath('/api/4.0/queries/run/{result_format}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'run_inline_query',
                method: 'POST',
                path: '/api/4.0/queries/run/{result_format}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'run_inline_query',
                method: 'POST',
                path: '/api/4.0/queries/run/{result_format}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute run_inline_query: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listSpaces(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_spaces',
            method: 'GET',
            path: '/api/4.0/spaces',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/spaces';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["sorts"] !== undefined) {
                queryParams["sorts"] = params["sorts"];
                extractedParams.push("sorts");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/spaces', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_spaces',
                method: 'GET',
                path: '/api/4.0/spaces',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_spaces',
                method: 'GET',
                path: '/api/4.0/spaces',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_spaces: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getSpace(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_space',
            method: 'GET',
            path: '/api/4.0/spaces/{space_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/spaces/{space_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.space_id) {
                throw new Error(`Missing required parameter: space_id`);
            }
            const path = this.buildPath('/api/4.0/spaces/{space_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_space',
                method: 'GET',
                path: '/api/4.0/spaces/{space_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_space',
                method: 'GET',
                path: '/api/4.0/spaces/{space_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_space: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createSpace(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_space',
            method: 'POST',
            path: '/api/4.0/spaces',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/spaces';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["name"] !== undefined) {
                bodyParams["name"] = params["name"];
                extractedParams.push("name");
            }
            if (params["parent_id"] !== undefined) {
                bodyParams["parent_id"] = params["parent_id"];
                extractedParams.push("parent_id");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.name) {
                throw new Error(`Missing required parameter: name`);
            }
            const path = this.buildPath('/api/4.0/spaces', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_space',
                method: 'POST',
                path: '/api/4.0/spaces',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_space',
                method: 'POST',
                path: '/api/4.0/spaces',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_space: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listFolders(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_folders',
            method: 'GET',
            path: '/api/4.0/folders',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/folders';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/folders', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_folders',
                method: 'GET',
                path: '/api/4.0/folders',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_folders',
                method: 'GET',
                path: '/api/4.0/folders',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_folders: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getFolder(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_folder',
            method: 'GET',
            path: '/api/4.0/folders/{folder_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/folders/{folder_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.folder_id) {
                throw new Error(`Missing required parameter: folder_id`);
            }
            const path = this.buildPath('/api/4.0/folders/{folder_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_folder',
                method: 'GET',
                path: '/api/4.0/folders/{folder_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_folder',
                method: 'GET',
                path: '/api/4.0/folders/{folder_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_folder: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createFolder(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_folder',
            method: 'POST',
            path: '/api/4.0/folders',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/folders';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["name"] !== undefined) {
                bodyParams["name"] = params["name"];
                extractedParams.push("name");
            }
            if (params["parent_id"] !== undefined) {
                bodyParams["parent_id"] = params["parent_id"];
                extractedParams.push("parent_id");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.name) {
                throw new Error(`Missing required parameter: name`);
            }
            const path = this.buildPath('/api/4.0/folders', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_folder',
                method: 'POST',
                path: '/api/4.0/folders',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_folder',
                method: 'POST',
                path: '/api/4.0/folders',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_folder: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async createQueryTask(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'create_query_task',
            method: 'POST',
            path: '/api/4.0/query_tasks',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/query_tasks';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["query_id"] !== undefined) {
                bodyParams["query_id"] = params["query_id"];
                extractedParams.push("query_id");
            }
            if (params["result_format"] !== undefined) {
                bodyParams["result_format"] = params["result_format"];
                extractedParams.push("result_format");
            }
            if (params["limit"] !== undefined) {
                queryParams["limit"] = params["limit"];
                extractedParams.push("limit");
            }
            if (params["apply_formatting"] !== undefined) {
                queryParams["apply_formatting"] = params["apply_formatting"];
                extractedParams.push("apply_formatting");
            }
            if (params["apply_vis"] !== undefined) {
                queryParams["apply_vis"] = params["apply_vis"];
                extractedParams.push("apply_vis");
            }
            if (params["cache"] !== undefined) {
                queryParams["cache"] = params["cache"];
                extractedParams.push("cache");
            }
            if (params["generate_drill_links"] !== undefined) {
                queryParams["generate_drill_links"] = params["generate_drill_links"];
                extractedParams.push("generate_drill_links");
            }
            if (params["force_production"] !== undefined) {
                queryParams["force_production"] = params["force_production"];
                extractedParams.push("force_production");
            }
            if (params["cache_only"] !== undefined) {
                queryParams["cache_only"] = params["cache_only"];
                extractedParams.push("cache_only");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.result_format) {
                throw new Error(`Missing required parameter: result_format`);
            }
            const path = this.buildPath('/api/4.0/query_tasks', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.post(path, Object.keys(bodyParams).length > 0 ? bodyParams : undefined, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'create_query_task',
                method: 'POST',
                path: '/api/4.0/query_tasks',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'create_query_task',
                method: 'POST',
                path: '/api/4.0/query_tasks',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute create_query_task: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getQueryTask(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_query_task',
            method: 'GET',
            path: '/api/4.0/query_tasks/{query_task_id}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/query_tasks/{query_task_id}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.query_task_id) {
                throw new Error(`Missing required parameter: query_task_id`);
            }
            const path = this.buildPath('/api/4.0/query_tasks/{query_task_id}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_query_task',
                method: 'GET',
                path: '/api/4.0/query_tasks/{query_task_id}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_query_task',
                method: 'GET',
                path: '/api/4.0/query_tasks/{query_task_id}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_query_task: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getQueryTaskResults(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_query_task_results',
            method: 'GET',
            path: '/api/4.0/query_tasks/{query_task_id}/results',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/query_tasks/{query_task_id}/results';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.query_task_id) {
                throw new Error(`Missing required parameter: query_task_id`);
            }
            const path = this.buildPath('/api/4.0/query_tasks/{query_task_id}/results', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_query_task_results',
                method: 'GET',
                path: '/api/4.0/query_tasks/{query_task_id}/results',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_query_task_results',
                method: 'GET',
                path: '/api/4.0/query_tasks/{query_task_id}/results',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_query_task_results: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listModels(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_models',
            method: 'GET',
            path: '/api/4.0/lookml_models',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/lookml_models';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/lookml_models', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_models',
                method: 'GET',
                path: '/api/4.0/lookml_models',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_models',
                method: 'GET',
                path: '/api/4.0/lookml_models',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_models: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getModel(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_model',
            method: 'GET',
            path: '/api/4.0/lookml_models/{model_name}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/lookml_models/{model_name}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.model_name) {
                throw new Error(`Missing required parameter: model_name`);
            }
            const path = this.buildPath('/api/4.0/lookml_models/{model_name}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_model',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_model',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_model: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async listExplores(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'list_explores',
            method: 'GET',
            path: '/api/4.0/lookml_models/{model_name}/explores',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/lookml_models/{model_name}/explores';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.model_name) {
                throw new Error(`Missing required parameter: model_name`);
            }
            const path = this.buildPath('/api/4.0/lookml_models/{model_name}/explores', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'list_explores',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}/explores',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'list_explores',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}/explores',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute list_explores: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async getExplore(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'get_explore',
            method: 'GET',
            path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/lookml_models/{model_name}/explores/{explore_name}';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.model_name) {
                throw new Error(`Missing required parameter: model_name`);
            }
            if (!params.explore_name) {
                throw new Error(`Missing required parameter: explore_name`);
            }
            const path = this.buildPath('/api/4.0/lookml_models/{model_name}/explores/{explore_name}', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'get_explore',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'get_explore',
                method: 'GET',
                path: '/api/4.0/lookml_models/{model_name}/explores/{explore_name}',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute get_explore: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async searchDashboards(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'search_dashboards',
            method: 'GET',
            path: '/api/4.0/dashboards/search',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/dashboards/search';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            if (params["title"] !== undefined) {
                queryParams["title"] = params["title"];
                extractedParams.push("title");
            }
            if (params["description"] !== undefined) {
                queryParams["description"] = params["description"];
                extractedParams.push("description");
            }
            if (params["content_favorite_id"] !== undefined) {
                queryParams["content_favorite_id"] = params["content_favorite_id"];
                extractedParams.push("content_favorite_id");
            }
            if (params["space_id"] !== undefined) {
                queryParams["space_id"] = params["space_id"];
                extractedParams.push("space_id");
            }
            if (params["deleted"] !== undefined) {
                queryParams["deleted"] = params["deleted"];
                extractedParams.push("deleted");
            }
            if (params["page"] !== undefined) {
                queryParams["page"] = params["page"];
                extractedParams.push("page");
            }
            if (params["per_page"] !== undefined) {
                queryParams["per_page"] = params["per_page"];
                extractedParams.push("per_page");
            }
            if (params["fields"] !== undefined) {
                queryParams["fields"] = params["fields"];
                extractedParams.push("fields");
            }
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            const path = this.buildPath('/api/4.0/dashboards/search', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'search_dashboards',
                method: 'GET',
                path: '/api/4.0/dashboards/search',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'search_dashboards',
                method: 'GET',
                path: '/api/4.0/dashboards/search',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute search_dashboards: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    async renderTaskResults(params) {
        const startTime = Date.now();
        this.logger.info('ENDPOINT_START', 'Endpoint execution started', {
            endpoint: 'render_task_results',
            method: 'GET',
            path: '/api/4.0/render_tasks/{render_task_id}/results',
            paramCount: Object.keys(params || {}).length,
            paramKeys: Object.keys(params || {})
        });
        try {
            // Extract and separate parameters by location: path, query, body
            const pathTemplate = '/api/4.0/render_tasks/{render_task_id}/results';
            const pathParams = {};
            const queryParams = {};
            const bodyParams = {};
            const extractedParams = [];
            // Handle Google-style path templates: {resourceName=people/*} and {person.resourceName=people/*}
            const googlePathTemplateRegex = /{([^}=]+)=[^}]*}/g;
            let match;
            while ((match = googlePathTemplateRegex.exec(pathTemplate)) !== null) {
                const paramName = match[1]; // e.g., "resourceName" or "person.resourceName"
                if (paramName && params[paramName] !== undefined) {
                    pathParams[paramName] = params[paramName];
                    extractedParams.push(paramName);
                }
            }
            // Handle standard path templates: {resourceName}
            const standardPathParams = pathTemplate.match(/{([^}=]+)}/g) || [];
            standardPathParams.forEach(paramTemplate => {
                const paramName = paramTemplate.slice(1, -1); // Remove { }
                // Only process if not already handled by Google template logic
                if (!extractedParams.includes(paramName)) {
                    if (params[paramName] !== undefined) {
                        pathParams[paramName] = params[paramName];
                        extractedParams.push(paramName);
                    }
                    else {
                        // Provide default values for optional path parameters
                        if (paramName === 'userId') {
                            pathParams[paramName] = 'me'; // Default to authenticated user
                            extractedParams.push(paramName);
                        }
                    }
                }
            });
            // Separate remaining parameters by location (query vs body)
            // Any remaining unprocessed parameters default to body for backward compatibility
            for (const [key, value] of Object.entries(params)) {
                if (!extractedParams.includes(key)) {
                    bodyParams[key] = value;
                }
            }
            // Validate required parameters
            if (!params.render_task_id) {
                throw new Error(`Missing required parameter: render_task_id`);
            }
            const path = this.buildPath('/api/4.0/render_tasks/{render_task_id}/results', pathParams);
            // Use standard HTTP client for other auth types
            const response = await this.httpClient.get(path, { params: queryParams });
            const duration = Date.now() - startTime;
            this.logger.info('ENDPOINT_SUCCESS', 'Endpoint execution completed successfully', {
                endpoint: 'render_task_results',
                method: 'GET',
                path: '/api/4.0/render_tasks/{render_task_id}/results',
                duration_ms: duration,
                responseDataSize: JSON.stringify(response.data).length
            });
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify(response.data, null, 2)
                    }
                ]
            };
        }
        catch (error) {
            const duration = Date.now() - startTime;
            this.logger.error('ENDPOINT_ERROR', 'Endpoint execution failed', {
                endpoint: 'render_task_results',
                method: 'GET',
                path: '/api/4.0/render_tasks/{render_task_id}/results',
                duration_ms: duration,
                error: error instanceof Error ? error.message : String(error),
                errorType: error instanceof Error ? error.constructor.name : 'unknown'
            });
            throw new Error(`Failed to execute render_task_results: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
}
//# sourceMappingURL=looker-client.js.map