UNPKG

plaier-mcp-server

Version:

MCP Server for Plaier Football API - Advanced football analytics and predictions

253 lines 10.3 kB
/** * Parameter validation utilities using Zod */ import { z } from 'zod'; // ==================== TEAM VALIDATION SCHEMAS ==================== export const TeamSearchSchema = z.object({ team_name: z.string().min(3, 'Team name must be at least 3 characters'), show_details: z.boolean().optional().default(false) }); export const TeamDetailsSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer') }); export const TeamsByTournamentSchema = z.object({ tournament_id: z.number().int().positive('Tournament ID must be a positive integer') }); export const AllTeamsSchema = z.object({ skip_national_teams: z.boolean().optional().default(true) }); // ==================== PLAYER VALIDATION SCHEMAS ==================== export const PlayerSearchSchema = z.object({ player_name: z.string().min(3, 'Player name must be at least 3 characters'), team_name: z.string().optional(), show_details: z.boolean().optional().default(false) }); export const PlayerDetailsSchema = z.object({ player_id: z.number().int().positive('Player ID must be a positive integer') }); export const PlayerRankingSchema = z.object({ tournament_ids: z.array(z.number().int().positive()).optional(), team_ids: z.array(z.number().int().positive()).optional(), age: z.number().int().min(16).max(50).optional(), min_age: z.number().int().min(16).max(50).optional(), max_age: z.number().int().min(16).max(50).optional(), nationality_ids: z.array(z.number().int().positive()).optional(), position_ids: z.array(z.number().int().positive()).optional(), position_group_ids: z.array(z.number().int().positive()).optional(), in_national_team: z.boolean().optional(), sort_by: z.enum(['score', 'fair-market-value', 'value-for-money']).optional().default('score'), limit: z.number().int().min(1).max(1000).optional().default(50) }).refine(data => { // Can't use age with min_age or max_age if (data.age && (data.min_age || data.max_age)) { return false; } // Can't use both tournament_ids and team_ids if (data.tournament_ids && data.team_ids) { return false; } // Can't use both position_ids and position_group_ids if (data.position_ids && data.position_group_ids) { return false; } // min_age must be less than max_age if (data.min_age && data.max_age && data.min_age >= data.max_age) { return false; } return true; }, { message: "Invalid parameter combination" }); export const TeamPlayersSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer') }); export const TournamentPlayersSchema = z.object({ tournament_id: z.number().int().positive('Tournament ID must be a positive integer') }); // ==================== MATCH VALIDATION SCHEMAS ==================== export const MatchPredictionSchema = z.object({ home_team_id: z.number().int().positive('Home team ID must be a positive integer'), away_team_id: z.number().int().positive('Away team ID must be a positive integer'), home_team_lineup: z.array(z.number().int().positive()).max(11, 'Maximum 11 players in lineup').optional(), away_team_lineup: z.array(z.number().int().positive()).max(11, 'Maximum 11 players in lineup').optional(), prediction_type: z.enum(['overall-result-prediction', 'exact-result-prediction']).optional().default('overall-result-prediction'), ignore_home_advantage: z.boolean().optional().default(false) }).refine(data => { // Home and away teams must be different return data.home_team_id !== data.away_team_id; }, { message: "Home and away teams must be different" }); export const BestLineupsSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer'), opponent_team_id: z.number().int().positive('Opponent team ID must be a positive integer'), home_match: z.boolean(), formation: z.string().optional(), skip_players: z.array(z.number().int().positive()).optional() }).refine(data => { return data.team_id !== data.opponent_team_id; }, { message: "Team and opponent must be different" }); export const BestFormationsSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer'), opponent_team_id: z.number().int().positive('Opponent team ID must be a positive integer'), home_match: z.boolean(), skip_players: z.array(z.number().int().positive()).optional(), format: z.enum(['json', 'csv', 'png', 'pdf']).optional().default('json'), dark_mode: z.boolean().optional().default(true), orientation: z.enum(['portrait', 'landscape']).optional().default('landscape') }).refine(data => { return data.team_id !== data.opponent_team_id; }, { message: "Team and opponent must be different" }); // ==================== TOURNAMENT VALIDATION SCHEMAS ==================== export const TournamentSearchSchema = z.object({ tournament_name: z.string().min(3, 'Tournament name must be at least 3 characters') }); export const TournamentFixturesSchema = z.object({ tournament_id: z.number().int().positive('Tournament ID must be a positive integer') }); export const TournamentPredictionSchema = z.object({ tournament_id: z.number().int().positive('Tournament ID must be a positive integer') }); // ==================== TRANSFER VALIDATION SCHEMAS ==================== export const TransferImpactSchema = z.object({ player_id: z.number().int().positive('Player ID must be a positive integer'), team_ids: z.array(z.number().int().positive()).optional(), tournament_id: z.number().int().positive().optional() }).refine(data => { // Must have either team_ids or tournament_id, but not both return (data.team_ids && !data.tournament_id) || (!data.team_ids && data.tournament_id); }, { message: "Must specify either team_ids or tournament_id, but not both" }); // ==================== ADVANCED ANALYSIS SCHEMAS ==================== export const TeamPerformanceSchema = z.object({ tournament_id: z.number().int().positive('Tournament ID must be a positive integer'), report_type: z.enum(['nominal-score', 'effective-score', 'effective-score-vs-nominal-score', 'goal-difference-per-season']), team_id: z.number().int().positive().optional(), position_group: z.string().optional(), only_best_player: z.boolean().optional().default(false), format: z.enum(['json', 'csv', 'png', 'pdf']).optional().default('json'), dark_mode: z.boolean().optional().default(true), orientation: z.enum(['portrait', 'landscape']).optional().default('landscape') }); export const TeamImprovementSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer'), report_type: z.enum(['matrix']).default('matrix'), format: z.enum(['json', 'csv']).optional().default('json') }); export const MostImportantPlayersSchema = z.object({ team_id: z.number().int().positive('Team ID must be a positive integer'), format: z.enum(['json', 'csv']).optional().default('json') }); // ==================== EXPORT DATA SCHEMAS ==================== export const ExportDataSchema = z.object({ endpoint: z.string(), parameters: z.record(z.any()).optional(), format: z.enum(['csv', 'xlsx', 'json']).default('csv'), filename: z.string().optional() }); // ==================== VALIDATION HELPER FUNCTIONS ==================== /** * Validate input parameters against a schema */ export function validateInput(schema, input) { const result = schema.safeParse(input); if (!result.success) { const errors = result.error.errors.map(e => { const path = e.path.length > 0 ? `${e.path.join('.')}` : 'root'; return `${path}: ${e.message}`; }); throw new Error(`Validation error: ${errors.join(', ')}`); } return result.data; } /** * Validate and sanitize team ID */ export function validateTeamId(teamId) { const result = z.number().int().positive().safeParse(teamId); if (!result.success) { throw new Error('Team ID must be a positive integer'); } return result.data; } /** * Validate and sanitize player ID */ export function validatePlayerId(playerId) { const result = z.number().int().positive().safeParse(playerId); if (!result.success) { throw new Error('Player ID must be a positive integer'); } return result.data; } /** * Validate and sanitize tournament ID */ export function validateTournamentId(tournamentId) { const result = z.number().int().positive().safeParse(tournamentId); if (!result.success) { throw new Error('Tournament ID must be a positive integer'); } return result.data; } /** * Validate array of IDs */ export function validateIdArray(ids, name) { const result = z.array(z.number().int().positive()).safeParse(ids); if (!result.success) { throw new Error(`${name} must be an array of positive integers`); } return result.data; } /** * Validate search term */ export function validateSearchTerm(term) { const result = z.string().min(3).safeParse(term); if (!result.success) { throw new Error('Search term must be at least 3 characters long'); } return result.data; } /** * Validate boolean parameter */ export function validateBoolean(value, defaultValue = false) { if (value === undefined || value === null) { return defaultValue; } const result = z.boolean().safeParse(value); if (!result.success) { return defaultValue; } return result.data; } /** * Validate and clamp numeric parameter within range */ export function validateNumberInRange(value, min, max, defaultValue) { if (value === undefined || value === null) { return defaultValue; } const result = z.number().min(min).max(max).safeParse(value); if (!result.success) { if (defaultValue !== undefined) { return defaultValue; } throw new Error(`Value must be between ${min} and ${max}`); } return result.data; } /** * Create a validation error message */ export function createValidationError(field, message) { return new Error(`Validation error for ${field}: ${message}`); } //# sourceMappingURL=validation.js.map