# Genomic Intelligence

> Hosted DNA language models: promoter, splice, enhancer, chromatin, expression, annotation

- name: ai.genomicintelligence/genomic-intelligence
- version: 1.0.0
- connection class: R0 (autonomous)
- trust: 80/100 flags: no-repository
- quality: 73/100 (needs work)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/ai.genomicintelligence%2Fgenomic-intelligence
- tools: https://api.protogrid.dev/v1/servers/ai.genomicintelligence%2Fgenomic-intelligence/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "genomic-intelligence": {
      "type": "http",
      "url": "https://mcp.genomicintelligence.ai/mcp",
      "headers": {
        "Authorization": "Bearer ${GENOMIC_INTELLIGENCE_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${GENOMIC_INTELLIGENCE_TOKEN}`.

## Trust

- hygiene: 80
- liveness: 100
- freshness: 85
- provenance: 55
- drivers: +dns-namespace +website +reachable +uptime-100% ~updated-85d-ago -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 73/100 (needs work)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 86 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 5 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 15 of 15 tools declare readOnlyHint or destructiveHint
- warn `tools.directory_hints`: 7 of 15 tools declare all four hints; missing: predict_enhancer (idempotentHint); predict_chromatin (idempotentHint); get_job (idempotentHint); …
- pass `tools.token_cost`: about 5,962 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 25 (weight 15)

- warn `stability.changes`: 10 tool changes in 30 days
- fail `stability.rug_pull`: 2 tools kept their name but changed most of their description in 30 days; review before trusting them

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 15, about 5,962 tokens to load them all
- tool set hash: 871d90823478efd276873058e852d6b7
- tools last changed: 2026-10-04T04:13:28.837Z
- badge: [![protogrid quality](https://protogrid.dev/badge/ai.genomicintelligence/genomic-intelligence.svg)](https://protogrid.dev/servers/ai.genomicintelligence/genomic-intelligence)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-04 `predict_expression` changed (description)
  - before: Predict a gene's expression from the sequence around its TSS. Expression is cell-type-specific, so `description` (cell type / assay context, e.g. 'K562 cell line') is REQUIRED — the API rejects requests without it. The input rule is the same for every expression model: at least 9,198 bp, with the TSS at least 4,599 bp from each end. Longer input is welcome, up to 500,000 bp. Each model's bio_spec.recommended_flank_bp (see list_models) says how many bp to supply on each side of the TSS: 4,599 for the default g0-expression, which reads 9,198 bp around the TSS, and 40,960 for g0-expression-8192, which reads much further. Less flank than a model recommends, down to 4,599 bp, is accepted and scored, but that model then reads less than it was trained on. - A 9,198 bp sequence with the TSS at offset 4,599 (the midpoint) needs no `tss_index`. - Any longer sequence needs `tss_index`: the 0-based offset of the TSS into it. The API cuts what the model reads around that offset and never scans for a TSS itself. Under 9,198 bp, or a TSS closer than 4,599 bp to either end, is rejected here and by the API (422). A locus with no offset is rejected too, because it is indistinguishable from a mis-centred window. A very N-rich or low-complexity window can also be refused by the API (422). An offset that is merely WRONG (e.g. counted over a wrapped FASTA's characters, or against a chromosome coordinate instead of an offset into THIS sequence) still succeeds and scores the wrong window — verify meta.task_specific_counts.scored_window in the response. Easiest paths: fetch_gene_for_expression(gene) returns a 9,198 bp handle with the TSS at its midpoint, valid for every expression model, and find_genes_and_predict_expression takes a raw region and finds each TSS for you.
  - after: Predict a gene's expression from the sequence around its TSS. Expression is cell-type-specific, so `description` (cell type / assay context, e.g. 'K562 cell line') is REQUIRED — the API rejects requests without it. The input rule is the same for every expression model: at least 9,198 bp, with the TSS at least 4,599 bp from each end, up to 500,000 bp. Longer TSS-centred sequence gives better predictions: each model's bio_spec.recommended_flank_bp (see list_models) says how many bp it reads on each side of the TSS, and flank beyond that is ignored. Less flank, down to 4,599 bp, is accepted and scored, but the model then reads less than it was trained on. Omit `model` for the server's default. - A 9,198 bp sequence with the TSS at offset 4,599 (the midpoint) needs no `tss_index`. - Any longer sequence needs `tss_index`: the 0-based offset of the TSS into it (a fetch_gene_for_expression handle carries its own). The API cuts what the model reads around that offset and never scans for a TSS itself. Under 9,198 bp, or a TSS closer than 4,599 bp to either end, is rejected here and by the API (422). A locus with no offset is rejected too, because it is indistinguishable from a mis-centred window. A very N-rich or low-complexity window can also be refused by the API (422). An offset that is merely WRONG (e.g. counted over a wrapped FASTA's characters, or against a chromosome coordinate instead of an offset into THIS sequence) still succeeds and scores the wrong window — verify meta.task_specific_counts.scored_window in the response. Easiest paths: fetch_gene_for_expression(gene) already fetches a long TSS-centred handle (as much flank as the listed models recommend) and records its `tss_index`, which is sent for you when you pass that handle without one; find_genes_and_predict_expression takes a raw region and finds each TSS for you.
- 2026-10-04 `fetch_gene_for_expression` changed (description) **meaning changed**
  - before: Fetch a gene's sequence prepared for expression prediction. Resolves the gene's TSS via Ensembl and returns a 9,198 bp gene-sense window with the TSS at offset 4,599 (its midpoint), as a handle to pass to predict_expression(sequence_ref=...). That is the minimum valid input for every expression model, and at 9,198 bp it needs no `tss_index`. It is all the default g0-expression reads, but a model may recommend a wider flank: bio_spec.recommended_flank_bp from list_models (e.g. 40,960 bp for g0-expression-8192). To supply flank F, call fetch_region(region=<this handle's region>, strand=<its strand>, flank_bp=F - 4,599), which returns 2F bp with the TSS at offset F, and pass tss_index=F to predict_expression. If the returned sequence is not exactly 2F bp (the gene is near a chromosome end), the TSS is not at F: use a smaller flank.
  - after: Fetch a gene's sequence prepared for expression prediction. Resolves the gene's canonical-transcript TSS via Ensembl and stores a gene-sense sequence centred on it, as a handle to pass to predict_expression(sequence_ref=...). Longer TSS-centred sequence gives better predictions, so this already fetches as much flank on each side of the TSS as the listed expression models recommend (the largest bio_spec.recommended_flank_bp from list_models). One handle serves every expression model: the API reads what the chosen model needs around the TSS and ignores the rest. The handle records `tss_index` (the TSS offset into it), and predict_expression uses it when you do not pass one, so no offset arithmetic is needed. Every expression model accepts at least 9,198 bp with the TSS at least 4,599 bp from each end. Near a chromosome end the flank is shortened to what fits (reported as `flank_shortened`), never below 4,599 bp; a TSS closer to the end than that is an error.
- 2026-10-04 `list_models` changed (description)
  - before: List available models for a task. Use to discover model ids before passing one as the `model` argument to a predict tool. The same catalog is also available as the resource `gi://models`. Returns a FLAT object — {task, default_model, models: [...]} — not the {data, meta} envelope the predict tools return. Each model carries a `bio_spec`, whose useful fields are `request_max_bp` (the enforced ceiling, 500,000 everywhere) and `context_window_bp` (what the model reads in one step — compare your sequence length against it: a shorter one is scored against a padded window). `trained_window_bp` is the fixed receptive field where there is no sliding window (9,198 for g0-expression; null for an expression model without one, such as g0-expression-8192). For expression, `recommended_flank_bp` is how many bp to supply on each side of the TSS (4,599 for g0-expression, 40,960 for g0-expression-8192). `request_max_bp` is the only cap; the other fields describe what the model reads, not what the route accepts.
  - after: List available models for a task. Use to discover model ids before passing one as the `model` argument to a predict tool. The same catalog is also available as the resource `gi://models`. Returns a FLAT object — {task, default_model, models: [...]} — not the {data, meta} envelope the predict tools return. Each model carries a `bio_spec`, whose useful fields are `request_max_bp` (the enforced ceiling, 500,000 everywhere) and `context_window_bp` (what the model reads in one step — compare your sequence length against it: a shorter one is scored against a padded window). `trained_window_bp` is the fixed receptive field where there is no sliding window (null for a model without one). For expression, `recommended_flank_bp` is how many bp the model reads on each side of the TSS; longer TSS-centred input is better, and fetch_gene_for_expression already fetches the largest listed value. `request_max_bp` is the only cap; the other fields describe what the model reads, not what the route accepts.
- 2026-10-03 `find_genes_and_predict_expression` changed (annotations)
- 2026-10-03 `find_genes` changed (annotations)
- 2026-10-02 `find_genes_and_predict_expression` changed (description)
  - before: Find genes in a sequence, then predict each gene's expression (composite). Server-side chaining in ONE call: finds genes (transcript intervals, with their TSS) in the sequence, then predicts expression off each discovered TSS in the given experimental context. This is the right tool whenever you want expression for a raw region or sequence — e.g. "find the genes in chr8:… and predict their expression in K562". predict_expression scores ONE TSS window and needs you to know where that TSS is (either a pre-centred 9,198 bp window or a `tss_index`); this tool discovers every gene's TSS itself. It has no 9,198 bp floor and no tss_index; it starts with gene finding, so it takes 1,000–500,000 bp. Runs async internally at every size (the annotate stage is slow even for small inputs), so progress always streams. With wait=True (default), blocks and streams progress, then returns the result {data, meta} — it never returns a job_id on this path. With wait=False (detached), returns {data: {job_id, status: 'submitted'}} immediately — poll it with get_job. Because it ends in expression, `description` (cell type / assay context) is REQUIRED.
  - after: Find genes in a sequence, then predict each gene's expression (composite). Server-side chaining in ONE call: finds genes (transcript intervals, with their TSS) in the sequence, then predicts expression off each discovered TSS in the given experimental context. This is the right tool whenever you want expression for a raw region or sequence — e.g. "find the genes in chr8:… and predict their expression in K562". predict_expression scores the sequence around ONE TSS and needs you to know where that TSS is (a 9,198 bp window with the TSS at its midpoint, or a longer sequence plus `tss_index`); this tool discovers every gene's TSS itself. It has no 9,198 bp floor and no tss_index; it starts with gene finding, so it takes 1,000–500,000 bp. Runs async internally at every size (the annotate stage is slow even for small inputs), so progress always streams. With wait=True (default), blocks and streams progress, then returns the result {data, meta} — it never returns a job_id on this path. With wait=False (detached), returns {data: {job_id, status: 'submitted'}} immediately — poll it with get_job. Because it ends in expression, `description` (cell type / assay context) is REQUIRED.
- 2026-10-02 `find_genes` changed (description)
  - before: Find genes (transcript intervals) in a genomic region (async, ~8-25s). Takes 1,000–500,000 bp. The floor is the strictest of the scanning tasks: gene finding needs a region, not a site. (Only expression's 9,198 bp is higher, and that is a fixed window rather than a minimum region size.) Gene-finding: detects transcript boundaries (TSS + PolyA) and returns one interval per predicted transcript — start/end, strand, a confidence score, and predicted TSS/PolyA positions (BED-style feature intervals, not free-text notes). Use this for "what genes are here", "find / locate genes", or "annotate this region". Each transcript also carries its type (mRNA/lnc_RNA) and internal exon/intron/CDS structure in `exons`/`introns`/`cds` arrays, plus a browser-ready GFF3 track in `data.formats.gff3`. To get each gene's *expression* from a raw region, use find_genes_and_predict_expression instead — expression needs a per-gene TSS window, so predict_expression cannot run on a whole region. Submits an async job internally. With wait=True (default), blocks and streams progress, then returns the result {data, meta} — it never returns a job_id on this path. (If a generous block ceiling is exceeded it returns a timeout error, not a job handle.) With wait=False (detached), returns {data: {job_id, status: 'submitted'}} immediately — poll it with get_job.
  - after: Find genes (transcript intervals) in a genomic region (async, ~8-25s). Takes 1,000–500,000 bp. The floor is the strictest of the scanning tasks: gene finding needs a region, not a site. (Only expression's 9,198 bp is higher, and that is the sequence around one TSS rather than a region to search.) Gene-finding: detects transcript boundaries (TSS + PolyA) and returns one interval per predicted transcript — start/end, strand, a confidence score, and predicted TSS/PolyA positions (BED-style feature intervals, not free-text notes). Use this for "what genes are here", "find / locate genes", or "annotate this region". Each transcript also carries its type (mRNA/lnc_RNA) and internal exon/intron/CDS structure in `exons`/`introns`/`cds` arrays, plus a browser-ready GFF3 track in `data.formats.gff3`. To get each gene's *expression* from a raw region, use find_genes_and_predict_expression instead — expression needs a per-gene TSS window, so predict_expression cannot run on a whole region. Submits an async job internally. With wait=True (default), blocks and streams progress, then returns the result {data, meta} — it never returns a job_id on this path. (If a generous block ceiling is exceeded it returns a timeout error, not a job handle.) With wait=False (detached), returns {data: {job_id, status: 'submitted'}} immediately — poll it with get_job.
- 2026-10-02 `predict_expression` changed (description, inputSchema)
  - before: Predict a gene's expression from a TSS-centred window. Expression is cell-type-specific, so `description` (cell type / assay context, e.g. 'K562 cell line') is REQUIRED — the API rejects requests without it. The model scores exactly 9,198 bp centred on the TSS (±4,599). Two ways to supply that: - A sequence of exactly 9,198 bp already centred on the TSS. No `tss_index` needed — the midpoint is the only legal TSS. - A longer locus, 9,198–500,000 bp, plus `tss_index`: the 0-based offset of the TSS into it. The API cuts the window for you (sequence[tss_index-4599 : tss_index+4599]) and never scans for a TSS itself. Anything under 9,198 bp is rejected, here and by the API (422) — there is no padding or truncation fallback. `tss_index` is required for every other length, because a locus with no offset is indistinguishable from a mis-centred window. An offset that is merely WRONG (e.g. counted over a wrapped FASTA's characters, or against a chromosome coordinate instead of an offset into THIS sequence) still succeeds and scores the wrong window — verify meta.task_specific_counts.scored_window in the response. Easiest paths: fetch_gene_for_expression(gene) returns a ready-centred handle, and find_genes_and_predict_expression takes a raw region and finds each TSS for you.
  - after: Predict a gene's expression from the sequence around its TSS. Expression is cell-type-specific, so `description` (cell type / assay context, e.g. 'K562 cell line') is REQUIRED — the API rejects requests without it. The input rule is the same for every expression model: at least 9,198 bp, with the TSS at least 4,599 bp from each end. Longer input is welcome, up to 500,000 bp. Each model's bio_spec.recommended_flank_bp (see list_models) says how many bp to supply on each side of the TSS: 4,599 for the default g0-expression, which reads 9,198 bp around the TSS, and 40,960 for g0-expression-8192, which reads much further. Less flank than a model recommends, down to 4,599 bp, is accepted and scored, but that model then reads less than it was trained on. - A 9,198 bp sequence with the TSS at offset 4,599 (the midpoint) needs no `tss_index`. - Any longer sequence needs `tss_index`: the 0-based offset of the TSS into it. The API cuts what the model reads around that offset and never scans for a TSS itself. Under 9,198 bp, or a TSS closer than 4,599 bp to either end, is rejected here and by the API (422). A locus with no offset is rejected too, because it is indistinguishable from a mis-centred window. A very N-rich or low-complexity window can also be refused by the API (422). An offset that is merely WRONG (e.g. counted over a wrapped FASTA's characters, or against a chromosome coordinate instead of an offset into THIS sequence) still succeeds and scores the wrong window — verify meta.task_specific_counts.scored_window in the response. Easiest paths: fetch_gene_for_expression(gene) returns a 9,198 bp handle with the TSS at its midpoint, valid for every expression model, and find_genes_and_predict_expression takes a raw region and finds each TSS for you.
- 2026-10-02 `fetch_gene_for_expression` changed (description) **meaning changed**
  - before: Fetch a gene's sequence prepared for expression prediction. Resolves the gene's TSS via Ensembl and returns the exact TSS-centred 9,198 bp window the expression model scores, as a handle to pass to predict_expression(sequence_ref=...). Because the window is exactly 9,198 bp, no `tss_index` is needed on that call.
  - after: Fetch a gene's sequence prepared for expression prediction. Resolves the gene's TSS via Ensembl and returns a 9,198 bp gene-sense window with the TSS at offset 4,599 (its midpoint), as a handle to pass to predict_expression(sequence_ref=...). That is the minimum valid input for every expression model, and at 9,198 bp it needs no `tss_index`. It is all the default g0-expression reads, but a model may recommend a wider flank: bio_spec.recommended_flank_bp from list_models (e.g. 40,960 bp for g0-expression-8192). To supply flank F, call fetch_region(region=<this handle's region>, strand=<its strand>, flank_bp=F - 4,599), which returns 2F bp with the TSS at offset F, and pass tss_index=F to predict_expression. If the returned sequence is not exactly 2F bp (the gene is near a chromosome end), the TSS is not at F: use a smaller flank.
- 2026-10-02 `list_models` changed (description)
  - before: List available models for a task. Use to discover model ids before passing one as the `model` argument to a predict tool. The same catalog is also available as the resource `gi://models`. Returns a FLAT object — {task, default_model, models: [...]} — not the {data, meta} envelope the predict tools return. Each model carries a `bio_spec`, whose useful fields are `request_max_bp` (the enforced ceiling, 500,000 everywhere) and `context_window_bp` (what the model reads in one step — compare your sequence length against it: a shorter one is scored against a padded window). `trained_window_bp` is the fixed receptive field where there is no sliding window (9,198 for g0-expression). `request_max_bp` is the only one of the three that is a cap; the window fields describe what the model scores, not what the route accepts.
  - after: List available models for a task. Use to discover model ids before passing one as the `model` argument to a predict tool. The same catalog is also available as the resource `gi://models`. Returns a FLAT object — {task, default_model, models: [...]} — not the {data, meta} envelope the predict tools return. Each model carries a `bio_spec`, whose useful fields are `request_max_bp` (the enforced ceiling, 500,000 everywhere) and `context_window_bp` (what the model reads in one step — compare your sequence length against it: a shorter one is scored against a padded window). `trained_window_bp` is the fixed receptive field where there is no sliding window (9,198 for g0-expression; null for an expression model without one, such as g0-expression-8192). For expression, `recommended_flank_bp` is how many bp to supply on each side of the TSS (4,599 for g0-expression, 40,960 for g0-expression-8192). `request_max_bp` is the only cap; the other fields describe what the model reads, not what the route accepts.

Full history: https://api.protogrid.dev/v1/servers/ai.genomicintelligence%2Fgenomic-intelligence/changes

## Remotes

- https://mcp.genomicintelligence.ai/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (15)

- `fetch_ensembl_sequence`: Fetch a gene's reference sequence from Ensembl and store it.

        Returns a handle ({ref, name, length, preview, ...}). Pass the
        `ref` to predict_* tools — the bases stay server-side. For
        expression, use fetch_gene_for_expression instead (it prepares
        the TSS-centred window that model needs).
        
- `fetch_gene_for_expression`: Fetch a gene's sequence prepared for expression prediction.

        Resolves the gene's canonical-transcript TSS via Ensembl and stores a
        gene-sense sequence centred on it, as a handle to pass to
        predict_expression(sequence_ref=...). Longer TSS-centred sequence
        gives better predictions, so this already fetches as much flank on
        each side of the TSS as the listed expression models recommend (the
        largest bio_spec.recommended_flank_bp from list_models). One handle
        serves every expression model: the API reads what the chosen model
        needs around the TSS and ignores the rest.

        The handle records `tss_index` (the TSS offset into it), and
        predict_expression uses it when you do not pass one, so no offset
        arithmetic is needed. Every expression model accepts at least
        9,198 bp with the TSS at least 4,599 bp from each end. Near a
        chromosome end the flank is shortened to what fits (reported as
        `flank_shortened`), never below 4,599 bp; a TSS closer to the end
        than that is an error.
        
- `fetch_region`: Fetch a genomic region by coordinates from Ensembl and store it.

        For "find the genes in chr8:127,680,000-127,800,000"-style requests:
        resolves a coordinate range to reference sequence and returns a handle
        ({ref, name, length, ...}) to pass to find_genes / predict_* — the bases
        stay server-side. Plus strand by default, which is what the gene-finder
        expects. For a gene by name use fetch_ensembl_sequence; for expression
        use fetch_gene_for_expression.
        
- `find_genes`: Find genes (transcript intervals) in a genomic region (async, ~8-25s).

        Takes 1,000–500,000 bp. The floor is the strictest of the scanning
        tasks: gene finding needs a region, not a site. (Only expression's
        9,198 bp is higher, and that is the sequence around one TSS rather
        than a region to search.)

        Gene-finding: detects transcript boundaries (TSS + PolyA) and returns
        one interval per predicted transcript — start/end, strand, a
        confidence score, and predicted TSS/PolyA positions (BED-style feature
        intervals, not free-text notes). Use this for "what genes are here",
        "find / locate genes", or "annotate this region".

        Each transcript also carries its type (mRNA/lnc_RNA) and internal
        exon/intron/CDS structure in `exons`/`introns`/`cds` arrays, plus a
        browser-ready GFF3 track in `data.formats.gff3`. To get each gene's
        *expression* from a raw region, use find_genes_and_predict_expression
        instead — expression needs a per-gene TSS window, so predict_expression
        cannot run on a whole region.

        Submits an async job internally. With wait=True (default), blocks and
        streams progress, then returns the result {data, meta} — it never
        returns a job_id on this path. (If a generous block ceiling is
        exceeded it returns a timeout error, not a job handle.) With
        wait=False (detached), returns {data: {job_id, status: 'submitted'}}
        immediately — poll it with get_job.
        
- `find_genes_and_predict_expression`: Find genes in a sequence, then predict each gene's expression (composite).

        Server-side chaining in ONE call: finds genes (transcript intervals,
        with their TSS) in the sequence, then predicts expression off each
        discovered TSS in the given experimental context. This is the right
        tool whenever you want expression for a raw region or sequence — e.g.
        "find the genes in chr8:… and predict their expression in K562".
        predict_expression scores the sequence around ONE TSS and needs you to
        know where that TSS is (a 9,198 bp window with the TSS at its
        midpoint, or a longer sequence plus `tss_index`); this tool discovers
        every gene's TSS itself. It has no 9,198 bp floor and no tss_index;
        it starts with gene finding, so it takes 1,000–500,000 bp.

        Runs async internally at every size (the annotate stage is slow even
        for small inputs), so progress always streams. With wait=True
        (default), blocks and streams progress, then returns the result
        {data, meta} — it never returns a job_id on this path. With wait=False
        (detached), returns {data: {job_id, status: 'submitted'}} immediately —
        poll it with get_job. Because it ends in expression, `description`
        (cell type / assay context) is REQUIRED.
        
- `get_job`: Poll an async job once.

        Returns the {data, meta} result if complete, a progress envelope
        if still running, or an error envelope if it failed.
        
- `list_jobs`: List the caller's recent async jobs (also available as gi://jobs/recent).
- `list_models`: List available models for a task.

        Use to discover model ids before passing one as the `model`
        argument to a predict tool. The same catalog is also available
        as the resource `gi://models`.

        Returns a FLAT object — {task, default_model, models: [...]} — not the
        {data, meta} envelope the predict tools return. Each model carries a
        `bio_spec`, whose useful fields are `request_max_bp` (the enforced
        ceiling, 500,000 everywhere) and `context_window_bp` (what the model
        reads in one step — compare your sequence length against it: a shorter
        one is scored against a padded window). `trained_window_bp` is the fixed
        receptive field where there is no sliding window (null for a model
        without one). For expression, `recommended_flank_bp` is how many bp the
        model reads on each side of the TSS; longer TSS-centred input is
        better, and fetch_gene_for_expression already fetches the largest
        listed value. `request_max_bp` is the only cap; the other
        fields describe what the model reads, not what the route accepts.
        
- `load_demo_sequence`: Load a bundled demo reference sequence and return a handle.

        The server ships one curated, task-correct positive control per task
        (list them via the gi://sequences resource) — e.g.
        `expression_hbb_k562` is a ready-to-use K562 expression window for
        predict_expression. Stores the demo and returns a handle to pass to a
        predict_* tool: no Ensembl fetch, no quota. Handy for smoke-testing a
        prediction end-to-end.
        
- `predict_chromatin`: Chromatin annotation across 919 features (G0 DeepSEA). 200–500,000 bp.

        The model reads a 1,000 bp context window; 200–999 bp is accepted and
        scored against a padded window.
        
- `predict_enhancer`: Predict enhancer activity (G0 DeepSTARR). 50–500,000 bp.

        50 bp is the task's admission floor (the API 422s below it), not a
        statement about what the model reads: enhancer models score a 249 bp
        context window, so 50–248 bp is accepted and scored against a padded
        window. For a meaningful call, submit at least the 249 bp context.
        
- `predict_expression`: Predict a gene's expression from the sequence around its TSS.

        Expression is cell-type-specific, so `description` (cell type /
        assay context, e.g. 'K562 cell line') is REQUIRED — the API
        rejects requests without it.

        The input rule is the same for every expression model: at least
        9,198 bp, with the TSS at least 4,599 bp from each end, up to
        500,000 bp. Longer TSS-centred sequence gives better predictions:
        each model's bio_spec.recommended_flank_bp (see list_models) says how
        many bp it reads on each side of the TSS, and flank beyond that is
        ignored. Less flank, down to 4,599 bp, is accepted and scored, but
        the model then reads less than it was trained on. Omit `model` for
        the server's default.

        - A 9,198 bp sequence with the TSS at offset 4,599 (the midpoint)
          needs no `tss_index`.
        - Any longer sequence needs `tss_index`: the 0-based offset of the
          TSS into it (a fetch_gene_for_expression handle carries its own).
          The API cuts what the model reads around that offset and never
          scans for a TSS itself.

        Under 9,198 bp, or a TSS closer than 4,599 bp to either end, is
        rejected here and by the API (422). A locus with no offset is
        rejected too, because it is indistinguishable from a mis-centred
        window. A very N-rich or low-complexity window can also be refused
        by the API (422).

        An offset that is merely WRONG (e.g. counted over a wrapped FASTA's
        characters, or against a chromosome coordinate instead of an offset
        into THIS sequence) still succeeds and scores the wrong window —
        verify meta.task_specific_counts.scored_window in the response.

        Easiest paths: fetch_gene_for_expression(gene) already fetches a
        long TSS-centred handle (as much flank as the listed models
        recommend) and records its `tss_index`, which is sent for you when
        you pass that handle without one; find_genes_and_predict_expression
        takes a raw region and finds each TSS for you.
        
- `predict_promoter`: Predict promoter regions (G0). 300–500,000 bp.

        Returns the {data, meta} envelope: data.regions lists predicted
        promoters with start/end/score.

        300 bp is the task floor for every promoter model. The default
        g0-promoter-2000bp scans a 2,000 bp context window, so a shorter
        (but ≥300 bp) sequence is still scored — against a window padded out
        to that size. Check the chosen model's bio_spec.context_window_bp via
        list_models to know whether it saw real sequence or padding.
        
- `predict_splice`: Predict splice donor/acceptor sites (G0 BigBird). 100–500,000 bp.

        The model reads a 15,000 bp context window, so anything shorter is
        scored against a padded window — feed a whole transcript locus when you
        can. It is also strand-specific, and the wrong strand fails silently and
        plausibly — it returns sites at different positions, often still scoring
        above 0.9, not the near-zero scores once documented here. Nothing in the
        response flags it, so submit the transcript's own orientation
        (fetch_region takes `strand`).
        
- `store_inline_sequence`: Store a human-pasted sequence and return a handle to re-use it.

        For a sequence you've already pasted into the conversation, this
        gives back a short handle so you can run several tasks on it
        without re-pasting the bases in each predict_* call. Note that the
        full sequence still passes through the LLM on THIS call — it does
        not save context on its own. For large sequences, prefer
        fetch_ensembl_sequence / fetch_gene_for_expression / load_local_fasta,
        which acquire the bases server-side and never round-trip them.

        A line-wrapped FASTA *body* may be pasted verbatim: whitespace is
        stripped before storing, so the handle's `length` counts bases and a
        later `tss_index` counts into the same string the API measures. (A
        FASTA `>` header line is not a sequence and is rejected by the API's
        alphabet check.)
        
