Skip to main content
Glama

Skolverket MCP Server

validator.ts3.89 kB
/** * Runtime validation med Zod för tool-parametrar */ import { z, ZodSchema } from 'zod'; import { ValidationError } from './errors.js'; import { log } from './logger.js'; /** * Validera input mot ett Zod-schema */ export function validate<T>(schema: ZodSchema<T>, data: unknown, toolName?: string): T { try { const validated = schema.parse(data); log.debug('Validation success', { toolName, data: validated }); return validated; } catch (error) { if (error instanceof z.ZodError) { const firstError = error.errors[0]; const field = firstError.path.join('.'); const message = `Valideringsfel i ${toolName || 'tool'}: ${firstError.message} (fält: ${field})`; log.warn('Validation failed', { toolName, field, message: firstError.message, value: data }); throw new ValidationError(message, field, data); } throw error; } } /** * Validera partiell input (endast de fält som skickas in) */ export function validatePartial<T>(schema: ZodSchema<T>, data: unknown, toolName?: string): Partial<T> { const partialSchema = schema instanceof z.ZodObject ? schema.partial() : schema; return validate(partialSchema as ZodSchema<Partial<T>>, data, toolName); } /** * Vanliga valideringsscheman som kan återanvändas */ export const commonSchemas = { // Kurskod (t.ex. MATMAT01c) courseCode: z.string() .min(1, 'Kurskod får inte vara tom') .regex(/^[A-Z0-9]+$/, 'Kurskod måste innehålla endast stora bokstäver och siffror'), // Ämneskod (t.ex. GRGRMAT01) subjectCode: z.string() .min(1, 'Ämneskod får inte vara tom') .regex(/^[A-Z0-9]+$/, 'Ämneskod måste innehålla endast stora bokstäver och siffror'), // Programkod (t.ex. NA, TE) programCode: z.string() .min(1, 'Programkod får inte vara tom') .regex(/^[A-Z]+$/, 'Programkod måste innehålla endast stora bokstäver'), // Läroplanskod (t.ex. LGR11) curriculumCode: z.string() .min(1, 'Läroplanskod får inte vara tom') .regex(/^[A-Z0-9]+$/, 'Läroplanskod måste innehålla endast stora bokstäver och siffror'), // Skoltyp schoolType: z.enum(['GR', 'GY', 'VUX', 'GRSÄR', 'GYSÄR'], { errorMap: () => ({ message: 'Ogiltig skoltyp. Tillåtna värden: GR, GY, VUX, GRSÄR, GYSÄR' }) }), // Tidsperiod timespan: z.enum(['LATEST', 'HISTORIC', 'ALL'], { errorMap: () => ({ message: 'Ogiltig tidsperiod. Tillåtna värden: LATEST, HISTORIC, ALL' }) }), // Versionsnummer version: z.number() .int('Versionsnummer måste vara ett heltal') .positive('Versionsnummer måste vara positivt'), // Skolenhetskod (8 siffror) schoolUnitCode: z.string() .length(8, 'Skolenhetskod måste vara 8 siffror') .regex(/^\d{8}$/, 'Skolenhetskod måste innehålla endast siffror'), // Status för skolenhet schoolUnitStatus: z.enum(['AKTIV', 'UPPHORT', 'VILANDE'], { errorMap: () => ({ message: 'Ogiltig status. Tillåtna värden: AKTIV, UPPHORT, VILANDE' }) }), // Utbildnings-ID educationId: z.string() .min(1, 'Utbildnings-ID får inte vara tomt'), // Studietakt paceOfStudy: z.string() .regex(/^\d+(-\d+)?$/, 'Studietakt måste vara ett tal eller intervall (t.ex. "100" eller "50-100")'), // Boolean som sträng (från API) booleanString: z.enum(['true', 'false']) .transform(val => val === 'true'), // Datum i ISO format isoDate: z.string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'Datum måste vara i format YYYY-MM-DD'), // Sidnummer för pagination page: z.number() .int('Sidnummer måste vara ett heltal') .nonnegative('Sidnummer måste vara 0 eller högre') .default(0), // Antal resultat per sida size: z.number() .int('Sidstorlek måste vara ett heltal') .min(1, 'Sidstorlek måste vara minst 1') .max(100, 'Sidstorlek kan max vara 100') .default(20) };

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/KSAklfszf921/skolverket-syllabus-mcp'

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