This server has fundamental quality gaps that would require significant rework before production deployment. While tool names follow verb-noun convention and descriptions exist, they lack sufficient detail for agent disambiguation. Parameter schemas are present but incomplete, types are declared but many lack actionable descriptions or constraints. Output schemas are completely undocumented. The most critical issue is that fetch_era5_single_levels has a bug in its internal implementation (missing 'request' parameter passed to _internal_fetch_and_inspect), and error handling is minimal. None of the tools include recovery guidance or suggest next steps on failure. Security is reasonable (no exposed credentials in parameters), but the server lacks structured output documentation, pagination support, and input validation.
Output schemas completely undocumented. All three tools return free-text strings with no documented structure, forcing LLMs to parse unstructured output. NetCDF inspection results and download confirmations return raw text rather than structured JSON with typed fields.
fetch_era5_single_levels has a runtime bug: the 'request' parameter is constructed but never passed to _internal_fetch_and_inspect. The function signature expects (dataset, request, output_filename) but _internal_fetch_era5_single_levels calls _internal_fetch_and_inspect with (dataset, output_filename) only. This will cause a TypeError at runtime.
Parameter descriptions lack actionable constraints and context. What is the valid range? 1979-present? Can an LLM pass arbitrary strings? No enums, no ranges, no format specification.
fetch_era5_pressure_levels
Recommendations
Convert all three tool return types from free-text strings to structured JSON. Example for inspect_netcdf: {"dimensions": {<name>: <size>}, "coordinates": [{"name": <string>, "dims": <array>, "long_name": <string>, "units": <string>}], "variables": [{"name": <string>, "dims": <array>, "long_name": <string>, "units": <string>}]}. This enables downstream tools to extract specific fields without text parsing.
Fix the bug in fetch_era5_single_levels: pass the constructed 'request' dict to _internal_fetch_and_inspect. Change line 'return await _internal_fetch_and_inspect('reanalysis-era5-single-levels-monthly-means', output_filename)' to 'return await _internal_fetch_and_inspect('reanalysis-era5-single-levels-monthly-means', request, output_filename)'.
Add enum constraints to parameter descriptions. For 'variable' in fetch_era5_pressure_levels, document the valid list (e.g., 'One of: geopotential, temperature, u_component_of_wind, v_component_of_wind, relative_humidity, ...') or link to the ERA5 documentation. For 'month', specify '01 through 12 (ISO 8601 format)'.
Add range constraints to numeric and date parameters. For 'pressure_level' in fetch_era5_pressure_levels, document valid values (e.g., '1, 2, 3, 5, 7, 10, 20, 30, 50, 70, 100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000 hPa'). For 'year', specify the valid range (e.g., '1979-present, ISO 8601 format').
Add error recovery guidance to tool descriptions. Update fetch_era5_pressure_levels description to: 'Downloads ERA5 monthly mean data on pressure levels. Returns structured metadata including file path, dimensions, and variable names. If the download fails due to authentication, ensure your CDS API key is configured. If a variable or pressure level is invalid, call inspect_era5_catalog() to list available options. Retryable on network timeouts; non-retryable on invalid parameters.'
Parameter descriptions for 'variable', 'pressure_level', 'month' lack validation guidance. What are valid variable names? (The description says 'e.g., geopotential, temperature' but these are examples, not constraints.) What pressure levels does ERA5 support? What month format? (01-12? 1-12? Jan?) Without this, LLMs will hallucinate invalid values.
No error handling guidance or recovery instructions. If a download fails (invalid variable, rate limit, network error, authentication failure), the error message is just a raw exception string. LLM cannot determine if the call is retryable, if it needs to try a different variable, or if the operation is unrecoverable.
inspect_netcdf lacks clear specification of what fields the LLM should expect in output. The function returns a formatted text summary with sections [Dimensions], [Coordinates], [Variables], but no schema or data structure is documented. If an LLM needs to extract specific coordinate names or variable types for a downstream tool call, it must parse unstructured text, error-prone and token-wasteful.
fetch_era5_pressure_levels accepts 'year' as 'Union[str, List[str]]' but the parameter description and validation are unclear. Can the LLM pass both a single year and a list in the same call? Is a list of thousands of years allowed, or is there a limit? No min/max constraints documented.
No pagination or result limiting for inspect_netcdf. If a NetCDF file has hundreds of variables or dimensions, the output text could be very long and waste tokens. No mechanism to ask for summaries, limiting output, or paginating results.
No input validation or sanitization. The 'filepath' parameter in inspect_netcdf accepts any string, no path traversal checks, no verification that the path is within an allowed directory. An LLM could be tricked into reading arbitrary files on the system (e.g., '/etc/passwd').
No idempotency or dry-run support for destructive operations. fetch_era5_pressure_levels and fetch_era5_single_levels write files to disk. If an LLM mistakenly calls one twice with the same output_filename, the second call will overwrite the first. No confirmation step, no dry-run, no protection against accidental data loss.
Implement input validation with actionable error messages. In inspect_netcdf, validate that filepath is within an allowed directory (e.g., /home/user/data/) and reject path traversal attempts. Return: 'Error: Path traversal not allowed. Ensure the file is in the data directory (/home/user/data/).' In fetch_* functions, validate month is 01-12 and year matches YYYY format before calling the CDS API.
Add a dry-run or confirmation step for file-writing operations. Add an optional 'confirm' parameter to fetch_era5_pressure_levels and fetch_era5_single_levels. When true, return a preview of what will be downloaded (variable name, years, pressure levels, estimated file size) without actually writing. This enables agents to confirm intent before committing to a large download.
Document structured output for fetch_era5_pressure_levels and fetch_era5_single_levels. Return: {"status": "success|error", "file_path": <string>, "file_size_mb": <number>, "dimensions": {<name>: <size>}, "variables": [<names>], "time_range": {"start": <ISO8601>, "end": <ISO8601>}, "message": <string>}. This allows downstream tools to verify the download and extract metadata without re-inspecting the file.
Add pagination to inspect_netcdf for large files. Accept optional parameters 'max_variables': 20 (default) and 'max_coordinates': 10 (default) to cap output. Return a 'has_more' field and 'continue_token' if results are truncated, enabling agents to request more details in a follow-up call.
Add tool annotations for destructive operations. Use the @mcp.tool decorator with metadata like `destructiveHint=True` and `idempotentHint=False` on fetch_era5_* to signal that these operations modify the file system and are not safe to retry without checking if the file already exists.
Create a companion discovery tool 'describe_era5_variables' that lists available variables, pressure levels, and valid year ranges. This enables agents to self-correct without failing downloads and reduces hallucinated parameter values.