Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ It supports local execution and optional remote execution on HPC clusters via

The tool surface is built by `uxarray_mcp.registry.build_registry()`:

- **`core` (default, ~27 tools)** — 11 front-door gateway tools at the
- **`core` (default, ~31 tools)** — 11 front-door gateway tools at the
top level, 12 control/status tools under `session/` and `hpc/`
namespaces, `io-list_datasets`, and 3 prompt helpers under `prompt/`.
namespaces, `io-list_datasets`, and 7 prompt helpers under `prompt/`.
No deferred tools, no BM25 discovery. This is what clients see by
default when running `uxarray-mcp serve`.

Expand All @@ -54,7 +54,8 @@ HPC control (`hpc/`): `endpoint_status`, `get_execution_mode`,
IO (`io/`): `list_datasets`.

Prompt helpers (`prompt/`): `first_look`, `vorticity_analysis`,
`hpc_diagnose`.
`cyclone_structure`, `eddy_activity`, `model_evaluation`,
`climatology_anomaly`, `hpc_diagnose`.

Low-level implementation functions such as `inspect_mesh`, `calculate_area`,
`plot_mesh`, and `calculate_curl` remain importable from `uxarray_mcp.tools`
Expand Down
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ uses Semantic Versioning for public releases.

## Unreleased

### Added
- Guided science workflows as `prompt/` tools, each composing existing
operations around a scientific question: `cyclone_structure` (storm radial
structure), `eddy_activity` (departures from the zonal mean),
`model_evaluation` (bias/RMSE/pattern correlation vs a reference), and
`climatology_anomaly` (time-mean state and anomalies). These join the existing
`vorticity_analysis` workflow.
- `run_analysis` operation `zonal_anomaly` — per-face deviation from the zonal
mean of each latitude band (`UxDataArray.zonal_anomaly`).
- `run_analysis` operation `remap_to_rectilinear` — remap an unstructured
variable onto a regular lon/lat grid (`UxDataArray.remap.to_rectilinear`).
- `gradient` and `curl` operations now accept a `scale_by_radius` flag. It
defaults to `False` to preserve unit-sphere results; set it to `True` to
divide by `uxgrid.sphere_radius` for physical units.

### Changed
- Bumped the `uxarray` floor to `>=2026.6.0` for the new zonal-anomaly,
rectilinear-remap, and radius-scaled gradient/curl APIs.

## 0.2.0 — 2026-06-19

