← Plugin catalog
Scientific Research

Helical

Helical v1.0.5

Bio foundation models

Create a free account to save this plugin.

From the developer

Declared capabilities

  • Upload datasets
  • Compute embeddings
  • Fine-tune models

Declared limitations

  • Searching for public datasets that are not in the user's project.
  • Billing actions: invoices, payment methods and refunds.
  • Deleting or renaming a registered dataset.

Not specified in the available declarations: pricing & account requirements.

Onboarding example

Embed my dataset with a Helical model.
Sources & dates

Developer declarations; not independently tested. Listing last checked Nov 7, 2026. Package observed Nov 7, 2026.

View package source →

Description

From the marketplace listing

Helical lets you run biological foundation models on your own single-cell data, from the chat you're already in. Upload an .h5ad dataset into your private Helical project, pick a model — scGPT, Geneformer, TranscriptFormer, Cell2Sentence or Nicheformer — and compute embeddings on Helical's GPUs. Follow the run while it goes, read the error if it fails, and download the embeddings when it finishes. Nothing starts on its own. A run is quoted and queued first, and only begins once you approve it in a second, separate step. Every tool works inside the one project your account owns. Runs use the credits in your existing Helical account.

Language: English · Automatically detected from descriptions.

Matches for “script”

Exact text from the indicated source. A mention alone does not establish support for your task.

Publisher full description

Helical lets you run biological foundation models on your own single-cell data, from the chat you're already in. Upload an .h5ad dataset into your private Helical project, pick a model — scGPT, Geneformer, TranscriptFormer, Cell2Sentence or Nicheformer — and compute embeddings on Helical's GPUs. Follow the run while it goes, read the error if it fails, and download the embeddings when it finishes. Nothing starts on its own. A run is quoted and queued first, and only begins once you approve it in a second, separate step. Every tool works inside the one project your account owns. Runs use the credits in your existing Helical account.

What changed

· 7 observations

Capabilities & instructions

Skill instructions changed from “Platform → **Connect**. - **Claude Desktop** and **claude.ai**: **Customize** → **Connectors** → Helical → **Connect**. Except through the `authenticate`...” to “→ **Connect**. - **Claude Desktop** and **claude.ai**: **Customize** → **Connectors** → Helical → **Connect**. Except...

View comparison →
Capabilities & instructions

Skill instructions changed from “Price it, then confirm Price before uploading anything: the cost depends on the combined file's cell count, so work it out with the rates from `listModels`...” to “Estimate the price Estimate before uploading anything: the cost depends on the combined file's cell count, so work it...

View comparison →
Capabilities & instructions

Skill instructions changed from “## 1. Select the dataset and confirm the label column `listDatasets(...)` → `getDataset({ id })`. The record names likely label columns: `celltypeColumn`,...” to “**Every run that spends credit needs the user's explicit approval.** That approval comes at `resolveConfirmation`, after...

View comparison →
Capabilities & instructions

Skill instructions: added “Every run that spends credit needs that explicit approval. So do not ask the user to approve the dataset or model before queuing. Choose them, queue the run,...”.

View comparison →
Positioning & listing

Plugin name changed from “Helical Platform” to “Helical”. Short description changed from “Single-cell foundation models” to “Bio foundation models”. Version changed from “1.0.2” to “1.0.5”.

View comparison →

Technical updates · 1

Package or technical metadata updated

View technical comparison →

Keywords

Files & skills

File archives

Plugin package15 files · 20.5 KBBrowse files →
Skill instructions
check-credits5.06 KB

View saved version →

---
name: check-credits
description: >-
  Read the user's Helical credit balance, tell them what a run will cost and when they are
  actually charged, and explain a run refused for insufficient credit. Use when the user
  asks what their balance is, whether they can afford a run, what an embedding or
  fine-tune will cost, or why a run would not start.
---

# Credits: read the balance, explain the charge

## The balance is readable

`whoami()` returns the signed-in `email`, the current `credits_balance`, and the `console`
URL. When the user asks how many credits they have, that number is the answer — give it.

**One credit is one USD**, so a credit figure is a dollar figure and there is nothing to
convert.

The figure is current as of the call, and it moves as runs are charged and refunded. Read
it again rather than reusing one from earlier in the conversation.

## What a run costs

A run costs **a fixed amount per job plus a rate per processed cell**, not per token:

```
credits = jobs × (credits_per_job + cells × passes × credits_per_cell)
```

