@cyanheads/ensembl-mcp-server 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Dockerfile CHANGED
@@ -4,7 +4,7 @@
4
4
  # This stage installs all dependencies (including dev), builds the TypeScript
5
5
  # source code into JavaScript, and prepares the production assets.
6
6
  # ==============================================================================
7
- FROM oven/bun:1.3.14 AS build
7
+ FROM --platform=$BUILDPLATFORM oven/bun:1.4.0 AS build
8
8
 
9
9
  WORKDIR /usr/src/app
10
10
 
@@ -30,7 +30,7 @@ RUN bun run build
30
30
  # application. It uses a slim base image and only includes production
31
31
  # dependencies and build artifacts.
32
32
  # ==============================================================================
33
- FROM oven/bun:1.3.14-slim AS production
33
+ FROM oven/bun:1.4.0-slim AS production
34
34
 
35
35
  WORKDIR /usr/src/app
36
36
 
@@ -41,7 +41,7 @@ ENV NODE_ENV=production
41
41
  # OCI image metadata (https://github.com/opencontainers/image-spec/blob/main/annotations.md)
42
42
  ARG APP_VERSION
43
43
  LABEL org.opencontainers.image.title="@cyanheads/ensembl-mcp-server"
44
- LABEL org.opencontainers.image.description="Look up genes, fetch sequences, predict variant consequences, find orthologs and cross-database xrefs via Ensembl REST via MCP. STDIO or Streamable HTTP."
44
+ LABEL org.opencontainers.image.description="Look up genes, fetch sequences, predict variant consequences, find orthologs, and retrieve cross-database xrefs from Ensembl REST via MCP. STDIO or Streamable HTTP."
45
45
  LABEL org.opencontainers.image.source="https://github.com/cyanheads/ensembl-mcp-server"
46
46
  LABEL org.opencontainers.image.licenses="Apache-2.0"
47
47
  LABEL org.opencontainers.image.version="${APP_VERSION}"
@@ -52,7 +52,7 @@ COPY package.json bun.lock ./
52
52
  # Install only production dependencies, ignoring any lifecycle scripts (like 'prepare')
53
53
  # that are not needed in the final production image.
54
54
  RUN --mount=type=cache,target=/root/.bun/install/cache \
55
- bun install --production --frozen-lockfile --ignore-scripts
55
+ bun install --production --frozen-lockfile --ignore-scripts --omit=peer
56
56
 
57
57
  # Conditionally install OpenTelemetry optional peer dependencies (Tier 3).
58
58
  # These are not bundled by default to keep the base image lean. Enable at build time
@@ -69,7 +69,8 @@ RUN --mount=type=cache,target=/root/.bun/install/cache \
69
69
  @opentelemetry/sdk-metrics \
70
70
  @opentelemetry/sdk-node \
71
71
  @opentelemetry/sdk-trace-node \
72
- @opentelemetry/semantic-conventions; \
72
+ @opentelemetry/semantic-conventions \
73
+ --omit=dev --omit=peer --ignore-scripts; \
73
74
  fi
74
75
 
75
76
  # Copy the compiled application code from the build stage
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  <div align="center">
2
2
  <h1>@cyanheads/ensembl-mcp-server</h1>
3
- <p><b>Look up genes, fetch sequences, predict variant consequences, find orthologs and cross-database xrefs via Ensembl REST via MCP. STDIO or Streamable HTTP.</b>
3
+ <p><b>Look up genes, fetch sequences, predict variant consequences, find orthologs, and retrieve cross-database xrefs from Ensembl REST via MCP. STDIO or Streamable HTTP.</b>
4
4
  <div>7 Tools • 4 Resources • 1 Prompt</div>
5
5
  </p>
6
6
  </div>
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.4.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/ensembl-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/ensembl-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/ensembl-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.14-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.4.4-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/ensembl-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/ensembl-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/ensembl-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -27,9 +27,11 @@
27
27
 
28
28
  ---
29
29
 
30
- ## Tools
30
+ ## Overview
31
31
 
32
- Seven tools covering the core Ensembl REST API surface — species discovery, gene/transcript lookup, sequence retrieval, genomic region overlap, variant consequence prediction, cross-species homology, and external database cross-references:
32
+ Gene, sequence, and variant data for vertebrates and other model organisms from the Ensembl REST API. Look up genes, fetch sequences, predict variant consequences, find orthologs, and cross-reference external databases from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
33
+
34
+ ### Tools
33
35
 
34
36
  | Tool | Description |
35
37
  |:-----|:------------|
@@ -41,103 +43,125 @@ Seven tools covering the core Ensembl REST API surface — species discovery, ge
41
43
  | `ensembl_get_homology` | Find orthologs and/or paralogs of a gene across species with percent identity and taxonomy level |
42
44
  | `ensembl_get_xrefs` | Retrieve cross-database references for a gene — HGNC, UniProt, EntrezGene, OMIM, RefSeq, Reactome, and others |
43
45
 
