diff --git a/AGENTS.md b/AGENTS.md index 78186c4..954fcac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -31,11 +31,11 @@ The tool surface is built by `uxarray_mcp.registry.build_registry()`: No deferred tools, no BM25 discovery. This is what clients see by default when running `uxarray-mcp serve`. -- **`deferred-full` (~58 loaded, ~28 visible)** — core set stays visible. - 30 raw implementation tools are loaded with `defer=True` so they don't - appear in the initial tool list. Agents discover them via - `discover_tools` (BM25 search), and operators promote them from the - admin panel. +- **`deferred-full` (~64 loaded, ~32 visible)** — core set stays visible. + 32 raw implementation tools are loaded with `defer=True` so they don't + appear in the initial tool list, plus `discover_tools`. Agents discover + the deferred tools via `discover_tools` (BM25 search), and operators + promote them from the admin panel. ### Core tools @@ -68,7 +68,7 @@ Documentation: `docs/` (Sphinx, built to ReadTheDocs). ## Key design decisions - **Domain/tool separation** — pure computation lives in `domain/`, server - wiring lives in `registry.py` + `server.py`. The same domain functions + wiring lives in `registry.py` + `app.py`. The same domain functions run locally or get serialized and sent to an HPC worker via Globus Compute. Never put MCP, provenance, or I/O logic in `domain/`. @@ -120,7 +120,7 @@ Documentation: `docs/` (Sphinx, built to ReadTheDocs). ``` src/uxarray_mcp/ registry.py # build_registry() — namespace plan, tags, prompt-as-tool - server.py # make_registry(), make_mcp_server(), run() — multi-transport + app.py # UXarrayApp, make_registry(), make_mcp_server() — multi-transport cli.py # uxarray-mcp serve/setup/doctor/endpoints/install-claude provenance.py # attach_provenance() used by all tools domain/ # Pure computation — no MCP, no I/O @@ -173,8 +173,8 @@ config.yaml.example # Template — private config is normally written by t - **Python** ≥ 3.12, < 3.13 (pinned for Globus Compute pickle compat) - **toolregistry** ≥ 0.11.0 — tool registration, schema generation, policy tags -- **toolregistry-server** ≥ 0.3.3 — MCP + OpenAPI adapters -- **UXarray** ≥ 2025.12.0 — unstructured mesh analysis +- **toolregistry-server** ≥ 0.4.0 — MCP + OpenAPI adapters +- **UXarray** ≥ 2026.6.0 — unstructured mesh analysis - **Matplotlib** ≥ 3.9.0 + **Holoviews** ≥ 1.19.0 — visualization - **PyYAML** ≥ 6.0 — config file parsing - **uv** — package management and script runner (not conda, not pip directly) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77951a..b5d0981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ uses Semantic Versioning for public releases. ## Unreleased +## 0.1.2 — 2026-07-05 + ### Added - Guided science workflows as `prompt/` tools, each composing existing operations around a scientific question: `cyclone_structure` (storm radial @@ -23,16 +25,12 @@ uses Semantic Versioning for public releases. ### 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) + [toolregistry-server](https://github.com/Oaklight/toolregistry-server). `fastmcp` is no longer a dependency. -- **Two-profile tool surface**: `core` (~27 tools, conservative default) and - `deferred-full` (all tools loaded, 30 deferred behind BM25 discovery). +- **Two-profile tool surface**: `core` (~31 tools, conservative default) and + `deferred-full` (all tools loaded, 32 deferred behind BM25 discovery). - **Namespace grouping**: control tools under `session/` and `hpc/`, IO under `io/`, prompts under `prompt/`. - **Policy tags**: every tool carries `ToolTag` metadata (`READ_ONLY`, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 48d16ed..72c2f7a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,8 +33,8 @@ Full coding conventions and architecture notes are in [AGENTS.md](AGENTS.md). - Work on a feature branch (`git checkout -b your-name/short-description`). - Keep changes focused — one logical change per PR. -- All new tools must call `attach_provenance()` and be registered in - `server.py` and exported from `tools/__init__.py`. +- All new tools must call `attach_provenance()`, be assigned to a bucket in + `registry.py`, and be exported from `tools/__init__.py`. - All new tool functions need tests (see `tests/` for patterns). - Run the full check suite before pushing: diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md index b8b82f4..ee443df 100644 --- a/GETTING_STARTED.md +++ b/GETTING_STARTED.md @@ -37,9 +37,11 @@ If you want HPC support too: uv sync --extra hpc ``` -## Claude Desktop Example +## MCP Client Example -Use absolute paths in your Claude Desktop MCP config: +The server speaks standard MCP over stdio, so it works with any MCP-compatible +client (Claude Desktop, Claude Code, Cursor, Continue, or your own). Most +clients accept an `mcpServers` block like the one below — use absolute paths: ```json { @@ -52,14 +54,14 @@ Use absolute paths in your Claude Desktop MCP config: "run", "python", "-m", - "uxarray_mcp.server" + "uxarray_mcp" ] } } } ``` -Then fully quit and reopen Claude Desktop. +Then restart your MCP client so it picks up the new server. ## If You Want HPC diff --git a/README.md b/README.md index 8ceb29b..3f16667 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,9 @@ client's MCP docs. uxarray-mcp doctor ``` -Should print `local execution: ok` and (if no endpoints configured) skip the -remote checks. +Prints a JSON diagnostic report. With no endpoints configured it reports a +passing local setup and skips the remote checks; the process exits `0` when +`passed` is true. ### Step 5 — Ask the AI to do something diff --git a/SETUP.sh b/SETUP.sh index 0068068..2e464f2 100755 --- a/SETUP.sh +++ b/SETUP.sh @@ -2,8 +2,8 @@ set -e echo "[SETUP] Checking prerequisites..." -if ! python3 -c "import sys; assert sys.version_info >= (3, 11)" &> /dev/null; then - echo "[ERROR] Python 3.11+ is required." +if ! python3 -c "import sys; assert (3, 12) <= sys.version_info < (3, 13)" &> /dev/null; then + echo "[ERROR] Python 3.12 is required (>=3.12,<3.13, pinned for Globus Compute compatibility)." exit 1 fi diff --git a/conda/recipe/meta.yaml b/conda/recipe/meta.yaml index d69e132..c07a214 100644 --- a/conda/recipe/meta.yaml +++ b/conda/recipe/meta.yaml @@ -27,11 +27,11 @@ requirements: # a second output/variant after globus-compute-sdk and academy-py solver # behavior is validated on conda-forge. - python >={{ python_min }} - - toolregistry-server >=0.3.3 + - toolregistry-server >=0.4.0 - holoviews >=1.19.0 - matplotlib-base >=3.9.0 - pyyaml >=6.0 - - uxarray >=2025.12.0 + - uxarray >=2026.6.0 test: requires: diff --git a/docs/getting-started.md b/docs/getting-started.md index f8f69d3..601f4af 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -8,7 +8,7 @@ This guide uses Claude Desktop as the MCP client. Other MCP-compatible clients s ## Prerequisites -- **Python 3.11+** — Check with: `python3 --version` +- **Python 3.12** — required (`>=3.12,<3.13`, pinned for Globus Compute compatibility). Check with: `python3 --version` - **uv** — Install with: `pip install uv` - **MCP Client** — Claude Desktop or any MCP-compatible client - **Git** (optional) — For cloning the repository diff --git a/docs/provenance.md b/docs/provenance.md index 01d4096..57de2e4 100644 --- a/docs/provenance.md +++ b/docs/provenance.md @@ -26,8 +26,8 @@ Every tool result includes a `_provenance` block that records what ran, when, wh "inputs": { "file_path": "healpix:4", "data_path": null, "variable_name": null }, "execution_venue": "local", "timestamp_utc": "2026-03-18T...", - "uxarray_version": "2025.12.0", - "python_version": "3.13.0", + "uxarray_version": "2026.6.0", + "python_version": "3.12.0", "warnings": [], "artifacts": [ { "type": "mesh_topology", "n_face": 3072, "n_node": 3074, "format": "HEALPix" }, diff --git a/docs/remote-hpc.md b/docs/remote-hpc.md index 9de2afb..2b89d13 100644 --- a/docs/remote-hpc.md +++ b/docs/remote-hpc.md @@ -84,8 +84,8 @@ This adds the `globus-compute-sdk` to your local install. Verify: uxarray-mcp doctor ``` -You should see the SDK listed. (No endpoint health checks yet — that's -Step 4.) +The JSON report should show the Globus Compute SDK as available. (No endpoint +health checks yet — that's Step 4.) --- @@ -202,7 +202,7 @@ back. Reasons appear in the response's `warnings` and in | Symptom | Likely cause | Fix | |---|---|---| | `globus_compute_sdk not installed` | Missing HPC extras | `uv tool upgrade --extra hpc uxarray-mcp` | -| Browser doesn't open on first auth | Headless laptop / SSH session | Run `uxarray-mcp doctor` with `--no-browser`, paste the URL into a local browser | +| Browser doesn't open on first auth | Headless laptop / SSH session | The Globus login prints an auth URL to the terminal — copy it into a local browser and paste the code back. | | `endpoint status: registered, probe timed out` | Worker isn't responding | Operator's problem. Ask them. May be scheduler backlog. | | `endpoint status: not found` | Wrong UUID or you've been removed | Re-check UUID with operator. Globus Auth identity must match endpoint's allow-list. | | Tool returns `execution_venue: local` when you asked for remote | Auto-fallback fired | Check `warnings` in response. Common: path didn't match `path_prefix`, or endpoint unhealthy. | diff --git a/src/uxarray_mcp/cli.py b/src/uxarray_mcp/cli.py index c3a4ac7..a9251fe 100644 --- a/src/uxarray_mcp/cli.py +++ b/src/uxarray_mcp/cli.py @@ -308,8 +308,8 @@ def build_parser() -> argparse.ArgumentParser: choices=("core", "deferred-full"), default="core", help=( - "core: gateway + control + list_datasets + prompts (~27 tools). " - "deferred-full: also load 30 raw tools as deferred, gated " + "core: gateway + control + list_datasets + prompts (~31 tools). " + "deferred-full: also load 32 raw tools as deferred, gated " "behind discover_tools / admin promotion." ), ) @@ -317,7 +317,7 @@ def build_parser() -> argparse.ArgumentParser: "--transport", choices=("stdio", "sse", "http"), default="stdio", - help="MCP transport. stdio for Claude Desktop subprocess use.", + help="MCP transport. stdio for subprocess use by MCP clients.", ) serve.add_argument("--host", default="127.0.0.1", help="Bind host for SSE/HTTP.") serve.add_argument("--port", type=int, default=8001, help="Port for SSE/HTTP.") @@ -330,8 +330,8 @@ def build_parser() -> argparse.ArgumentParser: choices=("core", "deferred-full"), default="core", help=( - "core: gateway + control + list_datasets + prompts (~27 tools). " - "deferred-full: also load 30 raw tools as deferred, gated " + "core: gateway + control + list_datasets + prompts (~31 tools). " + "deferred-full: also load 32 raw tools as deferred, gated " "behind discover_tools / admin promotion." ), ) diff --git a/src/uxarray_mcp/registry.py b/src/uxarray_mcp/registry.py index a63c1c2..c5c9a2f 100644 --- a/src/uxarray_mcp/registry.py +++ b/src/uxarray_mcp/registry.py @@ -5,9 +5,9 @@ * ``"core"`` (default) — small, predictable surface visible to LLMs. Mirrors the original MCP server's 11 front-door tools, adds 12 control/status tools, the ``list_datasets`` discovery helper, and - three prompt-as-tool helpers (former ``@mcp.prompt()`` decorators). + seven prompt-as-tool helpers (former ``@mcp.prompt()`` decorators). * ``"deferred-full"`` — loads every public function with the core set - enabled and 30 raw implementation tools marked ``defer=True``. + enabled and 32 raw implementation tools marked ``defer=True``. Includes ``discover_tools`` (BM25 search) so LLMs find deferred tools by intent. @@ -592,9 +592,9 @@ def build_registry( """Build a ``ToolRegistry`` for the chosen profile. Args: - profile: ``"core"`` for the small default surface (~27 tools), + profile: ``"core"`` for the small default surface (~31 tools), ``"deferred-full"`` for the complete pool (core visible, - 30 raw tools deferred, ``discover_tools`` added). + 32 raw tools deferred, ``discover_tools`` added). registry_name: Identifier for server titles and labels. Returns: diff --git a/uv.lock b/uv.lock index 7cbb38e..461fe22 100644 --- a/uv.lock +++ b/uv.lock @@ -2437,7 +2437,7 @@ wheels = [ [[package]] name = "uxarray-mcp" -version = "0.2.0" +version = "0.1.2" source = { editable = "." } dependencies = [ { name = "holoviews" },