- `jobs` is how many jobs the launch runs, and `cells` is the cells in each. An embedding
  launch is **one job**.
- `credits_per_job` pays for the work a job does before its first cell, so it is the same
  for ten cells or a million. On a small dataset it is most of the cost.
- `passes` is **1 for an embedding**. For fine-tuning it is **6 × the epoch count**: a
  training step does far more work per cell than an embedding. A validation dataset adds
  its own cells **once per epoch**. So fine-tuning a dataset costs many times what
  embedding it does. The per-job amount is paid once, not once per epoch. The `listModels`
  tool description states the current pass counts; trust it over this page if they differ.
- Both rates are on every `listModels` entry, and differ per model. A model whose rates are
  `null` is not priced and cannot be run here; it is not free.
- A fine-tuned model is charged at the rates of the `base_model` it descends from; it has no
  rates of its own and could not have them, since the user creates it at run time.
- There is no deduplication — the same cell twice is two processed cells.

Use this when the user is deciding **whether** to run: `cellCount` from `listDatasets` or
`getDataset`, and the two rates from `listModels`. For example, with a model at
`credits_per_job` 0.03 and `credits_per_cell` 0.000003, embedding 300,000 cells is
`1 × (0.03 + 300000 × 1 × 0.000003)` = **0.93 credits**. Fine-tuning the same 300,000 cells
for 2 epochs, with a 30,000-cell validation dataset, is
`0.03 + (300000 × 2 × 6 + 30000 × 2) × 0.000003` = **11.01 credits**. Read the real rates from
`listModels` rather than reusing these.

**But your arithmetic is an estimate, not the quote.** When a run is actually queued,
`triggerEmbedding` or `triggerFinetuning` prices it and returns the platform's own figure,
which is what the charge will read. Queuing is free and starts nothing, so prefer that
figure once it exists, and relay it rather than recomputing.

## When the charge actually happens

This is usually the user's real question, and it is reassuring:

- Queuing a run charges nothing.
- The credit is taken **when the run starts**, at approval.
- A run that **fails or is cancelled is refunded in full**.

So a failed run costs nothing. Say so plainly when one fails — it is the first thing they
will want to know.

## When the balance will not cover it

A **402 `insufficient_balance`** can come back either when the run is queued or when it is
approved. Either way nothing launched and nothing was charged — but **the confirmation is spent**.
A later change to the balance does not make it approvable again; the run has to be re-requested
from the trigger tool, which mints a fresh quote.

Credits are managed in their Helical account, not through this plugin.

Retrying the same request unchanged will not help, and the error says so. Do not loop.

## Where the account lives

The account lives o

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

compute-embeddings5.31 KB

View saved version →

---
name: compute-embeddings
description: >-
  Compute cell embeddings for a single-cell dataset with a Helical foundation model, then
  download the outputs. Use when the user wants embeddings, representations, or features
  from a dataset already in the platform catalogue. For training a model on labelled data,
  use fine-tune-model instead.
---

# Compute embeddings

Turns a catalogue dataset plus a foundation model into an embedding matrix.

**The one thing to understand before starting:** `triggerEmbedding` does not start
anything. It queues the run and returns a `confirmation_id` and the platform's price. The
run starts only when `resolveConfirmation` approves it, and **that call is the user's
approval**. State the dataset, the model and the price, and get an explicit yes before
making it.

Every run that spends credit needs that explicit approval. So do not ask the user to approve
the dataset or model before queuing. Choose them, queue the run, then ask once, showing the
choices and the price together. Queuing is free. To change a choice, reject and queue again.

You also cannot choose a project: scope comes from the signed-in user, and no tool accepts
a project or conversation identifier.

## 1. Select the dataset

`listDatasets` finds the dataset; its description covers the filters. `organism` matches
the full name exactly, so `"Homo sapiens"` matches but `"human"` does not.

`getDataset({ id })` for the full record, including `cellCount` and `geneCount`. Report
them: run time and price scale with the cell count.

A user's own `.h5ad` can be added with `initiateDatasetUpload` → `completeDatasetUpload`
→ `registerDataset`; follow those tools' descriptions for splitting the file. Once
registered, it is embedded like any catalogue dataset.

## 2. Choose a model

`listModels()`. It returns two lists:

- `base_models`: foundation models. Pass the `name` as `model` and omit `model_version`.
- `models`: the user's own fine-tuned models, promoted or not. Pass the `name` as `model`
  and the `version`, as a number, as `model_version`. Never pass `base_model`.

