{"id":"7c48b51e-98cd-4a24-b184-9d1a6d3df075","slug":"radio-analyst","kind":"mcp","name":"radio-analyst","summary":"","owner":"skunkworks-ra","repoUrl":"https://github.com/skunkworks-ra/radio-analyst","license":"GPL-3.0","licenseTier":"strong-copyleft","trust":"community","stars":5,"match":null,"fewStars":false,"format":"mcp","createdAt":"2026-03-11T17:35:10.000Z","addedAt":"2026-10-21T16:59:00.696Z","logoUrl":"https://avatars.githubusercontent.com/u/267406469?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T16:21:16.724Z","sample":false,"url":"https://conduits.dev/tools/radio-analyst","language":"Python","transports":["stdio"],"install":{"pypi":"ms-inspect"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# radio-analyst\n\nA Claude Code plugin for reducing radio interferometric data with CASA. It\ngives Claude 54 tools across three MCP servers, the reasoning of an\nexperienced interferometrist (skills), and step-by-step workflows (slash\ncommands) for VLA/JVLA/EVLA, MeerKAT, and uGMRT Measurement Sets, from a raw\nASDM to a first image.\n\n```bash\nclaude plugin marketplace add https://github.com/skunkworks-ra/radio-analyst\nclaude plugin install radio-analyst@radio-analyst\n```\n\nPrerequisites, first-run behaviour and troubleshooting are under\n[Install](#install).\n\n---\n\n## What you can do with it\n\nTalk about your data in plain language, or run a workflow command. Claude\npicks the tools, reads the numbers, and tells you what they mean.\n\n### Ask about a dataset\n\nWith a Measurement Set path in the conversation, just ask:\n\n| You say | What happens |\n|---|---|\n| *\"What's in /data/3c391.ms?\"* | Telescope, array configuration, band, fields with their intents, scans, spectral windows and correlations, summarised in a paragraph. |\n| *\"Which antenna should I use as the reference?\"* | Antennas ranked by distance from the array centre and by unflagged data, with both quantities shown so you can overrule the ranking. |\n| *\"Is there RFI in this observation? Which spectral windows are worst?\"* | Per-channel flag fractions and a per-SpW amplitude severity, separating a SpW to drop from one worth salvaging. |\n| *\"Will I get enough parallactic-angle coverage to solve for leakage?\"* | Identifies the polarisation calibrators and measures the PA spread per field. You get the numbers and what they allow you to claim, not a yes/no. |\n| *\"Is the phase calibrator in this MS a good one for B-config at L-band?\"* | Cross-matches its position against the NRAO VLA calibrator list and returns flux, UV limits and quality codes per configuration. |\n| *\"Plot the bandpass table in ./cal/bandpass.B\"* | An interactive Bokeh HTML dashboard of the solutions, routed by table type. |\n| *\"What's in this ASDM before I convert it?\"* | Continuum vs. line SpWs, HI coverage, sources and intents, scan balance, target elevation. Reads only the ASDM XML, so no CASA is needed. |\n| *\"What does `timecutoff` do in flagdata's tfcrop mode?\"* | Fetches and quotes the casadocs page, or the casa6 source if the docs don't cover it, instead of answering from memory. |\n\n### Run a reduction, stage by stage\n\nEach command is a workflow that runs a checked sequence of steps and stops to\nreport when a check fails. The commands are namespaced by the plugin:\n\n| Command | Takes you from → to |\n|---|---|\n| `/radio-analyst:inspect <ms>` | A new MS → a data-quality report with a go/no-go for calibration (orientation + instrument sanity, 12 tools, nothing written). |\n| `/radio-analyst:precal <ms>` | Imported MS → pre-calibrated calibrators: online flags, deterministic preflag, prior caltables (gain curves, opacity, requantizer, antenna positions), flux models, reference antenna, initial bandpass, residual RFI flagging. |\n| `/radio-analyst:calibrate <ms>` | Pre-calibrated MS → calibrated target: initial phase → delay → bandpass → gain → fluxscale → applycal, with solution statistics checked after every solve. |\n| `/radio-analyst:polcal <ms>` | Calibrated MS → polarisation-calibrated: cross-hand delay → leakage (D-terms) → position angle → applycal with parallactic-angle correction. |\n| `/radio-analyst:image <ms>` | Calibrated MS → first image, with tclean parameters derived from the data (cell, image size, gridder, deconvolver, threshold) and the result checked against the radiometer noise and expected beam. |\n| `/radio-analyst:simulate <description>` | A sentence → a synthetic MS, e.g. *\"VLA B-config, L-band, 2 hours on 3C286 with a 5 % gain drift\"*. |\n\nA typical first session on a new VLA dataset:\n\n```text\n> What's in /data/19A-123.sb1234.eb5678/ ?            # raw ASDM: look before importing\n> Import it to /data/work/obs.ms                        # writes an import script, then runs it\n> /radio-analyst:inspect /data/work/obs.ms              # go / no-go report\n> /radio-analyst:precal /data/work/obs.ms\n> /radio-analyst:calibrate /data/work/obs.ms\n> /radio-analyst:image /data/work/obs.ms\n> Give me the replay script for everything that worked.\n```\n\n### Keep a reproducible record\n\nAs a reduction proceeds, Claude records each call that actually worked, with\nits exact parameters and the reason for it, in `reduction_log.jsonl` in the\nworking directory. Ask for it back at any point, as a step list or as a single\nreplay script. Dead ends stay out, so the log is the clean path through your\ndata, not the search for it.\n\n---\n\n## How it works\n\n**Tools measure. The skill reasons.** Every tool answers one question with\nnumbers and a completeness flag on each field (`COMPLETE`, `INFERRED`,\n`PARTIAL`, `SUSPECT`, `UNAVAILABLE`). No tool decides whether you may proceed.\nThresholds depend on your science goal, so that judgement lives in the\n`radio-interferometry` skill, where Claude applies it and shows you the inputs.\nFor example, 24° of parallactic-angle coverage doesn't block a leakage solve.\nIt becomes \"proceed, and limit fractional-polarisation claims to a few percent\".\n\n**Nothing is written without a script you can read.** Every tool that modifies\ndata or imports an ASDM (17 in total) defaults to `execute=False`. It returns a\npreview or writes a plain CASA Python script into your working directory and\nreturns its path. The workflow then runs that script and checks the result with\nthe read-only tools.\n\n**Three servers, by what they can touch:**\n\n- **ms-inspect**: read-only inspection and diagnostics (34 tools).\n- **ms-modify**: flagging, calibration, imaging (16 tools, script-first).\n- **ms-create**: ASDM inspection and import, the reduction log and the report (4 tools).\n\n---\n\n## Install\n\n```bash\n# Register the marketplace (once per machine)\nclaude plugin marketplace add https://github.com/skunkworks-ra/radio-analyst\n\n# Install the plugin\nclaude plugin install radio-analyst@radio-analyst\n```\n\n**Prerequisites**\n\n- [pixi](https://pixi.sh) on `PATH`: `curl -fsSL https://pixi.sh/install.sh | bash`\n- Linux x86_64 or macOS arm64 (the platforms `pixi.toml` targets). On macOS,\n  casatools isn't in `pixi.lock`, so the environment build installs it with pip.\n- Roughly 1 GB of free disk for the Python/CASA environment.\n\n**First run.** Start Claude Code. A `SessionStart` hook starts building the\nPython/CASA environment in the background, and you'll see a message saying so\nwith the path to its log. The first build downloads casatools and its\ndependencies and takes several minutes. It is stored under\n`~/.claude/plugins/data/` and is kept across plugin updates. Until it finishes,\nthe three servers report that the build is in progress. When `build.log` ends\nwith `build complete`, run `/mcp` and reconnect them. Later updates only re-sync\nthe plugin's sources and reuse the installed packages, unless `pixi.lock`\nchanged.\n\n**Check it works:** `/mcp` lists `ms-inspect`, `ms-modify` and `ms-create` as\nconnected. Then ask *\"What's in <path to an MS>?\"*.\n\n**Update / remove.** The plugin carries no version number, so Claude Code\nversions it by commit: an update brings you to the latest commit on `main`.\n\n```bash\nclaude plugin update radio-analyst@radio-analyst\nclaude plugin uninstall radio-analyst@radio-analyst   # also deletes the environment\n```\n\nThird-party marketplaces don't auto-update by default. To turn that on, open\n`/plugin` → **Marketplaces** → `radio-analyst` → **Enable auto-update**.\n\n### Troubleshooting\n\n| Symptom | Cause and fix |\n|---|---|\n| Servers fail with *\"pixi is not on PATH\"* | Install pixi (above), then restart Claude Code. |\n| *\"this machine is …\"* at session start | The environment builds only on Linux x86_64 and macOS arm64 (the platforms `pixi.toml` targets). On other platforms the skills load but no tool can run. |\n| Servers fail with *\"still being built\"* | Expected on the first run and after some updates. Wait for `build complete` in `build.log`, then reconnect with `/mcp`. |\n| Servers fail with *\"build failed\"* | Read `build.log` (the message gives its path; the build before it is in `build.log.prev`). Reconnecting with `/mcp` retries the build. |\n| Tools return `CASA_NOT_AVAILABLE` | casatools didn't install or import. Look for `WARNING` lines in `build.log`. |\n| `INSUFFICIENT_METADATA` on a tool | The MS lacks a telescope name or antenna table. The error includes the exact repair command. |\n\n### Permissions\n\n- **Inside the workflow commands**, the MCP tools each command lists are\n  pre-approved, and so is `Bash`, which runs the generated scripts. Those\n  commands include the ms-modify tools that write to your MS and working\n  directory. They run without a prompt per step, but each step goes through a\n  generated script, and the workflow stops when a check fails.\n- **Outside the commands**, every tool call prompts as usual. Allow them\n  permanently in `/permissions` if you prefer. For example,\n  `mcp__plugin_radio-analyst_ms-inspect__*` covers the read-only tools.\n\n---\n\n## Reference\n\n### Skills\n\nLoaded automatically when relevant. No need to invoke them yourself.\n\n| Skill | Purpose |\n|---|---|\n| `radio-interferometry` | Interferometrist reasoning across the reduction: band tables, intent vocabulary, elevation/PA/flag thresholds, calibrator science, failure modes and recovery, and the execution playbooks the commands follow. |\n| `ms-simulator` | Turns a conversational description into a `casatools.simulator` script and a validated MS. |\n| `casa-docs` | Answers CASA task and parameter questions from the fetched casadocs page or casa6 source, never from memory. |\n\n### Tools\n\nThe per-tool inventory is in [`design_docs/DESIGN.md`](design_docs/DESIGN.md)\n(§8 ms-inspect, §8b ms-modify, §8c ms-create). Summary:\n\n- **ms-inspect (34)**:\n  - Orientation (6): observation info, fields, scans, scan intents, SpWs, correlator setup.\n  - Instrument sanity (7): antennas, baselines, elevation and parallactic angle vs. time, shadowing, flag preflight, per-antenna flag fraction.\n  - Calibration inspection (6): caltable statistics and detail, single and batch caltable plots, gaincal SNR prediction, caltable checks.\n  - Pre-calibration checks (5): import, model, prior caltables, online flag stats, flag summary.\n  - Instrument and RFI (7): reference antenna ranking, RFI channel stats, SpW amplitude severity, pol-cal conditions, residual and corrected-data statistics, phase-calibrator lookup.\n  - Imaging (1): image RMS, peak, dynamic range, beam.\n  - Workflow state (1).\n  - CASA docs lookup (1).\n- **ms-modify (16)**: intents, preflag, prior caltables, setjy / pol setjy,\n  initial bandpass, gaincal (incl. KCROSS), bandpass, polcal, fluxscale,\n  applycal, residual and post-cal RFI flagging, caltable autoflag, tclean.\n- **ms-create (3)**: ASDM summary, ASDM → MS import, reduction log.\n\n### Environment variables\n\n| Variable | Default | Effect |\n|---|---|---|\n| `RADIO_MCP_TRANSPORT` | `stdio` | `stdio` for Claude Code / Desktop; `http` for remote clients |\n| `RADIO_MCP_HOST` | `127.0.0.1` | HTTP bind address. **The HTTP transport has no authentication. Don't bind beyond localhost on shared or untrusted networks** |\n| `RADIO_MCP_PORT` | `8000` / `8001` / `8002` | HTTP port (inspect / modify / create) |\n| `RADIO_MCP_WORKERS` | `4` | Parallel workers for FLAG column reads (cap 8) |\n| `RADIO_MCP_ENV_WAIT` | `20` | Plugin only: seconds a server waits on an in-progress environment build before exiting with a pointer to `build.log` |\n\n---\n\n## Other clients\n\nClone the repo and build the environment:\n\n```bash\ngit clone https://github.com/skunkworks-ra/radio-analyst.git\ncd radio-analyst\npixi install && pixi run pip install casatools casatasks\n```\n\n**Claude Desktop** launches each server itself and talks to it over stdio.\nAdd to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ms-inspect\": {\n      \"command\": \"pixi\",\n      \"args\": [\"run\", \"--manifest-path\", \"/path/to/radio-analyst/pixi.toml\", \"serve\"]\n    },\n    \"ms-modify\": {\n      \"command\": \"pixi\",\n      \"args\": [\"run\", \"--manifest-path\", \"/path/to/radio-analyst/pixi.toml\", \"serve-modify\"]\n    },\n    \"ms-create\": {\n      \"command\": \"pixi\",\n      \"args\": [\"run\", \"--manifest-path\", \"/path/to/radio-analyst/pixi.toml\", \"serve-create\"]\n    }\n  }\n}\n```\n\nThis gives Desktop the tools. The skills and workflow commands are Claude Code\nplugin components.\n\n**Any MCP client over HTTP**: start the servers, then connect to\n`http://localhost:8000/mcp` (and `:8001`, `:8002`; streamable HTTP):\n\n```bash\nRADIO_MCP_TRANSPORT=http RADIO_MCP_PORT=8000 pixi run serve\nRADIO_MCP_TRANSPORT=http RADIO_MCP_PORT=8001 pixi run serve-modify\nRADIO_MCP_TRANSPORT=http RADIO_MCP_PORT=8002 pixi run serve-create\n```\n\n---\n\n## Development\n\nWorking on the plugin itself: register the servers against your clone instead\nof the plugin install.\n\n```bash\ngit clone https://github.com/skunkworks-ra/radio-analyst.git\ncd radio-analyst\npixi install\npixi run pip install casatools casatasks   # first time only\npixi run install-mcp                       # removes a plugin install first, if any\n```\n\n`install-mcp` (`scripts/dev/install-local.sh`) registers the three servers at\nuser scope, pointing at `.pixi/envs/default/bin/`. Re-run it after a\n`pixi install` that rebuilds the environment. `pixi run uninstall-mcp` undoes\nit. Opened in Claude Code, the clone also loads the skills and commands from\n`.claude/` directly, un-namespaced (`/inspect`, `/precal`, …).\n\nTo try the plugin packaging itself from a clone:\n`claude plugin marketplace add ./ && claude plugin install radio-analyst@radio-analyst`.\n\n```bash\npixi run test-unit     # unit tests (casatools required; builds a small real MS)\npixi run test-int      # integration: RADIO_MCP_TEST_MS=/path/to.ms or RADIO_MCP_TEST_MS_TGZ=/path/to.ms.tgz\npixi run check         # ruff lint + format check (CI gate)\nclaude plugin validate .claude-plugin/plugin.json\n```\n\n[`CLAUDE.md`](CLAUDE.md) holds the contributor contract and conventions, and\n[`design_docs/DESIGN.md`](design_docs/DESIGN.md) the architecture. Read both\nbefore a non-trivial change.\n\n---\n\n## License\n\nGPL-3.0\n"}