Skip to main content
Glama
Hug0x0

mcp-reunion

reunion_get_weather_observations

Retrieve synoptic weather observations from Météo-France stations in La Réunion, including temperature, humidity, wind, and rainfall for a specified station and date range.

Instructions

Météo-France SYNOP synoptic weather observations from stations located in La Réunion. SYNOP is the WMO standard for surface observations (every 3 hours typically). Returns: station name, observation timestamp, commune, current temperature (°C), 12h min/max temperature, relative humidity (%), wind speed (m/s) and direction (degrees), sea-level pressure (Pa), 1h and 24h rainfall (mm), present-weather code. Sorted by date descending. Use reunion_list_weather_stations to discover available stations.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
stationNoStation name prefix match (case-sensitive uppercase). Examples: "LE PORT", "GILLOT-AEROPORT" (Saint-Denis airport), "PIERREFONDS" (Saint-Pierre airport), "BELLECOMBE-JACOB"
fromNoInclusive lower bound on date, ISO format YYYY-MM-DD
toNoInclusive upper bound on date, ISO format YYYY-MM-DD
limitNoMax observations to return (1-100, default 20)

Implementation Reference

  • The tool registration for 'reunion_get_weather_observations' with the MCP server. The handler queries the 'donnees-synop-essentielles-ommpublic' dataset on data.regionreunion.com, filtering by region (La Réunion), optional station name, date range, and limit. It returns parsed observation fields like temperature, humidity, wind, pressure, rainfall, and present weather code.
    server.tool(
      'reunion_get_weather_observations',
      'Météo-France SYNOP synoptic weather observations from stations located in La Réunion. SYNOP is the WMO standard for surface observations (every 3 hours typically). Returns: station name, observation timestamp, commune, current temperature (°C), 12h min/max temperature, relative humidity (%), wind speed (m/s) and direction (degrees), sea-level pressure (Pa), 1h and 24h rainfall (mm), present-weather code. Sorted by date descending. Use reunion_list_weather_stations to discover available stations.',
      {
        station: z.string().optional().describe('Station name prefix match (case-sensitive uppercase). Examples: "LE PORT", "GILLOT-AEROPORT" (Saint-Denis airport), "PIERREFONDS" (Saint-Pierre airport), "BELLECOMBE-JACOB"'),
        from: z.string().optional().describe('Inclusive lower bound on date, ISO format YYYY-MM-DD'),
        to: z.string().optional().describe('Inclusive upper bound on date, ISO format YYYY-MM-DD'),
        limit: z.number().int().min(1).max(100).default(20).describe('Max observations to return (1-100, default 20)'),
      },
      async ({ station, from, to, limit }) => {
        try {
          const data = await client.getRecords<RecordObject>(DATASET_SYNOP, {
            where: buildWhere([
              `nom_reg = ${quote('La Réunion')}`,
              station ? `nom LIKE ${quote(`${station}%`)}` : undefined,
              from ? `date >= date${quote(from)}` : undefined,
              to ? `date <= date${quote(to)}` : undefined,
            ]),
            order_by: 'date DESC',
            limit,
          });
    
          return jsonResult({
            total_observations: data.total_count,
            observations: data.results.map((obs) => ({
              station: pickString(obs, ['nom']),
              date: pickString(obs, ['date']),
              commune: pickString(obs, ['libgeo']),
              temperature_c: pickNumber(obs, ['tc']),
              temp_min_12h_c: pickNumber(obs, ['tn12c']),
              temp_max_12h_c: pickNumber(obs, ['tx12c']),
              humidity_pct: pickNumber(obs, ['u']),
              wind_speed_ms: pickNumber(obs, ['ff']),
              wind_direction_deg: pickNumber(obs, ['dd']),
              pressure_sea_level_pa: pickNumber(obs, ['pmer']),
              rainfall_1h_mm: pickNumber(obs, ['rr1']),
              rainfall_24h_mm: pickNumber(obs, ['rr24']),
              present_weather: pickString(obs, ['temps_present']),
            })),
          });
        } catch (error) {
          return errorResult(error instanceof Error ? error.message : 'Failed to fetch weather observations');
        }
      }
  • Zod schema defining input parameters: station (optional string prefix match), from/to (optional ISO date strings), limit (integer 1-100, default 20).
    {
      station: z.string().optional().describe('Station name prefix match (case-sensitive uppercase). Examples: "LE PORT", "GILLOT-AEROPORT" (Saint-Denis airport), "PIERREFONDS" (Saint-Pierre airport), "BELLECOMBE-JACOB"'),
      from: z.string().optional().describe('Inclusive lower bound on date, ISO format YYYY-MM-DD'),
      to: z.string().optional().describe('Inclusive upper bound on date, ISO format YYYY-MM-DD'),
      limit: z.number().int().min(1).max(100).default(20).describe('Max observations to return (1-100, default 20)'),
    },
  • Registration of registerWeatherTools(server) in the registerAllTools function, which wires the tool into the MCP server.
      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);
    }
  • 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;
    }
    
    /**
     * Escape a string literal for ODSQL
     */
    export function escapeOdSqlString(value: string): string {
      return value.replace(/'/g, "''");
    }
    
    /**
     * Quote an ODSQL string literal
     */
    export function quote(value: string): string {
      return `'${escapeOdSqlString(value)}'`;
    }
  • ReunionClient.getRecords method - the API client function that actually fetches records from the OpenDataSoft API.
    async getRecords<T extends RecordObject = RecordObject>(
      datasetId: string,
      params: ODSQueryParams = {}
    ): Promise<ODSResponse<T>> {
      const url = this.buildUrl(`/catalog/datasets/${datasetId}/records`, params);
    
      if (REFERENTIAL_DATASETS.has(datasetId)) {
        const now = Date.now();
        const cached = this.recordsCache.get(url);
        if (cached && cached.expiresAt > now) {
          return cached.value as ODSResponse<T>;
        }
        const value = await this.fetchJson<ODSResponse<T>>(url);
        this.recordsCache.set(url, { value, expiresAt: now + REFERENTIAL_TTL_MS });
        return value;
      }
    
      return this.fetchJson<ODSResponse<T>>(url);
    }
    
    /**
     * Clear the in-memory caches. Intended for tests.
     */
    clearCaches(): void {
      this.metadataCache.clear();
      this.recordsCache.clear();
    }
    
    /**
     * Fetch aggregated data from a dataset
     */
    async getAggregates<T extends RecordObject = RecordObject>(
      datasetId: string,
      select: string,
      options: {
        where?: string;
        groupBy?: string;
        orderBy?: string;
        limit?: number;
      } = {}
    ): Promise<ODSResponse<T>> {
      const params: Record<string, string | number | undefined> = { select };
      if (options.where) params.where = options.where;
      if (options.groupBy) params.group_by = options.groupBy;
      if (options.orderBy) params.order_by = options.orderBy;
      if (options.limit !== undefined) params.limit = options.limit;
    
      const url = this.buildUrl(`/catalog/datasets/${datasetId}/aggregates`, params);
      return this.fetchJson<ODSResponse<T>>(url);
    }
    
    /**
     * Search across all datasets
     */
    async searchDatasets(query: string): Promise<CatalogResponse> {
      const url = this.buildUrl('/catalog/datasets', {
        where: `search(${quote(query)})`,
        limit: 20,
      });
      return this.fetchJson<CatalogResponse>(url);
    }
    
    /**
     * List datasets with an optional raw ODSQL where clause.
     */
    async listDatasets(
      options: { where?: string; limit?: number; offset?: number } = {}
    ): Promise<CatalogResponse> {
      const url = this.buildUrl('/catalog/datasets', {
        where: options.where,
        limit: options.limit ?? 20,
        offset: options.offset,
      });
      return this.fetchJson<CatalogResponse>(url);
    }
    
    /**
     * Fetch dataset metadata from the catalog
     */
    async getDatasetMetadata(datasetId: string): Promise<DatasetMetadata | undefined> {
      if (!this.metadataCache.has(datasetId)) {
        const promise = this.fetchJson<CatalogResponse>(
          this.buildUrl('/catalog/datasets', {
            where: `dataset_id = ${quote(datasetId)}`,
            limit: 1,
          })
        ).then((data) => data.results[0]);
    
        this.metadataCache.set(datasetId, promise);
      }
    
      return this.metadataCache.get(datasetId);
    }
    
    /**
     * Check whether a dataset currently exists in the public catalog
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite no annotations, description discloses sort order (date descending), typical observation frequency (every 3 hours), and all returned fields. No missing behavioral traits for a read-only operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with clear purpose, format, field list, sort order, and usage tip. Efficient, though the field list could be slightly more compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Fully explains return fields with units, sort order, and data source origin. No output schema exists, but description compensates completely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed descriptions; the description adds only minimal additional context (e.g., station name prefix match examples included in schema). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it retrieves Météo-France SYNOP weather observations from La Réunion stations, listing specific fields. It distinguishes from the sibling tool reunion_list_weather_stations by mentioning its use for station discovery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly recommends using reunion_list_weather_stations to discover stations. Provides context for typical use but does not explicitly state when not to use or alternatives beyond that one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/Hug0x0/mcp-reunion'

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