Any of them can run here; promotion is only a label. Only single-cell models are listed,
and only those can run here. Every entry carries its rates, `credits_per_job` and
`credits_per_cell`; a fine-tuned model is priced at its `base_model`'s rates. Pick one whose
`credits_per_cell` is not `null`; an unpriced model cannot run here.

## 3. Queue it, show the price, then approve

```
triggerEmbedding({ datasetId, model, model_version? })
```

Send only these fields (and `pretrained_embedding_species`, if the user asks for it). The
tool refuses any other field with a 400.

The reply carries the platform's quote: the cells it counts and the most it
will cost. Relay that figure; do not recompute it. Get an explicit yes, then call
`resolveConfirmation({ id: confirmation_id, decision: "approve" })`. If the user declines,
resolve it with `"reject"`.

Do not put several runs behind one approval, and do not treat an earlier "sounds good"
about the plan as approval for the run itself. Each model is its own run with its own
quote.

To change anything, reject the queued confirmation, then queue again. A 409 means the same
run is already queued. `listPendingConfirmations()` finds it, but its entry carries no
price, so if you do not still have that quote from this conversation, reject it and queue
again. For a 402 or an unusable quote, see `check-credits`.

## 4. Follow it through

On approval, `outcome.dag_run_id` names the run. Poll `getRunDetails({ runId })` until
`state` is `succeeded`, `failed` or `cancelled`. Runs take minutes to hours; poll at a
sensible interval and keep the user informed rather than going silent. On failure,
`getDagErrors({ runId })` says what went wrong. A failed or cancelled run is refunded in
full. `listDagRuns({ dagIds: "embedding" })` lists recent embedding runs if you lose track
of one.

## 5. Download the outputs

