Skip to content

cosmotron_mcp.tools.scripting

run_analysis_script

run_analysis_script(session_dir: str, code: str, desc: str = 'analysis', timeout: int = 300, allow_plotting: bool = False, allow_covered: bool = False) -> dict

Run a one-off Python script for a NON-PLOTTING step that has NO MCP tool.

This is the SANCTIONED way to run code: ONE call with code as a string. It saves the script to {session_dir}/scripts/step_NN_<desc>.py, runs it, quarantines it to failed_step_NN_<desc>.py on failure, and registers the script (and any declared outputs) as artefacts. Do NOT use the write/read tools or raw python … via bash for this — use this single tool.

PLOTTING IS REJECTED. matplotlib/pyplot/savefig code returns an error pointing to the deterministic plot tools — use plot_cls_comparison (measured vs UNBINNED theory + covariance error bars + shot-noise overlay via show_noise; pass component="BB"/"EB" for B-mode null-test / EB-cross plots — no theory fabricated, a zero reference line is drawn instead), plot_cls_grid (same component= support), plot_covariance, plot_covariance_validation (Knox check, also component=-aware), plot_healpix_maps (Mollweide maps — auto-detects shear Q/U maps too, roles shear_q/shear_u), plot_catalogue_diagnostics instead. They exist precisely so plots are never hand-written (which has fabricated theory/n(z)). Pass allow_plotting=True ONLY when no plot tool can produce the figure.

HAND-ROLLED PIPELINE NUMERICS ARE REJECTED. Code that imports sacc/tjpcov/pyccl/pymaster/healpy or calls a low-level covariance/spectra/map/ SACC primitive returns an error pointing to the *_from_session tools (compute_full_covariance_from_session, compute_all_cls_from_session, assemble_sacc_from_session, …). load_text_columns is allowed. Pass allow_covered=True ONLY when no session-driven tool covers the step.

The script SHOULD end by printing one JSON object, e.g. print(json.dumps({"outputs": ["results/foo.json"], "summary": "…"})); paths under outputs are registered. Inputs MUST come only from existing registered results / registry data — never fabricate inputs. To SAVE maps, do NOT write a script — call compute_cls_from_session(..., save_maps=True).

Parameters:

Name Type Description Default
session_dir str

Session directory the script runs against.

required
code str

The Python source to run, as a string.

required
desc str

Short label used in the saved script's filename.

'analysis'
timeout int

Wall-clock seconds before the script is killed.

300
allow_plotting bool

Allow matplotlib/pyplot/savefig code, only when no plot_* tool can produce the figure.

False
allow_covered bool

Allow hand-rolled sacc/tjpcov/pyccl/pymaster/healpy code, only when no *_from_session tool covers the step.

False

Returns:

Type Description
dict

{status: "ok"|"error", script_path, result, registered_outputs}.

Source code in cosmotron_mcp/server.py
@mcp.tool()
@sync_budget_guard
def run_analysis_script(
    session_dir: str, code: str, desc: str = "analysis", timeout: int = 300,
    allow_plotting: bool = False, allow_covered: bool = False,
) -> dict:
    """Run a one-off Python script for a NON-PLOTTING step that has NO MCP tool.

    This is the SANCTIONED way to run code: ONE call with `code` as a string.
    It saves the script to `{session_dir}/scripts/step_NN_<desc>.py`, runs it,
    quarantines it to `failed_step_NN_<desc>.py` on failure, and registers the
    script (and any declared outputs) as artefacts. Do NOT use the `write`/`read`
    tools or raw `python …` via bash for this — use this single tool.

    PLOTTING IS REJECTED. matplotlib/pyplot/savefig code returns an error pointing
    to the deterministic plot tools — use `plot_cls_comparison` (measured vs UNBINNED
    theory + covariance error bars + shot-noise overlay via `show_noise`; pass
    `component="BB"`/`"EB"` for B-mode null-test / EB-cross plots — no theory fabricated,
    a zero reference line is drawn instead), `plot_cls_grid` (same `component=` support),
    `plot_covariance`, `plot_covariance_validation` (Knox check, also `component=`-aware),
    `plot_healpix_maps` (Mollweide maps — auto-detects shear Q/U maps too, roles
    shear_q/shear_u), `plot_catalogue_diagnostics` instead. They exist precisely so
    plots are never hand-written (which has fabricated theory/n(z)).
    Pass `allow_plotting=True` ONLY when no plot tool can produce the figure.

    HAND-ROLLED PIPELINE NUMERICS ARE REJECTED. Code that imports
    sacc/tjpcov/pyccl/pymaster/healpy or calls a low-level covariance/spectra/map/
    SACC primitive returns an error pointing to the `*_from_session` tools
    (`compute_full_covariance_from_session`, `compute_all_cls_from_session`,
    `assemble_sacc_from_session`, …). `load_text_columns` is allowed. Pass
    `allow_covered=True` ONLY when no session-driven tool covers the step.

    The script SHOULD end by printing one JSON object, e.g.
    `print(json.dumps({"outputs": ["results/foo.json"], "summary": "…"}))`;
    paths under `outputs` are registered. Inputs MUST come only from existing
    registered results / registry data — never fabricate inputs. To SAVE maps,
    do NOT write a script — call compute_cls_from_session(..., save_maps=True).

    Args:
        session_dir: Session directory the script runs against.
        code: The Python source to run, as a string.
        desc: Short label used in the saved script's filename.
        timeout: Wall-clock seconds before the script is killed.
        allow_plotting: Allow matplotlib/pyplot/savefig code, only when no
            `plot_*` tool can produce the figure.
        allow_covered: Allow hand-rolled sacc/tjpcov/pyccl/pymaster/healpy
            code, only when no `*_from_session` tool covers the step.

    Returns:
        ``{status: "ok"|"error", script_path, result, registered_outputs}``.
    """
    _require_human_gates(session_dir)
    result = _run_analysis_script(session_dir, code, desc=desc, timeout=timeout,
                                  allow_plotting=allow_plotting, allow_covered=allow_covered)
    if result.get("status") == "ok":
        _log_tool_call(session_dir, "run_analysis_script", {
            "code": code, "desc": desc, "timeout": timeout,
            "allow_plotting": allow_plotting, "allow_covered": allow_covered,
        })
    return result