@cyanheads/ensembl-mcp-server 0.1.1

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.
Files changed (69) hide show
  1. package/AGENTS.md +383 -0
  2. package/CLAUDE.md +383 -0
  3. package/Dockerfile +99 -0
  4. package/LICENSE +201 -0
  5. package/README.md +326 -0
  6. package/changelog/0.1.x/0.1.1.md +31 -0
  7. package/changelog/template.md +127 -0
  8. package/dist/config/server-config.d.ts +14 -0
  9. package/dist/config/server-config.d.ts.map +1 -0
  10. package/dist/config/server-config.js +21 -0
  11. package/dist/config/server-config.js.map +1 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +40 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/mcp-server/prompts/definitions/gene-dossier.prompt.d.ts +10 -0
  17. package/dist/mcp-server/prompts/definitions/gene-dossier.prompt.d.ts.map +1 -0
  18. package/dist/mcp-server/prompts/definitions/gene-dossier.prompt.js +60 -0
  19. package/dist/mcp-server/prompts/definitions/gene-dossier.prompt.js.map +1 -0
  20. package/dist/mcp-server/resources/definitions/gene.resource.d.ts +15 -0
  21. package/dist/mcp-server/resources/definitions/gene.resource.d.ts.map +1 -0
  22. package/dist/mcp-server/resources/definitions/gene.resource.js +59 -0
  23. package/dist/mcp-server/resources/definitions/gene.resource.js.map +1 -0
  24. package/dist/mcp-server/resources/definitions/species.resource.d.ts +15 -0
  25. package/dist/mcp-server/resources/definitions/species.resource.d.ts.map +1 -0
  26. package/dist/mcp-server/resources/definitions/species.resource.js +48 -0
  27. package/dist/mcp-server/resources/definitions/species.resource.js.map +1 -0
  28. package/dist/mcp-server/resources/definitions/transcript.resource.d.ts +15 -0
  29. package/dist/mcp-server/resources/definitions/transcript.resource.d.ts.map +1 -0
  30. package/dist/mcp-server/resources/definitions/transcript.resource.js +53 -0
  31. package/dist/mcp-server/resources/definitions/transcript.resource.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/get-homology.tool.d.ts +43 -0
  33. package/dist/mcp-server/tools/definitions/get-homology.tool.d.ts.map +1 -0
  34. package/dist/mcp-server/tools/definitions/get-homology.tool.js +183 -0
  35. package/dist/mcp-server/tools/definitions/get-homology.tool.js.map +1 -0
  36. package/dist/mcp-server/tools/definitions/get-sequence.tool.d.ts +35 -0
  37. package/dist/mcp-server/tools/definitions/get-sequence.tool.d.ts.map +1 -0
  38. package/dist/mcp-server/tools/definitions/get-sequence.tool.js +154 -0
  39. package/dist/mcp-server/tools/definitions/get-sequence.tool.js.map +1 -0
  40. package/dist/mcp-server/tools/definitions/get-xrefs.tool.d.ts +28 -0
  41. package/dist/mcp-server/tools/definitions/get-xrefs.tool.d.ts.map +1 -0
  42. package/dist/mcp-server/tools/definitions/get-xrefs.tool.js +122 -0
  43. package/dist/mcp-server/tools/definitions/get-xrefs.tool.js.map +1 -0
  44. package/dist/mcp-server/tools/definitions/list-species.tool.d.ts +28 -0
  45. package/dist/mcp-server/tools/definitions/list-species.tool.d.ts.map +1 -0
  46. package/dist/mcp-server/tools/definitions/list-species.tool.js +105 -0
  47. package/dist/mcp-server/tools/definitions/list-species.tool.js.map +1 -0
  48. package/dist/mcp-server/tools/definitions/lookup-gene.tool.d.ts +57 -0
  49. package/dist/mcp-server/tools/definitions/lookup-gene.tool.d.ts.map +1 -0
  50. package/dist/mcp-server/tools/definitions/lookup-gene.tool.js +254 -0
  51. package/dist/mcp-server/tools/definitions/lookup-gene.tool.js.map +1 -0
  52. package/dist/mcp-server/tools/definitions/predict-variant.tool.d.ts +58 -0
  53. package/dist/mcp-server/tools/definitions/predict-variant.tool.d.ts.map +1 -0
  54. package/dist/mcp-server/tools/definitions/predict-variant.tool.js +246 -0
  55. package/dist/mcp-server/tools/definitions/predict-variant.tool.js.map +1 -0
  56. package/dist/mcp-server/tools/definitions/query-region.tool.d.ts +48 -0
  57. package/dist/mcp-server/tools/definitions/query-region.tool.d.ts.map +1 -0
  58. package/dist/mcp-server/tools/definitions/query-region.tool.js +162 -0
  59. package/dist/mcp-server/tools/definitions/query-region.tool.js.map +1 -0
  60. package/dist/services/ensembl/ensembl-service.d.ts +32 -0
  61. package/dist/services/ensembl/ensembl-service.d.ts.map +1 -0
  62. package/dist/services/ensembl/ensembl-service.js +366 -0
  63. package/dist/services/ensembl/ensembl-service.js.map +1 -0
  64. package/dist/services/ensembl/types.d.ts +289 -0
  65. package/dist/services/ensembl/types.d.ts.map +1 -0
  66. package/dist/services/ensembl/types.js +6 -0
  67. package/dist/services/ensembl/types.js.map +1 -0
  68. package/package.json +106 -0
  69. package/server.json +113 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @fileoverview Tool to find orthologs and paralogs of a gene across species.
