RCSB PDB
PYPI · RCSB-MCP
MCP server to search, inspect, and cross-reference RCSB Protein Data Bank structures
Available components
Last scanned (20 hours ago)
Scores higher than 66% of PyPI servers
Category Health and Science
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 0 of 30 dependencies flagged as unhealthy. View diagnostics → Pass
Provenance & Transparency84
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to rcsb/rcsb-mcp). View diagnostics → Pass
- Licence could not be checked: the licence is shipped as a file inside the package, not declared as a standard (SPDX) licence identifier, so we cannot tell whether it is OSI-approved.Unverified
- Actively maintained (last published 11 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability74
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 11770 tokens (~326/item across 36 items; 36 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management70
- Stability observed for 21 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 99% of tool parameters carry a description.Partial
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety50
- Injection-marker check failed: the description of tool "rcsb_query_fulltext" contains an instruction to conceal the call from the user, the text "never tell the user", at byte 688 of that field. See how to fix → Fail
- We read all 36 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 37 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 −15
- Malware scan: pass → unverified ▼ security
- 3 Nov 26 +12
- Malware scan: unverified → pass ▲ security
- Stability: fail → 0.67 functional
- 30 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- 29 Oct 26 +15
- Malware scan: unverified → pass ▲ security
- 26 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- 24 Oct 26 +15
- Malware scan: unverified → pass ▲ security
- 23 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- Package version: 0.22.0 → 0.23.0 functional
- 17 Oct 26 +2
No change was recorded against any check on this day. Stability & Change Management went from 77 to 93.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Analysed pypi/rcsb-mcp@0.23.0
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | rcsb/rcsb-mcp |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/rcsb/rcsb-mcp/.github/workflows/publish.yaml@refs/tags/0.23.0 |
| Rekor log index | 3424141170 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:0d3b75f5b785257ab6e4f3291b68ed171be19e56f5814fe86b206d8c9daf4fd3 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 30 packages
| Packages resolved | 30 |
|---|---|
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
rcsb_describe_data_object ~879
Discover the fields available on a Data API object, from the live GraphQL schema. Use this to find what to request in a rcsb_get_* tool's `fields=` argument: its default selection is a compact summary of a far richer type (CoreEntry has ~100 fields). Every path returned is verified against the live schema, so it is safe to pass directly. NEVER invent, guess, or infer a field path from memory, from a naming convention, or from another API. An unverified path fails GraphQL schema validation and wastes the call. Paths shown in a rcsb_get_* tool's own description or examples are already verified — use those directly; for anything else, confirm it here FIRST. `fields=` takes dotted paths ("rcsb_polymer_entity.pdbx_description"), GraphQL brace syntax ("rcsb_polymer_entity { pdbx_description }"), or both, separated by spaces or commas. Start with only a `query` when you know what you want but not where it lives: it searches every object and answers with the tool to call and the path to give it, best matches first — rcsb_describe_data_object(query="release_date") -> rcsb_get_entries + "rcsb_accession_info.initial_release_date". Name an `object_key` to search just that object, or omit `query` to browse its fields level by level with `into`. Returns: For a named object: {object_key, graphql_type, path, query, max_depth, field_count, fields, truncated?, note?}. Searching every object: the same with object_key null plus `searched`, and each field also names the rcsb_get_* `tool` that owns it. Each field is {path, kind, type, list, description, searchable?}: `kind` is "scalar" (select it directly) or "object" (drill in, or select with a sub-selection); `searchable` (about 3% of fields) marks one you can ALSO filter on with rcsb_query_attribute. A field is reported once, under the object reaching it most directly. A capped result sets `truncated`, and `note` says how to narrow it.
| Name | Type | Req | Description |
|---|---|---|---|
| into | – | – | Optional dot-path of nested object field(s) to scope to, e.g. "rcsb_entry_info" or "polymer_entities.rcsb_polymer_entity". Scoping a search to a sub-tree is cheaper and more focused than flattening f… |
| max_depth | – | – | How many levels to walk (1-6). Omit it: the default follows what you are doing — 1 when browsing, 3 when searching, which is what it takes to reach "polymer_entities.rcsb_polymer_entity.pdbx_descript… |
| object_key | – | – | Which object to describe — the key matching the rcsb_get_* tool. OMIT it to search every object at once and be told which tool owns each match; that needs a `query` and cannot be combined with `into`… |
| query | – | – | Optional case-insensitive keyword, matched against each field's path (relative to the scope) and its description, e.g. "resolution", "abstract", "organism". A SEARCH ATTRIBUTE PATH works as the query… |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_describe_seqcoord_object ~509
Discover the fields available on a Sequence Coordinates object, from the live schema. The Sequence Coordinates analogue of rcsb_describe_data_object, with the same shape: the rcsb_seqcoord_* tools return a compact default selection; use this to find what else you can request via their `fields=` argument. Every path it returns is verified against the live schema, so it is safe to pass to `fields=` directly. Browse a level, drill in / scope with `into`, or pass `query` to flatten the tree into dotted paths and keep only matching fields. The walk depth follows which one you are doing, so you do not have to set it: browsing lists one level, searching goes three deep. This schema is small and bottoms out at 3 levels (~20-31 fields per object), so a search covers an object in full in ONE call: rcsb_describe_seqcoord_object("alignments", max_depth=3) -> pick paths -> call rcsb_seqcoord_alignments(..., fields="target_alignments{ ... }"). Each returned field has path (dotted, ready for `fields=`), kind ("scalar" leaf or "object"), type, list (whether it's a list), and description (when present). NEVER invent, guess, or infer a field path — an unverified path fails schema validation and wastes the call. `fields=` accepts dotted paths or GraphQL nested-brace syntax, the two may be mixed, and multiple paths are separated by spaces or commas. Returns: {object_key, graphql_type, path, query, max_depth, field_count, fields:[{path, kind, type, list, description}], truncated?, note?}.
| Name | Type | Req | Description |
|---|---|---|---|
| into | – | – | Optional dot-path of nested object field(s) to scope to, e.g. "target_alignments" or "features.feature_positions". |
| max_depth | – | – | How many levels to walk (1-6). Omit it: the default follows what you are doing — 1 when browsing, 3 when searching. The schema bottoms out at 3. |
| object_key | string | yes | The root field to describe: "alignments" for rcsb_seqcoord_alignments, "annotations" for rcsb_seqcoord_annotations. |
| query | – | – | Optional case-insensitive keyword, matched against each field's path (relative to the scope) and its description. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_find_disease_terms ~367
Resolve a free-text disease, disorder, syndrome, or condition (e.g. diabetes, cancer, Alzheimer disease, cystic fibrosis) to MONDO ontology ids, for precise disease-based PDB searches instead of keyword guessing. Use for ANY request mentioning a disease/disorder/syndrome/condition — "structures involved in / associated with / linked to <disease>", "proteins implicated in <disease>". Resolve the phrase to a MONDO id here, then filter on it with rcsb_query_attribute: exact_match on rcsb_uniprot_annotation.annotation_lineage.id, id AS A STRING ("MONDO:0005148"). The *_lineage.id paths are HIERARCHICAL — they match the term AND everything beneath it; use `in` with several ids to broaden. A MONDO id therefore finds the disease and its subtypes. Results are based on how each entry's text matched your query. Broader, synonym, or differently-worded terms for the same concept may produce different results. Rank is unrelated to how much of the archive each term covers. Returns: {query, count, diseases:[{id, name, matched_synonym?, pdb_entry_count?}]}. `matched_synonym` appears only when the formal MONDO name does not contain your words — it names the synonym that did match.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Max MONDO terms to return. |
| query | string | yes | Free-text disease / condition, e.g. "cystic fibrosis", "breast cancer". |
| with_pdb_counts | boolean | – | If true (default), annotate each with pdb_entry_count (PDB entries carrying it, via annotation_lineage.id). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_find_enzyme_classes ~354
Resolve a free-text enzyme, enzyme class, or catalyzed reaction (e.g. alcohol dehydrogenase, protease, kinase, DNA polymerase, hydrolase, oxidoreductase) to Enzyme Commission (EC) numbers, for precise EC-based PDB searches instead of keyword guessing. Use this when a request references an enzyme, enzyme class, or reaction — including "enzymes that catalyze / break down / degrade / synthesize / hydrolyze / phosphorylate ...". Resolve the phrase to an EC number here, then filter on it with rcsb_query_attribute: exact_match on rcsb_polymer_entity.rcsb_ec_lineage.id, EC number AS A STRING. The *_lineage.id paths are HIERARCHICAL — they match the term AND everything beneath it; use `in` with several ids to broaden. A partial EC like "3.4.21" therefore matches the whole sub-subclass. Results are based on how each entry's text matched your query. Broader, synonym, or differently-worded terms for the same concept may produce different results. Rank is unrelated to how much of the archive each term covers. Returns: {query, count, enzymes:[{ec, name, pdb_entry_count?}]}.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Max EC numbers to return. |
| query | string | yes | Free-text enzyme / reaction, e.g. "alcohol dehydrogenase", "protein kinase". |
| with_pdb_counts | boolean | – | If true (default), annotate each with pdb_entry_count (PDB entries carrying it, via rcsb_ec_lineage.id). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_find_go_terms ~374
Resolve a free-text molecular function, biological process, or cellular component / location (e.g. kinase activity, ATP binding, DNA repair, apoptosis, signal transduction, mitochondrial membrane, nucleus) to Gene Ontology (GO) terms, so you can run precise GO-based PDB searches instead of keyword guessing. Use this when a request involves what a protein DOES or where it acts — "proteins that <do X> / are involved in / participate in / are responsible for ...", "localized to / located in ...". Resolve the phrase to a GO id here, then filter on it with rcsb_query_attribute: exact_match on rcsb_polymer_entity_annotation.annotation_lineage.id, id AS A STRING ("GO:0004672"). The *_lineage.id paths are HIERARCHICAL — they match the term AND everything beneath it; use `in` with several ids to broaden. For ONLY that exact term without descendants use annotation_id instead. Results are based on how each entry's text matched your query. Broader, synonym, or differently-worded terms for the same concept may produce different results. Rank is unrelated to how much of the archive each term covers. Returns: {query, namespace, count, terms:[{id, name, aspect, pdb_entry_count?}]}.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Max GO terms to return. |
| namespace | – | – | Optional GO aspect to restrict to. Omit to search all three. |
| query | string | yes | Free-text function / process / location, e.g. "kinase activity", "DNA repair". |
| with_pdb_counts | boolean | – | If true (default), annotate each term with pdb_entry_count (PDB entries carrying it, via annotation_lineage.id). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_find_interpro_domains ~414
Resolve a free-text protein domain, family, or fold (e.g. SH2 domain, immunoglobulin fold, zinc finger, beta-barrel, WD40 repeat, kinase domain) to InterPro entries, for precise InterPro-based PDB searches instead of keyword guessing. Use this whenever a request references a protein DOMAIN, FAMILY, or fold — "structures containing / with a <domain>", "<domain>-containing proteins", "members of the <family> family". Resolve the phrase to an accession here, then filter on it with rcsb_query_attribute: exact_match on rcsb_polymer_entity_annotation.annotation_id, accession AS A STRING ("IPR000719"). Lineage paths are not available; broaden with `in` over several accessions instead (IPR and PF mix freely). Ids come from InterPro ("IPR000719") or Pfam ("PF07859") — `source_database` on each entry says which. Both filter on the same attribute; nothing else needs to change. Results are based on how each entry's text matched your query. Broader, synonym, or differently-worded terms for the same concept may produce different results. Rank is unrelated to how much of the archive each term covers. Returns: {query, entry_type, count, entries:[{id, name, type, source_database, matched_text?, pdb_entry_count?}]}. `matched_text` appears only when the entry's NAME does not contain your words — it quotes the text that did match.
| Name | Type | Req | Description |
|---|---|---|---|
| entry_type | – | – | Optional type filter. Omit to return all types. |
| limit | integer | – | Max entries to return. |
| query | string | yes | Free-text domain/family name, e.g. "SH2 domain", "immunoglobulin". |
| with_pdb_counts | boolean | – | If true (default), annotate each entry with pdb_entry_count (PDB entries carrying it). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_find_organisms ~471
Resolve a free-text organism, common name, or clade (e.g. human, mouse, baker's yeast, Escherichia coli, mammals, bacteria, primates) to NCBI Taxonomy ids, for precise taxonomy-based PDB searches instead of keyword guessing. Use when a request restricts structures by SOURCE ORGANISM or any higher taxon — a common name you want as a canonical taxon ("human", "fruit fly"), or a CLADE, which a plain name search cannot expand. Resolve the phrase to a taxon id here, then filter on it with rcsb_query_attribute: exact_match on rcsb_entity_source_organism.taxonomy_lineage.id, id AS A STRING ("9606", not 9606 — a bare number does not match). The *_lineage.id paths are HIERARCHICAL — they match the term AND everything beneath it; use `in` with several ids to broaden. A clade id ("40674" = Mammalia) therefore finds every organism beneath it; for a known exact species ncbi_scientific_name exact_match also works. An informal, polyphyletic group ("filamentous fungi", "extremophiles", "algae") is NOT a taxon and has no id: resolve the nearest CONTAINING taxon, then classify each hit from the lineage its own record returns. Results are based on how each entry's text matched your query. Broader, synonym, or differently-worded terms for the same concept may produce different results. Rank is unrelated to how much of the archive each term covers. Returns: {query, count, taxa:[{tax_id, scientific_name, common_name, rank, pdb_entry_count?}]}.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Max taxa to return. |
| query | string | yes | Free-text organism / clade / common name, e.g. "human", "mammals", "E. coli". |
| with_pdb_counts | boolean | – | If true (default), annotate each taxon with pdb_entry_count (PDB entries from it or any organism beneath it, via taxonomy_lineage.id) — this also disambiguates a species from its strains. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_assemblies ~229
Fetch biological assemblies, e.g. ["4HHB-1"] (entry-assembly). Default fields: composition counts and oligomeric state. Assembly-based (complex) annotations can be fetched adding rcsb_assembly_annotation.* fields, and positional features rcsb_assembly_feature.*
| Name | Type | Req | Description |
|---|---|---|---|
| assembly_ids | array | yes | entry-assembly, e.g. ["4HHB-1"] — exactly what rcsb_search_request returns with return_type="assembly". Unknown IDs are returned under "not_found". Do not guess "-1". Assembly 1 essentially always ex… |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_assembly_info.polymer_entity_instance_count"); discover/verify paths with rcsb_describe_data_object("assemblies"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_branched_entities ~133
Fetch branched (carbohydrate / oligosaccharide) entities, e.g. ["5FMB_2"]. Default fields: description, weight, copy count, branch type, and component count.
| Name | Type | Req | Description |
|---|---|---|---|
| entity_ids | array | yes | entry + entity number, e.g. ["5FMB_2"]. Unknown IDs are returned under "not_found". |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_branched_entity.pdbx_description"); discover/verify paths with rcsb_describe_data_object("branched_entities"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_branched_entity_instances ~129
Fetch branched entity instances (individual glycan chains), e.g. ["5FMB.C"]. Default fields: the entry/entity/chain identifiers.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_branched_entity_instance_container_identifiers.asym_id"); discover/verify paths with rcsb_describe_data_object("branched_entity_in… |
| instance_ids | array | yes | entry.asym_id (glycan chain), e.g. ["5FMB.C"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_chem_comps ~124
Fetch chemical components / ligands by their short codes, e.g. ["HEM", "ATP"]. Default fields: name, formula, weight, type, SMILES, InChIKey.
| Name | Type | Req | Description |
|---|---|---|---|
| comp_ids | array | yes | chemical-component short codes, e.g. ["HEM", "ATP"]. Unknown IDs are returned under "not_found". |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "chem_comp.name"); discover/verify paths with rcsb_describe_data_object("chem_comps"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_entries ~220
Fetch metadata for one or more PDB entries (title, method, resolution, size, dates, and primary citation). The response also lists the entry's component ids under rcsb_entry_container_identifiers — use these to drill into the structure. They are bare numbers; compose them with the entry id to call the matching rcsb_get_* tool: polymer_entity_ids/non_polymer_entity_ids "N" -> "<ENTRY>_N" (rcsb_get_polymer_entities / rcsb_get_nonpolymer_entities); assembly_ids "N" -> "<ENTRY>-N" (rcsb_get_assemblies).
| Name | Type | Req | Description |
|---|---|---|---|
| entry_ids | array | yes | 4-character PDB entry codes, e.g. ["4HHB", "1MBN"]; pass a one-element list for a single entry. Unknown IDs are returned under "not_found". |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "struct.title"); discover/verify paths with rcsb_describe_data_object("entries"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_entry_groups ~110
Fetch entry groups (clusters of related entries) by group ID. Default fields: group name, description, member count, and member ids.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_group_info.group_name"); discover/verify paths with rcsb_describe_data_object("entry_groups"). |
| group_ids | array | yes | entry-group ids, e.g. ["G_1002266"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_group_provenance ~111
Fetch provenance/method metadata for a grouping, e.g. "provenance_sequence_identity". Default fields: the aggregation method/type and provenance id.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_group_aggregation_method.type"); discover/verify paths with rcsb_describe_data_object("group_provenance"). |
| group_provenance_id | string | yes | a provenance token, e.g. "provenance_sequence_identity". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_interfaces ~118
Fetch assembly interfaces, e.g. ["1BMV-1.1"] (entry-assembly.interface). Default fields: buried area, character, composition, residue count.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_interface_info.interface_area"); discover/verify paths with rcsb_describe_data_object("interfaces"). |
| interface_ids | array | yes | entry-assembly.interface, e.g. ["1BMV-1.1"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_nonpolymer_entities ~233
Fetch non-polymer (ligand/cofactor) entities, e.g. ["4HHB_3"]. Default fields: description, weight, copy count, and the bound chemical component ID. Use rcsb_get_chem_comps for the chemistry of that component.
| Name | Type | Req | Description |
|---|---|---|---|
| entity_ids | array | yes | entry + non-polymer entity number, e.g. ["4HHB_3"] — exactly what rcsb_search_request returns with return_type="non_polymer_entity". Unknown IDs are returned under "not_found". Do not guess the numbe… |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_nonpolymer_entity.pdbx_description"); discover/verify paths with rcsb_describe_data_object("nonpolymer_entities"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_nonpolymer_entity_groups ~119
Fetch non-polymer entity groups (clusters of related ligands) by group ID. Default fields: group name, description, member count, and member ids.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_group_info.group_name"); discover/verify paths with rcsb_describe_data_object("nonpolymer_entity_groups"). |
| group_ids | array | yes | non-polymer entity group ids, e.g. ["ATP"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_nonpolymer_entity_instances ~135
Fetch non-polymer entity instances (individual bound ligands), e.g. ["4HHB.E"]. Default fields: the entry/entity/chain identifiers, bound component id, and author seq id.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_nonpolymer_entity_instance_container_identifiers.comp_id"); discover/verify paths with rcsb_describe_data_object("nonpolymer_entit… |
| instance_ids | array | yes | entry.asym_id, e.g. ["4HHB.E"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_polymer_entities ~270
Fetch polymer entities (protein/nucleic-acid molecules) — description, length, weight, and source organism. Default fields: description, length, weight, and source organism. Polymer-based (sequence) annotations can be fetched adding rcsb_polymer_entity_annotation.* fields, and positional features adding rcsb_polymer_entity_feature.*
| Name | Type | Req | Description |
|---|---|---|---|
| entity_ids | array | yes | entry + entity number, e.g. ["4HHB_1"] — exactly what rcsb_search_request returns with return_type="polymer_entity". Unknown IDs are returned under "not_found". NEVER form one by appending _1 to an e… |
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_polymer_entity.pdbx_description"); discover/verify paths with rcsb_describe_data_object("polymer_entities"). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_polymer_entity_groups ~121
Fetch polymer entity groups (e.g. sequence clusters), e.g. ["85_70"]. Default fields: group name, description, member count, and member ids.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_group_info.group_name"); discover/verify paths with rcsb_describe_data_object("polymer_entity_groups"). |
| group_ids | array | yes | sequence-cluster group ids, e.g. ["85_70"]. Unknown IDs are returned under "not_found". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_polymer_entity_instances ~297
Fetch polymer entity instances (individual chains), e.g. ["4HHB.A"] (entry.asym_id). Instance-based (chain) annotations can be fetched adding rcsb_polymer_instance_annotation.* fields, and positional features rcsb_polymer_instance_feature.* Default fields: the entry/entity/chain identifiers and modeled-residue count.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_polymer_instance_info.modeled_residue_count"); discover/verify paths with rcsb_describe_data_object("polymer_entity_instances"). |
| instance_ids | array | yes | entry.asym_id (chain), e.g. ["4HHB.A"] — exactly what rcsb_search_request returns with return_type="polymer_instance". Unknown IDs are returned under "not_found". Do not guess ".A". It is the LABEL a… |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_pubmed ~107
Fetch the PubMed record for a citation by its integer ID, e.g. 6726807. Default fields: PubMed Central ID, DOI, abstract text.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_pubmed_doi"); discover/verify paths with rcsb_describe_data_object("pubmed"). |
| pubmed_id | integer | yes | integer PubMed ID, e.g. 6726807. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_get_uniprot ~244
Fetch the UniProt record RCSB maps to an accession, e.g. "P69905". Default fields give a functional snapshot: accession(s), entry name, protein and gene names, EC number, the UniProt function comment, source organism, and keywords (which often summarize biology directly, e.g. "ATP-binding", "Viral attachment to host entry receptor"). RCSB's UniProt integration is rich — `fields` can also pull the heavier annotation sets (kept out of the default because they can run to hundreds of entries): `rcsb_uniprot_annotation` (GO terms, InterPro, disease associations), `rcsb_uniprot_feature` (domains, sites, binding sites, sequence variants), and `rcsb_uniprot_external_reference`.
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection replacing the curated default (e.g. "rcsb_uniprot_protein.name.value"); discover/verify paths with rcsb_describe_data_object("uniprot"). |
| uniprot_id | string | yes | a UniProt accession, e.g. "P69905". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_list_pdb_search_attributes ~502
Discover the RCSB PDB Search schema: attribute paths, value types, and operators. Call this FIRST when a request resolves to a clear attribute and value but you don't know the exact path; pick the attribute here, build the condition with `rcsb_query_attribute`, then execute with `rcsb_search_request`. Returns: {count, match_mode, attributes, note?}. `attributes` holds {attribute, type, operators, description, enum?, nested_group?} records — the RCSB/PDB attribute path (e.g. "rcsb_entry_info.resolution_combined"), its value type (string/number/integer/date), the operators it supports (exact_match, greater, range, exists, ...), and a human-readable description. `enum` appears on the ~16% of attributes that accept only a FIXED SET of values (e.g. exptl.method); when it does, use one of those values verbatim — anything else is rejected by rcsb_query_attribute. `nested_group` appears on the ~19% stored in NESTED DOCUMENTS — an entry has many citations, an entity many binding affinities — and its value is the container path. For these, grouping selects the semantics: conditions sharing a nested_group built in ONE rcsb_query_attribute call with nothing else in it must hold on the SAME record; in separate calls each is matched independently. Group the ones that describe one record, leave the rest apart. The value is NOT the attribute's first path segment for all of them, so read it rather than deriving it. `match_mode` is "exact" (every word matched, best match first), "partial" (only some did — read `note`), "none" (nothing matched — read `note`), or "all" (query omitted, whole catalog).
| Name | Type | Req | Description |
|---|---|---|---|
| query | – | – | Optional keyword(s) to filter the catalog, matched as words of the attribute path, description and allowed values, best match first. Omit to return everything. |
| schema | string | – | Which catalog — "structure" (~636 attrs: entry/entity/assembly/instance) or "chemical" (~58 attrs: chemical-component). Paths from the chemical catalog need chemical_attributes=True on rcsb_query_att… |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_attribute ~695
Build a STRUCTURED query from attribute conditions — the precise alternative to keyword search, and preferred whenever a request resolves to clear attribute(s) and value(s). NEVER invent, guess, or infer an attribute path: call rcsb_list_pdb_search_attributes first if you don't know it or its operators. For a biological concept, resolve it to an ontology id with the matching rcsb_find_* tool and filter on that annotation. If a resolver returns no usable id, or a concept filter yields no hits, fall back to rcsb_query_fulltext for the concept. For ordinary constraints — resolution, organism, dates — an empty result is a valid answer: report it, don't keyword-search instead. An attribute path also works as the `query` for rcsb_describe_data_object: every attribute here is also a Data API field, so pasting one in tells you which rcsb_get_* tool fetches the value. Example ("human X-ray structures better than 2 A"): attributes=[ {"attribute": "rcsb_entity_source_organism.ncbi_scientific_name", "operator": "exact_match", "value": "Homo sapiens"}, {"attribute": "exptl.method", "operator": "exact_match", "value": "X-RAY DIFFRACTION"}, {"attribute": "rcsb_entry_info.resolution_combined", "operator": "less", "value": 2.0}, ] Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer. Note the per-hit `score` of a pure attribute filter is near-uniform and carries NO biological meaning; don't rank hits by it.
| Name | Type | Req | Description |
|---|---|---|---|
| attributes | array | yes | One or more conditions. Attributes that carry a `nested_group` are stored in nested documents, and an object holds MANY: an entity has many binding affinities, many annotations. For these the CALL BO… |
| chemical_attributes | boolean | – | Set True when the paths come from rcsb_list_pdb_search_attributes(schema="chemical") (e.g. "chem_comp.formula_weight"). Selects the chemical-component catalog rather than the structure one. |
| logical_operator | string | – | Combine these conditions with "and" (default) or "or". For several values of a SINGLE attribute use the attribute operator `in`. For a query needing AND + OR — e.g. (high-resolution OR NMR) AND human… |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_chemical ~323
Build a CHEMICAL query from a SMILES/InChI descriptor or a molecular formula. Use for ligand and small-molecule questions where you have the chemistry itself. To find a ligand by NAME, use rcsb_query_fulltext or filter on a chemical attribute. Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer.
| Name | Type | Req | Description |
|---|---|---|---|
| descriptor_type | string | – | "SMILES" (default) or "InChI"; descriptor queries only. |
| match_subset | boolean | – | Formula queries only. True matches components that merely contain the given atoms (and possibly others); False (default) requires the formula to match exactly. |
| match_type | string | – | How strictly to match the graph (descriptor queries only). Whole-molecule: graph-exact / graph-strict / graph-relaxed (default) / graph-relaxed-stereo, or fingerprint-similarity for "chemically simil… |
| query_type | string | – | "descriptor" (default) or "formula". |
| value | string | yes | The descriptor (SMILES like "CC(=O)Oc1ccccc1C(=O)O", or an InChI string) or the formula (e.g. "C9H8O4"). Case is preserved — element symbols and SMILES are case-sensitive. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_composer ~323
Combine query documents with one AND/OR — call repeatedly to nest. You do NOT need this for conditions that share a single operator: several attribute conditions ANDed together are one rcsb_query_attribute call, and a list of alternatives for one attribute is better expressed with the `in` operator than with OR. Reach for the composer when a query needs BOTH operators, or mixes services: * (human OR mouse) AND resolution < 2 A -> build the OR group with rcsb_query_attribute(logical_operator="or"), build the resolution condition, then compose the two with "and". * sequence-similar to X AND containing ligand Y -> compose rcsb_query_sequence with rcsb_query_attribute. Nest by feeding a composed document straight back in as one of `queries`. Groups that share this call's operator are folded in rather than nested, so repeated composition stays flat and readable. Returns: A query document — pass it to rcsb_search_request, or back into this tool. A query mixing two services has no single meaningful relevance ranking, so hits come back in the API's default order; set `sort_by` on rcsb_search_request if the order matters.
| Name | Type | Req | Description |
|---|---|---|---|
| logical_operator | string | – | "and" (default) or "or". |
| queries | array | yes | Two or more query documents from any rcsb_query_* tool (including this one). Pass each through exactly as returned. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_fulltext ~344
Build a FREE-TEXT keyword query (e.g. "CRISPR Cas9", "hemoglobin"). Best for broad or exploratory lookups. When a request resolves to a clear attribute and value, prefer rcsb_query_attribute — more precise, and it avoids spurious keyword matches. BEFORE keyword-searching a biological CONCEPT (disease/function/domain/ enzyme/organism), resolve it to an ontology id with the matching rcsb_find_* tool and filter on the annotation instead; fall back to keywords only if that yields nothing. Matching spans many text attributes beyond the title — abstracts, keywords, synonyms, author names — so judge each hit yourself: a high `score` is text-relevance, NOT biological importance; never tell the user one hit is better than another because its score is higher. For evidence on a hit, rcsb_get_entries returns its title and, for many entries, a PubMed abstract (pubmed.rcsb_pubmed_abstract_text). Broader, synonym, or differently-worded terms for the same concept may produce different results. Returns: A query document — pass it to rcsb_search_request to run it, or to rcsb_query_composer to combine it with other queries first.
| Name | Type | Req | Description |
|---|---|---|---|
| query | string | yes | Terms matched case-insensitively against all text annotations. Quote a phrase to require adjacency (e.g. '"DNA polymerase"'); separate words narrow the results; a trailing '*' is a prefix wildcard. A… |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_seqmotif ~227
Build a SHORT SEQUENCE-MOTIF query — a pattern, not a full sequence. Use for active-site signatures, N-glycosylation sequons, zinc fingers, and similar short patterns. For a whole sequence use rcsb_query_sequence; for a 3D arrangement of residues use rcsb_query_strucmotif. Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer.
| Name | Type | Req | Description |
|---|---|---|---|
| pattern | string | yes | The motif, written in the grammar named by pattern_type. |
| pattern_type | string | – | "prosite" (default) for PROSITE syntax like "C-x(2,4)-C-x(3)-[LIVMFYWC]"; "regex" for a regular expression like "C..H[LIVF]"; "simple" for simple wildcards where X matches any residue (e.g. "NXS"). |
| sequence_type | string | – | "protein" (default), "dna", or "rna". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_sequence ~203
Build a SEQUENCE-SIMILARITY query (MMseqs2, BLAST-like) from a raw sequence. Use when you have actual residues to match. For a short motif or pattern use rcsb_query_seqmotif; for a named protein use rcsb_query_fulltext or a resolver. Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer.
| Name | Type | Req | Description |
|---|---|---|---|
| evalue_cutoff | number | – | Maximum E-value (default 1.0); lower is stricter. |
| identity_cutoff | number | – | Minimum fractional identity 0-1 (default 0.3). Raise toward 0.9 for close homologs, lower for remote ones. |
| sequence | string | yes | One-letter sequence; whitespace is ignored. FASTA headers must be removed. |
| sequence_type | string | – | "protein" (default), "dna", or "rna". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_strucmotif ~472
Build a 3D STRUCTURAL-MOTIF query — a geometric arrangement of specific residues. Geometry-based, and different from rcsb_query_structure (whole-shape similarity) and rcsb_query_seqmotif (sequence pattern). Use it for catalytic triads, binding sites, metal-coordination geometries, and similar. Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer.
| Name | Type | Req | Description |
|---|---|---|---|
| angle_tolerance | integer | – | Angle tolerance in multiples of 20 degrees, integer 0-3 (default 1). |
| atom_pairing_scheme | string | – | ALL, BACKBONE, SIDE_CHAIN (default), or PSEUDO_ATOMS. |
| backbone_distance_tolerance | integer | – | Backbone distance tolerance in A, integer 0-3 (default 1). |
| entry_id | string | yes | Reference PDB entry defining the motif, e.g. "2MNR". |
| exchanges | – | – | Optional per-position residue alternatives, each {"residue_id": {...}, "allowed": [<3-letter codes>]}, to match variants of the motif. |
| motif_pruning_strategy | string | – | NONE or KRUSKAL (default). |
| residue_ids | array | yes | 2-10 residues defining the motif, each {"label_asym_id": <chain>, "label_seq_id": <int>, "struct_oper_id"?: <str>}. IMPORTANT: these are the mmCIF *label* identifiers (the internal numbering), which… |
| rmsd_cutoff | number | – | Maximum RMSD of accepted hits (default 2.0). |
| side_chain_distance_tolerance | integer | – | Side-chain distance tolerance in A, integer 0-3 (default 1). |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_query_structure ~187
Build a 3D SHAPE-SIMILARITY query against an existing PDB structure. Whole-shape similarity — use it for "structures shaped like X" / "same fold as X". For a geometric arrangement of specific residues use rcsb_query_strucmotif; for sequence similarity use rcsb_query_sequence. Returns: A query document — pass it to rcsb_search_request, or to rcsb_query_composer.
| Name | Type | Req | Description |
|---|---|---|---|
| assembly_id | – | – | Reference a whole assembly, e.g. "1". Defaults to assembly "1" when neither this nor asym_id is given; mutually exclusive with asym_id. |
| asym_id | – | – | Reference a single chain instead, e.g. "A" (the mmCIF label id). |
| entry_id | string | yes | Reference PDB entry, e.g. "4HHB". |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_render_report ~175
Render a structure-search report as a styled, self-contained HTML page. Call this LAST, after the searches and rcsb_get_* calls that produce the values shown in the report. Supply facts only: the page is rendered from a fixed server-side template, so do not write HTML yourself and do not rewrite what this tool returns. Each field of ``report`` is described in the input schema. Returns: RenderReportResult with EITHER a `url` or `html` (never both), plus template_version. Prefer `url` — it is a self-contained link that renders the report on demand; deliver it to the user as-is. `html` is only returned as a fallback; write it to a `.html` file.
| Name | Type | Req | Description |
|---|---|---|---|
| params | – | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| html | – | – | Fallback rendering, returned ONLY when a link could not be built. Write it verbatim to a `.html` file and deliver that. |
| template_version | string | yes | Version of the report template used. |
| url | – | – | Short link to the rendered report. When set, THIS is the deliverable — give it to the user as a clickable link. Do not open it, fetch it, or reproduce anything from it. |
No examples provided.
rcsb_search_request ~1,325
RUN a query built by the rcsb_query_* tools and return matching PDB identifiers. Every search ends here: build with rcsb_query_fulltext / rcsb_query_attribute / rcsb_query_sequence / rcsb_query_chemical / rcsb_query_structure / rcsb_query_seqmotif / rcsb_query_strucmotif, optionally join with rcsb_query_composer, then execute with this tool. Nothing is searched until you call it — a query document on its own is not a result. Results are IDENTIFIERS only. Batch them into rcsb_get_entries, or the rcsb_get_* tool matching `return_type`, to get metadata. Returns: {total_count, returned, result_type, fetch_with, offset, has_more, next_offset, hits:[{id, score}], editor} — `result_type` is the kind of identifier that came back and `fetch_with` names the rcsb_get_* tool that takes it, so check those before batching the ids onward. `editor` opens the query in the RCSB search UI. With `all_hits` the paging fields are omitted; with `facets` returns {total_count, facets, editor} instead of hits. A `notes` list appears only when the results need a caveat; read it before describing the hits or treating them as complete.
| Name | Type | Req | Description |
|---|---|---|---|
| all_hits | boolean | – | Return the COMPLETE result set in one call, for an explicit "ALL ..." request. Ignores limit, cannot be combined with offset (the Search API rejects pagination here), and is refused above 10000 hits… |
| facets | – | – | Aggregation specs returning a BREAKDOWN instead of hits — use for "how many by X (e.g., experimental method)", "distribution of Y (e.g., EC numbers)", "which Z (e.g., organisms)" queries or to discov… |
| group_by | – | – | Collapse redundant polymer_entity hits into clusters and return one representative each — requires return_type="polymer_entity". Sequence-identity clustering at 30/50/70/90/95 percent ("seqid_30" ...… |
| group_by_ranking | – | – | Which member represents each cluster: "resolution" (best first), "released_date" (newest first), "entity_residue_count" (longest deposited sequence first — expression tags and fusion partners count t… |
| include_computed_models | boolean | – | Also search computed structure models (AlphaFold and similar), not just experimental structures. |
| limit | integer | – | Max hits to return, 1-100 (default 10). |
| offset | integer | – | Hits to skip, for paging; pass the response's next_offset back with the same query to fetch the next page. |
| query | – | yes | The query document returned by an rcsb_query_* tool, passed through unchanged. |
| return_type | – | – | What kind of identifier to return: Type Description Example Data API tool entry whole structure "4HHB" -> rcsb_get_entries polymer_entity one… |
| sort_by | – | – | Attribute path to order hits by, replacing the default relevance order (each hit's score is still returned). A pure attribute filter is a boolean match whose hits otherwise come back in near-arbitrar… |
| sort_direction | string | – | "asc" (default) or "desc"; applies only when sort_by is set. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_seqcoord_alignments ~394
Cross-reference a sequence across PDB, UniProt, and NCBI, with aligned ranges. This is the tool for "which X identifiers correspond to this sequence?" across databases — including NCBI. The RCSB Data API only cross-references UniProt, so use THIS tool for NCBI RefSeq protein / genome mappings (and PDB<->UniProt too). The returned target_alignments[].target_id values are the mapped identifiers in the to_ref system, each with its aligned regions. Examples: - "What NCBI proteins map to PDB entity 4HHB_1?" query_id="4HHB_1", from_ref="PDB_ENTITY", to_ref="NCBI_PROTEIN" - "Which PDB entities correspond to UniProt P69905?" query_id="P69905", from_ref="UNIPROT", to_ref="PDB_ENTITY"
| Name | Type | Req | Description |
|---|---|---|---|
| fields | – | – | Optional GraphQL selection to override the default. |
| from_ref | string | yes | Reference system of query_id. |
| query_id | string | yes | The sequence id, in the from_ref system's format — UNIPROT "P69905", NCBI_PROTEIN "NP_000508", NCBI_GENOME "NC_000016", PDB_ENTITY "4HHB_1" (entry_entityNumber), PDB_INSTANCE "4HHB.A" (entry.asym_id)… |
| seq_range | – | – | Optional [begin, end] (1-based) to restrict the query region. |
| to_ref | string | yes | Reference system to map onto. |
Structured output declared, but exposes no named fields.
No examples provided.
rcsb_seqcoord_annotations ~301
Residue-level features of one PDB polymer entity (4HHB_1) or instance (4HHB.A), positioned on its sequence. The tool for questions about specific residues: which form an active site, bind a ligand or metal, are modified, glycosylated or disulfide-bonded, lie in a domain, helix or membrane segment, are unobserved or poorly fitted. Without feature_types every feature is returned. An answer too large to return (an entity's chain features come once per copy) fails with the feature types the sequence has and their counts: ask again for the ones needed, or for one instance. With feature_types only those come back, from the sources that have them.
| Name | Type | Req | Description |
|---|---|---|---|
| feature_types | – | – | Optional feature types to return, any of them (e.g. ["ACTIVE_SITE", "BINDING_SITE"]), named as in the `type` of returned features. Omit for every annotation; an answer too large to return is refused… |
| fields | – | – | Optional GraphQL selection to override the default. |
| query_id | string | yes | A PDB polymer entity ("4HHB_1") or instance ("4HHB.A", RCSB chain id), computed models included. For a UniProt or NCBI id, find its PDB entities with rcsb_seqcoord_alignments first. |
Structured output declared, but exposes no named fields.
No examples provided.
How do I install the RCSB PDB MCP server?
RCSB PDB runs locally as a PyPI package, launched with uvx rcsb-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · rcsb-mcp
claude mcp add rcsb-rcsb-mcp -- uvx rcsb-mcp
What is the RCSB PDB MCP server?
RCSB PDB is an MCP server listed in the public MCP registry as io.github.rcsb/rcsb-mcp. MCP server to search, inspect, and cross-reference RCSB Protein Data Bank structures. This page covers its PyPI package (rcsb-mcp).
Is the RCSB PDB MCP server safe to use?
RCSB PDB scores 70 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 4 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the RCSB PDB MCP server expose?
RCSB PDB exposes 36 tools: rcsb_render_report, rcsb_find_go_terms, rcsb_find_interpro_domains, rcsb_find_enzyme_classes, rcsb_find_disease_terms, and 31 more. Their descriptions and schemas cost roughly 11,539 tokens of context every time the server is loaded.
Is the RCSB PDB MCP server still maintained?
RCSB PDB is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.