[{"name":"push_results","description":"Push the agent's latest annotation results into a session (latest-wins).\n\n    Dashboard viewers see the update live.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"features","type":"array","required":true,"description":"Feature objects with: mz (number), rt (number), intensity (number), annotation (string), score (number)"},{"name":"run_label","type":"string/null","required":false,"description":""}]},{"name":"get_session","description":"Read the shared session: agent results, local software's latest update,\n    and whether the local worker is currently connected.","params":[{"name":"session_id","type":"string","required":true,"description":""}]},{"name":"set_session_display","description":"Push display content into a SESSION (latest-wins), cached so any viewer\n    who opens the session page — now or later — sees it.\n\n    The content is stored on the session's hub and fanned out live to everyone\n    currently viewing /d/{session_id}. A viewer that opens the page afterwards\n    replays the cached content on connect (pickup-on-visit).\n\n    Args:\n      session_id: the session UUID (minted on the home page, shared with you).\n      heading: the board heading shown at the top of the session page.\n      cards: optional labeled content blocks (title + text) rendered in order.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"heading","type":"string","required":true,"description":""},{"name":"cards","type":"array/null","required":false,"description":"Card objects with: title (string), text (string)"}]},{"name":"navigate_to","description":"Force THIS session's viewers to a page within the session (latest-wins).\n\nMoves only the viewers of session `session_id` — never another session's.\n`page` is a NAME from the allowlist, never a URL; the only reachable\ndestinations are this session's own /d/{session_id}/... routes. The full\nallowlist (each paired with the push tool that populates it):\n\n      home      set_session_display\n      announce  set_announcement\n      validate  set_structure_validation\n      classify  classify_structure\n      eb        show_eb_feature\n      eb_xics   show_eb_xics\n      mirror    show_mirror\n      network   show_network_component\n      notepad   set_notepad\n      journal   journal_note\n      dashboard dashboard_place_note\n\nAlways navigate to a page AFTER you have pushed content to it.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"page","type":"string","required":true,"description":""}]},{"name":"annotate_view","description":"Attach an agent commentary note to a view so the human sees, on the page\nitself, WHY you put this here and WHAT they should look at.\n\nEvery view carries a commentary banner at the top; this fills it. Use it right\nafter you push to a view (before you `navigate_to` it): the push supplies the\ndata, the note supplies your reasoning, and the navigate brings the user to both.\n\n`page` is a NAME from the same allowlist as `navigate_to`:\n\n      home      set_session_display\n      announce  set_announcement\n      validate  set_structure_validation\n      classify  classify_structure\n      eb        show_eb_feature\n      eb_xics   show_eb_xics\n      mirror    show_mirror\n      network   show_network_component\n      notepad   set_notepad\n      journal   journal_note\n      dashboard dashboard_place_note\n\n`why` (required): why you are showing this — the finding, the decision, the ask.\n`what` (optional): what specifically to look at / look for on the view.\n\nLatest-wins per page; the note persists across live data re-pushes, so re-annotate\nwhenever you change what the view is showing. Keep it short — a sentence or two.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"page","type":"string","required":true,"description":""},{"name":"why","type":"string","required":true,"description":""},{"name":"what","type":"string/null","required":false,"description":""}]},{"name":"set_announcement","description":"Post an announcement to a session's announce page (latest-wins).\n\n    Every open /d/{session_id}/announce tab updates live; a late joiner replays\n    the last announcement.\n\n    Args:\n      session_id: the session this announcement attaches to.\n      headline: the short, prominent message.\n      body: optional longer text shown beneath the headline.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"headline","type":"string","required":true,"description":""},{"name":"body","type":"string/null","required":false,"description":""}]},{"name":"journal_note","description":"Append a prose/narrative cell to the session's Journal (`/d/{sid}/journal`).\n\n    The Journal is an append-only narrative: use this for the words that tie the\n    pinned evidence together — what you found, what a chart shows, what's next.\n    Pin the evidence itself by passing `pin=True` to the `show_*` tools (e.g.\n    `show_eb_xics(..., pin=True)`); those append the widget snapshots. Together\n    they build one scrollable story.\n\n    `markdown` supports a small SAFE subset — headings (`#`), **bold**, *italic*,\n    `code`, `- ` bullet lists, and `[text](https://…)` links. No raw HTML or code\n    is rendered (this is a narrative, not a code notebook).\n\n    Navigate the user to `journal` when you want them to read the whole thread.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"markdown","type":"string","required":true,"description":""},{"name":"title","type":"string/null","required":false,"description":""}]},{"name":"clear_journal","description":"Wipe the session's Journal narrative and start fresh (viewers re-render an\n    empty feed). Use when beginning a new analysis thread in the same session.","params":[{"name":"session_id","type":"string","required":true,"description":""}]},{"name":"get_dashboard","description":"Read the current Dashboard layout so you know what's where BEFORE placing\n    a widget (which slots are filled, with what, and which are free).\n\n    The grid is `cols`×`rows` (4×2 = 8 slots), numbered **row-major**: slots 0..3\n    are the top row, 4..7 the bottom. Returns `{cols, rows, slots: {slot: {kind,\n    title}}, free: [ints]}`. Use `free[0]` for the next empty slot, or target a\n    filled slot to replace it (latest-wins).","params":[{"name":"session_id","type":"string","required":true,"description":""}]},{"name":"dashboard_place_note","description":"Place a prose/markdown widget into a Dashboard slot on\n    `/d/{session_id}/dashboard`. The Dashboard is a 4×2 grid (8 slots, numbered\n    row-major: 0..3 top row, 4..7 bottom), latest-wins per slot. Call\n    `get_dashboard` first to see which slots are free. For data widgets (XIC /\n    feature / structure / network / mirror) pass `dashboard_slot=<n>` to the\n    matching `show_*` tool instead — it places the same snapshot it would pin.\n    Safe markdown subset only (no code).","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"slot","type":"integer","required":true,"description":""},{"name":"markdown","type":"string","required":true,"description":""},{"name":"title","type":"string/null","required":false,"description":""}]},{"name":"clear_dashboard_cell","description":"Empty one Dashboard slot (0..7), leaving the others untouched.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"slot","type":"integer","required":true,"description":""}]},{"name":"clear_dashboard","description":"Empty the whole Dashboard grid for a session.","params":[{"name":"session_id","type":"string","required":true,"description":""}]},{"name":"classify_structure","description":"Classify a SMILES with NPClassifier and show it on a session's page.\n\n    Runs the structure through NPClassifier (GNPS2) and pushes its natural-product\n    classification — pathway, superclass, class, and a glycoside flag — to the\n    /d/{session_id}/classify page, where the structure is depicted alongside.\n    Every open tab updates live; a late joiner replays the last push (latest-wins).\n\n    Args:\n      session_id: the session this content attaches to.\n      smiles: candidate structure as a SMILES string (e.g. caffeine\n        \"Cn1c(=O)c2c(ncn2C)n(C)c1=O\"). Passed as a parameter — do not pass a URL.\n      label: short human-facing title (e.g. compound name / feature id).\n\n    Returns:\n      A one-line summary of the classification (or the error), for the agent.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"smiles","type":"string","required":true,"description":""},{"name":"label","type":"string/null","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"prewarm_eb_task","description":"Resolve a GNPS2 everything_bagel task into the shared cache + summarize it.\n\n    OPTIONAL — the data tools (`list_eb_features`, `get_eb_xic`,\n    `get_eb_feature_msms`) resolve a task on demand, so you never *need* to call\n    this first. Use it to (a) pre-probe which host has the task staged, or (b) get\n    an overview of what's in a task before drilling in.\n\n    Args:\n      task_id: the GNPS2 everything_bagel task id.\n      host: optionally force a host (e.g. \"https://beta.gnps2.org\"); otherwise\n        both public hosts are probed and the one holding the task is used.\n      force: re-probe + re-download even if the task is already cached (use when\n        a task was re-staged to a different host).\n\n    Returns a summary: host used, feature count, sample count + labels.","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"host","type":"string/null","required":false,"description":""},{"name":"force","type":"boolean","required":false,"description":""}]},{"name":"list_eb_features","description":"List/filter an EB task's aligned features.\n\n    Filters (all optional, AND-combined): `mz`±`mz_tol` (Da), `rt`±`rt_tol`\n    (minutes), `contains` (substring match against the feature's row ID or\n    representative source file), `ms2_only`, `min_area` (min peak area in the\n    strongest sample), `adduct` (exact ion-call match, e.g. \"[M+H]1+\"),\n    `annotation_network` (ion-identity group number — pass one to pull every\n    co-eluting ion of the same neutral, e.g. to overlay their XICs). Results are\n    sorted by descending peak area, capped at `limit`. The task is resolved from\n    the shared cache on demand.\n\n    Each returned feature carries the adduct/ion-identity annotations\n    everything_bagel derives (NOT native MZmine IIN): `adduct` (the per-feature\n    ion call — \"\" when EB assigned none for this task), `is_default_adduct`\n    (representative ion of its group), and `annotation_network` (the group id).\n    Use these to check, rather than assume, a precursor's charge/adduct state\n    before reasoning about its neutral mass.","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"mz","type":"number/null","required":false,"description":""},{"name":"mz_tol","type":"number","required":false,"description":""},{"name":"rt","type":"number/null","required":false,"description":""},{"name":"rt_tol","type":"number","required":false,"description":""},{"name":"contains","type":"string/null","required":false,"description":""},{"name":"ms2_only","type":"boolean","required":false,"description":""},{"name":"min_area","type":"number/null","required":false,"description":""},{"name":"adduct","type":"string/null","required":false,"description":""},{"name":"annotation_network","type":"string/null","required":false,"description":""},{"name":"limit","type":"integer","required":false,"description":""}]},{"name":"_fetch_one_msms","description":"Fetch one feature's MS/MS from the resolver. Pure per-row result: on\n    success the peak dict (row_id + precursor/adduct annotations + peaks + PNG),\n    on failure `{row_id, error}`. Shared by the single and batch tools — no\n    top-level `ok`/`task_id` (the callers add those).","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"binding","type":"object","required":true,"description":""},{"name":"row_id","type":"string","required":true,"description":""}]},{"name":"get_eb_features_msms","description":"Fetch MANY features' MS/MS spectra in one call (concurrent fan-out).\n\n    The MS/MS resolver serves one spectrum per request, so this fires the fetches\n    concurrently (bounded) instead of the one-slow-round-trip-per-row you'd get\n    looping `get_eb_feature_msms`. Use it for whole-family screens — e.g. pulling\n    every confirmed conjugate's peaks at once to rank the diagnostic/shared\n    fragment ions across them.\n\n    `row_ids` is capped at 200 per call. Returns `spectra[]` (each: row_id,\n    precursor_mz, the EB-derived adduct / is_default_adduct / annotation_network\n    call, usi, n_peaks, peaks, png_url) in `row_ids` order with failed rows moved\n    to `errors[]` — partial success, not all-or-nothing. `n_peaks == 0` is a\n    feature with no acquired MS/MS (normal, not an error).","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"row_ids","type":"array","required":true,"description":""}]},{"name":"get_eb_xic","description":"Pull an extracted-ion chromatogram (XIC) from the EB task's `/xic`.\n\n    Give a `row_id` (m/z + RT window are taken from the feature) or an explicit\n    `mz` (+ optional `rt_min`/`rt_max`, in minutes). The sample file traced is,\n    in order: the `sample` substring match, else the feature's representative\n    source file, else the feature's strongest sample. Returns the trace\n    (rt[], intensity[]) and its apex. The task is resolved from the shared cache;\n    the request goes to the resolved host (re-probed once on a 404).\n\n    For several features/samples at once, prefer `get_eb_xics` — it batches them\n    into a single /xic round-trip instead of one slow POST each.","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"row_id","type":"string/null","required":false,"description":""},{"name":"mz","type":"number/null","required":false,"description":""},{"name":"rt_min","type":"number/null","required":false,"description":""},{"name":"rt_max","type":"number/null","required":false,"description":""},{"name":"sample","type":"string/null","required":false,"description":""},{"name":"mz_tolerance","type":"number","required":false,"description":""}]},{"name":"get_eb_xics","description":"Pull several XICs in ONE /xic round-trip (vs. one slow POST per feature).\n\n    Two modes:\n      - **Many features:** pass `row_ids=[...]`. Each is traced on its own default\n        sample; pass a single `sample` substring to force them ALL onto the same\n        file (a clean overlay of co-eluting ions / an adduct series).\n      - **One m/z across files:** pass `mz` + `samples=[...substrings...]` (does\n        this feature show up, and where does it elute, across the cohort).\n\n    `rt_min`/`rt_max` (minutes) and `mz_tolerance` (Da) apply to every query;\n    omitted, the RT window falls back per-feature (RT ± tol) or wide open.\n\n    Returns `traces[]` (each: row_id?, mz, sample, rt window, apex, and the\n    rt[]/intensity[] trace) plus `errors[]` for any query that could not be\n    resolved or that /xic rejected — partial success, not all-or-nothing. A\n    batch-level failure (timeout / HTTP error on the single POST) fails them all.","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"row_ids","type":"array/null","required":false,"description":""},{"name":"sample","type":"string/null","required":false,"description":""},{"name":"mz","type":"number/null","required":false,"description":""},{"name":"samples","type":"array/null","required":false,"description":""},{"name":"rt_min","type":"number/null","required":false,"description":""},{"name":"rt_max","type":"number/null","required":false,"description":""},{"name":"mz_tolerance","type":"number","required":false,"description":""}]},{"name":"show_eb_feature","description":"Push one EB feature's evidence (MS/MS + XIC) onto the session's live\n    `/d/{session_id}/eb` page so a human sees it. Fetches both, then updates the\n    display cache (latest-wins) and fans out to every open tab.\n\n    Unlike the data tools this takes a `session_id` (it drives a dashboard), plus\n    the `task_id` to resolve the feature from — no prior bind step.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"task_id","type":"string","required":true,"description":""},{"name":"row_id","type":"string","required":true,"description":""},{"name":"sample","type":"string/null","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"show_eb_xics","description":"Push an OVERLAY of several XIC traces onto the session's live\n    `/d/{session_id}/eb_xics` page so a human sees them on one chart.\n\n    The server pulls every trace from the task's `/xic` in a single batched\n    round-trip (see `get_eb_xics`) then fans the overlay out to viewers. Two\n    selection modes, same as `get_eb_xics`:\n      - **Many features:** `row_ids=[...]` — each on its own default sample, or\n        pass one `sample` substring to force them ALL onto the same file.\n      - **One m/z across files:** `mz` + `samples=[...substrings...]`.\n\n    `rt_min`/`rt_max` (minutes) and `mz_tolerance` (Da) apply to every query.\n    Unlike the data tools this takes a `session_id` (it drives the dashboard) plus\n    the `task_id` to resolve from — no prior bind step.\n\n    Returns a short human summary (traces drawn + any per-query errors).","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"task_id","type":"string","required":true,"description":""},{"name":"row_ids","type":"array/null","required":false,"description":""},{"name":"sample","type":"string/null","required":false,"description":""},{"name":"mz","type":"number/null","required":false,"description":""},{"name":"samples","type":"array/null","required":false,"description":""},{"name":"rt_min","type":"number/null","required":false,"description":""},{"name":"rt_max","type":"number/null","required":false,"description":""},{"name":"mz_tolerance","type":"number","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"show_mirror","description":"Push an MS/MS mirror plot (top vs bottom) to `/d/{session_id}/mirror`.\n\n    Give both spectra as `[m/z, intensity]` peak lists: `top_peaks` (the query,\n    drawn upward) and `bottom_peaks` (the reference, drawn downward). Peaks that\n    match within `mz_tolerance` (Da) are highlighted so the shared fragments pop.\n    Pass `score` (e.g. the cosine from `search_libraries`) to caption it.\n\n    Typical use: compare an EB feature's MS/MS (`get_eb_feature_msms`) against its\n    top library hit (`get_library_spectrum`). Like the other display tools this\n    takes `session_id`; it does not fetch — you supply the peaks.\n\n    `pin=True` also appends the mirror to the Journal; `dashboard_slot=N` (0..7)\n    also places it in a Dashboard slot.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"top_peaks","type":"array","required":true,"description":""},{"name":"bottom_peaks","type":"array","required":true,"description":""},{"name":"top_label","type":"string","required":false,"description":""},{"name":"bottom_label","type":"string","required":false,"description":""},{"name":"top_precursor_mz","type":"number/null","required":false,"description":""},{"name":"bottom_precursor_mz","type":"number/null","required":false,"description":""},{"name":"top_usi","type":"string/null","required":false,"description":""},{"name":"bottom_usi","type":"string/null","required":false,"description":""},{"name":"score","type":"number/null","required":false,"description":""},{"name":"mz_tolerance","type":"number","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"prewarm_network_task","description":"Resolve a GNPS2 everything_bagel task's molecular network into the shared\n    cache + summarize it.\n\n    OPTIONAL — `list_network_components` / `show_network_component` resolve a task\n    on demand, so you never *need* to call this first. Use it to (a) pre-fetch the\n    (tens-of-MB) `network.graphml` once, or (b) get an overview before drilling in.\n\n    Args:\n      task_id: the GNPS2 everything_bagel task id.\n      force: re-fetch + re-parse even if already cached (use when a task was\n        re-staged to a different host).\n\n    Returns node/edge/annotation counts and the top propagation components (those\n    with a library seed and un-annotated neighbors).","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"force","type":"boolean","required":false,"description":""}]},{"name":"list_network_components","description":"List the connected components of an EB task's molecular network.\n\n    Sorted by seed count then size. `annotated_only` keeps only components with a\n    library seed (the ones where annotation can propagate); `min_size` filters out\n    tiny components. The task's network is resolved from the shared cache on demand.","params":[{"name":"task_id","type":"string","required":true,"description":""},{"name":"annotated_only","type":"boolean","required":false,"description":""},{"name":"min_size","type":"integer","required":false,"description":""},{"name":"limit","type":"integer","required":false,"description":""}]},{"name":"show_network_component","description":"Push one component's subgraph onto the live `/d/{session_id}/network` page.\n\n    Choose the component by `component` id, by a `row_id` it contains, or leave\n    both blank to show the strongest propagation component. Nodes are colored by\n    class (seed / propagated / dark), edges weighted by cosine. If the component\n    exceeds `max_nodes`, the highest-degree nodes (hubs) are kept.\n\n    Unlike the data tools this takes a `session_id` (it drives a dashboard), plus\n    the `task_id` to resolve the network from — no prior load step.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"task_id","type":"string","required":true,"description":""},{"name":"component","type":"string/null","required":false,"description":""},{"name":"row_id","type":"string/null","required":false,"description":""},{"name":"max_nodes","type":"integer","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"highlight_network_nodes","description":"Spotlight specific nodes on the session's live `/d/{session_id}/network` page.\n\n    Operates on whatever component is CURRENTLY shown there — call\n    `show_network_component` first, then highlight a subset by their `node_ids`\n    (each == a feature `row ID` / GraphML cluster index). Highlighted nodes get a\n    bright ring and the rest dim back, so the human's eye goes straight to the ones\n    you mean — e.g. the propagation candidates you're proposing, or the seed a\n    class was inferred from.\n\n    Args:\n      node_ids: the row IDs to spotlight. Pass an EMPTY list to clear the highlight.\n      label: optional short caption shown over the graph (why these are lit).\n      focus: if true (default), the view pans/zooms to frame the highlighted nodes.\n\n    The highlight is a separate overlay: it survives a live data re-push and\n    replays for late-joining viewers, but is applied only to nodes present on the\n    page (unknown ids are ignored client-side). Returns how many matched what's\n    currently shown.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"node_ids","type":"array","required":true,"description":""},{"name":"label","type":"string/null","required":false,"description":""},{"name":"focus","type":"boolean","required":false,"description":""}]},{"name":"set_notepad","description":"Push a draft into the session's shared notepad (latest-wins).\n\n    Think of the notepad as a shared scratch space for this session: a place to\n    leave notes the human can read, AND a collaborative workspace where the human\n    and another agent may be editing at the same time as you. It is NOT private\n    to you — every open /d/{session_id}/notepad tab updates live, the human can\n    edit the text in place, and a concurrent agent can call set_notepad too. It\n    is latest-wins with no locking, so treat what you last wrote as potentially\n    already changed: call get_notepad(session_id) to re-read the current text\n    before overwriting, and prefer appending/merging over clobbering others' work.\n\n    Args:\n      session_id: the session this note attaches to.\n      text: the text to place in the shared, editable notepad.\n      label: short human-facing title for what this note is / what you're asking\n        them to review or work on together.","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"text","type":"string","required":true,"description":""},{"name":"label","type":"string/null","required":false,"description":""}]},{"name":"get_notepad","description":"Read the shared notepad's CURRENT text — to see what people are doing.\n\n    The notepad is a shared workspace: the human and possibly another agent may\n    be writing to it concurrently. Poll this to see the latest — what the human\n    has typed, notes another agent left, or edits made since your own last push.\n\n    Returns the text plus `source` (\"agent\" if last set by an agent's push,\n    \"user\" if a human edited it last) and `updated_at`. Read this before you\n    overwrite with set_notepad so you merge with, rather than clobber, whatever\n    others have added.","params":[{"name":"session_id","type":"string","required":true,"description":""}]},{"name":"set_structure_validation","description":"Populate the MS/MS structure-validation page for a session (latest-wins).\n\n    Every open /d/{session_id}/validate tab updates live; a late joiner replays\n    the last push. Use this to lay out an MS/MS spectrum next to a candidate\n    structure so a human can confirm the annotation.\n\n    Args:\n      session_id: the session this content attaches to.\n      peaks: the experimental MS/MS fragment peaks (mz + intensity).\n      precursor_mz: the precursor m/z of the MS/MS scan.\n      usi: an authoritative Universal Spectrum Identifier (mzspec:...) to verify\n        the peaks against; its reference spectrum is embedded side-by-side.\n      smiles: candidate structure as SMILES; depicted on the page.\n      label: short human-facing title (e.g. compound name / feature id).","params":[{"name":"session_id","type":"string","required":true,"description":""},{"name":"peaks","type":"array","required":true,"description":"Peak objects with: mz (number), intensity (number)"},{"name":"precursor_mz","type":"number","required":true,"description":""},{"name":"usi","type":"string/null","required":false,"description":""},{"name":"smiles","type":"string/null","required":false,"description":""},{"name":"label","type":"string/null","required":false,"description":""},{"name":"pin","type":"boolean","required":false,"description":""},{"name":"dashboard_slot","type":"integer/null","required":false,"description":""}]},{"name":"list_spectral_libraries","description":"List the GNPS2 spectral-library indexes available to `search_libraries`.\n\n    Returns the live index names from fasst.gnps2.org (e.g. `gnpslibrary`,\n    `gnpsdata_index`, `massivekb_index`, the `metabolomicspanrepo_*` pan-repo\n    indexes). Pass one of these as the `library` argument when searching. If the\n    live listing can't be reached, a short known-good fallback list is returned\n    with `\"source\": \"fallback\"`.","params":[]},{"name":"search_libraries","description":"Search the GNPS2 MS/MS spectral libraries for matches to a query spectrum.\n\n    Provide EITHER `usi` (a Universal Spectrum Identifier pointing at the query\n    spectrum — e.g. `mzspec:GNPS2:TASK-<id>-...:scan:<n>` or a MassIVE/library\n    USI) OR raw `peaks` + `precursor_mz`. `peaks` is a list of `[m/z, intensity]`\n    pairs.\n\n    Parameters:\n      library: which index to search — see `list_spectral_libraries`\n        (default `gnpslibrary`).\n      analog: also return analog (delta-mass) hits, not just exact matches.\n      pm_tolerance: precursor m/z tolerance in Da (default 0.05).\n      fragment_tolerance: fragment-peak matching tolerance in Da (default 0.05).\n      cosine_threshold: minimum cosine similarity to report (0-1, default 0.7).\n      limit: cap the number of hits returned (default 50).\n\n    Each hit is a library match with its USI (fetch it with\n    `get_library_spectrum`), cosine score, matching-peak count and delta mass.\n    Returns `{\"ok\": False, \"error\": ...}` on bad input or a service error.","params":[{"name":"usi","type":"string/null","required":false,"description":""},{"name":"peaks","type":"array/null","required":false,"description":""},{"name":"precursor_mz","type":"number/null","required":false,"description":""},{"name":"precursor_charge","type":"integer","required":false,"description":""},{"name":"library","type":"string","required":false,"description":""},{"name":"analog","type":"boolean","required":false,"description":""},{"name":"pm_tolerance","type":"number","required":false,"description":""},{"name":"fragment_tolerance","type":"number","required":false,"description":""},{"name":"cosine_threshold","type":"number","required":false,"description":""},{"name":"limit","type":"integer","required":false,"description":""}]},{"name":"get_library_spectrum","description":"Fetch one library spectrum's peaks + precursor by USI or GNPS accession.\n\n    Provide EITHER a `usi` (any resolvable USI — typically a hit's USI from\n    `search_libraries`) OR a GNPS library `accession` (a `CCMSLIB...` id), which\n    is resolved as `mzspec:GNPS:GNPS-LIBRARY:accession:<accession>`.\n\n    Returns the precursor m/z/charge and the peak list (`[m/z, intensity]`\n    pairs, capped at `max_peaks`). For a GNPS `accession`, a `knowledgebase_url`\n    to that entry on library.gnps2.org is included. `{\"ok\": False, \"error\": ...}`\n    on bad input or an unresolvable spectrum.","params":[{"name":"usi","type":"string/null","required":false,"description":""},{"name":"accession","type":"string/null","required":false,"description":""},{"name":"max_peaks","type":"integer","required":false,"description":""}]}]