44
- ### `ensembl_list_species`
46
+ ### Resources
45
47
 
46
- Discovery tool for the Ensembl species catalog.
48
+ | Resource | Description |
49
+ |:---|:---|
50
+ | `ensembl://gene/{id}` | Gene record by stable ID (`ENSG…`) — location, biotype, description, and transcript list |
51
+ | `ensembl://transcript/{id}` | Transcript record by stable ID (`ENST…`) — parent gene, location, biotype, canonical flag, and length |
52
+ | `ensembl://species` | Supported Ensembl species for the endpoint default division (vertebrates on the default endpoint) |
53
+ | `ensembl://species/{division}` | Supported species in one division (`EnsemblVertebrates`, `EnsemblPlants`, `EnsemblFungi`, `EnsemblMetazoa`, `EnsemblProtists`) |
47
54
 
48
- - Filter by division: vertebrates, plants, fungi, metazoa, or protists
49
- - Optional name filter (`nameContains`) for local substring matching
50
- - Returns display name, common name, assembly, taxon ID, and Ensembl division for each species
51
- - Required first step — species names like `homo_sapiens` are opaque to non-biologists and are the input format every other tool expects
55
+ All resource data is also reachable via the `ensembl_list_species` tool, which additionally filters by name.
52
56
 
53
- ---
57
+ ### Prompts
58
+
59
+ | Prompt | Description |
60
+ |:---|:---|
61
+ | `ensembl_gene_dossier` | Structured workflow for assembling a complete gene profile: symbol → ID + location → sequence → variants → orthologs → xrefs |
54
62
 
55
- ### `ensembl_lookup_gene`
63
+ ## Capability reference
56
64
 
57
- Single entry point for resolving gene identity.
65
+ ### `ensembl_list_species` <sub>tool</sub>
58
66
 
59
- - Symbol + species lookup (`BRCA2` + `homo_sapiens`) or direct stable ID lookup (`ENSG00000139618`)
60
- - Batch lookup of up to 20 IDs or symbols in one call via POST endpoints
61
- - Optional transcript expansion — returns full transcript list with biotype and canonical flag
62
- - Returns Ensembl stable ID, genomic location (chr:start-end:strand), biotype, description, and transcript list
63
- - Errors: `not_found` (symbol or ID not in Ensembl), `invalid_species` (call `ensembl_list_species` to discover valid names)
67
+ - Filter by division (`EnsemblVertebrates`, `EnsemblPlants`, `EnsemblFungi`, `EnsemblMetazoa`, `EnsemblProtists`) or `nameContains` for a local substring match against name, display name, and common name
68
+ - Omit `division` to return the endpoint default division (vertebrates, ~356 species on the default GRCh38 endpoint)
69
+ - Returns internal name (the value every other tool expects), display name, common name, taxon ID, assembly, and division
70
+ - Required first step — species names like `homo_sapiens` are opaque to non-biologists
64
71
 
65
72
  ---
66
73
 
67
- ### `ensembl_get_sequence`
74
+ ### `ensembl_lookup_gene` <sub>tool</sub>
75
+
76
+ - Exactly one of `symbol` (+ optional `species`, default `homo_sapiens`), `id`, `ids` (batch, up to 20), or `symbols` (batch, up to 20)
77
+ - `expand_transcripts` (default `false`) adds the full transcript list with biotype and canonical flag
78
+ - Batch modes (`ids`/`symbols`) return a `succeeded`/`failed` split with per-item error strings instead of failing the call
79
+ - Errors: `not_found`, `invalid_species`, `no_input`, `conflicting_input`
80
+
81
+ ---
68
82
 
69
- Fetch any sequence type for any Ensembl feature.
83
+ ### `ensembl_get_sequence` <sub>tool</sub>
70
84
 
71
- - Molecule types: `genomic` (default, includes introns), `cdna` (spliced), `cds` (coding only), `protein`
72
- - Accepts stable IDs or `species:chr:start-end` region format for genomic region mode
73
- - Optional flanking sequence (`expand_5prime`, `expand_3prime`) in base pairs
74
- - Returns sequence with stable ID, molecule type, and character count — large sequences (e.g. BRCA2 at 85,183 bp genomic) returned in full with explicit length so callers can budget context usage
85
+ - `type`: `genomic` (default, includes introns), `cdna` (spliced), `cds` (coding only), `protein`
86
+ - Accepts a stable ID (`ENSG…`/`ENST…`/`ENSP…`) or a region — `species:chr:start-end`, or bare `chr:start-end` with `species` set
87
+ - `expand_5prime` / `expand_3prime` (default `0`) extend flanking base pairs for genomic and region queries
88
+ - `protein` and `cds` require a transcript or protein ID, not a gene ID
89
+ - Every response states `length` so callers can budget context before consuming large sequences
90
+ - Errors: `not_found`, `type_mismatch`, `missing_species`
75
91
 
76
92
  ---
77
93
 
