reunion_search_bal_possession
Find detailed addresses in La Possession's official address registry, including local place names, cadastral parcels, and last update timestamps. Returns precise coordinates and identifiers.
Instructions
Search the Base Adresse Locale (BAL) published directly by the Commune of La Possession (west Réunion). BALs are commune-level address registries that feed BAN. This dataset is more granular than BAN for Possession addresses, including local lieux-dits, cadastral parcels, and last-update timestamps. Returns UID, interop key, street name, lieu-dit complement, suffix, longitude, latitude, cadastral parcels, last update.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Free-text search on the address fields | |
| street | No | Street name prefix match (e.g. "Rue de", "Chemin") | |
| limit | No | Max addresses to return (1-100, default 20) |
Implementation Reference
- src/modules/geography.ts:59-94 (handler)The tool handler for 'reunion_search_bal_possession' — defines the async callback that queries the 'bal-la-possession' dataset via the ReunionClient, with optional 'query' and 'street' filters, and returns mapped address fields (uid, interop_key, street, lieu_dit, suffix, longitude, latitude, parcels, last_update).
server.tool( 'reunion_search_bal_possession', 'Search the Base Adresse Locale (BAL) published directly by the Commune of La Possession (west Réunion). BALs are commune-level address registries that feed BAN. This dataset is more granular than BAN for Possession addresses, including local lieux-dits, cadastral parcels, and last-update timestamps. Returns UID, interop key, street name, lieu-dit complement, suffix, longitude, latitude, cadastral parcels, last update.', { query: z.string().optional().describe('Free-text search on the address fields'), street: z.string().optional().describe('Street name prefix match (e.g. "Rue de", "Chemin")'), limit: z.number().int().min(1).max(100).default(20).describe('Max addresses to return (1-100, default 20)'), }, async ({ query, street, limit }) => { try { const data = await client.getRecords<RecordObject>(DATASET_BAL_POSSESSION, { where: buildWhere([ query ? `search(${quote(query)})` : undefined, street ? `voie_nom LIKE ${quote(`${street}%`)}` : undefined, ]), limit, }); return jsonResult({ total_addresses: data.total_count, addresses: data.results.map((row) => ({ uid: pickString(row, ['uid_adresse']), interop_key: pickString(row, ['cle_interop']), street: pickString(row, ['voie_nom']), lieu_dit: pickString(row, ['lieudit_complement_nom']), suffix: pickString(row, ['suffixe']), longitude: pickNumber(row, ['longitude']), latitude: pickNumber(row, ['latitude']), parcels: pickString(row, ['cad_parcelles']), last_update: pickString(row, ['date_der_maj']), })), }); } catch (error) { return errorResult(error instanceof Error ? error.message : 'Failed to search BAL Possession'); } } ); - src/modules/geography.ts:62-66 (schema)Input schema definition for the tool using Zod — accepts optional 'query' (string), 'street' (string), and 'limit' (integer, 1-100, default 20).
{ query: z.string().optional().describe('Free-text search on the address fields'), street: z.string().optional().describe('Street name prefix match (e.g. "Rue de", "Chemin")'), limit: z.number().int().min(1).max(100).default(20).describe('Max addresses to return (1-100, default 20)'), }, - src/modules/index.ts:33-57 (registration)Registration call — registerGeographyTools is called from registerAllTools, which is invoked in src/index.ts on server startup.
export function registerAllTools(server: McpServer): void { registerAdministrationTools(server); registerCatalogTools(server); registerCommuneTools(server); registerCultureTools(server); registerEconomyTools(server); registerEducationTools(server); registerEmploymentTools(server); registerEnvironmentTools(server); registerFacilityTools(server); registerGeographyTools(server); registerHealthTools(server); registerHospitalityTools(server); registerHousingTools(server); registerNationalElectionsTools(server); registerPossessionTools(server); registerSocialTools(server); registerTelecomTools(server); registerTerritoryTools(server); registerTourismTools(server); registerTransportTools(server); registerUrbanismTools(server); registerWeatherTools(server); } - src/modules/geography.ts:10-42 (helper)Dataset constant DATASET_BAL_POSSESSION = 'bal-la-possession' used by the tool to query the correct OpenDataSoft dataset.
const DATASET_BAL_POSSESSION = 'bal-la-possession'; const DATASET_COMMUNES = 'communes-millesime-france'; const DATASET_CANTONS = 'cantons-millesime-france'; const DATASET_EPCI = 'intercommunalites-millesime-france'; const DATASET_IRIS = 'iris-millesime-france'; const DATASET_SAINT_DENIS_QUARTERS = 'les-20-quartiers-villesaintdenis'; export function registerGeographyTools(server: McpServer): void { server.tool( 'reunion_search_ban_addresses', 'Search the Base Adresse Nationale (BAN) — France\'s authoritative geocoded address database — restricted to La Réunion (~353k addresses). Each address has lat/lon, street name, number, postal code, INSEE code, and a position type (entrance, parcel, segment). Use this for geocoding, address validation, last-mile delivery, mapping. Source: IGN / La Poste / DINUM via data.regionreunion.com.', { query: z.string().optional().describe('Free-text search across street name and city'), commune: z.string().optional().describe('Commune name prefix match (e.g. "Saint-Denis")'), insee: z.number().int().optional().describe('INSEE commune code (5 digits as integer, e.g. 97411 for Saint-Denis)'), postal_code: z.number().int().optional().describe('Postal code as integer (5 digits, Réunion uses 974xx)'), limit: z.number().int().min(1).max(100).default(20).describe('Max addresses to return (1-100, default 20)'), }, async ({ query, commune, insee, postal_code, limit }) => { try { const data = await client.getRecords<RecordObject>(DATASET_BAN, { where: buildWhere([ query ? `search(${quote(query)})` : undefined, commune ? `nom_commune LIKE ${quote(`${commune}%`)}` : undefined, insee !== undefined ? `code_insee = ${insee}` : undefined, postal_code !== undefined ? `code_postal = ${postal_code}` : undefined, ]), limit, }); return jsonResult({ total_addresses: data.total_count, addresses: data.results.map((row) => ({ number: pickNumber(row, ['numero']),