3
+ * @module mcp-server/tools/definitions/get-homology
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getEnsemblService } from '../../../services/ensembl/ensembl-service.js';
8
+ const HOMOLOGY_TYPES = ['orthologues', 'paralogues', 'all'];
9
+ const HomologyEntrySchema = z.object({
10
+ targetId: z.string().describe('Ensembl stable ID of the homologous gene in the target species.'),
11
+ targetSpecies: z
12
+ .string()
13
+ .optional()
14
+ .describe('Target species in Ensembl internal format (e.g. mus_musculus).'),
15
+ type: z
16
+ .string()
17
+ .optional()
18
+ .describe('Homology type: ortholog_one2one, ortholog_one2many, ortholog_many2many, ' +
19
+ 'paralog_many2many, within_species_paralog, or similar.'),
20
+ percId: z
21
+ .number()
22
+ .optional()
23
+ .describe('Percent identity between the query and target gene sequences (0-100). ' +
24
+ 'Higher values indicate more conserved sequences.'),
25
+ percPos: z
26
+ .number()
27
+ .optional()
28
+ .describe('Percent positive (similar) positions in the alignment (0-100). ' +
29
+ 'Includes conservative substitutions as well as identical residues.'),
30
+ taxonomyLevel: z
31
+ .string()
32
+ .optional()
33
+ .describe('Last common ancestor taxonomic level for this homology relationship ' +
34
+ '(e.g. Amniota, Vertebrata, Bilateria).'),
35
+ });
36
+ export const ensemblGetHomology = tool('ensembl_get_homology', {
37
+ title: 'Get Gene Homologs',
38
+ description: "Find orthologs and/or paralogs of a gene across species. Returns each homolog's stable ID, species, " +
39
+ 'homology type (ortholog_one2one, ortholog_one2many, paralog_many2many, etc.), perc_id (percent identity), ' +
40
+ 'perc_pos (percent positives), and taxonomy level. Essential for cross-species research — for example, ' +
41
+ '"what is the mouse equivalent of human TP53?" or "how conserved is BRCA2 across mammals?". ' +
42
+ 'Provide either symbol + species or a stable gene ID. Target species can be filtered to a single species ' +
43
+ 'or left open to return all available homologs.',
44
+ annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
45
+ input: z.object({
46
+ symbol: z
47
+ .string()
48
+ .optional()
49
+ .describe('Gene symbol in the source species (e.g. BRCA2, TP53). ' +
50
+ 'Requires species to be set. Cannot be used together with id.'),
51
+ id: z
52
+ .string()
53
+ .optional()
54
+ .describe('Ensembl stable gene ID (e.g. ENSG00000139618). ' +
55
+ 'Use ensembl_lookup_gene to get the stable ID from a symbol. ' +
56
+ 'Cannot be used together with symbol.'),
57
+ species: z
58
+ .string()
59
+ .default('homo_sapiens')
60
+ .describe('Source species (the species the query gene belongs to) in Ensembl internal format. ' +
61
+ 'Default is homo_sapiens. Use ensembl_list_species to discover valid values.'),
62
+ target_species: z
63
+ .string()
64
+ .optional()
65
+ .describe('Filter to homologs in a single target species (e.g. mus_musculus for mouse). ' +
66
+ 'Omit to return homologs across all available species. ' +
67
+ 'Use ensembl_list_species to discover valid values.'),
68
+ type: z
69
+ .enum(HOMOLOGY_TYPES)
70
+ .default('orthologues')
71
+ .describe('Type of homologs to return. ' +
72
+ 'orthologues: genes related by speciation (cross-species equivalents). ' +
73
+ 'paralogues: genes related by duplication (within or across species). ' +
74
+ 'all: both orthologs and paralogs.'),
75
+ }),
76
+ output: z.object({
77
+ homologs: z
78
+ .array(HomologyEntrySchema.describe('A single homologous gene with its stable ID, species, homology type, and sequence identity metrics.'))
79
+ .describe('Homologous genes found for the query gene.'),
80
+ totalCount: z.number().describe('Total number of homologs returned.'),
81
+ queryId: z.string().describe('The resolved Ensembl gene ID used for the homology query.'),
82
+ querySpecies: z.string().describe('The source species used for the query.'),
83
+ queryType: z.string().describe('The homology type queried (orthologues, paralogues, or all).'),
84
+ }),
85
+ enrichment: {
86
+ notice: z.string().optional().describe('Guidance when no homologs are found.'),
87
+ },
88
+ errors: [
89
+ {
90
+ reason: 'not_found',
91
+ code: JsonRpcErrorCode.NotFound,
92
+ when: 'The gene symbol or stable ID was not found in Ensembl.',
93
+ recovery: 'Verify the symbol spelling or use ensembl_lookup_gene to get the stable ID first. ' +
94
+ 'Confirm the species is correct with ensembl_list_species.',
95
+ },
96
+ {
97
+ reason: 'no_input',
98
+ code: JsonRpcErrorCode.InvalidParams,
99
+ when: 'Neither symbol nor id was provided.',
100
+ recovery: 'Provide either symbol (with species) or a stable Ensembl gene ID.',
101
+ },
102
+ ],
103
+ async handler(input, ctx) {
104
+ ctx.log.info('Getting homologs', {
105
+ symbol: input.symbol,
106
+ id: input.id,
107
+ species: input.species,
108
+ targetSpecies: input.target_species,
109
+ type: input.type,
110
+ });
111
+ const service = getEnsemblService();
112
+ if (!input.symbol?.trim() && !input.id?.trim()) {
113
+ throw ctx.fail('no_input', 'Provide either symbol (with species) or a stable gene ID.');
114
+ }
115
+ const idTrimmed = input.id?.trim();
116
+ const symbolTrimmed = input.symbol?.trim();
117
+ let queryId;
118
+ let homologs;
119
+ if (idTrimmed) {
120
+ queryId = idTrimmed;
121
+ homologs = await service
122
+ .getHomologyById(queryId, input.species, input.type, input.target_species, ctx)
123
+ .catch((err) => {
124
+ const msg = err instanceof Error ? err.message : String(err);
125
+ if (/not found|no valid lookup|page not found/i.test(msg)) {
126
+ throw ctx.fail('not_found', `Gene ID "${queryId}" not found in Ensembl.`);
127
+ }
128
+ throw err;
129
+ });
130
+ }
131
+ else {
132
+ queryId = symbolTrimmed ?? '';
133
+ homologs = await service
134
+ .getHomologyBySymbol(queryId, input.species, input.type, input.target_species, ctx)
135
+ .catch((err) => {
136
+ const msg = err instanceof Error ? err.message : String(err);
137
+ // Ensembl returns {"error":"<species_name>"} for invalid gene symbols in homology endpoint
138
+ if (/not found|no valid lookup/i.test(msg) || msg === input.species) {
139
+ throw ctx.fail('not_found', `Gene symbol "${queryId}" not found in ${input.species}.`);
140
+ }
141
+ throw err;
142
+ });
143
+ }
144
+ if (homologs.length === 0) {
145
+ ctx.enrich.notice(`No ${input.type} found for "${queryId}" in ${input.species}` +
146
+ (input.target_species ? ` targeting ${input.target_species}` : '') +
147
+ '. Try type=all or remove the target_species filter.');
148
+ }
149
+ ctx.enrich.total(homologs.length);
150
+ return {
151
+ homologs,
152
+ totalCount: homologs.length,
153
+ queryId,
154
+ querySpecies: input.species,
155
+ queryType: input.type,
156
+ };
157
+ },
158
+ format: (result) => {
159
+ const lines = [];
160
+ lines.push(`## Homologs of ${result.queryId} (${result.querySpecies})`);
161
+ lines.push(`**Type:** ${result.queryType} | **Found:** ${result.totalCount}\n`);
162
+ if (result.homologs.length === 0) {
163
+ lines.push('No homologs found. Try type=all or remove the target_species filter.');
164
+ return [{ type: 'text', text: lines.join('\n') }];
165
+ }
166
+ for (const h of result.homologs) {
167
+ lines.push(`### ${h.targetId}`);
168
+ if (h.targetSpecies)
169
+ lines.push(`**Species:** ${h.targetSpecies}`);
170
+ if (h.type)
171
+ lines.push(`**Homology type:** ${h.type}`);
172
+ if (h.percId != null)
173
+ lines.push(`**Percent identity:** ${h.percId.toFixed(1)}%`);
174
+ if (h.percPos != null)
175
+ lines.push(`**Percent positives:** ${h.percPos.toFixed(1)}%`);
176
+ if (h.taxonomyLevel)
177
+ lines.push(`**Last common ancestor:** ${h.taxonomyLevel}`);
178
+ lines.push('');
179
+ }
180
+ return [{ type: 'text', text: lines.join('\n') }];
181
+ },
182
+ });
183
+ //# sourceMappingURL=get-homology.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-homology.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-homology.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @fileoverview Tool to fetch DNA, cDNA, CDS, or protein sequences for Ensembl IDs or genomic regions.
3
+ * @module mcp-server/tools/definitions/get-sequence
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const ensemblGetSequence: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ id: z.ZodString;
9
+ type: z.ZodDefault<z.ZodEnum<{
10
+ genomic: "genomic";
11
+ cdna: "cdna";
12
+ cds: "cds";
13
+ protein: "protein";
14
+ }>>;
15
+ species: z.ZodOptional<z.ZodString>;
16
+ expand_5prime: z.ZodDefault<z.ZodNumber>;
17
+ expand_3prime: z.ZodDefault<z.ZodNumber>;
18
+ }, z.core.$strip>, z.ZodObject<{
19
+ id: z.ZodString;
20
+ type: z.ZodString;
21
+ seq: z.ZodString;
22
+ lengthInBp: z.ZodNumber;
23
+ description: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>, readonly [{
25
+ readonly reason: "not_found";
26
+ readonly code: JsonRpcErrorCode.NotFound;
27
+ readonly when: "The stable ID or region was not found in Ensembl.";
28
+ readonly recovery: string;
29
+ }, {
30
+ readonly reason: "type_mismatch";
31
+ readonly code: JsonRpcErrorCode.ValidationError;
32
+ readonly when: "The requested sequence type is incompatible with the provided ID type.";
33
+ readonly recovery: string;
34
+ }], undefined>;
35
+ //# sourceMappingURL=get-sequence.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-sequence.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-sequence.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+K7B,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * @fileoverview Tool to fetch DNA, cDNA, CDS, or protein sequences for Ensembl IDs or genomic regions.
3
+ * @module mcp-server/tools/definitions/get-sequence
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getEnsemblService } from '../../../services/ensembl/ensembl-service.js';
8
+ const SEQUENCE_TYPES = ['genomic', 'cdna', 'cds', 'protein'];
9
+ export const ensemblGetSequence = tool('ensembl_get_sequence', {
10
+ title: 'Get Sequence',
11
+ description: 'Fetch the DNA, cDNA, CDS, or protein sequence for a gene, transcript, protein, or genomic region. ' +
12
+ 'Returns the sequence with its stable ID, molecule type, and character count — large sequences are ' +
13
+ 'returned in full but the length is stated so callers can budget context. The type parameter selects ' +
14
+ 'which sequence is fetched: genomic (default, includes introns), cdna (spliced transcript), ' +
15
+ 'cds (coding sequence only), protein. For region mode, set id to the format species:chr:start-end ' +
16
+ '(e.g. homo_sapiens:13:32315086-32400268) and set species. Protein sequences require a transcript or ' +
17
+ 'protein stable ID (ENST…/ENSP…), not a gene ID — use ensembl_lookup_gene with expand_transcripts=true ' +
18
+ 'to get the canonical transcript ID first.',
19
+ annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
20
+ input: z.object({
21
+ id: z
22
+ .string()
23
+ .describe('Ensembl stable ID (ENSG…, ENST…, ENSP…) or region in the format ' +
24
+ 'species:chr:start-end (e.g. homo_sapiens:13:32315086-32400268) for region mode. ' +
25
+ 'For genomic region queries, species is also required.'),
26
+ type: z
27
+ .enum(SEQUENCE_TYPES)
28
+ .default('genomic')
29
+ .describe('Sequence type to retrieve. ' +
30
+ 'genomic: full genomic DNA including introns (default). ' +
31
+ 'cdna: spliced transcript sequence (requires ENST… ID). ' +
32
+ 'cds: coding sequence only, no UTRs (requires ENST… ID with coding transcript). ' +
33
+ 'protein: amino acid sequence (requires ENST… or ENSP… ID).'),
34
+ species: z
35
+ .string()
36
+ .optional()
37
+ .describe('Species in Ensembl internal format (e.g. homo_sapiens). ' +
38
+ 'Required for region mode (when id is a species:chr:start-end string). ' +
39
+ 'Optional for stable ID lookups — Ensembl infers species from the ID prefix.'),
40
+ expand_5prime: z
41
+ .number()
42
+ .int()
43
+ .min(0)
44
+ .default(0)
45
+ .describe("Number of base pairs to extend upstream (5' direction) of the requested feature. " +
46
+ 'Default 0. Only applies to genomic sequences and region queries.'),
47
+ expand_3prime: z
48
+ .number()
49
+ .int()
50
+ .min(0)
51
+ .default(0)
52
+ .describe("Number of base pairs to extend downstream (3' direction) of the requested feature. " +
53
+ 'Default 0. Only applies to genomic sequences and region queries.'),
54
+ }),
55
+ output: z.object({
56
+ id: z.string().describe('The stable ID or region used for the lookup.'),
57
+ type: z.string().describe('Sequence type returned (genomic, cdna, cds, or protein).'),
58
+ seq: z
59
+ .string()
60
+ .describe('The full sequence. DNA sequences use IUPAC nucleotide codes (ACGT + ambiguity codes). ' +
61
+ 'Protein sequences use single-letter amino acid codes. ' +
62
+ 'Large genomic sequences (e.g. 85 kb for BRCA2) are returned in full.'),
63
+ lengthInBp: z
64
+ .number()
65
+ .describe('Sequence length in characters (nucleotides or amino acids). ' +
66
+ 'Use this to budget context window usage before processing the sequence.'),
67
+ description: z.string().optional().describe('Sequence description from Ensembl, if provided.'),
68
+ }),
69
+ errors: [
70
+ {
71
+ reason: 'not_found',
72
+ code: JsonRpcErrorCode.NotFound,
73
+ when: 'The stable ID or region was not found in Ensembl.',
74
+ recovery: 'Verify the ID format (ENSG…, ENST…, ENSP…) or region coordinates. ' +
75
+ 'Use ensembl_lookup_gene to get valid stable IDs first.',
76
+ },
77
+ {
78
+ reason: 'type_mismatch',
79
+ code: JsonRpcErrorCode.ValidationError,
80
+ when: 'The requested sequence type is incompatible with the provided ID type.',
81
+ recovery: 'protein and cds sequences require a transcript ID (ENST…) or protein ID (ENSP…), not a gene ID. ' +
82
+ 'Use ensembl_lookup_gene with expand_transcripts=true to find the canonical transcript ID, ' +
83
+ 'then request the protein or cds sequence from that transcript ID.',
84
+ },
85
+ ],
86
+ async handler(input, ctx) {
87
+ ctx.log.info('Fetching sequence', { id: input.id, type: input.type });
88
+ const service = getEnsemblService();
89
+ // Detect region mode: contains ":" after optional species prefix.
90
+ // Scaffold/patch names carry dots (e.g. GL000220.1), so the chromosome
91
+ // segment allows "." in addition to word characters.
92
+ const regionPattern = /^[a-z_]+:[\w.]+:\d+-\d+$/i;
93
+ const isRegion = regionPattern.test(input.id);
94
+ if (isRegion) {
95
+ // Parse "species:chr:start-end"
96
+ const parts = input.id.split(':');
97
+ if (parts.length !== 3) {
98
+ throw ctx.fail('not_found', `Region format should be species:chr:start-end, got: ${input.id}`);
99
+ }
100
+ const [speciesFromId, chr, range] = parts;
101
+ const speciesStr = input.species?.trim() || speciesFromId;
102
+ const region = `${chr}:${range}`;
103
+ const seq = await service
104
+ .getSequenceByRegion(speciesStr, region, input.expand_5prime, input.expand_3prime, ctx)
105
+ .catch((err) => {
106
+ const msg = err instanceof Error ? err.message : String(err);
107
+ if (/not found|invalid|no stable id/i.test(msg)) {
108
+ throw ctx.fail('not_found', `Region ${input.id} not found: ${msg}`);
109
+ }
110
+ throw err;
111
+ });
112
+ return seq;
113
+ }
114
+ // Stable ID mode
115
+ const seq = await service
116
+ .getSequenceById(input.id.trim(), input.type, ctx)
117
+ .catch((err) => {
118
+ const msg = err instanceof Error ? err.message : String(err);
119
+ if (/protein.*gene|cds.*gene|type.*mismatch|incompatible/i.test(msg) ||
120
+ /requesting a gene and type not equal/i.test(msg) ||
121
+ /multiple sequences detected/i.test(msg)) {
122
+ throw ctx.fail('type_mismatch', `Cannot request type "${input.type}" from a gene ID — use a transcript or protein stable ID instead. ` +
123
+ `Call ensembl_lookup_gene with expand_transcripts=true to get transcript IDs.`);
124
+ }
125
+ if (/not found|no stable id/i.test(msg)) {
126
+ throw ctx.fail('not_found', `ID ${input.id} not found in Ensembl.`);
127
+ }
128
+ throw err;
129
+ });
130
+ return seq;
131
+ },
132
+ format: (result) => {
133
+ const lines = [];
134
+ lines.push(`## Sequence: ${result.id}`);
135
+ lines.push(`**Type:** ${result.type} | **Length:** ${result.lengthInBp.toLocaleString()} bp/aa`);
136
+ if (result.description)
137
+ lines.push(`**Description:** ${result.description}`);
138
+ lines.push('');
139
+ // Show first 200 chars + truncation note for large sequences
140
+ if (result.seq.length > 200) {
141
+ lines.push('```');
142
+ lines.push(result.seq.slice(0, 200));
143
+ lines.push(`… (${result.lengthInBp.toLocaleString()} total characters)`);
144
+ lines.push('```');
145
+ }
146
+ else {
147
+ lines.push('```');
148
+ lines.push(result.seq);
149
+ lines.push('```');
150
+ }
151
+ return [{ type: 'text', text: lines.join('\n') }];
152
+ },
153
+ });
154
+ //# sourceMappingURL=get-sequence.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-sequence.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-sequence.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAU,CAAC;AAEtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,sBAAsB,EAAE;IAC7D,KAAK,EAAE,cAAc;IACrB,WAAW,EACT,oGAAoG;QACpG,oGAAoG;QACpG,sGAAsG;QACtG,6FAA6F;QAC7F,mGAAmG;QACnG,sGAAsG;QACtG,wGAAwG;QACxG,2CAA2C;IAC7C,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;IAC9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,EAAE,EAAE,CAAC;aACF,MAAM,EAAE;aACR,QAAQ,CACP,kEAAkE;YAChE,kFAAkF;YAClF,uDAAuD,CAC1D;QACH,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,cAAc,CAAC;aACpB,OAAO,CAAC,SAAS,CAAC;aAClB,QAAQ,CACP,6BAA6B;YAC3B,yDAAyD;YACzD,yDAAyD;YACzD,iFAAiF;YACjF,4DAA4D,CAC/D;QACH,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,0DAA0D;YACxD,wEAAwE;YACxE,6EAA6E,CAChF;QACH,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,OAAO,CAAC,CAAC,CAAC;aACV,QAAQ,CACP,mFAAmF;YACjF,kEAAkE,CACrE;QACH,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,OAAO,CAAC,CAAC,CAAC;aACV,QAAQ,CACP,qFAAqF;YACnF,kEAAkE,CACrE;KACJ,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QACvE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0DAA0D,CAAC;QACrF,GAAG,EAAE,CAAC;aACH,MAAM,EAAE;aACR,QAAQ,CACP,wFAAwF;YACtF,wDAAwD;YACxD,sEAAsE,CACzE;QACH,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,CACP,8DAA8D;YAC5D,yEAAyE,CAC5E;QACH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;KAC/F,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,mDAAmD;YACzD,QAAQ,EACN,oEAAoE;gBACpE,wDAAwD;SAC3D;QACD;YACE,MAAM,EAAE,eAAe;YACvB,IAAI,EAAE,gBAAgB,CAAC,eAAe;YACtC,IAAI,EAAE,wEAAwE;YAC9E,QAAQ,EACN,kGAAkG;gBAClG,4FAA4F;gBAC5F,mEAAmE;SACtE;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;QAEpC,kEAAkE;QAClE,uEAAuE;QACvE,qDAAqD;QACrD,MAAM,aAAa,GAAG,2BAA2B,CAAC;QAClD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAE9C,IAAI,QAAQ,EAAE,CAAC;YACb,gCAAgC;YAChC,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,GAAG,CAAC,IAAI,CACZ,WAAW,EACX,uDAAuD,KAAK,CAAC,EAAE,EAAE,CAClE,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,aAAa,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,KAAiC,CAAC;YACtE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,aAAa,CAAC;YAC1D,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,OAAO;iBACtB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,GAAG,CAAC;iBACtF,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;gBACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,IAAI,iCAAiC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChD,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,KAAK,CAAC,EAAE,eAAe,GAAG,EAAE,CAAC,CAAC;gBACtE,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC,CAAC,CAAC;YACL,OAAO,GAAG,CAAC;QACb,CAAC;QAED,iBAAiB;QACjB,MAAM,GAAG,GAAG,MAAM,OAAO;aACtB,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC;aACjD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,IACE,sDAAsD,CAAC,IAAI,CAAC,GAAG,CAAC;gBAChE,uCAAuC,CAAC,IAAI,CAAC,GAAG,CAAC;gBACjD,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,EACxC,CAAC;gBACD,MAAM,GAAG,CAAC,IAAI,CACZ,eAAe,EACf,wBAAwB,KAAK,CAAC,IAAI,oEAAoE;oBACpG,8EAA8E,CACjF,CAAC;YACJ,CAAC;YACD,IAAI,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,KAAK,CAAC,EAAE,wBAAwB,CAAC,CAAC;YACtE,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CACR,aAAa,MAAM,CAAC,IAAI,kBAAkB,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,QAAQ,CACrF,CAAC;QACF,IAAI,MAAM,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,6DAA6D;QAC7D,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;YACzE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview Tool to retrieve cross-database references for Ensembl genes and features.
3
+ * @module mcp-server/tools/definitions/get-xrefs
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const ensemblGetXrefs: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ id: z.ZodString;
9
+ dbname: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ xrefs: z.ZodArray<z.ZodObject<{
12
+ dbname: z.ZodOptional<z.ZodString>;
13
+ dbDisplayName: z.ZodOptional<z.ZodString>;
14
+ primaryId: z.ZodOptional<z.ZodString>;
15
+ displayId: z.ZodOptional<z.ZodString>;
16
+ description: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>>;
18
+ totalCount: z.ZodNumber;
19
+ queriedId: z.ZodString;
20
+ }, z.core.$strip>, readonly [{
21
+ readonly reason: "not_found";
22
+ readonly code: JsonRpcErrorCode.NotFound;
23
+ readonly when: "The Ensembl stable ID was not found or has no cross-references.";
24
+ readonly recovery: string;
25
+ }], {
26
+ readonly notice: z.ZodOptional<z.ZodString>;
27
+ }>;
28
+ //# sourceMappingURL=get-xrefs.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-xrefs.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-xrefs.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAyBjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;EAmH1B,CAAC"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @fileoverview Tool to retrieve cross-database references for Ensembl genes and features.
3
+ * @module mcp-server/tools/definitions/get-xrefs
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getEnsemblService } from '../../../services/ensembl/ensembl-service.js';
8
+ const XrefEntrySchema = z.object({
9
+ dbname: z
10
+ .string()
11
+ .optional()
12
+ .describe('Database name in Ensembl internal format (e.g. HGNC, Uniprot_gn, EntrezGene, MIM_GENE, RefSeq_mRNA).'),
13
+ dbDisplayName: z.string().optional().describe('Human-readable database display name.'),
14
+ primaryId: z
15
+ .string()
16
+ .optional()
17
+ .describe('Primary identifier in the external database (e.g. HGNC:1101 for BRCA2 in HGNC, ' +
18
+ 'P51587 for BRCA2 in UniProt).'),
19
+ displayId: z
20
+ .string()
21
+ .optional()
22
+ .describe('Display identifier — often the same as primaryId but may be a formatted accession.'),
23
+ description: z.string().optional().describe('Description of the cross-reference entry.'),
24
+ });
25
+ export const ensemblGetXrefs = tool('ensembl_get_xrefs', {
26
+ title: 'Get Cross-Database References',
27
+ description: 'Retrieve cross-database references for a gene or feature — HGNC, UniProt, EntrezGene, OMIM, ' +
28
+ 'RefSeq, Reactome, and others. Returns each xref with its database name, primary ID, display ID, ' +
29
+ 'and description. The dbname filter narrows to specific databases; omit to return all xrefs. ' +
30
+ 'IDs returned here chain to protein (pubchem via UniProt), literature (pubmed via PubMed IDs), ' +
31
+ 'disease (OMIM via MIM_GENE), and pathway (Reactome) resources. ' +
32
+ 'Requires an Ensembl stable ID — use ensembl_lookup_gene to get the ENSG… ID first. ' +
33
+ 'Common dbname values: HGNC, Uniprot_gn, EntrezGene, MIM_GENE, RefSeq_mRNA, RefSeq_peptide, ' +
34
+ 'Reactome, GO (Gene Ontology), ChEMBL.',
35
+ annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
36
+ input: z.object({
37
+ id: z
38
+ .string()
39
+ .describe('Ensembl stable gene ID (ENSG…) or transcript ID (ENST…). ' +
40
+ 'Use ensembl_lookup_gene to get the stable ID from a gene symbol. ' +
41
+ 'xrefs/id returns the full cross-reference set (56+ entries for well-annotated genes like BRCA2).'),
42
+ dbname: z
43
+ .string()
44
+ .optional()
45
+ .describe('Filter to a specific external database by its Ensembl internal name. ' +
46
+ 'Examples: HGNC (HGNC gene ID), Uniprot_gn (UniProt gene name), ' +
47
+ 'EntrezGene (NCBI Gene ID), MIM_GENE (OMIM disease gene), ' +
48
+ 'RefSeq_mRNA (NCBI RefSeq transcript), Reactome (pathway IDs), ' +
49
+ 'GO (Gene Ontology terms). Omit to return all available xrefs.'),
50
+ }),
51
+ output: z.object({
52
+ xrefs: z
53
+ .array(XrefEntrySchema.describe('A single cross-database reference entry with database name, primary ID, and description.'))
54
+ .describe('Cross-database references for the queried Ensembl ID.'),
55
+ totalCount: z.number().describe('Total number of cross-references returned.'),
56
+ queriedId: z.string().describe('The Ensembl stable ID that was queried.'),
57
+ }),
58
+ enrichment: {
59
+ notice: z.string().optional().describe('Guidance when no cross-references are found.'),
60
+ },
61
+ errors: [
62
+ {
63
+ reason: 'not_found',
64
+ code: JsonRpcErrorCode.NotFound,
65
+ when: 'The Ensembl stable ID was not found or has no cross-references.',
66
+ recovery: 'Use ensembl_lookup_gene to verify the stable ID is current and valid. ' +
67
+ 'Versioned IDs (ENSG00000139618.7) should work with or without the version suffix.',
68
+ },
69
+ ],
70
+ async handler(input, ctx) {
71
+ ctx.log.info('Getting xrefs', { id: input.id, dbname: input.dbname });
72
+ const service = getEnsemblService();
73
+ const xrefs = await service
74
+ .getXrefsById(input.id.trim(), input.dbname?.trim() || undefined, ctx)
75
+ .catch((err) => {
76
+ const msg = err instanceof Error ? err.message : String(err);
77
+ if (/not found/i.test(msg)) {
78
+ throw ctx.fail('not_found', `ID "${input.id}" not found in Ensembl.`);
79
+ }
80
+ throw err;
81
+ });
82
+ if (xrefs.length === 0) {
83
+ const filterNote = input.dbname ? ` with dbname filter "${input.dbname}"` : '';
84
+ ctx.enrich.notice(`No cross-references found for ${input.id}${filterNote}. ` +
85
+ 'Try without the dbname filter to see all available databases.');
86
+ }
87
+ ctx.enrich.total(xrefs.length);
88
+ return { xrefs, totalCount: xrefs.length, queriedId: input.id };
89
+ },
90
+ format: (result) => {
91
+ const lines = [];
92
+ lines.push(`## Cross-References for ${result.queriedId}`);
93
+ lines.push(`**Total:** ${result.totalCount}\n`);
94
+ if (result.xrefs.length === 0) {
95
+ lines.push('No cross-references found.');
96
+ return [{ type: 'text', text: lines.join('\n') }];
97
+ }
98
+ // Group by database for readability
99
+ const byDb = new Map();
100
+ for (const x of result.xrefs) {
101
+ const db = x.dbname ?? 'Unknown';
102
+ if (!byDb.has(db))
103
+ byDb.set(db, []);
104
+ byDb.get(db)?.push(x);
105
+ }
106
+ for (const [db, entries] of byDb) {
107
+ const displayName = entries[0]?.dbDisplayName;
108
+ lines.push(`### ${displayName ?? db}${displayName && displayName !== db ? ` (${db})` : ''}`);
109
+ for (const x of entries) {
110
+ let line = `- **${x.primaryId ?? x.displayId ?? 'unknown'}**`;
111
+ if (x.displayId && x.displayId !== x.primaryId)
112
+ line += ` (${x.displayId})`;
113
+ if (x.description)
114
+ line += `: ${x.description}`;
115
+ lines.push(line);
116
+ }
117
+ lines.push('');
118
+ }
119
+ return [{ type: 'text', text: lines.join('\n') }];
120
+ },
121
+ });
122
+ //# sourceMappingURL=get-xrefs.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-xrefs.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-xrefs.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview Tool to list Ensembl-supported species with display names, assemblies, and taxon IDs.
3
+ * @module mcp-server/tools/definitions/list-species
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ export declare const ensemblListSpecies: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
7
+ division: z.ZodOptional<z.ZodEnum<{
8
+ EnsemblVertebrates: "EnsemblVertebrates";
9
+ EnsemblPlants: "EnsemblPlants";
10
+ EnsemblFungi: "EnsemblFungi";
11
+ EnsemblMetazoa: "EnsemblMetazoa";
12
+ EnsemblProtists: "EnsemblProtists";
13
+ }>>;
14
+ nameContains: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>, z.ZodObject<{
16
+ species: z.ZodArray<z.ZodObject<{
17
+ name: z.ZodString;
18
+ displayName: z.ZodOptional<z.ZodString>;
19
+ commonName: z.ZodOptional<z.ZodString>;
20
+ taxonId: z.ZodOptional<z.ZodString>;
21
+ assembly: z.ZodOptional<z.ZodString>;
22
+ division: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strip>>;
24
+ totalCount: z.ZodNumber;
25
+ }, z.core.$strip>, undefined, {
26
+ readonly notice: z.ZodOptional<z.ZodString>;
27
+ }>;
28
+ //# sourceMappingURL=list-species.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-species.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/list-species.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AA+BjD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAkF7B,CAAC"}