78
- ### `ensembl_query_region`
94
+ ### `ensembl_query_region` <sub>tool</sub>
95
+
96
+ - `region` in `chr:start-end` format; `feature` array defaults to `["gene"]`, also accepts `transcript`, `variation`, `regulatory`, `exon`; optional `biotype` filter
97
+ - Defaults to genes only — requesting `variation` on a large locus can return 44,000+ features
98
+ - Exon rows carry a `parentId` and `rank`, since one exon is reported once per parent transcript
99
+ - Errors: `invalid_region`, `invalid_species`
79
100
 
80
- Find all genomic features overlapping a chromosomal window.
101
+ ---
81
102
 
82
- - Region format: `chr:start-end` (e.g. `13:32315086-32400268`) — no `chr` prefix for vertebrates
83
- - Feature types: `gene` (default), `transcript`, `variation`, `regulatory`, `exon`
84
- - Optional biotype filter
85
- - Defaults to gene only to prevent context overload — a large locus can contain 44,000+ variants when all feature types are selected
103
+ ### `ensembl_predict_variant` <sub>tool</sub>
104
+
105
+ - `variant` accepts HGVS (transcript-relative or genomic), region+allele (`chr:start:end:strand/allele`), or a dbSNP rsID
106
+ - `max_transcript_consequences` (default `10`) and `max_pubmed_ids_per_variant` (default `10`) cap large VEP results; set either to `0` for the full set, or `include_all_colocated_pubmed: true` for uncapped PubMed IDs
107
+ - Returns most severe consequence term, per-transcript impact (HIGH/MODERATE/LOW/MODIFIER), and colocated known variants with clinical significance
108
+ - Totals (`transcriptConsequencesTotal`, `pubmedTotal`) are always reported even when capped
109
+ - Errors: `invalid_notation`, `not_found`
86
110
 
87
111
  ---
88
112
 
89
- ### `ensembl_predict_variant`
113
+ ### `ensembl_get_homology` <sub>tool</sub>
114
+
115
+ - Exactly one of `symbol` (+ `species`, default `homo_sapiens`) or `id`; optional `target_species` filter
116
+ - `type`: `orthologues` (default), `paralogues`, or `all`
117
+ - `max_results` caps the homolog list (default `25`, `0` uncapped); `totalCount` always reports the true count available
118
+ - Errors: `not_found`, `no_input`, `conflicting_input`
90
119
 
91
- Predict variant consequences via the Ensembl VEP.
120
+ ---
121
+
122
+ ### `ensembl_get_xrefs` <sub>tool</sub>
92
123
 
93
- - Accepts HGVS notation (transcript-relative: `ENST00000380152.8:c.2T>A`) or genomic region+allele format (`13:32316462:32316462:1/A`)
94
- - Returns most severe consequence term, affected transcripts and genes, impact level (HIGH/MODERATE/LOW/MODIFIER)
95
- - Includes colocated known variants with clinical significance (ClinVar, dbSNP)
96
- - Errors: `invalid_notation` (check format), `not_found` (location outside any known transcript)
124
+ - `id` (`ENSG…`/`ENST…`) required; optional `dbname` filter (e.g. `HGNC`, `Uniprot_gn`, `EntrezGene`, `MIM_GENE`, `RefSeq_mRNA`, `Reactome`, `GO`)
125
+ - Uses the `xrefs/id` endpoint, returning the full cross-reference set (56+ entries for well-annotated genes like BRCA2)
126
+ - Errors: `not_found`
97
127
 
98
128
  ---
99
129
 
100
- ### `ensembl_get_homology`
130
+ ### `ensembl://gene/{id}` <sub>resource</sub>
131
+
132
+ - Returns location, biotype, description, and transcript list for a gene stable ID (`ENSG…`); version suffix optional
133
+ - Errors: `not_found`
134
+
135
+ ---
101
136
 
102
- Cross-species homolog lookup.
137
+ ### `ensembl://transcript/{id}` <sub>resource</sub>
103
138
 
104
- - Returns orthologs (default) or paralogs, or both
105
- - Optional `target_species` filter to narrow to specific organisms
106
- - Each homolog carries stable ID, species, relationship type (ortholog_one2one, ortholog_one2many, etc.), `perc_id`, `perc_pos`, and taxonomy level
139
+ - Returns parent gene, location, biotype, canonical flag, and length for a transcript stable ID (`ENST…`); version suffix optional
140
+ - Errors: `not_found`
107
141
 
108
142
  ---
109
143
 
110
- ### `ensembl_get_xrefs`
144
+ ### `ensembl://species` <sub>resource</sub>
111
145
 
112
- Full cross-database reference set for any Ensembl feature.
146
+ - No parameters — returns the endpoint default division (vertebrates, ~356 species on the default GRCh38 endpoint)
147
+ - For a named division, read `ensembl://species/{division}` instead
113
148
 
