reunion_list_gen2024_schools
Retrieve schools in La Réunion awarded the 'Génération 2024' label for sport-oriented projects. Filter by commune, type, and limit results to get school details including enrollment and special programs.
Instructions
List schools in La Réunion that received the "Génération 2024" label — a Ministry of Education + Sport designation tied to the Paris 2024 Olympics, awarded to schools that develop sport-oriented projects (extra hours, partnerships with clubs, Olympic Day events). Returns school name, UAI, type (école/collège/lycée), sector, commune, total enrollment, priority-zone status, ULIS/SEGPA/sport-section flags, lycée-des-métiers flag.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| commune | No | Commune name prefix match | |
| type | No | Establishment type prefix match. Examples: "Ecole", "Collège", "Lycée" | |
| limit | No | Max schools to return (1-300, default 100) |
Implementation Reference
- src/modules/education.ts:57-94 (handler)Handler for the 'reunion_list_gen2024_schools' tool. Fetches schools labeled 'Génération 2024' from the OpenDataSoft dataset 'etablissements-labellises-generation-2024-a-la-reunion'. Accepts optional filters (commune, type, limit) and returns school details including name, UAI, type, sector, commune, enrollment, priority zone status, ULIS/SEGPA/sport-section flags, and lycée-des-métiers flag.
server.tool( 'reunion_list_gen2024_schools', 'List schools in La Réunion that received the "Génération 2024" label — a Ministry of Education + Sport designation tied to the Paris 2024 Olympics, awarded to schools that develop sport-oriented projects (extra hours, partnerships with clubs, Olympic Day events). Returns school name, UAI, type (école/collège/lycée), sector, commune, total enrollment, priority-zone status, ULIS/SEGPA/sport-section flags, lycée-des-métiers flag.', { commune: z.string().optional().describe('Commune name prefix match'), type: z.string().optional().describe('Establishment type prefix match. Examples: "Ecole", "Collège", "Lycée"'), limit: z.number().int().min(1).max(300).default(100).describe('Max schools to return (1-300, default 100)'), }, async ({ commune, type, limit }) => { try { const data = await client.getRecords<RecordObject>(DATASET_G2024, { where: buildWhere([ commune ? `commune LIKE ${quote(`${commune}%`)}` : undefined, type ? `type LIKE ${quote(`${type}%`)}` : undefined, ]), limit, }); return jsonResult({ total_schools: data.total_count, schools: data.results.map((row) => ({ name: pickString(row, ['nom_etablissement']), uai: pickString(row, ['uai']), type: pickString(row, ['type']), sector: pickString(row, ['statut_public_prive']), commune: pickString(row, ['commune']), enrollment: pickNumber(row, ['effectif']), priority_zone: pickString(row, ['educ_prio']), has_ulis: pickNumber(row, ['ulis']) === 1, has_segpa: pickNumber(row, ['segpa']) === 1, has_sport_section: pickNumber(row, ['section_sport']) === 1, is_lycee_des_metiers: pickNumber(row, ['lycee_des_metiers']) === 1, })), }); } catch (error) { return errorResult(error instanceof Error ? error.message : 'Failed to fetch G2024 schools'); } } ); - src/modules/education.ts:60-64 (schema)Zod schema for the tool's input validation: commune (optional string), type (optional string), limit (int 1-300, default 100).
{ commune: z.string().optional().describe('Commune name prefix match'), type: z.string().optional().describe('Establishment type prefix match. Examples: "Ecole", "Collège", "Lycée"'), limit: z.number().int().min(1).max(300).default(100).describe('Max schools to return (1-300, default 100)'), }, - src/modules/education.ts:57-94 (registration)Tool is registered via server.tool('reunion_list_gen2024_schools', ...) inside registerEducationTools(), which is called from src/modules/index.ts (line 39) and src/index.ts (line 22).
server.tool( 'reunion_list_gen2024_schools', 'List schools in La Réunion that received the "Génération 2024" label — a Ministry of Education + Sport designation tied to the Paris 2024 Olympics, awarded to schools that develop sport-oriented projects (extra hours, partnerships with clubs, Olympic Day events). Returns school name, UAI, type (école/collège/lycée), sector, commune, total enrollment, priority-zone status, ULIS/SEGPA/sport-section flags, lycée-des-métiers flag.', { commune: z.string().optional().describe('Commune name prefix match'), type: z.string().optional().describe('Establishment type prefix match. Examples: "Ecole", "Collège", "Lycée"'), limit: z.number().int().min(1).max(300).default(100).describe('Max schools to return (1-300, default 100)'), }, async ({ commune, type, limit }) => { try { const data = await client.getRecords<RecordObject>(DATASET_G2024, { where: buildWhere([ commune ? `commune LIKE ${quote(`${commune}%`)}` : undefined, type ? `type LIKE ${quote(`${type}%`)}` : undefined, ]), limit, }); return jsonResult({ total_schools: data.total_count, schools: data.results.map((row) => ({ name: pickString(row, ['nom_etablissement']), uai: pickString(row, ['uai']), type: pickString(row, ['type']), sector: pickString(row, ['statut_public_prive']), commune: pickString(row, ['commune']), enrollment: pickNumber(row, ['effectif']), priority_zone: pickString(row, ['educ_prio']), has_ulis: pickNumber(row, ['ulis']) === 1, has_segpa: pickNumber(row, ['segpa']) === 1, has_sport_section: pickNumber(row, ['section_sport']) === 1, is_lycee_des_metiers: pickNumber(row, ['lycee_des_metiers']) === 1, })), }); } catch (error) { return errorResult(error instanceof Error ? error.message : 'Failed to fetch G2024 schools'); } } ); - src/utils/helpers.ts:36-41 (helper)buildWhere helper used to construct the ODSQL WHERE clause from optional filter conditions.
export function buildWhere( conditions: Array<string | undefined | null | false> ): string | undefined { const valid = conditions.filter((condition): condition is string => Boolean(condition)); return valid.length > 0 ? valid.join(' AND ') : undefined; } - src/utils/helpers.ts:84-103 (helper)pickValue helper used to extract values from API response records.
export function pickValue<T = unknown>( record: RecordObject, candidates: string[] ): T | undefined { for (const candidate of candidates) { if (candidate in record) { const value = record[candidate]; if (value !== undefined && value !== null) { // OpenDataSoft v2.1 wraps some text fields as single-element arrays // (e.g. com_name → ["Saint-Denis"]). Unwrap so downstream pickers // see the scalar they expect. if (Array.isArray(value) && value.length === 1) { return value[0] as T; } return value as T; } } } return undefined; }