@cyanheads/interpro-mcp-server 0.1.2 → 0.2.0
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/AGENTS.md +39 -14
- package/CLAUDE.md +39 -14
- package/Dockerfile +9 -1
- package/README.md +92 -107
- package/changelog/0.1.x/0.1.3.md +24 -0
- package/changelog/0.2.x/0.2.0.md +31 -0
- package/dist/config/server-config.d.ts +13 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +19 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.d.ts +89 -2
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.js +80 -5
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.d.ts +59 -0
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.js +139 -5
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.d.ts +21 -2
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.js +99 -23
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-get-scan-result.tool.d.ts +133 -0
- package/dist/mcp-server/tools/definitions/interpro-get-scan-result.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-scan-result.tool.js +128 -0
- package/dist/mcp-server/tools/definitions/interpro-get-scan-result.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-structure-domains.tool.d.ts +171 -0
- package/dist/mcp-server/tools/definitions/interpro-get-structure-domains.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-structure-domains.tool.js +290 -0
- package/dist/mcp-server/tools/definitions/interpro-get-structure-domains.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-scan-sequence.tool.d.ts +168 -0
- package/dist/mcp-server/tools/definitions/interpro-scan-sequence.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-scan-sequence.tool.js +187 -0
- package/dist/mcp-server/tools/definitions/interpro-scan-sequence.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.d.ts +6 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.js +11 -2
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.js.map +1 -1
- package/dist/services/interpro/format.d.ts.map +1 -1
- package/dist/services/interpro/format.js +8 -17
- package/dist/services/interpro/format.js.map +1 -1
- package/dist/services/interpro/http-adapter.d.ts +11 -2
- package/dist/services/interpro/http-adapter.d.ts.map +1 -1
- package/dist/services/interpro/http-adapter.js +67 -9
- package/dist/services/interpro/http-adapter.js.map +1 -1
- package/dist/services/interpro/interpro-service.d.ts +1 -1
- package/dist/services/interpro/interpro-service.d.ts.map +1 -1
- package/dist/services/interpro/interpro-service.js +6 -24
- package/dist/services/interpro/interpro-service.js.map +1 -1
- package/dist/services/interpro/reference.d.ts.map +1 -1
- package/dist/services/interpro/reference.js +23 -2
- package/dist/services/interpro/reference.js.map +1 -1
- package/dist/services/interpro/schemas.d.ts +16 -0
- package/dist/services/interpro/schemas.d.ts.map +1 -1
- package/dist/services/interpro/schemas.js +13 -0
- package/dist/services/interpro/schemas.js.map +1 -1
- package/dist/services/interpro/structure-schemas.d.ts +116 -0
- package/dist/services/interpro/structure-schemas.d.ts.map +1 -0
- package/dist/services/interpro/structure-schemas.js +74 -0
- package/dist/services/interpro/structure-schemas.js.map +1 -0
- package/dist/services/sequence-scan/scan-output.d.ts +94 -0
- package/dist/services/sequence-scan/scan-output.d.ts.map +1 -0
- package/dist/services/sequence-scan/scan-output.js +174 -0
- package/dist/services/sequence-scan/scan-output.js.map +1 -0
- package/dist/services/sequence-scan/scan-schemas.d.ts +112 -0
- package/dist/services/sequence-scan/scan-schemas.d.ts.map +1 -0
- package/dist/services/sequence-scan/scan-schemas.js +97 -0
- package/dist/services/sequence-scan/scan-schemas.js.map +1 -0
- package/dist/services/sequence-scan/sequence-scan-service.d.ts +119 -0
- package/dist/services/sequence-scan/sequence-scan-service.d.ts.map +1 -0
- package/dist/services/sequence-scan/sequence-scan-service.js +453 -0
- package/dist/services/sequence-scan/sequence-scan-service.js.map +1 -0
- package/dist/services/sequence-scan/sequence.d.ts +32 -0
- package/dist/services/sequence-scan/sequence.d.ts.map +1 -0
- package/dist/services/sequence-scan/sequence.js +63 -0
- package/dist/services/sequence-scan/sequence.js.map +1 -0
- package/package.json +10 -7
- package/server.json +18 -4
- package/skills/interpro-guide/SKILL.md +72 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview PDB identifier grammar and lossless structure match schemas.
|
|
3
|
+
* @module services/interpro/structure-schemas
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { EntrySummarySchema, JsonValueSchema, LocationSchema } from './schemas.js';
|
|
7
|
+
/** Classic four-character PDB IDs; InterPro answers extended `pdb_0000…` IDs with 404. */
|
|
8
|
+
export const PDB_ID_PATTERN = /^[0-9][A-Za-z0-9]{3}$/;
|
|
9
|
+
/** Chain IDs as InterPro lists them: case-sensitive, one to four letters or digits. */
|
|
10
|
+
export const CHAIN_PATTERN = /^[A-Za-z0-9]{1,4}$/;
|
|
11
|
+
/** Caller-supplied PDB ID, matched case-insensitively and sent lowercase. */
|
|
12
|
+
export const PdbIdSchema = z
|
|
13
|
+
.string()
|
|
14
|
+
.trim()
|
|
15
|
+
.max(4)
|
|
16
|
+
.regex(PDB_ID_PATTERN, 'Expected a four-character PDB ID such as 1tsr.')
|
|
17
|
+
.describe('Four-character PDB ID such as 1tsr; case-insensitive. Extended pdb_0000… IDs are not supported.');
|
|
18
|
+
/** Caller-supplied chain ID, compared exactly against the structure's protein chains. */
|
|
19
|
+
export const ChainSchema = z
|
|
20
|
+
.string()
|
|
21
|
+
.trim()
|
|
22
|
+
.max(4)
|
|
23
|
+
.regex(CHAIN_PATTERN, 'Expected a chain ID of one to four letters or digits.')
|
|
24
|
+
.describe('Case-sensitive PDB chain ID, one to four letters or digits.');
|
|
25
|
+
/** Whether an upstream value is exactly a chain ID, the only form server-written text names it in. */
|
|
26
|
+
export const isChain = (value) => typeof value === 'string' && CHAIN_PATTERN.test(value);
|
|
27
|
+
/** Structure detail metadata: `chains` lists protein chains only; other fields are retained. */
|
|
28
|
+
export const StructureMetadataSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
accession: z.string().describe('Lowercase PDB ID.'),
|
|
31
|
+
source_database: z.string().describe('Structure source database.'),
|
|
32
|
+
chains: z
|
|
33
|
+
.array(z.string().describe('Protein chain ID.'))
|
|
34
|
+
.describe('Protein chain IDs; nucleic-acid chains are not listed.'),
|
|
35
|
+
})
|
|
36
|
+
.catchall(JsonValueSchema)
|
|
37
|
+
.describe('Complete upstream structure metadata.');
|
|
38
|
+
/**
|
|
39
|
+
* One upstream chain record of a structure match. `entry_structure_locations` fragments carry
|
|
40
|
+
* 1-based chain `start`/`end` beside author `auth_start`/`auth_end`, which may be null; the
|
|
41
|
+
* UniProt `protein`, its residue maps, and both protein-side location arrays may be null or empty.
|
|
42
|
+
*/
|
|
43
|
+
export const StructureRecordSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
accession: z.string().describe('Lowercase PDB ID.'),
|
|
46
|
+
chain: z.string().describe('Case-sensitive chain ID.'),
|
|
47
|
+
protein: z
|
|
48
|
+
.string()
|
|
49
|
+
.nullable()
|
|
50
|
+
.describe('Lowercase UniProt accession mapped to the chain; null when unmapped.'),
|
|
51
|
+
entry_structure_locations: z
|
|
52
|
+
.array(LocationSchema)
|
|
53
|
+
.describe('Match locations in chain numbering: start/end are 1-based chain positions; auth_start/auth_end are author residue numbers, possibly null.'),
|
|
54
|
+
entry_protein_locations: z
|
|
55
|
+
.array(LocationSchema)
|
|
56
|
+
.nullable()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Match locations in UniProt numbering; null or empty without a usable mapping.'),
|
|
59
|
+
structure_protein_locations: z
|
|
60
|
+
.array(LocationSchema)
|
|
61
|
+
.nullable()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Chain-to-UniProt residue maps: start/end in chain numbering, protein_start/protein_end in UniProt numbering.'),
|
|
64
|
+
})
|
|
65
|
+
.catchall(JsonValueSchema)
|
|
66
|
+
.describe('Complete upstream chain record.');
|
|
67
|
+
/** Upstream structure match row: entry metadata plus at most 20 nested chain records. */
|
|
68
|
+
export const StructureMatchSchema = z
|
|
69
|
+
.object({
|
|
70
|
+
metadata: EntrySummarySchema.describe('Entry metadata.'),
|
|
71
|
+
structures: z.array(StructureRecordSchema).describe('Nested chain records.'),
|
|
72
|
+
})
|
|
73
|
+
.catchall(JsonValueSchema);
|
|
74
|
+
//# sourceMappingURL=structure-schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure-schemas.js","sourceRoot":"","sources":["../../../src/services/interpro/structure-schemas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,cAAc,GAAG,uBAAuB,CAAC;AACtD,uFAAuF;AACvF,MAAM,CAAC,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAClD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC;KACzB,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,CAAC;KACN,KAAK,CAAC,cAAc,EAAE,gDAAgD,CAAC;KACvE,QAAQ,CACP,iGAAiG,CAClG,CAAC;AACJ,yFAAyF;AACzF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC;KACzB,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,CAAC;KACN,KAAK,CAAC,aAAa,EAAE,uDAAuD,CAAC;KAC7E,QAAQ,CAAC,6DAA6D,CAAC,CAAC;AAC3E,sGAAsG;AACtG,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAc,EAAmB,EAAE,CACzD,OAAO,KAAK,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzD,gGAAgG;AAChG,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC;KACrC,MAAM,CAAC;IACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IACnD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;IAClE,MAAM,EAAE,CAAC;SACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;SAC/C,QAAQ,CAAC,wDAAwD,CAAC;CACtE,CAAC;KACD,QAAQ,CAAC,eAAe,CAAC;KACzB,QAAQ,CAAC,uCAAuC,CAAC,CAAC;AACrD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IACnD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACtD,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,sEAAsE,CAAC;IACnF,yBAAyB,EAAE,CAAC;SACzB,KAAK,CAAC,cAAc,CAAC;SACrB,QAAQ,CACP,2IAA2I,CAC5I;IACH,uBAAuB,EAAE,CAAC;SACvB,KAAK,CAAC,cAAc,CAAC;SACrB,QAAQ,EAAE;SACV,QAAQ,EAAE;SACV,QAAQ,CAAC,+EAA+E,CAAC;IAC5F,2BAA2B,EAAE,CAAC;SAC3B,KAAK,CAAC,cAAc,CAAC;SACrB,QAAQ,EAAE;SACV,QAAQ,EAAE;SACV,QAAQ,CACP,8GAA8G,CAC/G;CACJ,CAAC;KACD,QAAQ,CAAC,eAAe,CAAC;KACzB,QAAQ,CAAC,iCAAiC,CAAC,CAAC;AAC/C,yFAAyF;AACzF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,QAAQ,EAAE,kBAAkB,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IACxD,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;CAC7E,CAAC;KACD,QAAQ,CAAC,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Output schema and budget-bounded segments of whole match records shared by the
|
|
3
|
+
* scan and scan-result tools, with cursors scoped to the sequence MD5 or the job ID.
|
|
4
|
+
* @module services/sequence-scan/scan-output
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import type { ScanOutcome } from './sequence-scan-service.js';
|
|
8
|
+
declare const PositionSchema: z.ZodObject<{
|
|
9
|
+
offset: z.ZodNumber;
|
|
10
|
+
total: z.ZodNumber;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
type Position = z.infer<typeof PositionSchema>;
|
|
13
|
+
/** Output fields both tools return. */
|
|
14
|
+
export declare const ScanOutputSchema: z.ZodObject<{
|
|
15
|
+
source: z.ZodEnum<{
|
|
16
|
+
interproscan: "interproscan";
|
|
17
|
+
precalculated: "precalculated";
|
|
18
|
+
}>;
|
|
19
|
+
status: z.ZodEnum<{
|
|
20
|
+
finished: "finished";
|
|
21
|
+
queued: "queued";
|
|
22
|
+
running: "running";
|
|
23
|
+
submitted: "submitted";
|
|
24
|
+
}>;
|
|
25
|
+
jobId: z.ZodOptional<z.ZodString>;
|
|
26
|
+
md5: z.ZodOptional<z.ZodString>;
|
|
27
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
interproVersion: z.ZodOptional<z.ZodString>;
|
|
29
|
+
interproscanVersion: z.ZodOptional<z.ZodString>;
|
|
30
|
+
matches: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
31
|
+
signature: z.ZodObject<{
|
|
32
|
+
accession: z.ZodString;
|
|
33
|
+
signatureLibraryRelease: z.ZodObject<{
|
|
34
|
+
library: z.ZodString;
|
|
35
|
+
version: z.ZodString;
|
|
36
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
37
|
+
entry: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
38
|
+
accession: z.ZodString;
|
|
39
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>>;
|
|
40
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
41
|
+
'model-ac': z.ZodNullable<z.ZodString>;
|
|
42
|
+
source: z.ZodString;
|
|
43
|
+
locations: z.ZodArray<z.ZodObject<{
|
|
44
|
+
start: z.ZodNumber;
|
|
45
|
+
end: z.ZodNumber;
|
|
46
|
+
'location-fragments': z.ZodArray<z.ZodObject<{
|
|
47
|
+
start: z.ZodNumber;
|
|
48
|
+
end: z.ZodNumber;
|
|
49
|
+
'dc-status': z.ZodString;
|
|
50
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
51
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
52
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>>;
|
|
53
|
+
coverage: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
totalMatches: z.ZodNumber;
|
|
55
|
+
offset: z.ZodNumber;
|
|
56
|
+
returnedMatches: z.ZodNumber;
|
|
57
|
+
hasMore: z.ZodBoolean;
|
|
58
|
+
nextCursor: z.ZodOptional<z.ZodString>;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
sourceUrl: z.ZodString;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
export type ScanOutput = z.infer<typeof ScanOutputSchema>;
|
|
63
|
+
/** Enrichment fields both tools declare. */
|
|
64
|
+
export declare const ScanEnrichment: {
|
|
65
|
+
notice: z.ZodOptional<z.ZodString>;
|
|
66
|
+
totalCount: z.ZodOptional<z.ZodNumber>;
|
|
67
|
+
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
68
|
+
shown: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
};
|
|
70
|
+
/** Decode a continuation for the given target before any upstream request. */
|
|
71
|
+
export declare function decodeScanCursor(cursor: string | undefined, target: {
|
|
72
|
+
readonly md5: string;
|
|
73
|
+
} | {
|
|
74
|
+
readonly jobId: string;
|
|
75
|
+
}): Position | undefined;
|
|
76
|
+
interface Enrich {
|
|
77
|
+
notice(text: string): void;
|
|
78
|
+
total(count: number): void;
|
|
79
|
+
truncated(details: {
|
|
80
|
+
shown: number;
|
|
81
|
+
}): void;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build one segment of a finished result, or the pending output, and the notices that go with
|
|
85
|
+
* it. `continuation` names the call that reads the next segment, as the agent should make it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function buildScanOutput(enrich: Enrich, state: ScanOutcome, options: {
|
|
88
|
+
readonly md5?: string;
|
|
89
|
+
readonly length?: number;
|
|
90
|
+
readonly start?: Position;
|
|
91
|
+
readonly continuation: (cursor: string) => string;
|
|
92
|
+
}): ScanOutput;
|
|
93
|
+
export {};
|
|
94
|
+
//# sourceMappingURL=scan-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-output.d.ts","sourceRoot":"","sources":["../../../src/services/sequence-scan/scan-output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAS3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAI9D,QAAA,MAAM,cAAc;;;kBAET,CAAC;AACZ,KAAK,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE/C,uCAAuC;AACvC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiD3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,4CAA4C;AAC5C,eAAO,MAAM,cAAc;IACzB,MAAM;IACN,UAAU;IACV,SAAS;IACT,KAAK;CACN,CAAC;AAOF,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D,QAAQ,GAAG,SAAS,CAItB;AAsBD,UAAU,MAAM;IACd,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE;IACP,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD,GACA,UAAU,CAwFZ"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Output schema and budget-bounded segments of whole match records shared by the
|
|
3
|
+
* scan and scan-result tools, with cursors scoped to the sequence MD5 or the job ID.
|
|
4
|
+
* @module services/sequence-scan/scan-output
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import { validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
8
|
+
import { BUDGET_LABEL, fitWithinBudget } from '../interpro/budget.js';
|
|
9
|
+
import { compareText, decodePositionCursor, encodePositionCursor, } from '../interpro/cursors.js';
|
|
10
|
+
import { ScanMatchSchema } from './scan-schemas.js';
|
|
11
|
+
const PRECALCULATED_OPERATION = 'interpro_scan_sequence.precalculated';
|
|
12
|
+
const JOB_OPERATION = 'interpro_get_scan_result.job';
|
|
13
|
+
const PositionSchema = z
|
|
14
|
+
.object({ offset: z.number().int().positive(), total: z.number().int().positive() })
|
|
15
|
+
.strict();
|
|
16
|
+
/** Output fields both tools return. */
|
|
17
|
+
export const ScanOutputSchema = z.object({
|
|
18
|
+
source: z
|
|
19
|
+
.enum(['precalculated', 'interproscan'])
|
|
20
|
+
.describe('Which path produced the result: precalculated matches from the InterPro Matches API, or an InterProScan 6 job run through the EBI Job Dispatcher.'),
|
|
21
|
+
status: z
|
|
22
|
+
.enum(['finished', 'queued', 'running', 'submitted'])
|
|
23
|
+
.describe('finished: matches are present. queued or running: the job is pending; read it later with interpro_get_scan_result. submitted: accepted in this call and not yet polled.'),
|
|
24
|
+
jobId: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('InterProScan job ID on the interproscan path; results stay retrievable for seven days.'),
|
|
28
|
+
md5: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Uppercase hex MD5 of the uppercased residues, the UniParc sequence digest.'),
|
|
32
|
+
length: z.number().int().optional().describe('Sequence length in residues.'),
|
|
33
|
+
interproVersion: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('InterPro release of a finished InterProScan job.'),
|
|
37
|
+
interproscanVersion: z.string().optional().describe('InterProScan version of a finished job.'),
|
|
38
|
+
matches: z
|
|
39
|
+
.array(ScanMatchSchema)
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Whole match records in this segment when finished, sorted by earliest location start then signature accession; coordinates are 1-based and inclusive. Each record keeps its own source and signatureLibraryRelease.'),
|
|
42
|
+
coverage: z
|
|
43
|
+
.object({
|
|
44
|
+
totalMatches: z.number().int().describe('Match records in the complete result.'),
|
|
45
|
+
offset: z.number().int().describe('Match records that precede this segment.'),
|
|
46
|
+
returnedMatches: z.number().int().describe('Match records in this segment.'),
|
|
47
|
+
hasMore: z.boolean().describe('Whether another segment remains.'),
|
|
48
|
+
nextCursor: z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Opaque cursor for the next segment; pass it unchanged to the tool the notice names.'),
|
|
52
|
+
})
|
|
53
|
+
.optional()
|
|
54
|
+
.describe('Where this segment sits in the complete match list; present when finished.'),
|
|
55
|
+
sourceUrl: z.string().describe('Upstream endpoint that supplied this result.'),
|
|
56
|
+
});
|
|
57
|
+
/** Enrichment fields both tools declare. */
|
|
58
|
+
export const ScanEnrichment = {
|
|
59
|
+
notice: z.string().optional().describe('Job, continuation, or empty-result guidance.'),
|
|
60
|
+
totalCount: z.number().optional().describe('Match records in the complete result.'),
|
|
61
|
+
truncated: z.boolean().optional().describe('More segments remain.'),
|
|
62
|
+
shown: z.number().int().optional().describe('Match records in this segment.'),
|
|
63
|
+
};
|
|
64
|
+
const cursorTarget = (state, md5) => state.source === 'precalculated'
|
|
65
|
+
? { operation: PRECALCULATED_OPERATION, scope: { md5 } }
|
|
66
|
+
: { operation: JOB_OPERATION, scope: { jobId: state.jobId } };
|
|
67
|
+
/** Decode a continuation for the given target before any upstream request. */
|
|
68
|
+
export function decodeScanCursor(cursor, target) {
|
|
69
|
+
return 'md5' in target
|
|
70
|
+
? decodePositionCursor(cursor, PRECALCULATED_OPERATION, { md5: target.md5 }, PositionSchema)
|
|
71
|
+
: decodePositionCursor(cursor, JOB_OPERATION, { jobId: target.jobId }, PositionSchema);
|
|
72
|
+
}
|
|
73
|
+
function minStart(match) {
|
|
74
|
+
let start = Number.POSITIVE_INFINITY;
|
|
75
|
+
for (const location of match.locations)
|
|
76
|
+
start = Math.min(start, location.start);
|
|
77
|
+
return start;
|
|
78
|
+
}
|
|
79
|
+
/** Deterministic order, so a cursor offset names the same record on every read. */
|
|
80
|
+
function sortMatches(matches) {
|
|
81
|
+
return matches
|
|
82
|
+
.map((match) => ({ match, start: minStart(match), json: JSON.stringify(match) }))
|
|
83
|
+
.sort((a, b) => a.start - b.start ||
|
|
84
|
+
compareText(a.match.signature.accession, b.match.signature.accession) ||
|
|
85
|
+
compareText(a.match.source, b.match.source) ||
|
|
86
|
+
compareText(a.json, b.json))
|
|
87
|
+
.map(({ match }) => match);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build one segment of a finished result, or the pending output, and the notices that go with
|
|
91
|
+
* it. `continuation` names the call that reads the next segment, as the agent should make it.
|
|
92
|
+
*/
|
|
93
|
+
export function buildScanOutput(enrich, state, options) {
|
|
94
|
+
const base = {
|
|
95
|
+
source: state.source,
|
|
96
|
+
...(state.source === 'interproscan' ? { jobId: state.jobId } : {}),
|
|
97
|
+
};
|
|
98
|
+
if (state.source === 'interproscan' && state.status !== 'FINISHED') {
|
|
99
|
+
const status = state.status === 'submitted' ? 'submitted' : state.status === 'QUEUED' ? 'queued' : 'running';
|
|
100
|
+
enrich.notice(`InterProScan job ${state.jobId} is ${status}; de novo scans commonly take about ten minutes. Call interpro_get_scan_result ${JSON.stringify({ jobId: state.jobId })} to wait for it. Results stay retrievable for seven days.`);
|
|
101
|
+
return {
|
|
102
|
+
...base,
|
|
103
|
+
status,
|
|
104
|
+
...(options.md5 ? { md5: options.md5 } : {}),
|
|
105
|
+
...(options.length ? { length: options.length } : {}),
|
|
106
|
+
sourceUrl: state.sourceUrl,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const finished = state.source === 'precalculated'
|
|
110
|
+
? { matches: state.matches, md5: options.md5, length: options.length }
|
|
111
|
+
: {
|
|
112
|
+
matches: state.result.matches,
|
|
113
|
+
md5: state.result.md5,
|
|
114
|
+
length: state.result.length,
|
|
115
|
+
interproVersion: state.result.interproVersion,
|
|
116
|
+
interproscanVersion: state.result.interproscanVersion,
|
|
117
|
+
};
|
|
118
|
+
const all = sortMatches(finished.matches);
|
|
119
|
+
const total = all.length;
|
|
120
|
+
const offset = options.start?.offset ?? 0;
|
|
121
|
+
if (options.start && (options.start.total !== total || offset >= total))
|
|
122
|
+
throw validationError('Cursor no longer matches this result; restart without cursor.', {
|
|
123
|
+
reason: 'invalid_cursor',
|
|
124
|
+
retryable: false,
|
|
125
|
+
});
|
|
126
|
+
const { operation, scope } = cursorTarget(state, finished.md5);
|
|
127
|
+
const remaining = total - offset;
|
|
128
|
+
const segment = (count) => {
|
|
129
|
+
const end = offset + count;
|
|
130
|
+
return {
|
|
131
|
+
...base,
|
|
132
|
+
status: 'finished',
|
|
133
|
+
...(finished.md5 ? { md5: finished.md5 } : {}),
|
|
134
|
+
...(finished.length ? { length: finished.length } : {}),
|
|
135
|
+
...('interproVersion' in finished
|
|
136
|
+
? {
|
|
137
|
+
interproVersion: finished.interproVersion,
|
|
138
|
+
interproscanVersion: finished.interproscanVersion,
|
|
139
|
+
}
|
|
140
|
+
: {}),
|
|
141
|
+
matches: all.slice(offset, end),
|
|
142
|
+
coverage: {
|
|
143
|
+
totalMatches: total,
|
|
144
|
+
offset,
|
|
145
|
+
returnedMatches: count,
|
|
146
|
+
hasMore: end < total,
|
|
147
|
+
...(end < total
|
|
148
|
+
? { nextCursor: encodePositionCursor(operation, scope, { offset: end, total }) }
|
|
149
|
+
: {}),
|
|
150
|
+
},
|
|
151
|
+
sourceUrl: state.sourceUrl,
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
const { count, output, oversized } = remaining
|
|
155
|
+
? fitWithinBudget(remaining, segment)
|
|
156
|
+
: { count: 0, output: segment(0), oversized: false };
|
|
157
|
+
const notices = [];
|
|
158
|
+
if (oversized)
|
|
159
|
+
notices.push(`Match ${all[offset]?.signature.accession} cannot be split, so this segment holds it alone and exceeds the ${BUDGET_LABEL}.`);
|
|
160
|
+
const next = output.coverage?.nextCursor;
|
|
161
|
+
if (next) {
|
|
162
|
+
notices.push(`This segment holds matches ${offset + 1}–${offset + count} of ${total} and stopped at the ${BUDGET_LABEL}. Continue with ${options.continuation(next)} before concluding a region has no match.`);
|
|
163
|
+
enrich.truncated({ shown: count });
|
|
164
|
+
}
|
|
165
|
+
else if (!total)
|
|
166
|
+
notices.push(state.source === 'precalculated'
|
|
167
|
+
? 'The InterPro Matches API holds a precalculated result for this sequence with no signature matches.'
|
|
168
|
+
: 'InterProScan finished and reported no signature matches for this sequence.');
|
|
169
|
+
enrich.total(total);
|
|
170
|
+
if (notices.length)
|
|
171
|
+
enrich.notice(notices.join(' '));
|
|
172
|
+
return output;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=scan-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-output.js","sourceRoot":"","sources":["../../../src/services/sequence-scan/scan-output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wire and output schemas for InterProScan match records, Matches API lookups, and
|
|
3
|
+
* Job Dispatcher iprscan6 jobs. Match records pass through verbatim, unknown fields included.
|
|
4
|
+
* @module services/sequence-scan/scan-schemas
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
/**
|
|
8
|
+
* Job Dispatcher iprscan6 job identifier, e.g. `iprscan6-R20261028-131532-0930-13189043-p1m`:
|
|
9
|
+
* submission channel letter and date, time, two numeric fields, then a short host suffix. The
|
|
10
|
+
* channel letter and suffix are kept open beyond the observed `R` and `p1m`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const JOB_ID_PATTERN: RegExp;
|
|
13
|
+
/** Longest job identifier the pattern admits, so the input bound and the grammar agree. */
|
|
14
|
+
export declare const MAX_JOB_ID_CHARS = 64;
|
|
15
|
+
/** Job Dispatcher `status` vocabulary; NOT_FOUND arrives as HTTP 200 for unknown and expired IDs. */
|
|
16
|
+
export declare const JobStatusSchema: z.ZodEnum<{
|
|
17
|
+
ERROR: "ERROR";
|
|
18
|
+
FAILURE: "FAILURE";
|
|
19
|
+
FINISHED: "FINISHED";
|
|
20
|
+
NOT_FOUND: "NOT_FOUND";
|
|
21
|
+
QUEUED: "QUEUED";
|
|
22
|
+
RUNNING: "RUNNING";
|
|
23
|
+
}>;
|
|
24
|
+
export type JobStatus = z.infer<typeof JobStatusSchema>;
|
|
25
|
+
/** One InterProScan match record, the shape the Matches API and iprscan6 JSON share. */
|
|
26
|
+
export declare const ScanMatchSchema: z.ZodObject<{
|
|
27
|
+
signature: z.ZodObject<{
|
|
28
|
+
accession: z.ZodString;
|
|
29
|
+
signatureLibraryRelease: z.ZodObject<{
|
|
30
|
+
library: z.ZodString;
|
|
31
|
+
version: z.ZodString;
|
|
32
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
33
|
+
entry: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
34
|
+
accession: z.ZodString;
|
|
35
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>>;
|
|
36
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
37
|
+
'model-ac': z.ZodNullable<z.ZodString>;
|
|
38
|
+
source: z.ZodString;
|
|
39
|
+
locations: z.ZodArray<z.ZodObject<{
|
|
40
|
+
start: z.ZodNumber;
|
|
41
|
+
end: z.ZodNumber;
|
|
42
|
+
'location-fragments': z.ZodArray<z.ZodObject<{
|
|
43
|
+
start: z.ZodNumber;
|
|
44
|
+
end: z.ZodNumber;
|
|
45
|
+
'dc-status': z.ZodString;
|
|
46
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
47
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
48
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
49
|
+
export type ScanMatch = z.infer<typeof ScanMatchSchema>;
|
|
50
|
+
/** `POST /interpro/matches/api/matches` response for one MD5. */
|
|
51
|
+
export declare const MatchesLookupSchema: z.ZodObject<{
|
|
52
|
+
results: z.ZodArray<z.ZodObject<{
|
|
53
|
+
md5: z.ZodString;
|
|
54
|
+
found: z.ZodBoolean;
|
|
55
|
+
matches: z.ZodArray<z.ZodObject<{
|
|
56
|
+
signature: z.ZodObject<{
|
|
57
|
+
accession: z.ZodString;
|
|
58
|
+
signatureLibraryRelease: z.ZodObject<{
|
|
59
|
+
library: z.ZodString;
|
|
60
|
+
version: z.ZodString;
|
|
61
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
62
|
+
entry: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
63
|
+
accession: z.ZodString;
|
|
64
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>>;
|
|
65
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
66
|
+
'model-ac': z.ZodNullable<z.ZodString>;
|
|
67
|
+
source: z.ZodString;
|
|
68
|
+
locations: z.ZodArray<z.ZodObject<{
|
|
69
|
+
start: z.ZodNumber;
|
|
70
|
+
end: z.ZodNumber;
|
|
71
|
+
'location-fragments': z.ZodArray<z.ZodObject<{
|
|
72
|
+
start: z.ZodNumber;
|
|
73
|
+
end: z.ZodNumber;
|
|
74
|
+
'dc-status': z.ZodString;
|
|
75
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
76
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
77
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
78
|
+
}, z.core.$strip>>;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
/** `result/{jobId}/json` body for a single-sequence iprscan6 job. */
|
|
81
|
+
export declare const ScanResultSchema: z.ZodObject<{
|
|
82
|
+
'interproscan-version': z.ZodString;
|
|
83
|
+
'interpro-version': z.ZodString;
|
|
84
|
+
results: z.ZodArray<z.ZodObject<{
|
|
85
|
+
md5: z.ZodString;
|
|
86
|
+
sequence: z.ZodString;
|
|
87
|
+
matches: z.ZodArray<z.ZodObject<{
|
|
88
|
+
signature: z.ZodObject<{
|
|
89
|
+
accession: z.ZodString;
|
|
90
|
+
signatureLibraryRelease: z.ZodObject<{
|
|
91
|
+
library: z.ZodString;
|
|
92
|
+
version: z.ZodString;
|
|
93
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
94
|
+
entry: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
95
|
+
accession: z.ZodString;
|
|
96
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>>;
|
|
97
|
+
}, z.core.$catchall<z.ZodJSONSchema>>;
|
|
98
|
+
'model-ac': z.ZodNullable<z.ZodString>;
|
|
99
|
+
source: z.ZodString;
|
|
100
|
+
locations: z.ZodArray<z.ZodObject<{
|
|
101
|
+
start: z.ZodNumber;
|
|
102
|
+
end: z.ZodNumber;
|
|
103
|
+
'location-fragments': z.ZodArray<z.ZodObject<{
|
|
104
|
+
start: z.ZodNumber;
|
|
105
|
+
end: z.ZodNumber;
|
|
106
|
+
'dc-status': z.ZodString;
|
|
107
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
108
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
109
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
110
|
+
}, z.core.$catchall<z.ZodJSONSchema>>>;
|
|
111
|
+
}, z.core.$strip>;
|
|
112
|
+
//# sourceMappingURL=scan-schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-schemas.d.ts","sourceRoot":"","sources":["../../../src/services/sequence-scan/scan-schemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAA6D,CAAC;AACzF,2FAA2F;AAC3F,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,qGAAqG;AACrG,eAAO,MAAM,eAAe;;;;;;;EAO1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AA2BxD,wFAAwF;AACxF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;qCAkC2B,CAAC;AACxD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxD,iEAAiE;AACjE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI9B,CAAC;AAEH,qEAAqE;AACrE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAU3B,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wire and output schemas for InterProScan match records, Matches API lookups, and
|
|
3
|
+
* Job Dispatcher iprscan6 jobs. Match records pass through verbatim, unknown fields included.
|
|
4
|
+
* @module services/sequence-scan/scan-schemas
|
|
5
|
+
*/
|
|
6
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
7
|
+
import { JsonValueSchema } from '../interpro/schemas.js';
|
|
8
|
+
/**
|
|
9
|
+
* Job Dispatcher iprscan6 job identifier, e.g. `iprscan6-R20261028-131532-0930-13189043-p1m`:
|
|
10
|
+
* submission channel letter and date, time, two numeric fields, then a short host suffix. The
|
|
11
|
+
* channel letter and suffix are kept open beyond the observed `R` and `p1m`.
|
|
12
|
+
*/
|
|
13
|
+
export const JOB_ID_PATTERN = /^iprscan6-[A-Z]\d{8}-\d{6}-\d{4}-\d{1,12}-[a-z0-9]{1,8}$/;
|
|
14
|
+
/** Longest job identifier the pattern admits, so the input bound and the grammar agree. */
|
|
15
|
+
export const MAX_JOB_ID_CHARS = 64;
|
|
16
|
+
/** Job Dispatcher `status` vocabulary; NOT_FOUND arrives as HTTP 200 for unknown and expired IDs. */
|
|
17
|
+
export const JobStatusSchema = z.enum([
|
|
18
|
+
'QUEUED',
|
|
19
|
+
'RUNNING',
|
|
20
|
+
'FINISHED',
|
|
21
|
+
'ERROR',
|
|
22
|
+
'FAILURE',
|
|
23
|
+
'NOT_FOUND',
|
|
24
|
+
]);
|
|
25
|
+
const ScanFragmentSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
start: z.number().int().positive().describe('Inclusive 1-based start residue.'),
|
|
28
|
+
end: z.number().int().positive().describe('Inclusive 1-based end residue.'),
|
|
29
|
+
'dc-status': z
|
|
30
|
+
.string()
|
|
31
|
+
.describe('Discontinuity status, such as CONTINUOUS, N_TERMINAL_DISC, or C_TERMINAL_DISC.'),
|
|
32
|
+
})
|
|
33
|
+
.catchall(JsonValueSchema)
|
|
34
|
+
.describe('One continuous piece of a possibly discontinuous match location.');
|
|
35
|
+
const ScanLocationSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
start: z.number().int().positive().describe('Inclusive 1-based start residue.'),
|
|
38
|
+
end: z.number().int().positive().describe('Inclusive 1-based end residue.'),
|
|
39
|
+
'location-fragments': z
|
|
40
|
+
.array(ScanFragmentSchema)
|
|
41
|
+
.min(1)
|
|
42
|
+
.describe('Nonempty fragments of this location.'),
|
|
43
|
+
})
|
|
44
|
+
.catchall(JsonValueSchema)
|
|
45
|
+
.describe('One match location with every upstream field, such as scores, e-values, HMM bounds, envelope, sites, and alignments.');
|
|
46
|
+
/** One InterProScan match record, the shape the Matches API and iprscan6 JSON share. */
|
|
47
|
+
export const ScanMatchSchema = z
|
|
48
|
+
.object({
|
|
49
|
+
signature: z
|
|
50
|
+
.object({
|
|
51
|
+
accession: z.string().describe('Member-database signature accession, such as PF13499.'),
|
|
52
|
+
signatureLibraryRelease: z
|
|
53
|
+
.object({
|
|
54
|
+
library: z
|
|
55
|
+
.string()
|
|
56
|
+
.describe('Member database name exactly as the source spells it, such as Pfam.'),
|
|
57
|
+
version: z.string().describe('Member database release that produced this match.'),
|
|
58
|
+
})
|
|
59
|
+
.catchall(JsonValueSchema)
|
|
60
|
+
.describe('Library and release of this signature.'),
|
|
61
|
+
entry: z
|
|
62
|
+
.object({
|
|
63
|
+
accession: z.string().describe('Integrated InterPro entry accession.'),
|
|
64
|
+
})
|
|
65
|
+
.catchall(JsonValueSchema)
|
|
66
|
+
.nullable()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe('InterPro entry the signature is integrated into; null when unintegrated.'),
|
|
69
|
+
})
|
|
70
|
+
.catchall(JsonValueSchema)
|
|
71
|
+
.describe('Matched signature, including name, description, and type when supplied.'),
|
|
72
|
+
'model-ac': z.string().nullable().describe('Model accession within the signature.'),
|
|
73
|
+
source: z
|
|
74
|
+
.string()
|
|
75
|
+
.describe('Method that produced the match, such as Pfam or InterPro-N, exactly as the source spells it.'),
|
|
76
|
+
locations: z.array(ScanLocationSchema).describe('Match locations on the sequence.'),
|
|
77
|
+
})
|
|
78
|
+
.catchall(JsonValueSchema)
|
|
79
|
+
.describe('One InterProScan match record, verbatim.');
|
|
80
|
+
const Md5Schema = z.string().regex(/^[0-9a-fA-F]{32}$/);
|
|
81
|
+
/** `POST /interpro/matches/api/matches` response for one MD5. */
|
|
82
|
+
export const MatchesLookupSchema = z.object({
|
|
83
|
+
results: z
|
|
84
|
+
.array(z.object({ md5: Md5Schema, found: z.boolean(), matches: z.array(ScanMatchSchema) }))
|
|
85
|
+
.length(1),
|
|
86
|
+
});
|
|
87
|
+
/** `result/{jobId}/json` body for a single-sequence iprscan6 job. */
|
|
88
|
+
export const ScanResultSchema = z.object({
|
|
89
|
+
'interproscan-version': z.string(),
|
|
90
|
+
'interpro-version': z.string(),
|
|
91
|
+
results: z
|
|
92
|
+
.array(z
|
|
93
|
+
.object({ md5: Md5Schema, sequence: z.string(), matches: z.array(ScanMatchSchema) })
|
|
94
|
+
.catchall(JsonValueSchema))
|
|
95
|
+
.length(1),
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=scan-schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-schemas.js","sourceRoot":"","sources":["../../../src/services/sequence-scan/scan-schemas.ts"],"names":[],"mappings":"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"}
|