`getRunDetails({ runId })` returns `arti

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

fine-tune-model8.29 KB

View saved version →

---
name: fine-tune-model
description: >-
  Fine-tune a Helical foundation model on a labelled single-cell dataset. Use when the
  user wants to personalize, train, or adapt a model to their own labels. For
  representations from an existing model without training, use compute-embeddings
  instead.
---

# Fine-tune a model

Trains a foundation model on a labelled dataset and registers the result in the user's
model list.

`triggerFinetuning` does not start anything. It queues the run and returns a
`confirmation_id` and the platform's price. The run starts only when
`resolveConfirmation` approves it, and **that call is the user's approval**. This is the
most expensive run on this surface, so the preparation below matters more than it does for
embeddings.

**Every run that spends credit needs the user's explicit approval.** That approval comes at
`resolveConfirmation`, after the platform's quote. So do not ask the user to approve the
configuration before queuing. Make the choices below, queue the run, then ask once, showing
the choices and the price together. Queuing is free. To change a choice, reject the queued
run and queue again.

## 1. Select the dataset and choose the label column

`listDatasets(...)` → `getDataset({ id })`. The record names likely label columns:
`celltypeColumn`, `celltypeColumnLv2`, `diseaseColumn`, `donorColumn`. Note `cellCount`
too; the price scales with it.

These tools cannot list a dataset's other `.obs` columns or their values. If the user wants
a column the record does not name, ask them for its exact name, or read it from a local
copy of the file (the record's `linkData`, when it has one; an uploaded dataset usually
does not).

**Choose the label column, and name it in the approval request.** Training on a
plausible-looking but wrong column wastes the whole run, and nothing downstream will catch
it. Where you can see the classes, check they look like what the user expects. A column
with one dominant class or hundreds of singletons will not train usefully. Ask before
queuing only when you cannot choose: several columns fit the request, none does, or the
classes look unusable.

**Validation needs its own dataset.** This surface does not split the training data. To
validate, the user registers a separate held-out dataset and you pass it as `valDatasetId`.
Without one, the run trains with no validation.

## 2. Choose a base model

`listModels()`. Fine-tune from a `base_models` entry: pass its `name` as `model` and omit
`model_version`. To train an existing fine-tune further, pass a `models` entry's `name`
plus its `version`, as a number, in `model_version`, promoted or not. Pick a model whose
`credits_per_cell` is not `null`; an unpriced model cannot run here.

Before committing: if the user wants representations rather than a classifier, a
zero-shot embedding may already answer it. `compute-embeddings` is far cheaper and faster.
Say so rather than fine-tuning by default.

## 3. Queue it

These fields are required, and a missing one is a 400:

```
triggerFinetuning({
  datasetId, model,
  labels:      ["cell_type"],      # one entry per prediction task
  task_type:   ["prediction"],     # "prediction" | "contrastive"
  model_type:  ["classification"], # one per prediction task: "classification" | "regression"
  learning_rate, batch_size, epochs, logging_steps,
  lr_scheduler,                    # "constant" | "linear" | "cosine_with_min_lr"
  min_lr, seed, num_trainable_layers,
  registered_model_name,           # letters, digits, _ - { } only
  # optional: model_version, valDatasetId, weight_decay, warmup_steps,
  #           early_stopping_patience, lora_config, task_weights, ...
})
```

`labels` and `model_type` describe the **prediction tasks only**, one entry each per task,
in the same order. `task_type` lists one entry per task, contrastive included. The tool's
own description calls all three parallel; that holds only when every task is a prediction.

At most one task can be contrastive. It ta

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

in-silico-perturbation7.47 KB

View saved version →

---
name: in-silico-perturbation
description: >-
  Run an in-silico gene knockout, knockdown or overexpression screen with Helical
  foundation models by editing the expression matrix locally, then embedding the
  perturbed cells on the platform. Use when the user wants to perturb genes, screen
  targets, or find genes whose perturbation shifts diseased cells toward a healthy state
  — even when no perturbation tool is available, because none is needed.
---

# In-silico perturbation

Finds which gene perturbations move cells from one state toward another, by showing a
foundation model perturbed cells and measuring where their embeddings land.

**The one thing to understand before starting:** a perturbation is an edit to the
expression matrix, and you can make it yourself. You do not need a perturbation, target-ID
or gene-validation tool, and their absence is not a reason to stop. The work splits in
two:

- **Locally:** download the dataset, edit the counts, build one file, and later score the
  embeddings.
- **On Helical:** upload that file, embed it with each model, download the embeddings.

**The model must see the perturbed counts.** Embedding the unperturbed dataset and then
"knocking down" a gene in embedding space, or scoring genes against centroids of the
original embeddings, measures nothing. Every perturbed condition goes through the model.

## 1. Get the expression matrix locally

`listDatasets(...)` → `getDataset({ id })`. Note `cellCount`, `geneCount`, and the
`.obs` columns it names: `celltypeColumn`, `diseaseColumn`, `donorColumn`. You need the
cell-type and state columns to choose cells and to score.

The platform does not hand back a dataset's own file. Get the `.h5ad` from the record's
`linkData` (the original download URL), or from the user if they have it. If neither
exists, say so plainly; do not substitute a different dataset.

Check before editing:

- **Raw counts.** The models normalise their input themselves. If `X` holds normalised or
  log values, use `layers["counts"]` or `raw` instead; if there are no counts, tell the
  user the perturbation will be less faithful.
- **Genes are present and expressed.** For each candidate, report the fraction of target
  cells with non-zero counts. Drop genes that are absent or barely detected — knocking out
  a gene the cells do not express changes nothing and wastes a slot.

## 2. Build one combined file

Put every condition in **one `.h5ad`**, so each model needs one embedding run, not one per
gene, and every condition goes through the same model pass. Tag each cell with a
`perturbation` column in `.obs`:

| Block | Cells | `perturbation` |
|---|---|---|
| Reference | target-state cells (e.g. healthy), unedited | `reference` |
| Control | source-state cells (e.g. injured), unedited | `control` |
| One per gene | a copy of the control cells with that gene edited | the gene name |
| Null | a copy of the control cells with a random, expression-matched gene edited | `null_<gene>` |

- **Include the null.** Any edit moves an embedding a little. Without 3–5 random genes,
  matched to the candidates on detection rate and edited the same way, there is nothing
  to say a candidate's shift is more than noise.
- **Subsample.** The file holds `reference + control × (1 + genes + nulls)` cells. A few
  hundred control cells per cell type is enough; balance donors where the metadata allows.
- **Keep the layout of the source.** Change only count values and add the `perturbation`
  column. Keep `.var` and the existing `.obs` columns as they were, so the same gene
  identifiers and column names apply. Give each copied cell a unique `obs_names`, such as
  `<cell>__<perturbation>`.

How to edit a gene, on raw counts:

- **Knockout:** set the gene to 0.
- **Knockdown:** multiply its counts by a factor, e.g. 0.25. Geneformer reads gene *rank*,
  so a partial knockdown may not change its input at all — use a knockout for it, and say so.
- **Overexpression:** raise it, e.g. to its 99th p

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

reconnect-helical8.66 KB

View saved version →

---
name: reconnect-helical
description: >-
  Get a Helical connection working when it is not: the plugin was installed but never
  connected, a tool call came back with an authorization link, or a connection that worked
  before is now refused. Use when the helical tools are missing from the session or the
  host offers only an `authenticate` tool for it; when a Helical call returns "Authorization
  required before this tool can run", "This request requires more information" or a link to
  open; when it fails with invalid_grant, invalid_request, invalid_client, invalid_token,
  unauthorized_client, a 401, "OAuth authorization required", "Missing Bearer token" or
  "Invalid JWT"; when a call fails without saying why; or when the user asks how to sign in.
  For a run refused over credit, use check-credits.
---

# Reconnect Helical

Helical asks for two approvals, both in the browser: **connecting the plugin** in the
client, and **one authorization the first time a tool runs**. Each failure below is one of
them missing. Tell which from what you see, and put the user's next step in the same
message that reports the problem — never leave them to ask "so what do I do?".

| What you see | Case |
|---|---|
| No `helical` tools at all, or only an `authenticate` tool for it | 1 — not connected |
| A call returns a link to open, "Authorization required before this tool can run", or "This request requires more information" | 2 — authorization link |
| A connection that worked before now fails with a 401 or an OAuth code | 3 — connection refused |

Not these: **`402` / `insufficient_balance`** is credit (`check-credits`), and **`403`** is
a signed-in account without permission — reconnecting returns the same `403`.

## 1. Not connected

Installing the plugin and connecting it are two separate steps in every client. Skip the
second and the plugin shows as enabled with none of its tools. Confirm it before you fix
it, where the client lets you:

- **Claude Code**: `claude mcp list`. The plugin's server is
  `plugin:helical-platform:helical` (`claude.ai Helical` when added from the Claude
  directory, plain `helical` when added by hand). `! Needs authentication` is this case;
  `✔ Connected` is not.
- **Codex**, and the ChatGPT desktop app with a plugin added from GitHub: `codex mcp list`.
  `Not logged in` under **Auth** is this case; `OAuth` is not.
- **ChatGPT** from the public directory, **Claude Desktop** and **claude.ai** have no
  command: ask whether Helical still offers **Connect** where the fix below points.

Then connect it:

- **Claude Code** (CLI, and the Code tab in Claude Desktop). If the host offers a helical
  `authenticate` tool (e.g. `mcp__plugin_helical-platform_helical__authenticate`), call it
  and relay the link it returns; the tools load once the user approves, with no new
  session. If their browser then lands on a `localhost` page that will not load, ask for
  the address-bar URL and pass it to the matching `complete_authentication` tool.
  Otherwise the user runs `/mcp` → the Helical server → **Authenticate**, or
  `claude mcp login plugin:helical-platform:helical` in their own terminal. Do not run that
  command yourself: it needs an interactive terminal and refuses without one.
- **Codex**: `codex mcp login helical`. You can run this one: it opens their browser and
  waits for the approval. `/mcp` inside Codex only lists servers. In the ChatGPT desktop
  app the same step is **Settings** → **MCP servers** → **Authenticate**.
- **ChatGPT** from the public directory: **Settings** → **Plugins** → Helical →
  **Connect**.
- **Claude Desktop** and **claude.ai**: **Customize** → **Connectors** → Helical →
  **Connect**.

Except through the `authenticate` tool, say a new session may be needed: hosts that load
their tools at session start will not add them to this one. The Connect step of the
walkthrough at `<who-am-i-tool-console-url>docs?section=walkthrough` has the same steps
for every client.

## 2. Authorization link

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
AGPL-3.0-or-later
Package author
Helical
Keywords
See keywords
Review scenarios
5 positive · 3 negativeScenario counts, not test results.

Declared capabilities

  • Upload datasets
  • Compute embeddings
  • Fine-tune models
  • Download results

Package observed Nov 7, 2026.

Technical details
First seen
Oct 24, 2026 · 12:40 UTC
Last seen
Nov 7, 2026 · 18:00 UTC
Latest observed change
Oct 28, 2026 · 13:02 UTC
Collection status
Collected

plugin_asdk_app_6abe37bd8c6c8191afaf84a1b31585b4

Download plugin data (JSON)

Plugin details: served from cache. Prepared . Refreshed when plugin data changes or after 6 hours. Your account and Follow status are live.