### Changed
- **Server engine**: replaced FastMCP with
[toolregistry](https://github.com/Oaklight/ToolRegistry) +
Expand Down Expand Up @@ -32,6 +53,14 @@ uses Semantic Versioning for public releases.
- `fastmcp` dependency.
- `@mcp.prompt()` decorators (replaced by `prompt/` namespace tools).

## 0.1.1 — 2026-06-11

### Changed
- Pinned Python to `>=3.12,<3.13` to match the supported runtime and avoid
Globus Compute pickle version-mismatch failures.
- Aligned the published package metadata with the current PyPI release for the
conda-forge recipe.

## 0.1.0 — 2026-06-04

Initial public release.
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ remotely on an HPC system you have access to.
> / vorticity / divergence, subset, remap, plot, and run multi-step workflows.
> All as natural-language prompts.

> **Local by default; HPC is opt-in.** Everything runs on your machine unless
> you configure a [Globus Compute](https://www.globus.org/compute) endpoint.
> The remote option only becomes available once such an endpoint exists —
> running one requires an account and allocation on that HPC system, though a
> shared/service-account endpoint can let authorized users submit without their
> own login.

> **⚠️ What the AI can access.** Any file you (or your HPC account) can read.
> Any compute the configured endpoint can submit. Outputs are written to your
> disk. **See [SECURITY.md](SECURITY.md) before connecting any remote endpoint.**
Expand Down
12 changes: 12 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ These modules contain the pure computation logic, separate from MCP and I/O.
:members:
:undoc-members:

.. automodule:: uxarray_mcp.domain.vector_calc
:members:
:undoc-members:

.. automodule:: uxarray_mcp.domain.plotting
:members:
:undoc-members:
Expand All @@ -33,10 +37,18 @@ Tools

MCP tool functions that are exposed to AI agents.

.. automodule:: uxarray_mcp.tools.frontdoor
:members:
:undoc-members:

.. automodule:: uxarray_mcp.tools.inspection
:members:
:undoc-members:

.. automodule:: uxarray_mcp.tools.vector_calc
:members:
:undoc-members:

.. automodule:: uxarray_mcp.tools.capabilities
:members:
:undoc-members:
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ <h1>UXarray MCP Server — Architecture Diagram</h1>
</div>
<div class="branch">
<svg width="12" height="12" viewBox="0 0 16 16" fill="#58a6ff"><path d="M11.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5zm-2.25.75a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.492 2.492 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25z"/></svg>
<b>feature/tool-discovery</b> &nbsp;·&nbsp; Python 3.13 &nbsp;·&nbsp; FastMCP
<b>main</b> &nbsp;·&nbsp; Python 3.12 &nbsp;·&nbsp; toolregistry-server
</div>
</div>

Expand Down Expand Up @@ -173,7 +173,7 @@ <h1>UXarray MCP Server — Architecture Diagram</h1>
<text x="180" y="30" text-anchor="middle" font-size="14" font-weight="700" fill="#58a6ff" font-family="Inter,sans-serif">CLAUDE DESKTOP</text>
<text x="180" y="43" text-anchor="middle" font-size="10" fill="#484f58" font-family="Inter,sans-serif">MCP Client</text>
<text x="540" y="30" text-anchor="middle" font-size="14" font-weight="700" fill="#58a6ff" font-family="Inter,sans-serif">MCP SERVER</text>
<text x="540" y="43" text-anchor="middle" font-size="10" fill="#484f58" font-family="Inter,sans-serif">FastMCP · Provenance · Dynamic Registration</text>
<text x="540" y="43" text-anchor="middle" font-size="10" fill="#484f58" font-family="Inter,sans-serif">toolregistry-server · Provenance · Policy Tags</text>
<text x="900" y="30" text-anchor="middle" font-size="14" font-weight="700" fill="#bc8cff" font-family="Inter,sans-serif">SCIENTIFIC AGENT</text>
<text x="900" y="43" text-anchor="middle" font-size="10" fill="#484f58" font-family="Inter,sans-serif">Analyze → Plan → Execute → Verify</text>
<text x="1260" y="30" text-anchor="middle" font-size="14" font-weight="700" fill="#56d364" font-family="Inter,sans-serif">LOCAL UXARRAY</text>
Expand Down
7 changes: 6 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@
}

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
exclude_patterns = [
"_build",
"Thumbs.db",
".DS_Store",
"onepager-uxarray-mcp.md",
]

# -- Options for HTML output -------------------------------------------------

Expand Down
23 changes: 16 additions & 7 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,33 @@ UXarray MCP Server

An MCP server that connects AI assistants like Claude to
`UXarray <https://uxarray.readthedocs.io/>`_ for analyzing unstructured
climate and weather meshes. Supports local execution and remote HPC
via Globus Compute.
climate and weather meshes. It runs locally by default; HPC execution via
Globus Compute is optional and only active once you configure an endpoint.

The same tools are served over MCP (for AI clients) or OpenAPI/REST (for
HTTP clients) from a single install.

.. toctree::
:maxdepth: 2
:caption: User Guide
:caption: Getting started

getting-started
tools
serving
workflows
scientific-agent

.. toctree::
:maxdepth: 2
:caption: Running on HPC (optional)

remote-hpc
operating-an-endpoint
globus-compute
tools
operating-an-endpoint
hpc
improv
ucar
chrysalis
workflows
scientific-agent

.. toctree::
:maxdepth: 2
Expand Down
102 changes: 102 additions & 0 deletions docs/serving.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Serving and Transports

The server is built on
[toolregistry](https://github.com/Oaklight/ToolRegistry) +
[toolregistry-server](https://github.com/Oaklight/toolregistry-server). The same
tool implementations are exposed over multiple protocols from a single process,
so the server is not tied to any one client. Claude Desktop is the default
target, but the tools are equally usable over REST or from plain Python.

For the Claude Desktop quickstart, see {doc}`getting-started`. This page covers
the additional surfaces the engine provides.

## The `serve` command

```bash
uxarray-mcp serve [--profile {core,deferred-full}]
[--transport {stdio,sse,http}]
[--host HOST] [--port PORT]
```

With no flags, `uxarray-mcp serve` starts MCP over stdio with the `core`
profile — the same behavior earlier releases had. Existing Claude Desktop
configurations work unchanged.

The server is assembled by `UXarrayApp`, an `App` subclass from
toolregistry-server that carries a single `ServerIdentity` (name, version,
description) shared by every transport. The same object also drives the
`openapi` command below.

## Profiles

The visible tool surface is selected by `--profile`:

| Profile | Visible tools | Use when |
|---|---|---|
| `core` (default) | ~31 | Most clients. Front-door gateway tools, session/HPC control, `list_datasets`, and prompts. Predictable, conservative. |
| `deferred-full` | ~31 visible (+32 deferred) | You want the full low-level surface. The raw implementation tools load with `defer=True`, so they do not appear in the initial list; agents find them with `discover_tools`. |

```bash
uxarray-mcp serve --profile deferred-full
```

In `core`, low-level operations are still reachable through the front-door
dispatchers (for example `run_analysis(operation="curl", ...)`).

## Transports

`--transport` selects the MCP transport:

| Transport | Description |
|---|---|
| `stdio` (default) | Subprocess transport used by Claude Desktop and Claude Code. |
| `sse` | Server-Sent Events over HTTP. Bind with `--host`/`--port`. |
| `http` | Streamable HTTP. Bind with `--host`/`--port`. |

```bash
uxarray-mcp serve --transport sse --host 127.0.0.1 --port 8001
uxarray-mcp serve --transport http --port 8000
```

## OpenAPI / REST

The same tools can be exposed as an OpenAPI/REST service for clients that speak
HTTP rather than MCP — curl, cloud assistants, chat UIs, or scripts. Install the
optional extra and start the `openapi` command:

```bash
pip install "uxarray-mcp[openapi]"

uxarray-mcp openapi [--profile {core,deferred-full}] [--host HOST] [--port PORT]
```

The tool implementations, provenance, and HPC dispatch are shared across MCP and
REST; only the protocol adapter differs. MCP and OpenAPI can run as separate
processes from the same install — for example `uxarray-mcp serve` for AI clients
and `uxarray-mcp openapi` for HTTP clients, behind a reverse proxy if needed.

## Tool discovery (`deferred-full`)

In the `deferred-full` profile, deferred tools are searchable via
`discover_tools`, which ranks tools by a BM25 match over names, docstrings, and
domain search hints. For example, a query like `"compute vorticity wind curl"`
surfaces `calculate_curl`. Operators can also promote deferred tools to the
visible set from the admin panel.

## Using the tools without an MCP client

Because the tools are ordinary Python functions, you can drive them directly —
no AI client, no transport:

```python
from uxarray_mcp.tools import inspect_mesh
result = inspect_mesh(file_path="grid.nc") # dict with a _provenance block

# Or call by name through the same registry the server uses:
from uxarray_mcp.app import make_registry
reg = make_registry(profile="core")
run_analysis = reg.get_callable("run_analysis")
stats = run_analysis(operation="calculate_area", grid_path="grid.nc")
```

This is the basis for the REST surface and for pipeline/post-processing use.
66 changes: 59 additions & 7 deletions docs/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ clients should use the intent-shaped tools below.
Most tools return structured dictionaries with a `_provenance` block. Plotting
returns MCP content blocks: an inline PNG plus JSON metadata.

The visible tool set depends on the profile (`core` by default, or
`deferred-full`), and the server can expose these tools over MCP stdio/SSE/HTTP
or OpenAPI/REST. See {doc}`serving` for profiles, transports, and tool
discovery.

## Front-Door Tools

### `get_capabilities`
Expand Down Expand Up @@ -43,10 +48,12 @@ Supported operations:
| `validate_dataset` | NaN/Inf/fill-value checks |
| `calculate_area` | Face area statistics |
| `calculate_zonal_mean` | Latitude-band mean for a face-centered variable |
| `zonal_anomaly` | Per-face deviation from its latitude-band zonal mean |
| `gradient`, `curl`, `divergence`, `azimuthal_mean` | Vector/radial diagnostics |
| `subset_bbox`, `subset_polygon`, `cross_section` | Spatial selections |
| `compare_fields`, `bias`, `rmse`, `pattern_correlation` | Same-grid comparisons |
| `remap_variable`, `regrid_dataset` | UXarray-backed remapping |
| `remap_to_rectilinear` | Remap a variable onto a regular lon/lat grid |
| `temporal_mean`, `anomaly` | Time-dimension summaries |
| `ensemble_mean`, `ensemble_spread` | Multi-file ensemble summaries |
| `export` | Write a persisted result or dataset to NetCDF/CSV |
Expand All @@ -57,11 +64,40 @@ Common parameters include `grid_path`, `data_path`, `variable_name`,
`endpoint`. Each operation validates the parameters it requires and returns a
clear error if one is missing.

`gradient` and `curl` accept `scale_by_radius` (default `False`). When `False`,
results stay on the unit sphere (the historical behavior). Set it to `True` to
divide by `uxgrid.sphere_radius` for physical units; the grid must define
`sphere_radius`.

`zonal_anomaly` and `remap_to_rectilinear` are backed by
`UxDataArray.zonal_anomaly` and `UxDataArray.remap.to_rectilinear`, available in
the pinned UXarray (`>=2026.6.0`).

> **Local-only:** `zonal_anomaly` and `remap_to_rectilinear` currently run on the
> local machine and do not have a remote (Globus Compute) execution path yet, so
> they cannot operate on files that live only on an HPC filesystem. The other
> compute operations accept `use_remote=True`. Uniform HPC routing across all
> operations is tracked as a design item.

Examples:

```python
run_analysis(operation="inspect_mesh", grid_path="healpix:4")
run_analysis(operation="calculate_area", grid_path="/path/grid.nc")
run_analysis(
operation="zonal_anomaly",
grid_path="/path/grid.nc",
data_path="/path/data.nc",
variable_name="temperature",
)
run_analysis(
operation="remap_to_rectilinear",
grid_path="/path/grid.nc",
data_path="/path/data.nc",
variable_name="temperature",
target_lon=[0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330],
target_lat=[-60, -30, 0, 30, 60],
)
run_analysis(
operation="calculate_zonal_mean",
grid_path="/path/grid.nc",
Expand Down Expand Up @@ -134,13 +170,29 @@ dispatcher either falls back locally or reports a structured readiness error.

## MCP Prompts

Prompts are user-invokable slash commands. In Claude Code or Claude Desktop
they appear as `/first_look`, `/vorticity_analysis`, and `/hpc_diagnose`.
Prompts are user-invokable slash commands that return a guided, multi-step
analysis plan (instruction text, not results) — the assistant then runs the
chained operations and interprets them. In Claude Code or Claude Desktop they
appear as `/first_look`, `/vorticity_analysis`, etc.

General:

- `/first_look path` calls `get_capabilities` and `analyze_dataset`.
- `/vorticity_analysis grid_path data_path u_var v_var` calls
`run_analysis(operation="curl")` and
`run_analysis(operation="divergence")`.
- `/hpc_diagnose [endpoint]` calls
`diagnose_endpoint(action="status")` and
- `/hpc_diagnose [endpoint]` calls `diagnose_endpoint(action="status")` and
`diagnose_endpoint(action="validate")`.

Science workflows (each composes existing `run_analysis` operations around a
scientific question):

- `/vorticity_analysis grid_path data_path u_var v_var` — rotation and
divergence of a wind field (`curl` + `divergence`).
- `/cyclone_structure grid_path data_path variable_name center_lon center_lat [u_var v_var outer_radius]`
— radial structure of a storm/vortex (`azimuthal_mean` + `subset_bbox`,
optionally `curl`).
- `/eddy_activity grid_path data_path variable_name` — departures from the
latitudinal background state (`calculate_zonal_mean` + `zonal_anomaly` +
`gradient`).
- `/model_evaluation grid_path data_path_a data_path_b variable_name` — verify a
field against a reference (`bias` + `rmse` + `pattern_correlation`).
- `/climatology_anomaly data_path variable_name [grid_path]` — time-mean state
and departures (`temporal_mean` + `anomaly`, optionally `calculate_zonal_mean`).
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dependencies = [
"holoviews>=1.19.0",
"matplotlib>=3.9.0",
"pyyaml>=6.0",
"uxarray>=2025.12.0",
"uxarray>=2026.6.0",
]

[project.optional-dependencies]
Expand Down
Loading
Loading