114
- - Returns all external IDs by default: HGNC, UniProt, EntrezGene, OMIM, RefSeq, Reactome, and more (56 xrefs for BRCA2)
115
- - Optional `dbname` filter (e.g. `HGNC`, `Uniprot_gn`, `EntrezGene`, `MIM_GENE`) to narrow output
116
- - Uses the `xrefs/id` endpoint (not `xrefs/symbol`) — returns the full cross-reference set
117
- - IDs returned here chain directly to protein, literature, disease, and pathway resources in other MCP servers
149
+ ---
118
150
 
119
- ## Resources and prompts
151
+ ### `ensembl://species/{division}` <sub>resource</sub>
120
152
 
121
- | Type | Name | Description |
122
- |:-----|:-----|:------------|
123
- | Resource | `ensembl://gene/{id}` | Gene record by stable ID (`ENSG…`) — location, biotype, description, and transcript list |
124
- | Resource | `ensembl://transcript/{id}` | Transcript record by stable ID (`ENST…`) — parent gene, location, biotype, canonical flag, and length |
125
- | Resource | `ensembl://species` | Supported Ensembl species for the endpoint default division (vertebrates on the default endpoint) with name, display name, assembly, taxon ID, and division |
126
- | Resource | `ensembl://species/{division}` | Supported species in one division (`EnsemblVertebrates`, `EnsemblPlants`, `EnsemblFungi`, `EnsemblMetazoa`, `EnsemblProtists`) |
127
- | Prompt | `ensembl_gene_dossier` | Structured workflow for assembling a complete gene profile: symbol → ID + location → sequence → variants → orthologs → xrefs |
153
+ - `division` required: `EnsemblVertebrates`, `EnsemblPlants`, `EnsemblFungi`, `EnsemblMetazoa`, or `EnsemblProtists`
128
154
 
129
- All resource data is also reachable via tools. `ensembl://species` returns the endpoint default division (vertebrates) and `ensembl://species/{division}` returns a named division; `ensembl_list_species` is the tool equivalent, filtering by division and name.
155
+ ---
130
156
 
131
- ## Features
157
+ ### `ensembl_gene_dossier` <sub>prompt</sub>
132
158
 
133
- Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
159
+ - Arguments: `gene_symbol` required; `species` optional (default `homo_sapiens`)
160
+ - Sequences a 7-step workflow: resolve the gene → fetch the protein sequence → find variants in the locus → predict variant consequences → find cross-species orthologs → get external database IDs → synthesize the dossier
161
+
162
+ ## Features
134
163
 
135
- - Declarative tool, resource, and prompt definitions — single file per primitive, framework handles registration and validation
136
- - Unified error handling — handlers throw, framework catches, classifies, and formats
137
- - Pluggable auth: `none`, `jwt`, `oauth`
138
- - Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
139
- - Structured logging with optional OpenTelemetry tracing
140
- - STDIO and Streamable HTTP transports
164
+ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): stdio and Streamable HTTP transports, pluggable auth (`none` / `jwt` / `oauth`), swappable storage (`in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`), structured logging with optional OpenTelemetry tracing.
141
165
 
142
166
  Ensembl-specific:
143
167
 
@@ -151,7 +175,7 @@ Agent-friendly output:
151
175
 
152
176
  - Sequence character count stated on every `ensembl_get_sequence` response so callers can budget context before consuming large genomic sequences
153
177
  - `ensembl_list_species` is explicitly the discovery step — tool descriptions call out the opaque internal-name format and direct agents to it before using species-dependent tools
154
- - Cross-tool chaining made explicit: xref IDs from `ensembl_get_xrefs` are described as inputs for protein and literature servers; the `ensembl_gene_dossier` prompt sequences the full 7-tool research workflow
178
+ - Cross-tool chaining made explicit: xref IDs from `ensembl_get_xrefs` are described as inputs for protein and literature servers; the `ensembl_gene_dossier` prompt sequences all 6 tools into one research workflow
155
179
 
156
180
  ## Getting started
157
181
 
@@ -235,7 +259,7 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
235
259
 
236
260
  ### Prerequisites
237
261
 
