@czi-sds/mcp 0.19.0 → 0.20.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.
@@ -24,12 +24,13 @@ The viewer fills its parent. Mol\* sizes its canvas from the laid-out container,
24
24
 
25
25
  ### **Default ProteinStructureViewer**
26
26
 
27
- Raw PDB text is the only required prop. Supplying per-residue `plddt` scores on a 0-1 scale colors the structure by confidence and puts the pLDDT key in the legend.
27
+ The structure to render, as raw PDB or mmCIF (PDBx) text, is the only required prop. Supplying per-residue `plddt` scores on a 0-1 scale colors the structure by confidence and puts the pLDDT key in the legend.
28
28
 
29
29
  **Example: DefaultProteinStructureViewer**
30
30
 
31
31
  ```tsx
32
- // Raw PDB text is the only required prop. Adding per-residue pLDDT scores on a
32
+ // The structure to render, as raw PDB or mmCIF (PDBx) text, is the only
33
+ // required prop. Adding per-residue pLDDT scores on a
33
34
  // 0-1 scale colors the structure by confidence and puts the pLDDT key in the
34
35
  // legend.
35
36
  //
@@ -244,7 +245,101 @@ function App() {
244
245
  return (
245
246
  <div className="app" style={{ height: 480 }}>
246
247
  <ProteinStructureViewer
247
- pdb={PDB}
248
+ structure={PDB}
249
+ plddt={PLDDT}
250
+ stats={[
251
+ { label: "Known", value: "62%" },
252
+ { label: "pTM", value: "0.874" },
253
+ { label: "Mean pLDDT", value: "0.781" },
254
+ ]}
255
+ />
256
+ </div>
257
+ );
258
+ }
259
+
260
+ export default App;
261
+ ```
262
+
263
+ ### PDB and mmCIF
264
+
265
+ `structure` is the structure text, not a filename, and it accepts both legacy PDB and mmCIF (PDBx). The viewer detects the format from the contents: a `data_` block or an `_atom_site.` loop is treated as mmCIF, everything else as PDB. Binary CIF (`.bcif`) is not accepted.
266
+
267
+ **Example: MmcifProteinStructureViewer**
268
+
269
+ ```tsx
270
+ // `structure` accepts mmCIF (PDBx) as well as PDB. The viewer detects the
271
+ // format from the text.
272
+ //
273
+ // The structure below is crambin (PDB 1CRN), trimmed to the backbone atoms the
274
+ // polymer cartoon traces. A chain needs enough residues to trace: a single
275
+ // residue renders an empty canvas.
276
+
277
+ import { ProteinStructureViewer } from "@czi-sds/data-viz";
278
+
279
+ const MMCIF = `data_1CRN
280
+ #
281
+ loop_
282
+ _atom_site.group_PDB
283
+ _atom_site.id
284
+ _atom_site.type_symbol
285
+ _atom_site.label_atom_id
286
+ _atom_site.label_alt_id
287
+ _atom_site.label_comp_id
288
+ _atom_site.label_asym_id
289
+ _atom_site.label_entity_id
290
+ _atom_site.label_seq_id
291
+ _atom_site.pdbx_PDB_ins_code
292
+ _atom_site.Cartn_x
293
+ _atom_site.Cartn_y
294
+ _atom_site.Cartn_z
295
+ _atom_site.occupancy
296
+ _atom_site.B_iso_or_equiv
297
+ _atom_site.auth_seq_id
298
+ _atom_site.auth_comp_id
299
+ _atom_site.auth_asym_id
300
+ _atom_site.auth_atom_id
301
+ _atom_site.pdbx_PDB_model_num
302
+ ATOM 1 N N . THR A 1 1 ? 17.047 14.099 3.625 1.00 13.79 1 THR A N 1
303
+ ATOM 2 C CA . THR A 1 1 ? 16.967 12.784 4.338 1.00 10.80 1 THR A CA 1
304
+ ATOM 3 C C . THR A 1 1 ? 15.685 12.755 5.133 1.00 9.19 1 THR A C 1
305
+ ATOM 4 O O . THR A 1 1 ? 15.268 13.825 5.594 1.00 9.85 1 THR A O 1
306
+ ATOM 5 N N . THR A 1 2 ? 15.115 11.555 5.265 1.00 7.81 2 THR A N 1
307
+ ATOM 6 C CA . THR A 1 2 ? 13.856 11.469 6.066 1.00 8.31 2 THR A CA 1
308
+ ATOM 7 C C . THR A 1 2 ? 14.164 10.785 7.379 1.00 5.80 2 THR A C 1
309
+ ATOM 8 O O . THR A 1 2 ? 14.993 9.862 7.443 1.00 6.94 2 THR A O 1
310
+ ATOM 9 N N . CYS A 1 3 ? 13.488 11.241 8.417 1.00 5.24 3 CYS A N 1
311
+ ATOM 10 C CA . CYS A 1 3 ? 13.660 10.707 9.787 1.00 5.39 3 CYS A CA 1
312
+ ATOM 11 C C . CYS A 1 3 ? 12.269 10.431 10.323 1.00 4.45 3 CYS A C 1
313
+ ATOM 12 O O . CYS A 1 3 ? 11.393 11.308 10.185 1.00 6.54 3 CYS A O 1
314
+ ATOM 13 N N . CYS A 1 4 ? 12.019 9.272 10.928 1.00 3.90 4 CYS A N 1
315
+ ATOM 14 C CA . CYS A 1 4 ? 10.646 8.991 11.408 1.00 4.24 4 CYS A CA 1
316
+ ATOM 15 C C . CYS A 1 4 ? 10.654 8.793 12.919 1.00 3.72 4 CYS A C 1
317
+ ATOM 16 O O . CYS A 1 4 ? 11.659 8.296 13.491 1.00 5.30 4 CYS A O 1
318
+ ATOM 17 N N . PRO A 1 5 ? 9.561 9.108 13.563 1.00 3.96 5 PRO A N 1
319
+ ATOM 18 C CA . PRO A 1 5 ? 9.448 9.034 15.012 1.00 4.25 5 PRO A CA 1
320
+ ATOM 19 C C . PRO A 1 5 ? 9.288 7.670 15.606 1.00 4.96 5 PRO A C 1
321
+ ATOM 20 O O . PRO A 1 5 ? 9.490 7.519 16.819 1.00 7.44 5 PRO A O 1
322
+ ATOM 21 N N . SER A 1 6 ? 8.875 6.686 14.796 1.00 4.83 6 SER A N 1
323
+ ATOM 22 C CA . SER A 1 6 ? 8.673 5.314 15.279 1.00 4.45 6 SER A CA 1
324
+ ATOM 23 C C . SER A 1 6 ? 8.753 4.376 14.083 1.00 4.99 6 SER A C 1
325
+ ATOM 24 O O . SER A 1 6 ? 8.726 4.858 12.923 1.00 4.61 6 SER A O 1
326
+ ATOM 25 N N . ILE A 1 7 ? 8.881 3.075 14.358 1.00 4.94 7 ILE A N 1
327
+ ATOM 26 C CA . ILE A 1 7 ? 8.912 2.083 13.258 1.00 6.33 7 ILE A CA 1
328
+ ATOM 27 C C . ILE A 1 7 ? 7.581 2.090 12.506 1.00 5.32 7 ILE A C 1
329
+ ATOM 28 O O . ILE A 1 7 ? 7.670 2.031 11.245 1.00 6.85 7 ILE A O 1
330
+ ATOM 29 N N . VAL A 1 8 ? 6.458 2.162 13.159 1.00 5.02 8 VAL A N 1
331
+ ATOM 30 C CA . VAL A 1 8 ? 5.145 2.209 12.453 1.00 6.93 8 VAL A CA 1
332
+ ATOM 31 C C . VAL A 1 8 ? 5.115 3.379 11.461 1.00 5.39 8 VAL A C 1
333
+ ATOM 32 O O . VAL A 1 8 ? 4.664 3.268 10.343 1.00 6.30 8 VAL A O 1
334
+ #`;
335
+
336
+ const PLDDT = [0.45, 0.515, 0.557, 0.569, 0.567, 0.578, 0.618, 0.681];
337
+
338
+ function App() {
339
+ return (
340
+ <div className="app" style={{ height: 480 }}>
341
+ <ProteinStructureViewer
342
+ structure={MMCIF}
248
343
  plddt={PLDDT}
249
344
  stats={[
250
345
  { label: "Known", value: "62%" },
@@ -494,7 +589,7 @@ function App() {
494
589
  return (
495
590
  <div className="app" style={{ height: 480 }}>
496
591
  <ProteinStructureViewer
497
- pdb={PDB}
592
+ structure={PDB}
498
593
  residueOverlay={{
499
594
  colorScale: PLASMA_COLOR_SCALE,
500
595
  label: "Feature activation",
@@ -520,6 +615,8 @@ Selection is controlled through one prop. Every way of making one - clicking a r
520
615
 
521
616
  A `StructureSelection` says what is selected in either of two ways, which combine: `residues` is a list of 0-based indices, and `chains` names whole chains by `chainId`. A drag across the sequence comes back as `residues`, a chain caption as `chains`, so a whole-chain selection survives the round trip at its original size rather than as the hundreds of indices it stands for. The camera frames whatever the selection covers, so a range or a chain is fitted to the view rather than approached as a point.
522
617
 
618
+ The two are shown differently, because they are different sizes of answer. Selected residues are drawn in ball-and-stick over the cartoon, with the residues around them, which is the point of looking at a site. A selected chain is left exactly as it was and the other chains dim around it - the same way pointing at a chain's name behaves, and for the same reason: a whole chain is already visible, so anything painted over it would only hide it.
619
+
523
620
  `onResidueClick` and `onResidueHover` are separate, and still report a single `ResidueRef`: they describe the residue under the pointer, which is a different fact from what the selection covers. Use them for a readout that follows the cursor, and `onSelectionChange` for what the user has actually chosen.
524
621
 
525
622
  A `ResidueRef` carries the residue in each addressing scheme a caller might need. `index` is the viewer's own key, shared with `plddt` and `residueOverlay`, and counts residues in file order straight through a chain break. `chainId` and `seqId` are what the file says, which is what the sequence panel displays and what the system that produced the structure will recognise. On a single chain numbered from 1 the two agree; on a complex they do not, so map a click back onto your own numbering with `chainId` and `seqId` rather than arithmetic on `index`.
@@ -760,7 +857,7 @@ function App() {
760
857
  : next
761
858
  )
762
859
  }
763
- pdb={PDB}
860
+ structure={PDB}
764
861
  plddt={PLDDT}
765
862
  selection={selection}
766
863
  stats={[
@@ -778,11 +875,11 @@ export default App;
778
875
 
779
876
  ### Complexes and chains
780
877
 
781
- A multi-chain structure needs nothing special: pass the whole complex as one PDB string and the viewer finds the chains itself, reporting them through `onChainsChange` as `ChainRef`s. It draws one cartoon per chain, splits the sequence panel into one grid per chain, and - when neither `plddt` nor `residueOverlay` is coloring the structure - paints each chain its own color and shows a chain legend with a swatch and a visibility toggle for each.
878
+ A multi-chain structure needs nothing special: pass the whole complex as one structure string and the viewer finds the chains itself, reporting them through `onChainsChange` as `ChainRef`s. It draws one cartoon per chain, splits the sequence panel into one grid per chain, and - when neither `plddt` nor `residueOverlay` is coloring the structure - paints each chain its own color and shows a chain legend with a swatch and a visibility toggle for each.
782
879
 
783
880
  Visibility works out of the box: the toggles own it unless you pass `hiddenChains`, which takes it over and leaves the toggles reporting through `onChainVisibilityChange`. Hiding a chain removes everything it is drawn with, which also takes it out of reach of hover and click; its sequence stays in the panel, dimmed, so the panel does not reflow on every toggle. `chainColors` overrides the palette per chain.
784
881
 
785
- Pointing at a chain's name, in the legend or above its grid in the sequence panel, lights that chain's cartoon up in the 3D view. The highlight is pink rather than the theme's usual hover tint, so it cannot be mistaken for the chain palette, the pLDDT bands or an overlay underneath it. Keyboard focus does the same, and nothing is reported to the consumer - it answers "which one is this?" without changing what is selected. `disableChainHighlightOnHover` turns it off.
882
+ Pointing at a chain's name, in the legend or above its grid in the sequence panel, dims every other chain in the 3D view so the one under the pointer stands out. The hovered chain keeps whatever coloring it already has, rather than being washed in a highlight color that would hide it. Keyboard focus does the same, and nothing is reported to the consumer - it answers "which one is this?" without changing what is selected. `disableChainHighlightOnHover` turns it off.
786
883
 
787
884
  Residue indices run straight through the chain break: on the pair below, barnase occupies 0-109 and barstar 110-198, so `plddt` is one flat array over the whole complex and one `residueOverlay` map spans both chains. Because a file numbers a complex however it likes - barstar here starts at residue 111, not 1 - `index` and `seqId` part company, so map a click back onto your own data with `chainId` and `seqId` rather than arithmetic on `index`.
788
885
 
@@ -798,7 +895,7 @@ import { useState } from "react";
798
895
 
799
896
  // A two-chain complex: barnase (chain A) with barstar (chain B) bound to it,
800
897
  // which is the shape a designed binder arrives in alongside its target. The
801
- // whole complex goes in as one `pdb` string; the viewer finds the chains and
898
+ // whole complex goes in as one `structure` string; the viewer finds the chains and
802
899
  // draws one cartoon per chain.
803
900
  //
804
901
  // Trimmed to the first 30 residues of each chain and to backbone atoms, which
@@ -1075,7 +1172,7 @@ export default function App(): JSX.Element {
1075
1172
  // produced the structure will recognise.
1076
1173
  console.log(residue.chainId, residue.seqId, residue.index)
1077
1174
  }
1078
- pdb={PDB}
1175
+ structure={PDB}
1079
1176
  plddt={PLDDT}
1080
1177
  selection={selection}
1081
1178
  stats={[
@@ -1091,7 +1188,7 @@ export default function App(): JSX.Element {
1091
1188
 
1092
1189
  ### Ligands and ions
1093
1190
 
1094
- Whatever a PDB entry carries besides its protein - ligands, ions, glycans, lipids - is drawn as ball-and-stick alongside the cartoon, with no prop to turn on. A cartoon traces a polymer backbone and a heme has none, so the two halves of a chain need two representations between them.
1191
+ Whatever a structure file carries besides its protein - ligands, ions, glycans, lipids - is drawn as ball-and-stick alongside the cartoon, with no prop to turn on. A cartoon traces a polymer backbone and a heme has none, so the two halves of a chain need two representations between them.
1095
1192
 
1096
1193
  The residue holding a ligand is drawn as sticks too, one bond out, which is what makes the ligand look bound rather than dropped in. Myoglobin's heme is held by His93, and without it the heme floats loose in the middle of a cartoon it is visibly bonded to. Covalent and metallic-coordination bonds both count - the heme's iron is held by the latter - and only the residue that holds the ligand comes, not that residue's own neighbours.
1097
1194
 
@@ -1327,7 +1424,7 @@ function App() {
1327
1424
  return (
1328
1425
  <div className="app" style={{ height: 240 }}>
1329
1426
  <ProteinStructureViewer
1330
- pdb={PDB}
1427
+ structure={PDB}
1331
1428
  plddt={PLDDT}
1332
1429
  showAxes={false}
1333
1430
  showLegend={false}
@@ -1355,7 +1452,7 @@ Passing `download` adds a capture button beneath the reset-camera control, which
1355
1452
 
1356
1453
  ```tsx
1357
1454
  <ProteinStructureViewer
1358
- pdb={PDB}
1455
+ structure={PDB}
1359
1456
  download={{ resolution: "high", filename: "barnase-barstar" }}
1360
1457
  />
1361
1458
  ```
@@ -1381,7 +1478,7 @@ Anything named in it wins, and anything left out keeps the viewer's default. So
1381
1478
  import { PluginConfig } from "molstar/lib/mol-plugin/config";
1382
1479
 
1383
1480
  <ProteinStructureViewer
1384
- pdb={PDB}
1481
+ structure={PDB}
1385
1482
  molstarSpec={{
1386
1483
  canvas3d: {
1387
1484
  // Slow the trackball down, leaving the rest of it alone.
@@ -1413,14 +1510,14 @@ The viewer spreads any remaining props onto its root div, so standard HTML attri
1413
1510
 
1414
1511
  | Name | Type | Default | Description |
1415
1512
  | ------------------------------- | ----------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1416
- | `pdb` | `string` | - (required) | The structure to render, as raw PDB text. |
1513
+ | `structure` | `string` | - (required) | The structure to render, as raw PDB or mmCIF (PDBx) text. |
1417
1514
  | `plddt` | `number[] \| null` | - | Per-residue pLDDT confidence on a 0-1 scale, in chain order. When supplied, the structure is colored by confidence unless `residueOverlay` takes over. Residues past the end of the array fall back to mid confidence. |
1418
1515
  | `residueOverlay` | `ResidueValueOverlay \| null` | - | Per-residue values painted over the structure, replacing pLDDT coloring while set. See the table below for its shape. |
1419
- | `selection` | `StructureSelection \| null` | `null` | What is selected. Controlled: the camera frames whatever it covers, and clearing it zooms back out. See the table below for its shape. |
1516
+ | `selection` | `StructureSelection \| null` | `null` | What is selected. Controlled: the camera frames whatever it covers, and clearing it zooms back out. Residues are drawn in ball-and-stick; a whole chain dims the chains around it instead. See the table below for its shape. |
1420
1517
  | `hiddenChains` | `string[]` | - | Chains hidden from the 3D view, by `chainId`. Leave undefined to let the chain legend's toggles own visibility; passing it takes that over, and the toggles then only report through `onChainVisibilityChange`. |
1421
1518
  | `chainColors` | `Record<string, string>` | - | Color per chain, by `chainId`, as `#RRGGBB`. Chains left out fall back to the viewer's palette. Only visible while chain coloring is what is on screen, which is when neither `plddt` nor `residueOverlay` is set. |
1422
1519
  | `showChainLegend` | `boolean` | `true` | Show the chain legend, which lists each chain with its color and a visibility toggle. Ignored on a single-chain structure, where there is nothing to tell apart or hide. |
1423
- | `disableChainHighlightOnHover` | `boolean` | `false` | Stop a chain from lighting up in the 3D view while its name is pointed at, in the legend or above its grid in the sequence panel. Turn it off where the movement is more distracting than the answer is useful. |
1520
+ | `disableChainHighlightOnHover` | `boolean` | `false` | Stop other chains from dimming in the 3D view while a chain's name is pointed at, in the legend or above its grid in the sequence panel. Turn it off where the movement is more distracting than the answer is useful. |
1424
1521
  | `download` | `StructureDownload \| null` | - | Adds a capture button beneath the reset-camera control, which downloads a PNG of the structure. Omit for no button. See _Downloading an image_ above. |
1425
1522
  | `molstarSpec` | `Partial<PluginUISpec>` | - | Mol* plugin spec laid over the viewer's own, which is how the whole of Mol*'s configuration is reachable without a prop here for each setting. Anything named wins; list-valued keys are appended to. Read once at creation, except `canvas3d`, which is re-applied when it changes. See _Configuring Mol\*_ above. |
1426
1523
  | `stats` | `(StructureStat \| null)[]` | - | Up to three whole-structure stats shown along the bottom. A `null` entry reserves its column without rendering anything, so the columns never shift as values come and go. |
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "disableChainHighlightOnHover": {
30
30
  "defaultValue": false,
31
- "description": "Stop a chain from lighting up in the 3D view while its name is pointed at,\nin the legend or above its grid in the sequence panel.\n\nThe highlight is on by default, since on a complex it is how a reader\nfinds out which chain is which. Turn it off where the movement is more\ndistracting than the answer is useful - a grid of viewers a pointer\ncrosses on its way somewhere else, or a page driving its own highlighting\nthrough `selection`.",
31
+ "description": "Stop other chains from dimming in the 3D view while a chain's name is\npointed at, in the legend or above its grid in the sequence panel.\n\nThe dim is on by default, since on a complex it is how a reader finds out\nwhich chain is which. Turn it off where the movement is more distracting\nthan the answer is useful - a grid of viewers a pointer crosses on its way\nsomewhere else, or a page driving its own highlighting through `selection`.",
32
32
  "isRequired": false,
33
33
  "type": "boolean"
34
34
  },
@@ -77,9 +77,9 @@
77
77
  "isRequired": false,
78
78
  "type": "string"
79
79
  },
80
- "pdb": {
80
+ "structure": {
81
81
  "defaultValue": "- (required)",
82
- "description": "Structure to render, as raw PDB text.",
82
+ "description": "Structure to render, as raw PDB or mmCIF (PDBx) text.",
83
83
  "isRequired": true,
84
84
  "type": "string"
85
85
  },
@@ -95,7 +95,7 @@
95
95
  },
96
96
  "selection": {
97
97
  "defaultValue": null,
98
- "description": "What is selected, or null when nothing is. Controlled: the camera frames\nwhatever the selection covers, and clearing it zooms back out to the\ndefault view.",
98
+ "description": "What is selected, or null when nothing is. Controlled: the camera frames\nwhatever the selection covers, and clearing it zooms back out to the\ndefault view.\n\nResidues are drawn in ball-and-stick over the cartoon; whole chains are\nleft as they are and the chains around them dim, the same as hovering a\nchain's name.",
99
99
  "isRequired": false,
100
100
  "type": "StructureSelection | null"
101
101
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@czi-sds/mcp",
3
3
  "description": "The official MCP server for SDS",
4
- "version": "0.19.0",
4
+ "version": "0.20.0",
5
5
  "main": "dist/stdio.js",
6
6
  "files": [
7
7
  "dist",
@@ -66,5 +66,5 @@
66
66
  "turndown": "^7.2.4",
67
67
  "typescript": "^5.9.2"
68
68
  },
69
- "gitHead": "d2e4320c4fe8a6a90abde1ce2633faa76d4c73fa"
69
+ "gitHead": "f40631b6abb44a4851ba9bc888dfdf703e44a3d4"
70
70
  }