Oceanum MCP
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Oceanum MCPsearch for sea surface temperature datasets in the North Atlantic"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Oceanum MCP
An MCP server package that provides AI assistants with access to the Oceanum platform for ocean/environmental data and cloud storage.
Servers
This package contains multiple MCP servers, selectable at runtime:
Server | Description |
| Search, query, and manage ocean/environmental datasets |
| List, read, write, and delete files in Oceanum cloud storage |
| All tools from both servers under a single endpoint (default) |
Related MCP server: Code Ocean MCP Server
Prerequisites
Get an API token from oceanum.io. Set it as the DATAMESH_TOKEN environment variable
(or keep it out of the client config: see Supplying the token without
putting it in the client config).
Installation
Requires Python 3.10–3.13. Python 3.14 is not supported yet: the zarr 2.x
stack that oceanum depends on needs numcodecs<0.16, which has no Python
3.14 wheels.
pip install oceanum-mcpOr run directly with uvx. Pass --python 3.13 so uv doesn't pick Python
3.14 (uv downloads 3.13 if it isn't installed):
uvx --python 3.13 oceanum-mcp # combined server (default)
uvx --python 3.13 oceanum-mcp datamesh # datamesh only
uvx --python 3.13 oceanum-mcp storage # storage only
uvx --python 3.13 oceanum-mcp --list # show available serversConfiguration
Claude Desktop
Add to your claude_desktop_config.json:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Combined server (all tools):
{
"mcpServers": {
"oceanum": {
"command": "uvx",
"args": ["--python", "3.13", "oceanum-mcp"],
"env": {
"DATAMESH_TOKEN": "your-token-here"
}
}
}
}Individual server (datamesh only):
{
"mcpServers": {
"oceanum-datamesh": {
"command": "uvx",
"args": ["--python", "3.13", "oceanum-mcp", "datamesh"],
"env": {
"DATAMESH_TOKEN": "your-token-here"
}
}
}
}Claude Code
# Combined server
claude mcp add --transport stdio oceanum -- uvx --python 3.13 oceanum-mcp
# Individual server
claude mcp add --transport stdio oceanum-datamesh -- uvx --python 3.13 oceanum-mcp datameshSet the token in your environment:
export DATAMESH_TOKEN=your-token-hereVS Code / Cline / Continue
Use stdio transport with the same command:
{
"command": "uvx",
"args": ["--python", "3.13", "oceanum-mcp"],
"env": {
"DATAMESH_TOKEN": "your-token-here"
}
}If the server reports that the token "looks like an unresolved client
variable", your client passed a config variable such as
${input:datamesh-token} through literally instead of substituting it.
Restart the server from the client so it prompts for the input again, or use
one of the options below.
Supplying the token without putting it in the client config
For the stdio transport the server takes its token from the first of these that is set:
DATAMESH_TOKEN— the token itself.DATAMESH_TOKEN_FILE— path to a file containing the token (~is expanded). On macOS/Linux the file must be accessible only by you; the server refuses it otherwise:install -m 600 /dev/null ~/.config/oceanum/token echo "your-token-here" > ~/.config/oceanum/token"env": { "DATAMESH_TOKEN_FILE": "~/.config/oceanum/token" }The file is read on every call, so a replaced token takes effect without restarting the server.
DATAMESH_TOKEN_KEYRING=1— read the token from the OS credential store (macOS Keychain, Secret Service/libsecret on Linux, Windows Credential Manager) via thekeyringpackage, under serviceoceanum-mcp, userdatamesh-token. Store it once with:uvx keyring set oceanum-mcp datamesh-tokenThe token is looked up once per server process, so restart the server after changing it.
keyringcurrently arrives as an indirect dependency offastmcp, which is not guaranteed to last: to be sure, install theoceanum-mcp[keyring]extra (with uvx:uvx --python 3.13 --from "oceanum-mcp[keyring]" oceanum-mcp).
Troubleshooting: -32022 on the first initialize
A client may log "connection is serving the 2026-07-28 protocol; the
initialize handshake is not accepted" (error -32022) once on connect. This
comes from the MCP Python SDK, not from this server's code: in SDK 2.3.0
(mcp/server/runner.py, serve_dual_era_loop) a connection's first request
fixes its protocol era. A client that opens with a 2026-07-28 request and
then sends the older initialize handshake on the same connection is
refused, with the supported versions in the error. Clients are expected to
retry with a supported version; GitHub Copilot did so and connected.
Environment Variables
Variable | Required | Description |
| Yes* | Oceanum API token (shared by all servers) |
| Yes* | Path to a file holding the token, readable only by its owner; used when |
| Yes* |
|
| No | Custom datamesh service URL (default: |
| No | Custom storage service URL (default: |
| No | Override the base domain for all services (default: |
| No |
|
| No | Max staged result size returned inline by |
| No | Max rows/records previewed inline before truncation (default 100) |
| No | If set, |
| No | Seconds a Datamesh staging/query request may wait on the gateway before the tool returns a timeout error (default 120) |
| No | Auth scheme for |
| No | Auth0 tenant domain for |
| No | Auth0 API audience for |
| No | Externally visible base URL (e.g. |
| No | Comma-separated browser origins allowed by CORS on http (default: |
* One token source (DATAMESH_TOKEN, DATAMESH_TOKEN_FILE or
DATAMESH_TOKEN_KEYRING) is required for the stdio transport (and for
--transport http with OCEANUM_MCP_AUTH=none); in authenticated http mode
each request carries its own credential and no server-side token is needed.
Hosted mode (HTTP transport)
Run any server as a shared, multi-tenant HTTP service:
oceanum-mcp datamesh --transport http --host 0.0.0.0 --port 8000This serves the MCP streamable-HTTP endpoint at http://<host>:<port>/<server>
(/datamesh here; override with --path). Each server owning its own path
lets several MCP servers share one domain behind an ingress — e.g.
https://mcp.oceanum.io/datamesh and https://mcp.oceanum.io/storage.
Every request must present a bearer credential, and all Datamesh/Storage calls
are made as that request's user — connections are cached per credential and
never shared between tokens.
Auth schemes (OCEANUM_MCP_AUTH):
auto(default) — accepts either credential, detected per request: Datamesh tokens arrive in theX-DATAMESH-TOKENheader (the same header the gateway itself uses), Auth0 JWTs inAuthorization: Bearer. A Datamesh token sent as the bearer also works (JWT-shape detection routes it), but the dedicated header is the canonical form. Each request runs as the identity its own credential resolves to.datamesh— only Datamesh tokens are accepted. The server validates them against the gateway. Add to Claude Code with:claude mcp add --transport http oceanum-datamesh https://mcp.oceanum.io/datamesh \ --header "X-DATAMESH-TOKEN: <datamesh-token>"auth0— clients send an Auth0-issued JWT, validated against the tenant JWKS and forwarded to the Datamesh gateway as-is.none— no authentication; every request uses the server's ownDATAMESH_TOKEN. Only for trusted-network deployments.
Notes:
export_queryworks over HTTP but changes shape: instead of writing to the server's local filesystem (meaningless for remote clients), it returns a time-limited, self-authenticating gatewaydownload_urlthat the caller fetches out-of-band. Thepathargument is ignored on hosted servers. The URL needs no credential, so it is a capability — treat it as a secret. Gateways with scoped download links (OCE-317) also limit its lifetime and number of fetches; the response then reports them asexpires_atandmax_uses. Hosted exports are capped at 10 GB to bound what one link can pull, and exports above 1 GB needconfirm_size_bytes(seeexport_query).A rejected Datamesh token (in
X-DATAMESH-TOKEN, or a non-JWTAuthorization: Bearer) gets a 401 saying the token was not accepted, without the OAuthresource_metadatachallenge (which would send clients such as VS Code into a sign-in flow that cannot fix a Datamesh token). Requests with no credential, and failed JWT (OAuth) bearers, still get the challenge, so OAuth discovery and re-authorization are unaffected. If the token could not be verified because the Datamesh service was unreachable, the response is a 503 asking to retry instead. A credential that is an unsubstituted client variable (${input:...}) gets a 401 saying so (except withOCEANUM_MCP_AUTH=none, where client credentials are ignored).Combine with
OCEANUM_MCP_READ_ONLY=1to run a read-only public service.Pass
--statelesswhen running behind a load balancer or on autoscaled platforms (Cloud Run, etc.): sessions are otherwise held in instance memory, and consecutive requests routed to different instances would fail.Breaking change for
--transport sse(deprecated): sse is a network transport and now behaves like http — authenticated by default and noexport_query. SetOCEANUM_MCP_AUTH=noneto restore the old unauthenticated behavior.
Serving under an external ASGI server
To run under uvicorn/gunicorn (multiple workers, serverless platforms), use
the packaged app factory — it applies the same auth and tool policy as the
CLI; serving mcp.http_app() directly would bypass both:
uvicorn --factory oceanum_mcp.app:create_http_app --host 0.0.0.0 --port 8000Requests on a network transport never fall back to the server's
DATAMESH_TOKEN: an unauthenticated request fails unless
OCEANUM_MCP_AUTH=none was set explicitly.
Browser clients (CORS)
Browser-based MCP clients send a CORS preflight (OPTIONS) before every
cross-origin request. The http app answers preflights for an allowlist of
origins, ahead of authentication (a preflight never carries a credential);
all other requests still require one. Configure the allowlist with
OCEANUM_MCP_CORS_ORIGINS, comma-separated:
OCEANUM_MCP_CORS_ORIGINS="https://*.oceanum.io,https://vscode.dev,http://localhost:6274"Unset:
https://*.oceanum.io,https://*.oceanum.techandhttps://vscode.dev.Empty string: CORS disabled — no CORS headers, preflights are not answered.
Each entry is an exact origin (
scheme://host[:port], no path). A leading*.matches exactly one subdomain label:https://*.oceanum.ioallowshttps://app.oceanum.iobut nothttps://oceanum.io,https://a.b.oceanum.ioorhttps://oceanum.io.evil.com. Bare*, single-label wildcards (https://*.io) and malformed entries are rejected at startup; a scheme-default port (:443on https) is dropped, as browsers omit it. Multi-label public suffixes (https://*.co.uk,https://*.github.io) cannot be detected — never configure them: they would admit every site under that suffix.Credentials travel in
Authorization/X-DATAMESH-TOKENheaders, never cookies, soAccess-Control-Allow-Credentialsis never sent.Mcp-Session-IdandWWW-Authenticateare exposed to browser scripts.
claude.ai custom connectors
Set OCEANUM_MCP_PUBLIC_URL to the server's public base URL and the auto
and auth0 modes additionally serve OAuth 2.0 Protected Resource Metadata
(RFC 9728) naming the Auth0 tenant, plus a WWW-Authenticate challenge on
401s — which is how claude.ai discovers where to send users to authorize.
The Auth0 tenant must allow client registration for Claude (Dynamic Client
Registration, or a pre-registered application) and issue JWT access tokens
for the configured audience. Header/bearer clients are unaffected either way.
Post-deploy smoke test
scripts/smoke_hosted.py opens real gridded datasources over zarr through a
deployed server (load_datasource, and a whole-grid query_data), which
catches a broken data stack in the image that tools/list does not. There is
no deploy pipeline (the hosted service is deployed by hand with the local
deploy_cloudrun*.sh scripts), so run it manually after each deploy:
DATAMESH_TOKEN=<token> uv run python scripts/smoke_hosted.py https://mcp.oceanum.io/datameshThe token must be valid for the gateway the server uses. --load-datasource,
--query-datasource and --query-variable override the default datasets.
The URL must be https unless the host is local, since the token is sent with
every request. Exit status: 0 all checks passed; 1 a check failed, or the
server was unreachable or rejected the token; 2 usage error
(DATAMESH_TOKEN unset, or a non-https remote URL); 3 inconclusive (a
datasource was not found, not shared or empty, the query was refused, or it
was small enough to be downloaded instead of opened over zarr).
The hosted image installs this package from the source checkout
(pip install .), not from PyPI, so dependency fixes take effect on the next
deploy from main without a release.
Datamesh Tools
The intended workflow is: search_catalog → get_datasource_info → stage_query
(dry run: learn the result size without downloading) → query_data for small
results inline, or export_query to write large results to a file that analysis
code reads directly.
search_catalog
Search the Datamesh catalog with optional text search, time range, and bounding box filters.
Returns a JSON object with count and results; if count equals limit, more matches may exist.
Only datasources accessible to the request's credentials are searched. An empty or short
(below limit, with nothing omitted) result carries a fixed scope note saying a missing datasource either does
not exist or is not accessible with these credentials; it never reveals whether, how many,
or which inaccessible datasources exist.
By default each result is a compact summary: id, name, a description
cut to 200 characters, tstart/tend, bounds (rounded outward to 4
decimals), variable names when the catalog provides them (first 20, with
variables_total), and the first 5 tags (each clipped to 60 characters,
with tags_total). Unusable bounds (empty or non-finite) are null.
detail="full" returns each datasource's complete catalog record instead.
The response is compact JSON, and its total size is bounded (~20k characters
for summaries, ~100k for full records): matches beyond the bound are dropped,
counted in omitted, and a note asks to refine the search.
The catalog ranks datasources by fuzzy similarity to the search text and
returns the closest ones even when none contains it. With search text, the
response therefore carries text_matches: how many results have every
search word (as a whole word, singular or plural) in their id, name, description, tags, labels
or variable names. or separates alternatives and negated words or phrases (-era5, -"era5 grid",
not era5) are ignored. This count is only a signal: no result is dropped
for failing it, but results that fail are marked "text_match": false, and
a text_note ahead of the results explains. If no result contains the text
as whole words (text_matches: 0), every result is still returned, but in
summary mode as id and name only, with a text_note first and no
scope note.
Parameter | Type | Description |
| string | Text search for name, description, or tags |
| string | ISO 8601 start time |
| string | ISO 8601 end time |
| list[float] | Bounding box |
| int | Max results to return (default 20) |
| string |
|
get_datasource_info
Get the metadata for a datasource: coverage, schema dims and coordinates, variables, and attributes.
The default (detail="summary") is a compact view with the same fields as
the full record. Each variable and coordinate keeps its dims, shape,
dtype and units/long_name/standard_name attributes only (other
attributes are counted in attrs_omitted); the description is clipped to
1,000 characters, global attributes and info are capped at 25 entries
(with *_omitted counts), and long values are clipped to 200 characters.
schema.data_vars/schema.attrs are omitted as duplicates of
variables/attributes. Past ~30k characters the summary sheds, in order
and only as far as needed: global attributes, coordinate attributes,
variable attributes other than units, variable shape/dtype, and finally
per-variable details; the note names what was shed. Every variable name is
always listed. detail="full" returns the complete record. Both are compact
JSON.
An unknown id adds suggestions: visible datasources whose id or name
differs from the requested one by a typo (at most one character edit per 7 characters, up
to 3, with the differing words still similar), or extends a request of two
or more words. An id that merely shares generic words such as
oceanum_wave_..._era5, or a single word such as wave, is never
suggested.
Parameter | Type | Description |
| string | Datasource ID |
| string |
|
stage_query
Dry-run a query on the Datamesh gateway: reports the result size, container
type, and domain length without downloading any data, echoes the canonical
query, and recommends the next step (inline query vs export vs narrowing).
The inline recommendation counts records as well as bytes: a result with more
records than OCEANUM_MCP_MAX_INLINE_ROWS would come back from query_data as
a preview, so it is steered to resampling, aggregation or export_query
instead. Accepts the same query parameters as query_data.
query_data
Query a datasource with filters and return small results inline as
coordinate-attributed JSON records with explicit truncated/lazy flags.
The query is staged first: gridded results above the inline limit are
summarized lazily (structure only); tabular results above the limit, and any
result above 1 GB, are refused with the staged size and alternatives (the
1 GB refusal also lists each variable's dims). The exception is limit
combined with time_resolution or aggregate_operations: the limited slice
may be small, so it is still opened lazily. Library warnings (e.g. the
2,000,000-row cap on tabular queries) are included in the response.
Parameter | Type | Description |
| string | Datasource to query |
| list[string] | Variables to select |
| string | ISO 8601 start of a time range (open-ended if omitted) |
| string | ISO 8601 end of a time range (open-ended if omitted) |
| list[string] | Discrete times (series selection); excludes |
| string | Server-side temporal downsampling (pandas frequency, e.g. |
| string | Resampling method for |
| list[float] | Bounding box |
| object | GeoJSON Feature (Point, MultiPoint, or Polygon) for selection |
| string | Interpolation for feature selection: nearest or linear |
| float | Max spatial resolution for downsampling, in CRS units |
| float | Minimum vertical level |
| float | Maximum vertical level |
| list[float] | Discrete vertical levels (series selection) |
| string | Interpolation for level series: nearest or linear |
| list[object] | Coordinate selections: |
| string/int | CRS for filter coordinates and returned data |
| list[string] | Aggregation ops: mean, min, max, std, sum |
| bool | Aggregate over spatial dims (default true) |
| bool | Aggregate over temporal dims (default true) |
| int | Keep the last N records (see below) |
limit keeps the last N records (Datamesh semantics: the last N steps along
time/ensemble), with the same meaning in stage_query, query_data, and
export_query. Combined with time_resolution or aggregate_operations it is
applied by this server after resampling/aggregation instead of being sent
to Datamesh (which would apply it to the native records first), so
stage_query reports the unlimited size as an upper bound. Hosted
export_query cannot apply it to a gateway download and refuses that
combination: drop limit or narrow the time range.
export_query
Export the full result of a query — the data-handle path for results too large to return inline. Behaviour depends on transport:
Local (stdio): writes the result to the local file
path(required) and returns that path. Gridded datasets stream lazily to NetCDF; tabular results write Parquet or CSV.Hosted (http/sse): returns a time-limited, self-authenticating gateway
download_url(chooseformat;pathis ignored). Fetch it out-of-band. When the response includesexpires_atormax_uses(gateways with scoped links), fetch it beforeexpires_atand at mostmax_usestimes. Results above 10 GB (for CSV, the estimated text size, about 3x the staged size) are refused (narrow the query); above 2 GB the link is returned with a large-download warning.
export_query sizes the result itself, whether or not stage_query was
called, and refuses before anything is exported. Results above the export cap
are refused outright: the cap limits the transfer, so splitting the request
into parts is not a way round it. An export that writes more than 1 GB in the
chosen format (CSV text is estimated at about 3x the staged size; locally, a
dataset written as CSV/Parquet is sized as the flattened table, and a limited
one on its limited slice) is refused unless confirm_size_bytes equals that
size. On hosted servers a value within 5% is accepted, because the download
stage is sized separately from stage_query's stage. The refusal reports the
exact value as export_size_bytes. The agent should pass it only after the
user has agreed. The server cannot see whether the user was asked, so the check
is advisory: it forces an explicit, size-aware step for each large export.
Accepts the same query parameters as query_data plus:
Parameter | Type | Description |
| string | Destination file path (parent directories are created) |
| string |
|
| bool | Overwrite an existing file (default false) |
| int | Bytes (in the chosen format) the user agreed to export; required above 1 GB; exact match (within 5% on hosted) |
load_datasource
Summarize an entire datasource. Gridded datasources are opened lazily (no data download); tabular datasources are downloaded only if under the inline size limit.
Parameter | Type | Description |
| string | Datasource to load |
update_metadata
Update metadata on an existing datasource. Only provided fields are changed.
Disabled when the server runs with OCEANUM_MCP_READ_ONLY set.
Parameter | Type | Description |
| string | Datasource to update |
| string | New name |
| string | New description |
| list[string] | New tags |
| list[string] | New labels |
| object | Additional metadata object |
| string | URL for datasource details |
Storage Tools
list_files
List files and directories in Oceanum cloud storage.
Parameter | Type | Description |
| string | Directory path to list (default: "/") |
| bool | List subdirectories recursively |
file_exists
Check if a file or directory exists in storage.
Parameter | Type | Description |
| string | Path to check |
read_file
Read the contents of a text file from storage.
Parameter | Type | Description |
| string | Path to the file |
write_file
Write text content to a file in storage.
Parameter | Type | Description |
| string | Destination path |
| string | Text content to write |
delete_file
Delete a file or directory from storage.
Parameter | Type | Description |
| string | Path to delete |
| bool | Delete directory contents recursively |
file_info
Get metadata about a file or directory.
Parameter | Type | Description |
| string | Path to inspect |
Example Workflows
Discover wave data in the Pacific:
search_catalog(search="wave", bbox=[120, -50, 180, 10])get_datasource_info(datasource_id="some-wave-dataset")stage_query(datasource_id="some-wave-dataset", variables=["Hs", "Tp"], time_start="2024-01-01", time_end="2024-01-31")to check the result sizequery_data(...)with the same parameters if small, orexport_query(..., path="waves.nc")if large
Shrink a 40-year hourly time series to something inline-sized:
stage_query(datasource_id="hindcast", variables=["Hs"], time_start="1984-01-01", time_end="2024-01-01")— too largequery_data(..., time_resolution="30D", time_resample="mean")— roughly monthly means, small enough to return inline (calendar aliases such as"1MS"are refused until a Datamesh engine fix ships: the engine currently reads"1MS"as 1 millisecond)
Browse and read files in cloud storage:
list_files(path="/")to see top-level contentslist_files(path="/my-project", recursive=True)to drill downread_file(path="/my-project/config.json")to read a file
Get a quick summary of a dataset:
get_datasource_info(datasource_id="my-dataset")to see variables and time rangequery_data(datasource_id="my-dataset", limit=10)to preview the data
Available Tools
13 toolsdatamesh_export_queryDatamesh Export QueryAIdempotent
Export the FULL result of a query — the data never enters the conversation.
Behavior depends on how the server is running:
Hosted (http/sse): returns a time-limited, self-authenticating gateway download_url (choose format via
format);pathis ignored. Fetch the URL out-of-band — it needs no credential, so treat it as a secret. When the response includes expires_at or max_uses, fetch it before expires_at and at most max_uses times. Refused above the hosted export cap, and for limit combined with time_resolution/aggregate_operations.Local (stdio): writes the result to the local file
path(required) and returns that path. Gridded datasets stream to NetCDF; tabular results write Parquet or CSV, as do datasets small enough to flatten into a table (e.g. point time series). Refused up front if the result exceeds the local export cap or the destination's free disk space. With limit plus time_resolution/aggregate_operations, the last N resampled steps are written.
The size is checked before anything is exported, whether or not stage_query was called. An export writing more than 1 GB in the chosen format (CSV text is about 3x; locally, a dataset written as CSV/Parquet is sized as the flattened table, and a limited one on its limited slice) is refused unless confirm_size_bytes equals that size (on hosted, within 5%, since the download stage is sized separately): ask the user first. The refusal states the exact value. The server cannot see whether the user was asked, so this is advisory: it forces an explicit, size-aware step. The export caps limit the transfer, not the size of each file: never split a refused request into parts to get under them.
A variable given as the exact CF standard_name of exactly one of the datasource's variables (e.g. "sea_surface_wave_significant_height" for "hs") is resolved to that variable; the response then includes resolved_variables ({requested: used}) and echoes the resolved names.
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | CRS for filter coordinates and returned data (EPSG code or CRS string). | |
| bbox | No | Bounding box [xmin, ymin, xmax, ymax] in WGS84 (or crs units if crs is set). | |
| path | No | Local (stdio) destination file path (required on stdio; parent directories are created; confined to OCEANUM_MCP_EXPORT_DIR when set). Ignored on hosted servers, which return a download URL. | |
| limit | No | Keep only the last N records (Datamesh semantics: the last N steps along time/ensemble). Combined with time_resolution or aggregate_operations it is applied AFTER resampling/aggregation (by this server, not sent to Datamesh), so stage_query sizes the unlimited result as an upper bound; hosted export_query refuses that combination. | |
| times | No | Discrete times to select (series selection). Mutually exclusive with time_start/time_end. | |
| format | No | Output format: netcdf (datasets), parquet or csv (tabular, or datasets small enough to flatten into a table such as point time series). Defaults by container: dataset -> netcdf, tabular -> parquet. | |
| levels | No | Discrete vertical levels to select (series selection). Mutually exclusive with level_min/level_max. | |
| time_end | No | ISO 8601 end of a time range. Open-ended if omitted. | |
| level_max | No | Maximum vertical level of a range. | |
| level_min | No | Minimum vertical level of a range. | |
| overwrite | No | Overwrite an existing local file (default false). Local export only. | |
| variables | No | List of variable names to select (e.g. ["temperature", "salinity"]). | |
| time_start | No | ISO 8601 start of a time range (e.g. "2023-01-01T00:00:00Z"). Open-ended if omitted. | |
| level_interp | No | Interpolation for level series selection: nearest or linear. | |
| coord_filters | No | Additional coordinate selections, e.g. [{"coord": "station", "values": ["A1", "B2"]}]. | |
| datasource_id | Yes | The datasource to query. | |
| time_resample | No | Resampling method when time_resolution is set: mean, nearest, or linear. | |
| time_resolution | No | Downsample a time range server-side to this resolution (pandas frequency string, e.g. "1h", "6h", "1D", "7D", or "30D" for roughly monthly). Drastically shrinks long time series. Monthly/quarterly/yearly calendar aliases (MS, ME, QS, YS) are not supported until a Datamesh engine fix ships: use "30D", "90D" or "365D". Finer than 1 minute is refused. | |
| geofilter_interp | No | Interpolation for feature selection: nearest or linear (default linear). | |
| aggregate_spatial | No | Aggregate over spatial dimensions (default true). | |
| geofilter_feature | No | GeoJSON Feature object (Point, MultiPoint, or Polygon geometry) for spatial selection/interpolation. Mutually exclusive with bbox. | |
| aggregate_temporal | No | Aggregate over the temporal dimension (default true). | |
| confirm_size_bytes | No | Required for results above 1 GB: the size in bytes, in the chosen format, the user has agreed to export (stage_query's size_bytes for the default format, or export_size_bytes from a refusal). Must match exactly (within 5% on hosted servers). Ignored for exports of 1 GB or less. | |
| aggregate_operations | No | Aggregations to apply after filtering: mean, min, max, std, sum. | |
| geofilter_resolution | No | Maximum spatial resolution for downsampling, in CRS units. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Given annotations only declare readOnlyHint=false, openWorldHint=true, idempotentHint=true, and destructiveHint=false, the description adds substantial behavioral context: hosted download URL secrecy, expiry/max_uses semantics, local file writing with overwrite behavior, size-check-before-export, and the advisory nature of confirm_size_bytes. It also warns against splitting refused requests. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and mode-dependent behavior, and every paragraph carries operational weight (size caps, secret handling, refusal conditions). It is however quite long and dense for a tool description; a bullet or table structure for hosted vs local differences could improve scanability without losing content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 25 parameters, an output schema (so return values need not be described), and the complexity of dual hosted/local behavior, the description covers all critical decision points: environment-dependent behavior, size confirmation, variable resolution, and refusal conditions. Nothing an agent needs in order to call it correctly or handle its response appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 100%, the baseline would be 3, but the description adds cross-parameter semantics not captured per-parameter in the schema: hosted vs local effects on `path` and `format`, the interaction of `limit` with `time_resolution`/`aggregate_operations`, and CF standard_name resolution for `variables`. These are meaningful additions beyond the schema, though many individual parameters (bbox, times, levels) are still only explained in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Export the FULL result of a query' and immediately differentiates itself by stating 'the data never enters the conversation'. This clearly distinguishes it from sibling tools like datamesh_query_data that presumably return data in-conversation. An agent can tell what this tool does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives rich context on when behavior changes (hosted vs local), when `path` is required or ignored, and when `confirm_size_bytes` is needed, including 'ask the user first'. It provides explicit refusal conditions (hosted cap, limit combined with resampling) but does not explicitly name an alternative sibling (e.g., datamesh_query_data or stage_query) for routine retrieval, leaving the when-to-use-this-vs-that inference to the reader.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_get_datasource_infoDatamesh Get Datasource InfoARead-only
Get the metadata for one datasource: coverage, coordinates and variables.
The default view keeps every field of the full record but reduces each variable and coordinate to its dims, shape, dtype, units, long_name and standard_name, clips the description and long attribute values, caps global attributes. On very large records it sheds attributes and then per-variable details (the note says which), but every variable name is always listed.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | "summary" (default) returns the compact view described above. "full" returns the complete record, including every attribute and variable; it can be very large. | summary |
| datasource_id | Yes | The unique ID of the datasource. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and openWorldHint already provided, the description adds significant behavioral context beyond annotations. It explains that the default view reduces fields, clips long values, caps global attributes, and may shed attributes on very large records while always listing every variable name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, and the second paragraph is dense but every clause explains useful truncation behavior. There is no redundant or filler text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema and annotations covering safety and openness, and the description supplies the missing behavioral details about truncation and large-record handling. An agent has enough information to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description nonetheless adds meaning about what the default/summary view actually returns, especially truncation and field reduction, beyond the enum descriptions in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: getting metadata for one datasource, including coverage, coordinates and variables. It is clear enough to distinguish this from sibling query/load/search tools, but it does not explicitly name or contrast those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the purpose: use this to retrieve metadata for a known datasource. The description does not explicitly say when to choose this over siblings such as datamesh_search_catalog or datamesh_query_data, nor does it state prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_load_datasourceDatamesh Load DatasourceARead-only
Summarize an entire datasource.
Gridded datasources are opened lazily (no data download). Tabular datasources are downloaded only if under the inline size limit; use query_data with filters to retrieve larger ones.
| Name | Required | Description | Default |
|---|---|---|---|
| datasource_id | Yes | The datasource to load. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavioral context beyond the readOnlyHint/openWorldHint annotations: gridded sources open lazily with no data download, tabular sources download only under an inline size limit, and oversize tabular data must go through query_data. It does not quantify the limit or describe failure behavior when a tabular source is too large and no query is issued.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action, then the type-specific behavior and the fallback path. No filler or restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description covers both datasource classes and the oversize fallback. The only remaining gap is the unquantified size limit and what a caller observes when a tabular source is skipped.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for the single datasource_id parameter, so the baseline is 3. The description adds no syntax, format, or ID-provenance detail beyond what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Summarize an entire datasource") and further splits behavior by datasource type (gridded vs tabular), which lets an agent scope it precisely. It names the sibling query_data as the alternative for large tabular data, though it does not contrast with other nearby siblings like datamesh_get_datasource_info.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit context: use this for whole-datasource summarization, and switch to query_data with filters when a tabular datasource exceeds the inline size limit. No explicit "do not use when" clause for gridded/tabular edge cases, but the routing condition is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_query_dataDatamesh Query DataARead-only
Query a datasource and return small results inline.
The query is staged first; results larger than the inline limit are not downloaded (datasets are summarized lazily, tabular queries are refused with alternatives), and results above 1 GB are refused with narrowing advice and each variable's dims, unless limit is combined with time_resolution/aggregate_operations (the limited slice may be small, so a dataset is then opened lazily). Use stage_query to size a query before calling this.
Inline values are a preview when preview is true (returned of total
records): never compute statistics from a preview; use
aggregate_operations or time_resolution instead.
limit keeps the last N records (Datamesh semantics: the last N steps along time/ensemble). Combined with time_resolution or aggregate_operations, limit is applied by this server AFTER resampling/aggregation (to the last N resampled steps, or the last N rows of a table) rather than sent to Datamesh. A limited result is a subset of the requested range, so it is flagged as a preview, with a limit_note.
A variable given as the exact CF standard_name of exactly one of the datasource's variables (e.g. "sea_surface_wave_significant_height" for "hs") is resolved to that variable; the response then includes resolved_variables ({requested: used}) and echoes the resolved names.
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | CRS for filter coordinates and returned data (EPSG code or CRS string). | |
| bbox | No | Bounding box [xmin, ymin, xmax, ymax] in WGS84 (or crs units if crs is set). | |
| limit | No | Keep only the last N records (Datamesh semantics: the last N steps along time/ensemble). Combined with time_resolution or aggregate_operations it is applied AFTER resampling/aggregation (by this server, not sent to Datamesh), so stage_query sizes the unlimited result as an upper bound; hosted export_query refuses that combination. | |
| times | No | Discrete times to select (series selection). Mutually exclusive with time_start/time_end. | |
| levels | No | Discrete vertical levels to select (series selection). Mutually exclusive with level_min/level_max. | |
| time_end | No | ISO 8601 end of a time range. Open-ended if omitted. | |
| level_max | No | Maximum vertical level of a range. | |
| level_min | No | Minimum vertical level of a range. | |
| variables | No | List of variable names to select (e.g. ["temperature", "salinity"]). | |
| time_start | No | ISO 8601 start of a time range (e.g. "2023-01-01T00:00:00Z"). Open-ended if omitted. | |
| level_interp | No | Interpolation for level series selection: nearest or linear. | |
| coord_filters | No | Additional coordinate selections, e.g. [{"coord": "station", "values": ["A1", "B2"]}]. | |
| datasource_id | Yes | The datasource to query. | |
| time_resample | No | Resampling method when time_resolution is set: mean, nearest, or linear. | |
| time_resolution | No | Downsample a time range server-side to this resolution (pandas frequency string, e.g. "1h", "6h", "1D", "7D", or "30D" for roughly monthly). Drastically shrinks long time series. Monthly/quarterly/yearly calendar aliases (MS, ME, QS, YS) are not supported until a Datamesh engine fix ships: use "30D", "90D" or "365D". Finer than 1 minute is refused. | |
| geofilter_interp | No | Interpolation for feature selection: nearest or linear (default linear). | |
| aggregate_spatial | No | Aggregate over spatial dimensions (default true). | |
| geofilter_feature | No | GeoJSON Feature object (Point, MultiPoint, or Polygon geometry) for spatial selection/interpolation. Mutually exclusive with bbox. | |
| aggregate_temporal | No | Aggregate over the temporal dimension (default true). | |
| aggregate_operations | No | Aggregations to apply after filtering: mean, min, max, std, sum. | |
| geofilter_resolution | No | Maximum spatial resolution for downsampling, in CRS units. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already signaling a read-only, open-world operation, the description adds extensive behavioral detail: staging happens first, oversized results are refused with narrowing advice, tabular queries may be refused, limited results are flagged as previews, and variable resolution is reported via resolved_variables. None of this contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The most important constraints — small inline results, staging, size refusals, and preview warnings — are front-loaded. The description is long but largely earns its length for a 21-parameter tool, though some limit and resampling details duplicate the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complex schema, annotations, and available output schema, the description covers the critical operational behavior: sizing, refusal conditions, preview limitations, and variable resolution. It could be more complete by explicitly directing large-result use cases to export_query, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 21 parameters thoroughly, including limit and time_resolution interactions. The description adds meaningful semantics for CF standard_name variable resolution and preview behavior, but much of its parameter discussion repeats what is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource — query a datasource and return small results inline — and clarifies the inline-size scope. It also mentions stage_query for sizing, but does not explicitly distinguish this tool's purpose from the sibling export_query, leaving some sibling selection ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear operational context: use stage_query before calling, previews should not be used for statistics, and aggregate_operations or time_resolution should be used instead. It also explains when large results are refused, but it does not explicitly name export_query as the alternative for larger exports, leaving one key routing decision implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_search_catalogDatamesh Search CatalogARead-only
Search the Oceanum Datamesh catalog for datasets.
Catalog search only covers datasources accessible to the credentials used for this request; a datasource missing from the results either does not exist or is not accessible with these credentials, so do not report it as nonexistent.
| Name | Required | Description | Default |
|---|---|---|---|
| bbox | No | Bounding box as [xmin, ymin, xmax, ymax] in WGS84 coordinates. | |
| limit | No | Maximum number of datasources to return (default 20, minimum 1). | |
| detail | No | "summary" (default) returns id, name, a short description, time range, bounds, and variable names when known. "full" returns each datasource's complete catalog record; prefer get_datasource_info for one datasource's details. | summary |
| search | No | Text search string to filter datasources by name, description, or tags. | |
| time_end | No | ISO 8601 datetime for end of time range filter (e.g. "2023-12-31"). | |
| time_start | No | ISO 8601 datetime for start of time range filter (e.g. "2023-01-01"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds real behavioral context beyond that: results are credential-scoped, and a datasource absent from results may simply be inaccessible rather than nonexistent—an important constraint for interpreting output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, purpose front-loaded, no wasted preamble. The second sentence is slightly redundant—'either does not exist or is not accessible with these credentials' largely restates 'do not report it as nonexistent'—but the constraint is worth stating once.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return-value detail is unnecessary, and the description covers the key interpretive caveat for a search tool. It could go further by noting pagination/limit interaction or pointing to get_datasource_info for single-record lookups, but nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (bbox, limit, detail, search, time_start, time_end) is already documented in the schema. The description contributes no additional parameter meaning, which is the expected baseline when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search the Oceanum Datamesh catalog for datasets'), making the operation unambiguous. It does not, however, differentiate itself from siblings like datamesh_get_datasource_info; that routing distinction only appears in the schema's 'detail' parameter, not in the description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The accessibility caveat ('catalog search only covers datasources accessible to the credentials used for this request') is genuinely useful usage guidance. But the description never says when to prefer this tool over siblings such as get_datasource_info for a single dataset, or when a text/bbox/time filter is the right approach—usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_stage_queryDatamesh Stage QueryARead-only
Dry-run a query: report the result size WITHOUT downloading any data.
Always stage before retrieving data you have not sized. The response says whether the result is small enough for query_data to return inline, and echoes the canonical query. With limit plus time_resolution or aggregate_operations the reported size is that of the unlimited result (limit is applied after resampling), so it is an upper bound.
A variable given as the exact CF standard_name of exactly one of the datasource's variables (e.g. "sea_surface_wave_significant_height" for "hs") is resolved to that variable; the response then includes resolved_variables ({requested: used}) and echoes the resolved names.
| Name | Required | Description | Default |
|---|---|---|---|
| crs | No | CRS for filter coordinates and returned data (EPSG code or CRS string). | |
| bbox | No | Bounding box [xmin, ymin, xmax, ymax] in WGS84 (or crs units if crs is set). | |
| limit | No | Keep only the last N records (Datamesh semantics: the last N steps along time/ensemble). Combined with time_resolution or aggregate_operations it is applied AFTER resampling/aggregation (by this server, not sent to Datamesh), so stage_query sizes the unlimited result as an upper bound; hosted export_query refuses that combination. | |
| times | No | Discrete times to select (series selection). Mutually exclusive with time_start/time_end. | |
| levels | No | Discrete vertical levels to select (series selection). Mutually exclusive with level_min/level_max. | |
| time_end | No | ISO 8601 end of a time range. Open-ended if omitted. | |
| level_max | No | Maximum vertical level of a range. | |
| level_min | No | Minimum vertical level of a range. | |
| variables | No | List of variable names to select (e.g. ["temperature", "salinity"]). | |
| time_start | No | ISO 8601 start of a time range (e.g. "2023-01-01T00:00:00Z"). Open-ended if omitted. | |
| level_interp | No | Interpolation for level series selection: nearest or linear. | |
| coord_filters | No | Additional coordinate selections, e.g. [{"coord": "station", "values": ["A1", "B2"]}]. | |
| datasource_id | Yes | The datasource to query. | |
| time_resample | No | Resampling method when time_resolution is set: mean, nearest, or linear. | |
| time_resolution | No | Downsample a time range server-side to this resolution (pandas frequency string, e.g. "1h", "6h", "1D", "7D", or "30D" for roughly monthly). Drastically shrinks long time series. Monthly/quarterly/yearly calendar aliases (MS, ME, QS, YS) are not supported until a Datamesh engine fix ships: use "30D", "90D" or "365D". Finer than 1 minute is refused. | |
| geofilter_interp | No | Interpolation for feature selection: nearest or linear (default linear). | |
| aggregate_spatial | No | Aggregate over spatial dimensions (default true). | |
| geofilter_feature | No | GeoJSON Feature object (Point, MultiPoint, or Polygon geometry) for spatial selection/interpolation. Mutually exclusive with bbox. | |
| aggregate_temporal | No | Aggregate over the temporal dimension (default true). | |
| aggregate_operations | No | Aggregations to apply after filtering: mean, min, max, std, sum. | |
| geofilter_resolution | No | Maximum spatial resolution for downsampling, in CRS units. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint/openWorldHint, so the safety bar is already met; the description still earns credit by disclosing non-obvious behavior: no data is downloaded, limit+resampling makes the size an upper bound, and CF standard_name variables get resolved with resolved_variables echoed back. It omits cost/latency or rate-limit context for what is effectively a repeated exploratory call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core dry-run semantics, then caveats in descending priority; every sentence carries information. It is a bit long and partially restates the limit/time_resolution interaction already present in the limit parameter description, which is mild redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 21 parameters, an output schema, and annotations, the description covers what structured fields cannot: that nothing is downloaded, how the size verdict relates to query_data, and the upper-bound caveat. Nothing essential for correct invocation is missing, though staging cost and whether the echoed canonical query is reusable could be stated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3 and the schema already documents all 21 parameters. The description adds genuine meaning beyond it by specifying the CF standard_name resolution rule for variables and how the response echoes resolved names, a behavior not stated in the variables schema field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource pairing ("Dry-run a query: report the result size WITHOUT downloading any data") that immediately distinguishes it from siblings like datamesh_query_data and datamesh_export_query. An agent can tell exactly what this tool does without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit usage rule ("Always stage before retrieving data you have not sized") and routes the agent by naming query_data as the consumer of the size verdict. It does not explicitly cover the export path or state the inverse exclusion ("do not use this to fetch data"), so routing is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
datamesh_update_metadataDatamesh Update MetadataADestructiveIdempotent
Update metadata properties on an existing datasource.
Only the provided fields will be updated; others remain unchanged. Not available when the server runs with OCEANUM_MCP_READ_ONLY set.
| Name | Required | Description | Default |
|---|---|---|---|
| info | No | Additional metadata as a JSON object. | |
| name | No | New human-readable name (max 128 chars). | |
| tags | No | New list of keyword tags. | |
| labels | No | New list of metadata labels. | |
| details | No | URL with further details about the datasource. | |
| description | No | New description (max 1500 chars). | |
| datasource_id | Yes | The datasource to update. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true. The description adds genuinely new behavioral context: only supplied fields are modified and the rest remain untouched, plus the read-only-mode availability gate. It does not explain what makes the operation destructive (e.g. overwriting existing field values), which is the one remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action, then the partial-update rule, then the availability gate. No filler and every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. For a mutation tool with full schema coverage and rich annotations, the description covers scope, partial-update semantics, and the read-only limitation. Only the destructive consequence is left implicit for the agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all seven parameters including datasource_id, info, name, tags, labels, details, and description are already documented with formats and length limits in the schema. The description adds nothing parameter-specific here, which is the expected baseline when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ("Update metadata properties on an existing datasource"), which is unambiguous and clearly distinct from the read-oriented siblings (search_catalog, get_datasource_info, query_data). It stops short of naming any sibling, but since no other tool in the set performs updates, differentiation is implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear when-not condition ("Not available when the server runs with OCEANUM_MCP_READ_ONLY set") and clarifies the partial-update contract, so an agent knows changes are additive per-field. No alternative tool is named, but none exists in this family for metadata mutation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_delete_fileStorage Delete FileC
Delete a file or directory from Oceanum storage.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to delete. | |
| recursive | No | For directories, delete contents recursively. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it says nothing about permanence, whether directories must be empty, permission requirements, or whether the operation can be undone. For a destructive delete tool with zero annotation coverage, this is a substantial gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single efficient sentence with the resource front-loaded and no padding. It is well-sized, though its brevity is partly under-specification rather than tight information density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, but a destructive tool with no annotations and no description of irreversibility or failure modes leaves the agent without critical context for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both 'path' and 'recursive' are already documented in the schema. The description adds no syntax, format, or behavioral nuance beyond what the schema states, which is the baseline expectation when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (file or directory) scoped to Oceanum storage, which is enough to separate it from storage_write_file, storage_read_file, and storage_list_files. It does not explicitly name a sibling or contrast with one, so it falls short of the top score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers no guidance on when to use this tool versus alternatives, no prerequisites, and no mention that deletion is likely irreversible. The only usage-adjacent hint lives in the schema's 'recursive' field, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_file_existsStorage File ExistsB
Check if a file or directory exists in Oceanum storage.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to check. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. 'Check if ... exists' strongly implies a side-effect-free boolean query, and the existence of an output schema means return format need not be explained. However, it says nothing explicit about read-only semantics, permissions, or behavior for non-existent/invalid paths.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the verb and scope front-loaded and zero wasted words. Nothing to trim and nothing important buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter existence check with a fully documented schema and an output schema covering the return value, the description is nearly sufficient. The only missing piece is any hint about path conventions or behavior for special cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and there is a single required parameter, so baseline is 3. The description adds no extra meaning about path format (absolute vs relative, bucket prefixes, directory conventions) beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('check if a file or directory exists') scoped to 'Oceanum storage', which is unambiguous and distinct from siblings like storage_read_file or storage_list_files. It doesn't explicitly name those siblings, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this versus alternatives such as storage_file_info or storage_list_files, nor any note about prerequisites or typical contexts. The agent must infer usage entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_file_infoStorage File InfoB
Get metadata about a file or directory in Oceanum storage.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to inspect. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It adds only that the target may be a file or a directory; it does not say whether a missing path errors or returns empty, whether it follows symlinks, or what permissions are required for Oceanum storage. For a bare read tool this leaves notable gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler. The core verb and resource lead the sentence, and nothing is repeated from the title or restated redundantly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple: one required path parameter and an output schema that already documents the returned metadata fields, so the description need not explain return values. It is largely complete for such a low-complexity read operation, though it omits error behavior on nonexistent paths.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage ('Path to inspect.'), so the schema already documents it. The description adds no format examples, accepted path prefixes, or relative-vs-absolute semantics beyond what the schema provides, matching the baseline of 3 when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'Get metadata about a file or directory in Oceanum storage.' An agent can distinguish it from storage_read_file, storage_list_files and storage_write_file because it returns metadata rather than content or listings. It stops short of explicitly naming siblings or the info-only scope, so it is clear but not fully differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no when-to-use guidance: nothing says when to prefer this over storage_file_exists (existence check) or storage_list_files (enumerate a directory). Usage is only implied by the tool's name and purpose. No prerequisites, exclusions, or alternatives are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_list_filesStorage List FilesC
List files and directories in Oceanum cloud storage.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Directory path to list (default: root "/"). | / |
| recursive | No | Whether to list subdirectories recursively. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. 'List' implies a read-only operation, but the description says nothing about permissions, authentication, non-recursive default behavior, or rate/pagination limits, leaving behavioral traits to inference.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler or redundancy. It is efficient, though its brevity edges toward under-specification rather than maximal information density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (two optional params) and has an output schema, so return values need not be described. However, with no annotations the agent gets no explicit confirmation of the read-only nature or permission requirements, leaving a small but real gap for an otherwise minimal definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both 'path' and 'recursive' are fully documented in the schema, making 3 the baseline. The description adds no syntax or format detail (e.g., what a recursive listing returns) beyond what the schema already conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and resource ('files and directories in Oceanum cloud storage'), which an agent can easily distinguish from sibling reads like storage_file_info or storage_read_file. It stops short of explicitly naming sibling alternatives, so it is clear but not differentiated at the highest level.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no alternatives are named. The listing verb implies a browse/explore use case, but nothing tells the agent when to prefer this over storage_file_info or datamesh_search_catalog.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_read_fileStorage Read FileB
Read the contents of a text file from Oceanum storage.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden; 'Read' implies a non-mutating operation, and the 'text file' qualifier usefully signals that binary content may be unsupported. However, it says nothing about missing-file behavior, permissions, encoding, or size limits, which are real risks for a file fetch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence that front-loads the action and resource with zero filler. Correctly sized for a one-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, the sole parameter is documented in the schema, and an output schema exists so return values need not be described. Only error/edge-case behavior (missing file, binary content) is left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter exists and schema description coverage is 100%, so the schema already documents 'path' fully. The description adds no path syntax, relative-vs-absolute, or format detail beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (read) and resource (contents of a text file) scoped to Oceanum storage, which cleanly distinguishes it from write/delete/list siblings. It stops short of naming an alternative or explicitly contrasting with storage_list_files or storage_file_info.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use guidance, no prerequisites, and no reference to alternatives such as storage_file_info (metadata) versus this tool (contents). Usage is only inferable from the verb.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
storage_write_fileStorage Write FileA
Write text content to a file in Oceanum storage.
Creates the file if it doesn't exist, overwrites if it does.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Destination path in Oceanum storage. | |
| content | Yes | Text content to write. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does disclose the most consequential behavior — silent overwrite of existing files — which is genuinely useful for data-loss avoidance. However it says nothing about required permissions, content encoding/type handling, size limits, or whether the write is atomic, leaving meaningful gaps for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler. The core action is front-loaded and the create-or-overwrite caveat immediately follows, so nothing has to be hunted for.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the schema fully covers both parameters. For a simple two-parameter write, the description covers the essential behavioral surprise (overwrite). Only minor gaps remain — no auth/permission note, which matters for a mutation tool with no annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are documented there, so the baseline is 3. The description adds no syntax, path-format, or content-format detail beyond what 'path' and 'content' already convey in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Write text content to a file in Oceanum storage.' The verb contrasts naturally with siblings like storage_read_file and storage_delete_file, though it never names a sibling explicitly. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the operation itself (write/overwrite a file), but there is no statement of when to prefer this over storage_delete_file or storage_file_exists, nor any prerequisite guidance. The 'creates if absent, overwrites if present' line does hint at idempotent upsert semantics, which is the closest thing to usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.6.0- Changed
datamesh_export_query1 field changed- added
Input schema / properties / confirm_size_bytesAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Required for results above 1 GB: the size in bytes, in the chosen format, the user has agreed to export (stage_query's size_bytes for the default format, or export_size_bytes from a refusal). Must match exactly (within 5% on hosted servers). Ignored for exports of 1 GB or less." +}
- Changed
datamesh_get_datasource_info1 field changed- changed
Input schema / properties / detail / descriptionPrevious value: -"\"summary\" (default) returns the bounded view described above. \"full\" returns the complete record, including every attribute; it can be very large."New value: +"\"summary\" (default) returns the compact view described above. \"full\" returns the complete record, including every attribute and variable; it can be very large."
13 tool updates
v0.5.2- First observed
datamesh_export_query - First observed
datamesh_get_datasource_info - First observed
datamesh_load_datasource - First observed
datamesh_query_data - First observed
datamesh_search_catalog - First observed
datamesh_stage_query - First observed
datamesh_update_metadata - First observed
storage_delete_file - First observed
storage_file_exists - First observed
storage_file_info - First observed
storage_list_files - First observed
storage_read_file - First observed
storage_write_file
TDQS
Scored across 13 tools
The data-access tools are clearly tiered by role: search_catalog finds datasources, get_datasource_info/stage_query inspect metadata and size, query_data returns inline previews, and export_query offloads large results. The only real friction is load_datasource ('summarize an entire datasource') versus get_datasource_info ('metadata for one datasource'), which can look interchangeable at a glance, plus the storage_file_exists/storage_file_info pair.
Every name is snake_case with a clear domain prefix (datamesh_/storage_) and most follow verb_noun (query_data, export_query, stage_query, list_files, read_file, delete_file). The deviations are minor: load_datasource rather than get_datasource, and the noun-first storage_file_exists/storage_file_info.
Thirteen tools split cleanly into two domains (7 datamesh, 6 storage), each earning its place in the query/export workflow. Nothing feels redundant or padded at this size.
The data pipeline is covered end-to-end (discover → inspect → stage → query → export → update metadata) and storage has full create/read/list/delete/stat coverage. Gaps remain: no datasource creation or deletion, no storage copy/move, and metadata updates are the only write path for the catalog.
Maintenance
Related MCP Connectors
Access Pollinations models and API capabilities through agent tools.
Read and write KukGit repositories, files, issues and pull requests from an AI assistant.
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
Read Physical AI datasets, projects, fleet and quality data. Requires authorized Avala access.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAccess oceanographic and environmental data from 63+ ERDDAP servers worldwide through natural language queries. Search datasets, retrieve metadata, and download scientific data for climate research, marine biology, and coastal management.18-

Code Ocean MCP Serverofficial
AlicenseBqualityBmaintenanceProvides tools to search and execute Code Ocean capsules and pipelines while managing platform data assets. It enables users to interact with Code Ocean's computational resources and scientific workflows directly through natural language interfaces.26270 PyPI5MIT- FlicenseCqualityDmaintenanceEnables LLMs to interact with ERDDAP search, metadata, and tabledap services for oceanographic data.51-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with the OSDU® data platform through Model Context Protocol, providing tools for search, storage, schema management, and dataset operations.2Apache 2.0