238
- - [Bun v1.3.14](https://bun.sh/) or higher (or Node.js v24+).
262
+ - [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
239
263
  - No API key required — Ensembl REST is fully public.
240
264
 
241
265
  ### Installation
@@ -275,6 +299,7 @@ All configuration is validated at startup via Zod schemas in `src/config/server-
275
299
  | `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http` | `stdio` |
276
300
  | `MCP_HTTP_PORT` | HTTP server port | `3010` |
277
301
  | `MCP_HTTP_ENDPOINT_PATH` | HTTP endpoint path | `/mcp` |
302
+ | `MCP_SESSION_MODE` | HTTP session mode: `auto`, `stateful`, or `stateless`. Schema default `auto` resolves to stateful; this server explicitly uses stateless. | `stateless` |
278
303
  | `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth` | `none` |
279
304
  | `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.) | `info` |
280
305
  | `LOGS_DIR` | Directory for log files (Node.js only) | `<project-root>/logs` |
@@ -338,7 +363,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
338
363
 
339
364
  ## Contributing
340
365
 
341
- Issues and pull requests are welcome. Run checks and tests before submitting:
366
+ Issues are welcome. Run checks and tests before submitting:
342
367
 
343
368
  ```sh
344
369
  bun run devcheck
@@ -0,0 +1,29 @@
1
+ ---
2
+ summary: "MCP 2026-07-28 and SDK v2 adoption adds strict tool inputs, public cache hints, and an explicit stateless HTTP deployment"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.3 — 2026-08-22
8
+
9
+ ## Added
10
+
11
+ - **Public cache hints** now mark tool, prompt, resource, and discovery catalogs cacheable for one hour and resource reads for five minutes on MCP 2026-07-28 clients.
12
+
13
+ ## Changed
14
+
15
+ - **MCP SDK v2 and protocol revision 2026-07-28** are available alongside the existing 2025-era clients. Tool calls reject undeclared top-level arguments, advertised schemas use JSON Schema 2020-12 and declare error envelopes, and `ctx.log` messages can reach clients that opt into MCP logging.
16
+ - **`MCP_SESSION_MODE=stateless`** is explicit across the Docker image, `.env.example`, and README, so source and container HTTP runs use the same session policy.
17
+ - **Request context propagation** now carries the handler's canonical trace, operation, tenant, and correlation fields into Ensembl upstream requests instead of retaining only the request ID.
18
+ - **Build and test configuration** typechecks `tests/` separately from the production emit; prompt/resource tests follow the SDK v2 async and optional-schema contracts.
19
+ - **Packaging and project templates** adopt Bun 1.4, production peer omission, portable MCPB cleanup, current dependency checks, community-health files, and the latest framework scripts, skills, and agent protocol.
20
+
21
+ ## Dependencies
22
+
23
+ - `@cyanheads/mcp-ts-core` `^0.10.14` → `^0.12.3`
24
+ - `@biomejs/biome` `^2.5.0` → `^2.5.9`
25
+ - `@types/node` `^26.0.0` → `^26.2.0`
26
+ - `ignore` `^7.0.5` → `^7.0.6`
27
+ - `tsc-alias` `^1.9.0` → `^1.9.2`
28
+ - `typescript` `^6.0.3` → `^7.0.2`
29
+ - `vitest` `^4.1.10` → `^4.1.11`
@@ -0,0 +1,27 @@
1
+ ---
2
+ summary: "mcp-ts-core 0.13.6 adoption: an unrecognized or misspelled argument key now succeeds instead of failing, argument rejections carry a reason and recovery hint under Invalid params, and every declared tool error closes with a (reason ...) suffix"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.4 — 2026-09-19
8
+
9
+ ## Changed
10
+
11
+ - **Tool calls tolerate minor argument mismatches instead of rejecting them** — an unrecognized top-level key is dropped, a differently-cased spelling of a declared parameter (`dbName` for `dbname`, `maxTranscriptConsequences` for `max_transcript_consequences`) is rewritten onto the real key, and a JSON-stringified array is parsed and retried once. Advertised `inputSchema` is unchanged; only calls that previously failed now succeed.
12
+ - **Argument rejections report `Invalid params` (`-32602`)** instead of the previous validation-error code, with `data.reason: "invalid_arguments"` and a synthesized `Recovery: …` hint derived from the offending field and the root schema.
13
+ - **Every declared tool error closes with `(reason <reason>)`** — e.g. `not_found`, `invalid_notation` — on the `content[]` text. `structuredContent.error.data.reason` already carried the reason and is unchanged; resource errors are unaffected.
14
+ - **A caller that disconnects mid-call is reported as a cancellation**, not an internal server error.
15
+ - **`sessionMode: 'stateless'`** is declared directly in `src/index.ts`, matching the deployment default it was previously left to.
16
+ - **Bun engines floor raised to `>=1.4.0`**, matching the framework requirement.
17
+ - **Framework scripts, skills, agent protocol, and issue templates** sync to `@cyanheads/mcp-ts-core` 0.13.6 — the development skill tree moves from `skills/` to `framework-skills/` so a plugin install no longer surfaces it to the installing agent, `devcheck` gains a Worker typecheck step and a README version-badge check, and a CodeQL workflow is added.
18
+
19
+ ## Dependencies
20
+
21
+ - `@cyanheads/mcp-ts-core` `^0.12.3` → `^0.13.6`
22
+ - `zod` `^4.4.3` → `^4.6.5`
23
+ - `@biomejs/biome` `^2.5.9` → `^2.5.14`
24
+ - `@types/node` `^26.2.0` → `^26.6.1`
25
+ - `ignore` `^7.0.6` → `^7.0.9`
26
+ - `tsc-alias` `^1.9.2` → `^1.9.5`
27
+ - `vitest` `^4.1.11` → `^5.0.1`
@@ -4,10 +4,11 @@
4
4
  # to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
5
5
  # with a concrete date.
6
6
 
7
- # Required. One-line GitHub Release-style headline. 350 character cap.
8
- # Default short and scannable. Don't pad, don't stitch unrelated changes with
9
- # semicolons — pick the headline. Quotes required: unquoted YAML treats `: `
10
- # inside the value as a key separator and fails GitHub's strict parser.
7
+ # Required. One-line GitHub Release-style headline. 350 character cap — a
8
+ # ceiling, not a target. Default short and scannable. Don't pad, don't stitch
9
+ # unrelated changes with commas/semicolons into an inventory — pick the one
10
+ # headline the release is about. Quotes required: unquoted YAML treats
11
+ # `: ` inside the value as a key separator and fails GitHub's strict parser.
11
12
  summary: ""
12
13
 
13
14
  # Set `true` when consumers must change code to upgrade: API removals,
@@ -24,9 +25,10 @@ security: false
24
25
 
25
26
  # Optional free-form notes for maintenance agents processing this release.
26
27
  # Not rendered in CHANGELOG — consumed by agents running `maintenance` on
27
- # downstream servers. Use for adoption instructions that don't fit the
28
- # human-facing sections: new files to create, fields to populate, one-time
29
- # migration steps. Omit the field entirely when there's nothing to say.
28
+ # downstream servers. ADOPTION STEPS ONLY — new files to create, fields to
29
+ # populate, one-time migration steps. Never a second rendering of the body:
30
+ # if a body bullet already says it, name the bullet's symbol instead of
31
+ # re-explaining. Omit the field entirely when there's nothing to say.
30
32
  # agent-notes: |
31
33
  # <instructions for downstream maintenance agents>
32
34
  ---
@@ -41,17 +43,54 @@ security: false
41
43
  each bullet with the symbol or concept name in **bold** so they can skip
42
44
  what's irrelevant and zoom in on what's not.
43
45
 
44
- Tone: terse, fact-dense, not verbose. Default to one sentence per bullet —
45
- name the symbol, state what changed, stop. Use a second sentence only when
46
- it carries weight. If a bullet feels long, it is.
47
-
48
- Cut: mechanism walkthroughs (those belong in JSDoc, CLAUDE.md/AGENTS.md, or the
49
- relevant skill), ceremonial framings ("This release introduces…",
50
- backwards-compat paragraphs), file-by-file test enumerations, internal
51
- implementation notes. Prefer code/symbol names over English re-explanations.
46
+ Tone: terse, fact-dense, not verbose. Bullet shape: **symbol** + what
47
+ changed + at most one consumer-facing caveat. One sentence by default, two
48
+ when the second carries weight — a bullet past ~40 words or three sentences
49
+ is wrong. The depth lives one hop away: the linked issue carries the why,
50
+ the commit diff carries the how. The changelog names what changed and what
51
+ a consumer does about it; a reader who wants mechanism opens the link.
52
+
53
+ Model length on THIS guide, never on the previous entry — entries modeled
54
+ on entries compound.
55
+
56
+ Cut (each has shipped as a wall of text; these are the cruft):
57
+ - History/justification narration — how the bug worked, why the old
58
+ behavior was wrong. One short clause at most; the issue carries the story.
59
+ - Design-rationale defense — "chosen over Y because…", "guarding the
60
+ getter is not enough…". That is the author arguing with a reviewer;
61
+ reviewers read the PR, not the changelog.
62
+ - Defensive unchanged-clauses — "X is unchanged", "byte-identical to
63
+ <prev>". Keep one only where its absence would cause a real misread,
64
+ as a short parenthetical.
65
+ - Edge-case inventories — marker lists, not-flagged lists, escape tables.
66
+ Tests and the issue carry those.
67
+ - Mechanism walkthroughs (JSDoc, CLAUDE.md/AGENTS.md, or the relevant
68
+ skill own those), ceremonial framings ("This release introduces…"),
69
+ backwards-compat paragraphs, file-by-file test enumerations. Prefer
70
+ code/symbol names over English re-explanations.
71
+
72
+ Verified ≠ included: the every-claim-verified-from-the-diff rule bounds
73
+ the TRUTH of what you write, never the AMOUNT.
74
+
75
+ Example — same fact, right size:
76
+
77
+ TOO LONG: **`fetchWithTimeout`'s `timeoutMs` bounds the whole exchange**
78
+ (#341). `fetch` resolves once headers arrive and the deadline was
79
+ cleared as the helper returned, so a peer that answered promptly and
80
+ then stalled the stream held the request open indefinitely. A 2xx
81
+ carrying a body now comes back as a passthrough wrapper that disarms
82
+ the deadline when the body closes, errors, or is cancelled; …
83
+ [+90 more words of mechanism and edge cases]
84
+
85
+ RIGHT: **`fetchWithTimeout`'s `timeoutMs` now bounds the whole
86
+ exchange, not just the headers** (#341). A stalled body aborts with
87
+ the same `Timeout` error; the returned `Response` is a wrapper, so
88
+ identity assertions (`toBe(response)`) no longer hold.
52
89
 
53
90
  Narrative intro: skip by default. Add one short sentence only when the
54
- release theme genuinely needs framing the bullets can't carry.
91
+ release theme genuinely needs framing the bullets can't carry. When many
92
+ bullets share one upgrade consequence, state it ONCE — intro line or
93
+ agent-notes — never per bullet.
55
94
 
56
95
  Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
57
96
  Fixed, Security. Include only sections with entries; delete the rest
@@ -78,30 +117,13 @@ security: false
78
117
  in that unrelated item's metadata.
79
118
 
80
119
  TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
81
- via `gh release create --notes-from-tag`. The tag is a derivative of this
82
- changelog entry — a condensed, scannable version, not a copy. Format:
83
-
84
- <theme — omit version number, GitHub prepends it>
85
- ← blank line
86
- <1-2 sentence context: what this release does>
87
- ← blank line
88
- Dependency bumps: ← section header
89
- ← blank line
90
- - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
91
- ← blank line
92
- Changed: ← only sections with entries
93
- ← blank line
94
- - `format()` output includes `query` in text mode
95
- ← blank line
96
- Added:
97
- ← blank line
98
- - `manifest.json` scaffolded for MCPB bundle support
99
- - Install badges (Claude Desktop, Cursor, VS Code)
100
- ← blank line
101
- <N> tests pass; `bun run devcheck` clean. ← footer
102
-
103
- Never a flat comma-separated string. Always structured markdown with
104
- sections. The tag must scan well as a rendered GitHub Release page.
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): a short subject line without the
123
+ version, flat headline bullets — no Keep-a-Changelog section headers, no
124
+ gates line — at most one deps line, issue backlinks, and the changelog link
125
+ last. In release-PR mode the `git-wrapup` skill authors those bullets as the
126
+ PR body's `## Changes` and the tag copies them.
105
127
  -->
106
128
 
107
129
  ## Added
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;iBAQtB,CAAC;AAIH,wBAAgB,eAAe;;EAK9B;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;iBAOtB,CAAC;AAIH,wBAAgB,eAAe;;EAK9B;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -8,8 +8,7 @@ const ServerConfigSchema = z.object({
8
8
  baseUrl: z
9
9
  .string()
10
10
  .default('https://rest.ensembl.org')
11
- .describe('Ensembl REST API base URL. Override to point at GRCh37 legacy endpoint ' +
12
- '(https://grch37.rest.ensembl.org) or a local mirror.'),
11
+ .describe('Ensembl REST API base URL. Override to point at the GRCh37 legacy endpoint (https://grch37.rest.ensembl.org) or a local mirror.'),
13
12
  });
14
13
  let _config;
15
14
  export function getServerConfig() {
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,OAAO,CAAC,0BAA0B,CAAC;SACnC,QAAQ,CACP,yEAAyE;QACvE,sDAAsD,CACzD;CACJ,CAAC,CAAC;AAEH,IAAI,OAAuD,CAAC;AAE5D,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,OAAO,CAAC,0BAA0B,CAAC;SACnC,QAAQ,CACP,iIAAiI,CAClI;CACJ,CAAC,CAAC;AAEH,IAAI,OAAuD,CAAC;AAE5D,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.js CHANGED
@@ -19,6 +19,21 @@ import { initEnsemblService } from './services/ensembl/ensembl-service.js';
19
19
  await createApp({
20
20
  name: 'ensembl-mcp-server',
21
21
  title: 'ensembl-mcp-server',
22
+ /**
23
+ * Every tool here is a read-only Ensembl REST lookup — no handler calls
24
+ * `ctx.requestInput`, so nothing needs a session to come back to. `stateless`
25
+ * is declared in source rather than left to the deployment's
26
+ * `MCP_SESSION_MODE`, which still wins when it carries a meaningful value.
27
+ */
28
+ sessionMode: 'stateless',
29
+ cacheHints: {
30
+ 'prompts/list': { ttlMs: 3_600_000, cacheScope: 'public' },
31
+ 'resources/list': { ttlMs: 3_600_000, cacheScope: 'public' },
32
+ 'resources/read': { ttlMs: 300_000, cacheScope: 'public' },
33
+ 'resources/templates/list': { ttlMs: 3_600_000, cacheScope: 'public' },
34
+ 'server/discover': { ttlMs: 3_600_000, cacheScope: 'public' },
35
+ 'tools/list': { ttlMs: 3_600_000, cacheScope: 'public' },
36
+ },
22
37
  tools: [
23
38
  ensemblListSpecies,
24
39
  ensemblLookupGene,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yDAAyD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAC1F,OAAO,EACL,gCAAgC,EAChC,sBAAsB,GACvB,MAAM,wDAAwD,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2DAA2D,CAAC;AACtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AACvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE;QACL,kBAAkB;QAClB,iBAAiB;QACjB,kBAAkB;QAClB,kBAAkB;QAClB,qBAAqB;QACrB,kBAAkB;QAClB,eAAe;KAChB;IACD,SAAS,EAAE;QACT,mBAAmB;QACnB,yBAAyB;QACzB,sBAAsB;QACtB,gCAAgC;KACjC;IACD,OAAO,EAAE,CAAC,wBAAwB,CAAC;IACnC,YAAY,EAAE;;;;oHAIoG;IAClH,KAAK,CAAC,IAAI;QACR,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yDAAyD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAC1F,OAAO,EACL,gCAAgC,EAChC,sBAAsB,GACvB,MAAM,wDAAwD,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2DAA2D,CAAC;AACtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AACvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,oBAAoB;IAC3B;;;;;OAKG;IACH,WAAW,EAAE,WAAW;IACxB,UAAU,EAAE;QACV,cAAc,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC1D,gBAAgB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC5D,gBAAgB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC1D,0BAA0B,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QACtE,iBAAiB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC7D,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;KACzD;IACD,KAAK,EAAE;QACL,kBAAkB;QAClB,iBAAiB;QACjB,kBAAkB;QAClB,kBAAkB;QAClB,qBAAqB;QACrB,kBAAkB;QAClB,eAAe;KAChB;IACD,SAAS,EAAE;QACT,mBAAmB;QACnB,yBAAyB;QACzB,sBAAsB;QACtB,gCAAgC;KACjC;IACD,OAAO,EAAE,CAAC,wBAAwB,CAAC;IACnC,YAAY,EAAE;;;;oHAIoG;IAClH,KAAK,CAAC,IAAI;QACR,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;CACF,CAAC,CAAC"}
@@ -8,11 +8,11 @@ import { z } from '@cyanheads/mcp-ts-core';
8
8
  export declare const ensemblSpeciesResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{}, z.core.$strip>, undefined, undefined>;
9
9
  export declare const ensemblSpeciesByDivisionResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{
10
10
  division: z.ZodEnum<{
11
- EnsemblVertebrates: "EnsemblVertebrates";
12
- EnsemblPlants: "EnsemblPlants";
13
11
  EnsemblFungi: "EnsemblFungi";
14
12
  EnsemblMetazoa: "EnsemblMetazoa";
13
+ EnsemblPlants: "EnsemblPlants";
15
14
  EnsemblProtists: "EnsemblProtists";
15
+ EnsemblVertebrates: "EnsemblVertebrates";
16
16
  }>;
17
17
  }, z.core.$strip>, undefined, undefined>;
18
18
  //# sourceMappingURL=species.resource.d.ts.map
@@ -10,9 +10,9 @@ export declare const ensemblGetHomology: import("@cyanheads/mcp-ts-core").ToolDe
10
10
  species: z.ZodDefault<z.ZodString>;
11
11
  target_species: z.ZodOptional<z.ZodString>;
12
12
  type: z.ZodDefault<z.ZodEnum<{
13
+ all: "all";
13
14
  orthologues: "orthologues";
14
15
  paralogues: "paralogues";
15
- all: "all";
16
16
  }>>;
17
17
  max_results: z.ZodDefault<z.ZodNumber>;
18
18
  }, z.core.$strip>, z.ZodObject<{
@@ -7,9 +7,9 @@ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
7
  export declare const ensemblGetSequence: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
8
  id: z.ZodString;
9
9
  type: z.ZodDefault<z.ZodEnum<{
10
- genomic: "genomic";
11
10
  cdna: "cdna";
12
11
  cds: "cds";
12
+ genomic: "genomic";
13
13
  protein: "protein";
14
14
  }>>;
15
15
  species: z.ZodOptional<z.ZodString>;
@@ -5,11 +5,11 @@
5
5
  import { z } from '@cyanheads/mcp-ts-core';
6
6
  export declare const ensemblListSpecies: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
7
7
  division: z.ZodOptional<z.ZodEnum<{
8
- EnsemblVertebrates: "EnsemblVertebrates";
9
- EnsemblPlants: "EnsemblPlants";
10
8
  EnsemblFungi: "EnsemblFungi";
11
9
  EnsemblMetazoa: "EnsemblMetazoa";
10
+ EnsemblPlants: "EnsemblPlants";
12
11
  EnsemblProtists: "EnsemblProtists";
12
+ EnsemblVertebrates: "EnsemblVertebrates";
13
13
  }>>;
14
14
  nameContains: z.ZodOptional<z.ZodString>;
15
15
  }, z.core.$strip>, z.ZodObject<{
@@ -10,9 +10,9 @@ export declare const ensemblQueryRegion: import("@cyanheads/mcp-ts-core").ToolDe
10
10
  feature: z.ZodDefault<z.ZodArray<z.ZodEnum<{
11
11
  exon: "exon";
12
12
  gene: "gene";
13
+ regulatory: "regulatory";
13
14
  transcript: "transcript";
14
15
  variation: "variation";
15
- regulatory: "regulatory";
16
16
  }>>>;
17
17
  biotype: z.ZodOptional<z.ZodString>;
18
18
  }, z.core.$strip>, z.ZodObject<{