MCP Server
NEREIDS can run as a local Model Context Protocol (MCP) server so an AI agent can inspect neutron-resonance inputs, validate a dataset manifest, and launch spectrum or density-map fitting through the Python bindings. The MCP server is intended for local agent orchestration, for example a user prompt such as “help me process the data here” in a directory that contains a NEREIDS manifest.
The MCP interface is experimental. It is useful for demos and agent-assisted workflows, but the Python and Rust APIs remain the stable interfaces for scripted analysis.
See also: Data I/O and NeXus/TOF for the raw-Python NeXus, TIFF, normalization, and TOF energy-grid flow that the MCP workflow wraps.
Installation
Install the optional MCP dependency and run the stdio server:
pip install "nereids[mcp]"
nereids-mcp
From a source checkout, build the Python extension first:
pip install maturin
maturin develop --release -m bindings/python/Cargo.toml
pip install "fastmcp>=3.0"
python -m nereids.mcp
In the repository Pixi environment, fastmcp is intentionally not a default
dependency because it can conflict with conda metadata packages. Install it
manually in the environment when MCP support is needed.
Behavior when fastmcp is not installed
The two entry points differ on purpose:
| Entry point | Without fastmcp |
|---|---|
nereids.mcp.main() (called by the nereids-mcp console script) | Raises ImportError("fastmcp is required for the MCP server. Install it with: pip install nereids[mcp]"). |
nereids.mcp.mcp (lazy attribute) | Raises AttributeError with the same install instruction embedded in the message. |
The attribute path raises AttributeError rather than ImportError so that
attribute-walking tools (pdoc, IDE introspection, hasattr) can treat mcp
as absent rather than crashing. Callers who explicitly catch ImportError
to detect a “MCP not installed” state should switch to either calling
nereids.mcp.main() (which still raises ImportError) or using
hasattr(nereids.mcp, "mcp") as the feature-detection probe.
Client Configuration
An MCP client can launch the server with the nereids-mcp console script:
{
"mcpServers": {
"nereids": {
"command": "nereids-mcp"
}
}
}
Tools
The server exposes two groups of tools.
Low-level physics tools operate on an in-memory isotope registry:
list_isotopes(z)lists naturally occurring isotopes.load_endf(isotope, library="endf8.1")loads resonance data such as"U-238"or"Fe-56"into the registry.get_resonance_parameters(isotope)returns loaded resonance metadata.compute_cross_sections(...),compute_transmission(...),forward_model(...), anddetect_isotopes(...)run direct physics calculations.
Workflow tools operate on a dataset directory or a manifest path:
extract_resonance_manifest(dataset_path)reads the manifest and returns parsed metadata.validate_resonance_dataset(dataset_path)checks required paths, isotope entries, and resolution configuration.process_resonance_dataset(dataset_path, output_dir=None, max_pixels=None, dry_run=False)runs the analysis and writes compact result artifacts.
Dataset Manifests
The workflow tools look for one of these files in the dataset directory:
manifest_intermediate.mdsmcp_manifest.mdnereids_manifest.mdnereids_mcp.jsonanalysis.json
Markdown manifests must contain JSON-compatible frontmatter between ---
delimiters. Pure JSON manifests must contain the frontmatter object directly.
The workflow configuration may be placed under analysis, workflow, or
processing; otherwise the root object is treated as the workflow.
Minimal single-spectrum manifest:
---
{
"name": "u238-spectrum-demo",
"tool": "nereids",
"physics": "neutron-resonance",
"analysis": {
"mode": "single_spectrum",
"data": {
"kind": "transmission_npz",
"path": "spectrum.npz"
},
"isotopes": [
{
"isotope": "U-238",
"initial_density": 0.001,
"library": "endf8.1"
}
],
"fit": {
"solver": "lm",
"max_iter": 100
},
"resolution": {
"kind": "gaussian",
"flight_path_m": 25.0,
"delta_t_us": 0.5,
"delta_l_m": 0.005
},
"output": {
"directory": "output"
}
}
}
---
For synthetic demo data, resolution can be disabled:
"resolution": {"kind": "none"}
For real instrument data, use Gaussian resolution parameters or a tabulated resolution file. Synthetic data often does not need an instrument resolution file; real experiments normally do.
Supported Workflow Inputs
single_spectrum fits one spectrum. It supports:
counts_npzorcounts: a.npzfile withsample_counts,open_beam_counts, andenergies_evby default. Arrays may be 1D spectra or 3D cubes; 3D cubes are summed over pixels before fitting one spectrum.transmission_npz,transmission, orspectrum: a.npzor text file withtransmission, optionaluncertainty, and an energy grid.
density_map and spatial_map fit every pixel in a 3D cube. They support:
transmission_npzortransmission: a.npzfile with 3Dtransmissionand optional 3Duncertaintyarrays.transmission_tiffortiff: a multi-frame TIFF transmission stack plus anenergy_gridentry.counts_npzorcounts: a.npzfile with 3Dsample_countsandopen_beam_countsarrays.nexus_histogramornexus: sample and open-beam NeXus histogram files, configured withsample_pathandopen_beam_path.
Paired arrays must have matching shapes. The number of energy points must match the first axis of the data arrays. Energy grids must be strictly monotonic. See Data I/O and NeXus/TOF for the energy-ordering contract (descending grids are reversed with the aligned arrays before fitting).
For NeXus histogram inputs, MCP follows the conventions documented in
Data I/O and NeXus/TOF. Briefly: NeXus loaders return counts
in ascending TOF order; the workflow derives ascending energy centers with
tof_to_energy_centers(...) and reverses counts along axis 0 to match before
fitting. If the manifest does not specify flight_path_m, the loader metadata
is used when available, with a 25 m fallback. delay_us defaults to 0.
Example NeXus density-map manifest:
---
{
"name": "venus-nexus-density-map",
"tool": "nereids",
"analysis": {
"mode": "density_map",
"data": {
"kind": "nexus",
"sample_path": "sample.nxs",
"open_beam_path": "open_beam.nxs",
"flight_path_m": 25.0,
"delay_us": 0.0
},
"isotopes": [
{"isotope": "U-238", "initial_density": 0.001}
],
"fit": {
"solver": "lm",
"max_iter": 100
},
"resolution": {
"kind": "gaussian",
"flight_path_m": 25.0,
"delta_t_us": 0.5,
"delta_l_m": 0.005
}
}
}
---
Result Files
process_resonance_dataset(...) writes outputs under the configured output
directory, or under <dataset>/output by default.
For single_spectrum, it writes:
nereids_spectrum_fit.npznereids_mcp_result.json
For density_map or spatial_map, it writes:
nereids_density_map.npznereids_mcp_result.json
The JSON summary is strict JSON: non-finite fit values are represented as
null, not NaN or Infinity.