agr-mcp-server 4.0.3 → 5.0.2
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/dist/client.d.ts +58 -2
- package/dist/client.js +336 -3
- package/dist/index.js +439 -1
- package/dist/types.d.ts +51 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityType, SearchResponse, GeneData, DiseaseResponse, ExpressionResponse, OrthologyResponse, PhenotypeResponse, InteractionResponse, AlleleResponse, Species } from "./types.js";
|
|
1
|
+
import { EntityType, SearchResponse, GeneData, DiseaseResponse, ExpressionResponse, OrthologyResponse, PhenotypeResponse, InteractionResponse, AlleleResponse, Species, QueryBuilder, PathQueryResult, MineTemplate, MineList, ListContents } from "./types.js";
|
|
2
2
|
export declare class AllianceClient {
|
|
3
3
|
private agrApiUrl;
|
|
4
4
|
private allianceMineUrl;
|
|
@@ -9,9 +9,14 @@ export declare class AllianceClient {
|
|
|
9
9
|
*/
|
|
10
10
|
search(query: string, category?: EntityType, species?: string, limit?: number): Promise<SearchResponse>;
|
|
11
11
|
/**
|
|
12
|
-
* Search using AllianceMine for more advanced queries
|
|
12
|
+
* Search using AllianceMine for more advanced queries.
|
|
13
|
+
* Falls back to PathQuery-based search if keyword search fails.
|
|
13
14
|
*/
|
|
14
15
|
searchMine(query: string, type?: string, limit?: number): Promise<SearchResponse>;
|
|
16
|
+
/**
|
|
17
|
+
* Fallback search using PathQuery when keyword search is unavailable
|
|
18
|
+
*/
|
|
19
|
+
private searchMineViaPathQuery;
|
|
15
20
|
private parseMineResults;
|
|
16
21
|
/**
|
|
17
22
|
* Get detailed gene information
|
|
@@ -57,4 +62,55 @@ export declare class AllianceClient {
|
|
|
57
62
|
* Helper to resolve species short name
|
|
58
63
|
*/
|
|
59
64
|
resolveSpecies(input: string): Species | null;
|
|
65
|
+
private getAuthToken;
|
|
66
|
+
private fetchWithAuth;
|
|
67
|
+
/**
|
|
68
|
+
* Run a raw PathQuery XML query against AllianceMine
|
|
69
|
+
*/
|
|
70
|
+
runPathQuery(xml: string): Promise<PathQueryResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Build PathQuery XML from QueryBuilder definition
|
|
73
|
+
*/
|
|
74
|
+
buildPathQueryXml(query: QueryBuilder): string;
|
|
75
|
+
private escapeXml;
|
|
76
|
+
/**
|
|
77
|
+
* Build and run a query using the QueryBuilder DSL
|
|
78
|
+
*/
|
|
79
|
+
buildAndRunQuery(query: QueryBuilder): Promise<PathQueryResult>;
|
|
80
|
+
/**
|
|
81
|
+
* List available query templates
|
|
82
|
+
*/
|
|
83
|
+
listTemplates(): Promise<MineTemplate[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Run a template query with parameters.
|
|
86
|
+
* Parameters should be provided as { "1": { path: "Gene", op: "LOOKUP", value: "BRCA1" } }
|
|
87
|
+
* or simplified as { "1": "BRCA1" } for LOOKUP constraints (path and op inferred from template).
|
|
88
|
+
*/
|
|
89
|
+
runTemplate(name: string, params: Record<string, string | {
|
|
90
|
+
path?: string;
|
|
91
|
+
op?: string;
|
|
92
|
+
value: string;
|
|
93
|
+
}>, limit?: number): Promise<PathQueryResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Get all available lists
|
|
96
|
+
*/
|
|
97
|
+
getLists(type?: string): Promise<MineList[]>;
|
|
98
|
+
/**
|
|
99
|
+
* Get contents of a specific list
|
|
100
|
+
*/
|
|
101
|
+
getList(name: string): Promise<ListContents | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Create a new list (requires authentication)
|
|
104
|
+
*/
|
|
105
|
+
createList(name: string, type: string, identifiers: string[], description?: string): Promise<MineList>;
|
|
106
|
+
/**
|
|
107
|
+
* Add items to an existing list (requires authentication)
|
|
108
|
+
*/
|
|
109
|
+
addToList(name: string, identifiers: string[]): Promise<MineList>;
|
|
110
|
+
/**
|
|
111
|
+
* Delete a list (requires authentication)
|
|
112
|
+
*/
|
|
113
|
+
deleteList(name: string): Promise<{
|
|
114
|
+
success: boolean;
|
|
115
|
+
}>;
|
|
60
116
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SPECIES_MAP, SPECIES, } from "./types.js";
|
|
2
2
|
const AGR_API_URL = "https://www.alliancegenome.org/api";
|
|
3
|
-
const ALLIANCEMINE_URL = "https://
|
|
3
|
+
const ALLIANCEMINE_URL = "https://alliancemine.alliancegenome.org/alliancemine/service";
|
|
4
4
|
export class AllianceClient {
|
|
5
5
|
agrApiUrl;
|
|
6
6
|
allianceMineUrl;
|
|
@@ -64,9 +64,11 @@ export class AllianceClient {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* Search using AllianceMine for more advanced queries
|
|
67
|
+
* Search using AllianceMine for more advanced queries.
|
|
68
|
+
* Falls back to PathQuery-based search if keyword search fails.
|
|
68
69
|
*/
|
|
69
70
|
async searchMine(query, type, limit = 20) {
|
|
71
|
+
// Try keyword search first
|
|
70
72
|
const params = new URLSearchParams({
|
|
71
73
|
q: query,
|
|
72
74
|
size: String(limit),
|
|
@@ -77,13 +79,51 @@ export class AllianceClient {
|
|
|
77
79
|
const url = `${this.allianceMineUrl}/search?${params.toString()}`;
|
|
78
80
|
try {
|
|
79
81
|
const response = await this.fetch(url);
|
|
82
|
+
// Check if search service returned an error
|
|
83
|
+
if (response.wasSuccessful === false || response.error) {
|
|
84
|
+
throw new Error(response.error || "Search service unavailable");
|
|
85
|
+
}
|
|
80
86
|
return {
|
|
81
87
|
query,
|
|
82
88
|
results: this.parseMineResults(response.results, limit),
|
|
83
89
|
total: response.totalHits,
|
|
84
90
|
};
|
|
85
91
|
}
|
|
86
|
-
catch
|
|
92
|
+
catch {
|
|
93
|
+
// Fallback to PathQuery-based search
|
|
94
|
+
return this.searchMineViaPathQuery(query, type, limit);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Fallback search using PathQuery when keyword search is unavailable
|
|
99
|
+
*/
|
|
100
|
+
async searchMineViaPathQuery(query, type, limit = 20) {
|
|
101
|
+
const searchType = type || "Gene";
|
|
102
|
+
const xml = `<query model="genomic" view="${searchType}.primaryIdentifier ${searchType}.symbol ${searchType}.name ${searchType}.organism.shortName">
|
|
103
|
+
<constraint path="${searchType}.symbol" op="CONTAINS" value="${this.escapeXml(query)}"/>
|
|
104
|
+
</query>`;
|
|
105
|
+
const params = new URLSearchParams({
|
|
106
|
+
query: xml,
|
|
107
|
+
format: "json",
|
|
108
|
+
size: String(limit),
|
|
109
|
+
});
|
|
110
|
+
const url = `${this.allianceMineUrl}/query/results?${params.toString()}`;
|
|
111
|
+
try {
|
|
112
|
+
const response = await this.fetch(url);
|
|
113
|
+
const results = response.results.map((row) => ({
|
|
114
|
+
id: String(row[0] || ""),
|
|
115
|
+
symbol: String(row[1] || ""),
|
|
116
|
+
name: String(row[2] || row[1] || ""),
|
|
117
|
+
species: String(row[3] || ""),
|
|
118
|
+
category: searchType.toLowerCase(),
|
|
119
|
+
}));
|
|
120
|
+
return {
|
|
121
|
+
query,
|
|
122
|
+
results,
|
|
123
|
+
total: results.length,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
87
127
|
return { query, results: [], total: 0 };
|
|
88
128
|
}
|
|
89
129
|
}
|
|
@@ -238,4 +278,297 @@ export class AllianceClient {
|
|
|
238
278
|
}
|
|
239
279
|
return null;
|
|
240
280
|
}
|
|
281
|
+
// ============================================
|
|
282
|
+
// AllianceMine API Methods
|
|
283
|
+
// ============================================
|
|
284
|
+
getAuthToken() {
|
|
285
|
+
return process.env.ALLIANCEMINE_TOKEN || null;
|
|
286
|
+
}
|
|
287
|
+
async fetchWithAuth(url, options = {}) {
|
|
288
|
+
const token = this.getAuthToken();
|
|
289
|
+
if (!token) {
|
|
290
|
+
throw new Error("Authentication required. Set ALLIANCEMINE_TOKEN environment variable.");
|
|
291
|
+
}
|
|
292
|
+
const headers = {
|
|
293
|
+
Accept: "application/json",
|
|
294
|
+
"Content-Type": "application/json",
|
|
295
|
+
Authorization: `Token ${token}`,
|
|
296
|
+
};
|
|
297
|
+
const response = await fetch(url, {
|
|
298
|
+
...options,
|
|
299
|
+
headers: { ...headers, ...options.headers },
|
|
300
|
+
});
|
|
301
|
+
if (!response.ok) {
|
|
302
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
303
|
+
}
|
|
304
|
+
return response.json();
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Run a raw PathQuery XML query against AllianceMine
|
|
308
|
+
*/
|
|
309
|
+
async runPathQuery(xml) {
|
|
310
|
+
const params = new URLSearchParams({
|
|
311
|
+
query: xml,
|
|
312
|
+
format: "json",
|
|
313
|
+
});
|
|
314
|
+
const url = `${this.allianceMineUrl}/query/results?${params.toString()}`;
|
|
315
|
+
try {
|
|
316
|
+
const response = await this.fetch(url);
|
|
317
|
+
// Convert array results to objects using column headers
|
|
318
|
+
const headers = response.columnHeaders || [];
|
|
319
|
+
const results = response.results.map((row) => {
|
|
320
|
+
const obj = {};
|
|
321
|
+
row.forEach((val, idx) => {
|
|
322
|
+
const key = headers[idx] || `col${idx}`;
|
|
323
|
+
obj[key] = val;
|
|
324
|
+
});
|
|
325
|
+
return obj;
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
results,
|
|
329
|
+
columnHeaders: headers,
|
|
330
|
+
rootClass: response.rootClass,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
throw new Error(`PathQuery failed: ${error}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Build PathQuery XML from QueryBuilder definition
|
|
339
|
+
*/
|
|
340
|
+
buildPathQueryXml(query) {
|
|
341
|
+
const { from, select, where, joins, sort } = query;
|
|
342
|
+
// Prefix select fields with root class if not already prefixed
|
|
343
|
+
const viewFields = select.map((field) => field.startsWith(`${from}.`) ? field : `${from}.${field}`);
|
|
344
|
+
let xml = `<query model="genomic" view="${viewFields.join(" ")}"`;
|
|
345
|
+
if (sort) {
|
|
346
|
+
xml += ` sortOrder="${sort.field} ${sort.direction}"`;
|
|
347
|
+
}
|
|
348
|
+
xml += ">";
|
|
349
|
+
// Add outer joins
|
|
350
|
+
if (joins && joins.length > 0) {
|
|
351
|
+
for (const join of joins) {
|
|
352
|
+
xml += `<join path="${from}.${join}" style="OUTER"/>`;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// Add constraints
|
|
356
|
+
if (where) {
|
|
357
|
+
let code = "A";
|
|
358
|
+
for (const [field, constraint] of Object.entries(where)) {
|
|
359
|
+
const path = field.includes(".") ? `${from}.${field}` : `${from}.${field}`;
|
|
360
|
+
if (typeof constraint === "string") {
|
|
361
|
+
xml += `<constraint path="${path}" op="=" value="${this.escapeXml(constraint)}" code="${code}"/>`;
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
const c = constraint;
|
|
365
|
+
if (Array.isArray(c.value)) {
|
|
366
|
+
xml += `<constraint path="${path}" op="${c.op}" code="${code}">${c.value.map((v) => `<value>${this.escapeXml(v)}</value>`).join("")}</constraint>`;
|
|
367
|
+
}
|
|
368
|
+
else if (c.op === "IS NULL" || c.op === "IS NOT NULL") {
|
|
369
|
+
xml += `<constraint path="${path}" op="${c.op}" code="${code}"/>`;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
xml += `<constraint path="${path}" op="${c.op}" value="${this.escapeXml(String(c.value))}" code="${code}"/>`;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
code = String.fromCharCode(code.charCodeAt(0) + 1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
xml += "</query>";
|
|
379
|
+
return xml;
|
|
380
|
+
}
|
|
381
|
+
escapeXml(str) {
|
|
382
|
+
return str
|
|
383
|
+
.replace(/&/g, "&")
|
|
384
|
+
.replace(/</g, "<")
|
|
385
|
+
.replace(/>/g, ">")
|
|
386
|
+
.replace(/"/g, """)
|
|
387
|
+
.replace(/'/g, "'");
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Build and run a query using the QueryBuilder DSL
|
|
391
|
+
*/
|
|
392
|
+
async buildAndRunQuery(query) {
|
|
393
|
+
const xml = this.buildPathQueryXml(query);
|
|
394
|
+
// Add limit via size parameter
|
|
395
|
+
const params = new URLSearchParams({
|
|
396
|
+
query: xml,
|
|
397
|
+
format: "json",
|
|
398
|
+
size: String(query.limit || 100),
|
|
399
|
+
});
|
|
400
|
+
const url = `${this.allianceMineUrl}/query/results?${params.toString()}`;
|
|
401
|
+
try {
|
|
402
|
+
const response = await this.fetch(url);
|
|
403
|
+
const headers = response.columnHeaders || [];
|
|
404
|
+
const results = response.results.map((row) => {
|
|
405
|
+
const obj = {};
|
|
406
|
+
row.forEach((val, idx) => {
|
|
407
|
+
const key = headers[idx] || `col${idx}`;
|
|
408
|
+
obj[key] = val;
|
|
409
|
+
});
|
|
410
|
+
return obj;
|
|
411
|
+
});
|
|
412
|
+
return {
|
|
413
|
+
results,
|
|
414
|
+
columnHeaders: headers,
|
|
415
|
+
rootClass: response.rootClass,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
throw new Error(`Query failed: ${error}`);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* List available query templates
|
|
424
|
+
*/
|
|
425
|
+
async listTemplates() {
|
|
426
|
+
const url = `${this.allianceMineUrl}/templates?format=json`;
|
|
427
|
+
try {
|
|
428
|
+
const response = await this.fetch(url);
|
|
429
|
+
return Object.entries(response.templates).map(([name, template]) => ({
|
|
430
|
+
...template,
|
|
431
|
+
name,
|
|
432
|
+
}));
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Run a template query with parameters.
|
|
440
|
+
* Parameters should be provided as { "1": { path: "Gene", op: "LOOKUP", value: "BRCA1" } }
|
|
441
|
+
* or simplified as { "1": "BRCA1" } for LOOKUP constraints (path and op inferred from template).
|
|
442
|
+
*/
|
|
443
|
+
async runTemplate(name, params, limit = 100) {
|
|
444
|
+
const queryParams = new URLSearchParams({
|
|
445
|
+
name,
|
|
446
|
+
format: "json",
|
|
447
|
+
size: String(limit),
|
|
448
|
+
});
|
|
449
|
+
// Add template parameters
|
|
450
|
+
for (const [key, param] of Object.entries(params)) {
|
|
451
|
+
if (typeof param === "string") {
|
|
452
|
+
// Simple format: just the value, assume LOOKUP
|
|
453
|
+
queryParams.set(`value${key}`, param);
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
// Full format with path, op, value
|
|
457
|
+
if (param.path)
|
|
458
|
+
queryParams.set(`constraint${key}`, param.path);
|
|
459
|
+
if (param.op)
|
|
460
|
+
queryParams.set(`op${key}`, param.op);
|
|
461
|
+
queryParams.set(`value${key}`, param.value);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
const url = `${this.allianceMineUrl}/template/results?${queryParams.toString()}`;
|
|
465
|
+
try {
|
|
466
|
+
const response = await this.fetch(url);
|
|
467
|
+
const headers = response.columnHeaders || [];
|
|
468
|
+
const results = response.results.map((row) => {
|
|
469
|
+
const obj = {};
|
|
470
|
+
row.forEach((val, idx) => {
|
|
471
|
+
const key = headers[idx] || `col${idx}`;
|
|
472
|
+
obj[key] = val;
|
|
473
|
+
});
|
|
474
|
+
return obj;
|
|
475
|
+
});
|
|
476
|
+
return {
|
|
477
|
+
results,
|
|
478
|
+
columnHeaders: headers,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
throw new Error(`Template query failed: ${error}`);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Get all available lists
|
|
487
|
+
*/
|
|
488
|
+
async getLists(type) {
|
|
489
|
+
const params = new URLSearchParams();
|
|
490
|
+
if (type) {
|
|
491
|
+
params.set("type", type);
|
|
492
|
+
}
|
|
493
|
+
const url = `${this.allianceMineUrl}/lists?${params.toString()}`;
|
|
494
|
+
try {
|
|
495
|
+
const response = await this.fetch(url);
|
|
496
|
+
return response.lists || [];
|
|
497
|
+
}
|
|
498
|
+
catch (error) {
|
|
499
|
+
return [];
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Get contents of a specific list
|
|
504
|
+
*/
|
|
505
|
+
async getList(name) {
|
|
506
|
+
const url = `${this.allianceMineUrl}/list/results/${encodeURIComponent(name)}?format=json`;
|
|
507
|
+
try {
|
|
508
|
+
const response = await this.fetch(url);
|
|
509
|
+
const headers = response.columnHeaders || [];
|
|
510
|
+
const results = response.results.map((row) => {
|
|
511
|
+
const obj = {};
|
|
512
|
+
row.forEach((val, idx) => {
|
|
513
|
+
const key = headers[idx] || `col${idx}`;
|
|
514
|
+
obj[key] = val;
|
|
515
|
+
});
|
|
516
|
+
return obj;
|
|
517
|
+
});
|
|
518
|
+
return {
|
|
519
|
+
name: response.listInfo?.name || name,
|
|
520
|
+
type: response.listInfo?.type || "unknown",
|
|
521
|
+
size: response.listInfo?.size || results.length,
|
|
522
|
+
results,
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Create a new list (requires authentication)
|
|
531
|
+
*/
|
|
532
|
+
async createList(name, type, identifiers, description) {
|
|
533
|
+
const params = new URLSearchParams({
|
|
534
|
+
name,
|
|
535
|
+
type,
|
|
536
|
+
});
|
|
537
|
+
if (description) {
|
|
538
|
+
params.set("description", description);
|
|
539
|
+
}
|
|
540
|
+
const url = `${this.allianceMineUrl}/lists?${params.toString()}`;
|
|
541
|
+
const response = await this.fetchWithAuth(url, {
|
|
542
|
+
method: "POST",
|
|
543
|
+
body: identifiers.join("\n"),
|
|
544
|
+
headers: {
|
|
545
|
+
"Content-Type": "text/plain",
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
return response;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Add items to an existing list (requires authentication)
|
|
552
|
+
*/
|
|
553
|
+
async addToList(name, identifiers) {
|
|
554
|
+
const url = `${this.allianceMineUrl}/lists/append/${encodeURIComponent(name)}`;
|
|
555
|
+
const response = await this.fetchWithAuth(url, {
|
|
556
|
+
method: "POST",
|
|
557
|
+
body: identifiers.join("\n"),
|
|
558
|
+
headers: {
|
|
559
|
+
"Content-Type": "text/plain",
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
return response;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Delete a list (requires authentication)
|
|
566
|
+
*/
|
|
567
|
+
async deleteList(name) {
|
|
568
|
+
const url = `${this.allianceMineUrl}/lists/${encodeURIComponent(name)}`;
|
|
569
|
+
await this.fetchWithAuth(url, {
|
|
570
|
+
method: "DELETE",
|
|
571
|
+
});
|
|
572
|
+
return { success: true };
|
|
573
|
+
}
|
|
241
574
|
}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ENTITY_TYPES } from "./types.js";
|
|
|
7
7
|
const client = new AllianceClient();
|
|
8
8
|
const server = new McpServer({
|
|
9
9
|
name: "agr-genomics",
|
|
10
|
-
version: "
|
|
10
|
+
version: "5.0.2",
|
|
11
11
|
});
|
|
12
12
|
// Tool: Search genes
|
|
13
13
|
server.tool("search_genes", "Search for genes across all Alliance of Genome Resources model organisms. Supports species filtering.", {
|
|
@@ -234,6 +234,444 @@ server.tool("get_species_list", "Get list of model organisms supported by Allian
|
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
236
|
});
|
|
237
|
+
// ============================================
|
|
238
|
+
// AllianceMine Tools
|
|
239
|
+
// ============================================
|
|
240
|
+
// Tool: Mine Search
|
|
241
|
+
server.tool("mine_search", "Search AllianceMine for genes, proteins, diseases, and other biological entities using keyword search.", {
|
|
242
|
+
query: z.string().describe("Search query - keyword, gene symbol, protein name, etc."),
|
|
243
|
+
type: z
|
|
244
|
+
.string()
|
|
245
|
+
.optional()
|
|
246
|
+
.describe("Filter by type: Gene, Protein, Disease, Pathway, etc."),
|
|
247
|
+
limit: z.number().optional().default(20).describe("Maximum results"),
|
|
248
|
+
}, async ({ query, type, limit }) => {
|
|
249
|
+
try {
|
|
250
|
+
const results = await client.searchMine(query, type, limit);
|
|
251
|
+
return {
|
|
252
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
return {
|
|
257
|
+
content: [{ type: "text", text: `Error searching AllianceMine: ${error}` }],
|
|
258
|
+
isError: true,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
// Tool: Mine Query (raw PathQuery XML)
|
|
263
|
+
server.tool("mine_query", "Run a raw PathQuery XML query against AllianceMine. For power users who know InterMine PathQuery syntax.", {
|
|
264
|
+
xml: z.string().describe("PathQuery XML string"),
|
|
265
|
+
}, async ({ xml }) => {
|
|
266
|
+
try {
|
|
267
|
+
const results = await client.runPathQuery(xml);
|
|
268
|
+
return {
|
|
269
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
return {
|
|
274
|
+
content: [{ type: "text", text: `PathQuery error: ${error}` }],
|
|
275
|
+
isError: true,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
// Tool: Mine Query Builder
|
|
280
|
+
server.tool("mine_query_builder", `Build and run structured queries against AllianceMine using a JSON DSL.
|
|
281
|
+
|
|
282
|
+
Example query - find human genes in DNA repair pathway:
|
|
283
|
+
{
|
|
284
|
+
"from": "Gene",
|
|
285
|
+
"select": ["symbol", "name", "organism.name", "pathways.name"],
|
|
286
|
+
"where": {
|
|
287
|
+
"organism.name": "Homo sapiens",
|
|
288
|
+
"pathways.name": { "op": "CONTAINS", "value": "DNA repair" }
|
|
289
|
+
},
|
|
290
|
+
"limit": 50
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
Supported operators: =, !=, CONTAINS, LIKE, <, >, <=, >=, ONE OF, NONE OF, IS NULL, IS NOT NULL`, {
|
|
294
|
+
from: z.string().describe("Root class: Gene, Protein, Disease, Pathway, Phenotype, etc."),
|
|
295
|
+
select: z.array(z.string()).describe("Fields to return, e.g., ['symbol', 'organism.name']"),
|
|
296
|
+
where: z
|
|
297
|
+
.record(z.union([
|
|
298
|
+
z.string(),
|
|
299
|
+
z.object({
|
|
300
|
+
op: z.string(),
|
|
301
|
+
value: z.union([z.string(), z.array(z.string())]),
|
|
302
|
+
}),
|
|
303
|
+
]))
|
|
304
|
+
.optional()
|
|
305
|
+
.describe("Constraints as field: value or field: {op, value}"),
|
|
306
|
+
joins: z.array(z.string()).optional().describe("OUTER JOIN paths for optional relationships"),
|
|
307
|
+
sort: z
|
|
308
|
+
.object({
|
|
309
|
+
field: z.string(),
|
|
310
|
+
direction: z.enum(["ASC", "DESC"]),
|
|
311
|
+
})
|
|
312
|
+
.optional()
|
|
313
|
+
.describe("Sort order"),
|
|
314
|
+
limit: z.number().optional().default(100).describe("Maximum results"),
|
|
315
|
+
}, async ({ from, select, where, joins, sort, limit }) => {
|
|
316
|
+
try {
|
|
317
|
+
const results = await client.buildAndRunQuery({
|
|
318
|
+
from,
|
|
319
|
+
select,
|
|
320
|
+
where: where,
|
|
321
|
+
joins,
|
|
322
|
+
sort,
|
|
323
|
+
limit,
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
return {
|
|
331
|
+
content: [{ type: "text", text: `Query error: ${error}` }],
|
|
332
|
+
isError: true,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
// Tool: Mine Natural Query
|
|
337
|
+
server.tool("mine_natural_query", `Process a natural language query and return schema information to construct a structured AllianceMine query.
|
|
338
|
+
|
|
339
|
+
This tool returns the AllianceMine schema so you can convert the user's natural language into a mine_query_builder call.`, {
|
|
340
|
+
query: z.string().describe("Natural language query describing what to find"),
|
|
341
|
+
limit: z.number().optional().default(100).describe("Maximum results"),
|
|
342
|
+
}, async ({ query, limit }) => {
|
|
343
|
+
// Return comprehensive schema for LLM to construct the query
|
|
344
|
+
const schema = {
|
|
345
|
+
user_query: query,
|
|
346
|
+
requested_limit: limit,
|
|
347
|
+
instruction: "Use mine_query_builder to execute this query. Analyze the user's natural language and construct the appropriate structured query using the schema below.",
|
|
348
|
+
classes: {
|
|
349
|
+
Gene: {
|
|
350
|
+
description: "Genes from all model organisms",
|
|
351
|
+
common_fields: ["primaryIdentifier", "symbol", "name", "description", "secondaryIdentifier"],
|
|
352
|
+
relationships: {
|
|
353
|
+
"organism": "Organism (use organism.shortName or organism.name)",
|
|
354
|
+
"chromosome": "Chromosome (use chromosome.primaryIdentifier)",
|
|
355
|
+
"diseases": "Disease associations",
|
|
356
|
+
"phenotypes": "Phenotype annotations",
|
|
357
|
+
"pathways": "Pathway memberships",
|
|
358
|
+
"alleles": "Gene alleles/variants",
|
|
359
|
+
"goAnnotation": "GO term annotations",
|
|
360
|
+
"homologues": "Ortholog/paralog relationships",
|
|
361
|
+
"proteins": "Encoded proteins",
|
|
362
|
+
"publications": "Related publications"
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
Protein: {
|
|
366
|
+
description: "Protein records",
|
|
367
|
+
common_fields: ["primaryIdentifier", "primaryAccession", "name", "length"],
|
|
368
|
+
relationships: {
|
|
369
|
+
"genes": "Encoding genes",
|
|
370
|
+
"organism": "Source organism",
|
|
371
|
+
"proteinDomains": "Protein domains"
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
Disease: {
|
|
375
|
+
description: "Disease ontology terms (DO)",
|
|
376
|
+
common_fields: ["primaryIdentifier", "name", "description"],
|
|
377
|
+
relationships: {
|
|
378
|
+
"genes": "Associated genes",
|
|
379
|
+
"alleles": "Associated alleles",
|
|
380
|
+
"parents": "Parent terms",
|
|
381
|
+
"children": "Child terms"
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
Pathway: {
|
|
385
|
+
description: "Biological pathways",
|
|
386
|
+
common_fields: ["primaryIdentifier", "name", "description"],
|
|
387
|
+
relationships: {
|
|
388
|
+
"genes": "Genes in pathway",
|
|
389
|
+
"dataSets": "Data sources"
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
Phenotype: {
|
|
393
|
+
description: "Phenotype annotations",
|
|
394
|
+
common_fields: ["primaryIdentifier", "description"],
|
|
395
|
+
relationships: {
|
|
396
|
+
"genes": "Associated genes",
|
|
397
|
+
"alleles": "Associated alleles"
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
Allele: {
|
|
401
|
+
description: "Gene alleles and variants",
|
|
402
|
+
common_fields: ["primaryIdentifier", "symbol", "name", "alleleClass", "description"],
|
|
403
|
+
relationships: {
|
|
404
|
+
"gene": "Parent gene",
|
|
405
|
+
"organism": "Source organism",
|
|
406
|
+
"phenotypes": "Associated phenotypes"
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
GOTerm: {
|
|
410
|
+
description: "Gene Ontology terms",
|
|
411
|
+
common_fields: ["primaryIdentifier", "name", "description", "namespace"],
|
|
412
|
+
relationships: {
|
|
413
|
+
"genes": "Annotated genes",
|
|
414
|
+
"parents": "Parent terms",
|
|
415
|
+
"children": "Child terms"
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
Publication: {
|
|
419
|
+
description: "Scientific publications",
|
|
420
|
+
common_fields: ["primaryIdentifier", "pubMedId", "title", "firstAuthor", "year", "journal"],
|
|
421
|
+
relationships: {
|
|
422
|
+
"genes": "Mentioned genes",
|
|
423
|
+
"authors": "Author list"
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
Organism: {
|
|
427
|
+
description: "Species/organisms",
|
|
428
|
+
common_fields: ["shortName", "name", "taxonId"],
|
|
429
|
+
short_names: {
|
|
430
|
+
"H. sapiens": "Human",
|
|
431
|
+
"M. musculus": "Mouse",
|
|
432
|
+
"R. norvegicus": "Rat",
|
|
433
|
+
"D. rerio": "Zebrafish",
|
|
434
|
+
"D. melanogaster": "Fly",
|
|
435
|
+
"C. elegans": "Worm",
|
|
436
|
+
"S. cerevisiae": "Yeast",
|
|
437
|
+
"X. laevis": "Frog (Xenopus laevis)",
|
|
438
|
+
"X. tropicalis": "Frog (Xenopus tropicalis)"
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
operators: {
|
|
443
|
+
"=": "Exact match",
|
|
444
|
+
"!=": "Not equal",
|
|
445
|
+
"CONTAINS": "Contains substring (case-insensitive)",
|
|
446
|
+
"LIKE": "Pattern match with wildcards (*)",
|
|
447
|
+
"<": "Less than",
|
|
448
|
+
">": "Greater than",
|
|
449
|
+
"<=": "Less than or equal",
|
|
450
|
+
">=": "Greater than or equal",
|
|
451
|
+
"ONE OF": "Match any in list (value should be array)",
|
|
452
|
+
"NONE OF": "Match none in list (value should be array)",
|
|
453
|
+
"IS NULL": "Field is empty",
|
|
454
|
+
"IS NOT NULL": "Field has value"
|
|
455
|
+
},
|
|
456
|
+
query_builder_format: {
|
|
457
|
+
from: "Root class name (e.g., 'Gene')",
|
|
458
|
+
select: "Array of fields to return (e.g., ['primaryIdentifier', 'symbol', 'name'])",
|
|
459
|
+
where: "Object with field constraints (e.g., { 'symbol': { op: 'CONTAINS', value: 'BRCA' } })",
|
|
460
|
+
joins: "Optional: array of paths to OUTER JOIN (for optional relationships)",
|
|
461
|
+
sort: "Optional: { field: 'symbol', direction: 'ASC' }",
|
|
462
|
+
limit: "Optional: max results (default 100)"
|
|
463
|
+
},
|
|
464
|
+
examples: [
|
|
465
|
+
{
|
|
466
|
+
natural: "human genes related to cancer",
|
|
467
|
+
structured: {
|
|
468
|
+
from: "Gene",
|
|
469
|
+
select: ["primaryIdentifier", "symbol", "name", "organism.shortName"],
|
|
470
|
+
where: {
|
|
471
|
+
"organism.shortName": "H. sapiens",
|
|
472
|
+
"name": { op: "CONTAINS", value: "cancer" }
|
|
473
|
+
},
|
|
474
|
+
limit: 100
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
natural: "mouse genes on chromosome 11",
|
|
479
|
+
structured: {
|
|
480
|
+
from: "Gene",
|
|
481
|
+
select: ["primaryIdentifier", "symbol", "name", "chromosome.primaryIdentifier"],
|
|
482
|
+
where: {
|
|
483
|
+
"organism.shortName": "M. musculus",
|
|
484
|
+
"chromosome.primaryIdentifier": "11"
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
natural: "diseases associated with BRCA1",
|
|
490
|
+
structured: {
|
|
491
|
+
from: "Disease",
|
|
492
|
+
select: ["primaryIdentifier", "name", "genes.symbol"],
|
|
493
|
+
where: {
|
|
494
|
+
"genes.symbol": "BRCA1"
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
natural: "all yeast genes with kinase activity",
|
|
500
|
+
structured: {
|
|
501
|
+
from: "Gene",
|
|
502
|
+
select: ["primaryIdentifier", "symbol", "name", "goAnnotation.ontologyTerm.name"],
|
|
503
|
+
where: {
|
|
504
|
+
"organism.shortName": "S. cerevisiae",
|
|
505
|
+
"goAnnotation.ontologyTerm.name": { op: "CONTAINS", value: "kinase" }
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
]
|
|
510
|
+
};
|
|
511
|
+
return {
|
|
512
|
+
content: [
|
|
513
|
+
{
|
|
514
|
+
type: "text",
|
|
515
|
+
text: JSON.stringify(schema, null, 2),
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
};
|
|
519
|
+
});
|
|
520
|
+
// Tool: List Templates
|
|
521
|
+
server.tool("mine_list_templates", "List available query templates in AllianceMine. Templates are pre-built queries for common use cases.", {}, async () => {
|
|
522
|
+
try {
|
|
523
|
+
const templates = await client.listTemplates();
|
|
524
|
+
return {
|
|
525
|
+
content: [{ type: "text", text: JSON.stringify(templates, null, 2) }],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
return {
|
|
530
|
+
content: [{ type: "text", text: `Error listing templates: ${error}` }],
|
|
531
|
+
isError: true,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
// Tool: Run Template
|
|
536
|
+
server.tool("mine_run_template", `Run a pre-built query template with parameters.
|
|
537
|
+
|
|
538
|
+
Parameter format: Use numeric keys ("1", "2", etc.) matching constraint positions.
|
|
539
|
+
- Simple: {"1": "BRCA1"} - just the value
|
|
540
|
+
- Full: {"1": {"path": "Gene", "op": "LOOKUP", "value": "BRCA1"}}
|
|
541
|
+
|
|
542
|
+
Common templates:
|
|
543
|
+
- Gene_Orthologs: Find orthologs (params: {"1": {"path": "Gene", "op": "LOOKUP", "value": "HGNC:1100"}})
|
|
544
|
+
- Gene_GOTerms: GO annotations for a gene
|
|
545
|
+
- Gene_DOTerm: Disease annotations for a gene
|
|
546
|
+
- GOTerm_Genes: Find genes by GO term
|
|
547
|
+
|
|
548
|
+
Use mine_list_templates to discover all available templates and their constraints.`, {
|
|
549
|
+
name: z.string().describe("Template name (e.g., 'Gene_Orthologs')"),
|
|
550
|
+
params: z
|
|
551
|
+
.record(z.union([
|
|
552
|
+
z.string(),
|
|
553
|
+
z.object({
|
|
554
|
+
path: z.string().optional(),
|
|
555
|
+
op: z.string().optional(),
|
|
556
|
+
value: z.string(),
|
|
557
|
+
}),
|
|
558
|
+
]))
|
|
559
|
+
.describe("Template parameters with numeric keys, e.g., {'1': {'path': 'Gene', 'op': 'LOOKUP', 'value': 'HGNC:1100'}}"),
|
|
560
|
+
limit: z.number().optional().default(100).describe("Maximum results"),
|
|
561
|
+
}, async ({ name, params, limit }) => {
|
|
562
|
+
try {
|
|
563
|
+
const results = await client.runTemplate(name, params, limit);
|
|
564
|
+
return {
|
|
565
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
catch (error) {
|
|
569
|
+
return {
|
|
570
|
+
content: [{ type: "text", text: `Template error: ${error}` }],
|
|
571
|
+
isError: true,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
// Tool: Get Lists
|
|
576
|
+
server.tool("mine_get_lists", "Get all available gene/protein lists in AllianceMine.", {
|
|
577
|
+
type: z
|
|
578
|
+
.string()
|
|
579
|
+
.optional()
|
|
580
|
+
.describe("Filter by type: Gene, Protein, etc."),
|
|
581
|
+
}, async ({ type }) => {
|
|
582
|
+
try {
|
|
583
|
+
const lists = await client.getLists(type);
|
|
584
|
+
return {
|
|
585
|
+
content: [{ type: "text", text: JSON.stringify(lists, null, 2) }],
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
return {
|
|
590
|
+
content: [{ type: "text", text: `Error fetching lists: ${error}` }],
|
|
591
|
+
isError: true,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
// Tool: Get List Contents
|
|
596
|
+
server.tool("mine_get_list", "Get the contents of a specific list.", {
|
|
597
|
+
name: z.string().describe("List name"),
|
|
598
|
+
}, async ({ name }) => {
|
|
599
|
+
try {
|
|
600
|
+
const data = await client.getList(name);
|
|
601
|
+
if (!data) {
|
|
602
|
+
return {
|
|
603
|
+
content: [{ type: "text", text: `List not found: ${name}` }],
|
|
604
|
+
isError: true,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
return {
|
|
608
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
catch (error) {
|
|
612
|
+
return {
|
|
613
|
+
content: [{ type: "text", text: `Error fetching list: ${error}` }],
|
|
614
|
+
isError: true,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
// Tool: Create List (requires auth)
|
|
619
|
+
server.tool("mine_create_list", "Create a new list in AllianceMine. Requires ALLIANCEMINE_TOKEN environment variable.", {
|
|
620
|
+
name: z.string().describe("List name"),
|
|
621
|
+
type: z.string().describe("List type: Gene, Protein, etc."),
|
|
622
|
+
identifiers: z
|
|
623
|
+
.array(z.string())
|
|
624
|
+
.describe("Array of identifiers to add to the list"),
|
|
625
|
+
description: z.string().optional().describe("List description"),
|
|
626
|
+
}, async ({ name, type, identifiers, description }) => {
|
|
627
|
+
try {
|
|
628
|
+
const result = await client.createList(name, type, identifiers, description);
|
|
629
|
+
return {
|
|
630
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
return {
|
|
635
|
+
content: [{ type: "text", text: `Error creating list: ${error}` }],
|
|
636
|
+
isError: true,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
// Tool: Add to List (requires auth)
|
|
641
|
+
server.tool("mine_add_to_list", "Add items to an existing list. Requires ALLIANCEMINE_TOKEN environment variable.", {
|
|
642
|
+
name: z.string().describe("List name"),
|
|
643
|
+
identifiers: z.array(z.string()).describe("Identifiers to add"),
|
|
644
|
+
}, async ({ name, identifiers }) => {
|
|
645
|
+
try {
|
|
646
|
+
const result = await client.addToList(name, identifiers);
|
|
647
|
+
return {
|
|
648
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
return {
|
|
653
|
+
content: [{ type: "text", text: `Error adding to list: ${error}` }],
|
|
654
|
+
isError: true,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
// Tool: Delete List (requires auth)
|
|
659
|
+
server.tool("mine_delete_list", "Delete a list from AllianceMine. Requires ALLIANCEMINE_TOKEN environment variable.", {
|
|
660
|
+
name: z.string().describe("List name to delete"),
|
|
661
|
+
}, async ({ name }) => {
|
|
662
|
+
try {
|
|
663
|
+
const result = await client.deleteList(name);
|
|
664
|
+
return {
|
|
665
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
catch (error) {
|
|
669
|
+
return {
|
|
670
|
+
content: [{ type: "text", text: `Error deleting list: ${error}` }],
|
|
671
|
+
isError: true,
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
});
|
|
237
675
|
// Resource: Entity types
|
|
238
676
|
server.resource("entity-types", "agr://entity-types", async () => ({
|
|
239
677
|
contents: [
|
package/dist/types.d.ts
CHANGED
|
@@ -160,6 +160,57 @@ export interface AllianceMineResponse {
|
|
|
160
160
|
totalHits: number;
|
|
161
161
|
facets?: Record<string, unknown>;
|
|
162
162
|
}
|
|
163
|
+
export type QueryOperator = "=" | "!=" | "CONTAINS" | "LIKE" | "<" | ">" | "<=" | ">=" | "ONE OF" | "NONE OF" | "IS NULL" | "IS NOT NULL";
|
|
164
|
+
export interface QueryConstraint {
|
|
165
|
+
op: QueryOperator;
|
|
166
|
+
value: string | string[];
|
|
167
|
+
}
|
|
168
|
+
export interface QuerySort {
|
|
169
|
+
field: string;
|
|
170
|
+
direction: "ASC" | "DESC";
|
|
171
|
+
}
|
|
172
|
+
export interface QueryBuilder {
|
|
173
|
+
from: string;
|
|
174
|
+
select: string[];
|
|
175
|
+
where?: Record<string, string | QueryConstraint>;
|
|
176
|
+
joins?: string[];
|
|
177
|
+
sort?: QuerySort;
|
|
178
|
+
limit?: number;
|
|
179
|
+
}
|
|
180
|
+
export interface PathQueryResult {
|
|
181
|
+
results: Record<string, unknown>[];
|
|
182
|
+
columnHeaders?: string[];
|
|
183
|
+
rootClass?: string;
|
|
184
|
+
}
|
|
185
|
+
export interface MineTemplate {
|
|
186
|
+
name: string;
|
|
187
|
+
title: string;
|
|
188
|
+
description?: string;
|
|
189
|
+
rank?: number;
|
|
190
|
+
constraintLogic?: string;
|
|
191
|
+
constraints?: Record<string, unknown>[];
|
|
192
|
+
}
|
|
193
|
+
export interface TemplateParameter {
|
|
194
|
+
name: string;
|
|
195
|
+
path: string;
|
|
196
|
+
op: string;
|
|
197
|
+
value?: string;
|
|
198
|
+
code?: string;
|
|
199
|
+
}
|
|
200
|
+
export interface MineList {
|
|
201
|
+
name: string;
|
|
202
|
+
type: string;
|
|
203
|
+
size: number;
|
|
204
|
+
description?: string;
|
|
205
|
+
dateCreated?: string;
|
|
206
|
+
authorized?: boolean;
|
|
207
|
+
}
|
|
208
|
+
export interface ListContents {
|
|
209
|
+
name: string;
|
|
210
|
+
type: string;
|
|
211
|
+
size: number;
|
|
212
|
+
results: Record<string, unknown>[];
|
|
213
|
+
}
|
|
163
214
|
export interface APIError {
|
|
164
215
|
status: number;
|
|
165
216
|
message: string;
|