Skip to main content
Glama
validation.ts5.88 kB
/** * Validation utilities for the Metabase MCP server. */ import { ErrorCode, McpError } from '../types/core.js'; /** * Validate positive integer with detailed error message */ export function validatePositiveInteger( value: unknown, fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void ): asserts value is number { if (typeof value !== 'number') { logWarn(`Invalid ${fieldName} parameter - must be a number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a number`); } if (!Number.isInteger(value)) { logWarn(`Invalid ${fieldName} parameter - must be an integer`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be an integer`); } if (value <= 0) { logWarn(`Invalid ${fieldName} parameter - must be a positive number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a positive number`); } } /** * Parse and validate positive integer with detailed error message */ export function parseAndValidatePositiveInteger( value: unknown, fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void ): number { // Try to coerce to number if it's a string let numValue: number; if (typeof value === 'string') { numValue = parseInt(value, 10); if (isNaN(numValue)) { logWarn(`Invalid ${fieldName} parameter - cannot parse as number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a number`); } } else if (typeof value === 'number') { numValue = value; } else { logWarn(`Invalid ${fieldName} parameter - must be a number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a number`); } if (!Number.isInteger(numValue)) { logWarn(`Invalid ${fieldName} parameter - must be an integer`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be an integer`); } if (numValue <= 0) { logWarn(`Invalid ${fieldName} parameter - must be a positive number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a positive number`); } return numValue; } /** * Parse and validate non-negative integer (>= 0) with detailed error message */ export function parseAndValidateNonNegativeInteger( value: unknown, fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void ): number { // Try to coerce to number if it's a string let numValue: number; if (typeof value === 'string') { numValue = parseInt(value, 10); if (isNaN(numValue)) { logWarn(`Invalid ${fieldName} parameter - cannot parse as number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a number`); } } else if (typeof value === 'number') { numValue = value; } else { logWarn(`Invalid ${fieldName} parameter - must be a number`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a number`); } if (!Number.isInteger(numValue)) { logWarn(`Invalid ${fieldName} parameter - must be an integer`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be an integer`); } if (numValue < 0) { logWarn(`Invalid ${fieldName} parameter - must be non-negative`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be non-negative (>= 0)`); } return numValue; } /** * Validate non-empty string with detailed error message */ export function validateNonEmptyString( value: unknown, fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void ): asserts value is string { if (typeof value !== 'string') { logWarn(`Invalid ${fieldName} parameter - must be a string`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} must be a string`); } if (value.trim() === '') { logWarn(`Invalid ${fieldName} parameter - cannot be empty`, { requestId, value }); throw new McpError(ErrorCode.InvalidParams, `${fieldName} cannot be empty`); } } /** * Validate enum value with case-insensitive matching */ export function validateEnumValue<T extends string>( value: unknown, validValues: readonly T[], fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void ): T { if (typeof value !== 'string') { logWarn(`Invalid ${fieldName} parameter - must be a string`, { requestId, value }); throw new McpError( ErrorCode.InvalidParams, `${fieldName} must be one of: ${validValues.join(', ')}` ); } const normalizedValue = value.toLowerCase(); const validValue = validValues.find(v => v.toLowerCase() === normalizedValue); if (!validValue) { logWarn(`Invalid ${fieldName} parameter: ${value}`, { requestId, validValues }); throw new McpError( ErrorCode.InvalidParams, `${fieldName} must be one of: ${validValues.join(', ')}` ); } return validValue; } /** * Validate row limit with range checking (for execute command) */ export function validateRowLimit( value: unknown, fieldName: string, requestId: string, logWarn: (message: string, data?: unknown, error?: Error) => void, min: number = 1, max: number = 500 ): asserts value is number { if (typeof value !== 'number' || !Number.isInteger(value) || value < min || value > max) { const errorMessage = `Invalid ${fieldName} parameter: ${value}. Must be between ${min} and ${max}.`; logWarn(errorMessage, { requestId }); throw new McpError(ErrorCode.InvalidParams, errorMessage); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jerichosequitin/Metabase'

If you have feedback or need assistance with the MCP directory API, please join our Discord server