RCSB PDB README

The full upstream README, mirrored for reference. Install config, tool schemas, adoption signals and our own overview live on the RCSB PDB listing page.

rcsb-mcp

An MCP server for interrogating Protein Data Bank structures — discover, inspect, and cross-reference — from LLM clients (Claude Desktop, MCP Inspector, Cursor, etc.). It spans three RCSB APIs:

  • Discover — find structures with the Search API (keyword, attribute, sequence, chemistry, 3D shape, motif).
  • Inspect — fetch entry / entity / assembly / ligand details and annotations from the Data API.
  • Relate — map sequences and positional features across PDB, UniProt, and NCBI with the Sequence Coordinates API.

Tools

Search (search.rcsb.org)

Searching is two steps: build a query with an rcsb_query_* tool, then execute it with rcsb_search_request. The builders are pure — they return a query document (readable JSON plus a digest) and touch no network, so nothing is searched until you call rcsb_search_request. rcsb_query_composer joins two or more documents with AND/OR, which is also how a single search mixes services (e.g. sequence similarity AND an organism filter).

Build

ToolWhat it does
rcsb_query_fulltextFree-text keyword query (e.g. "CRISPR Cas9").
rcsb_query_attributeStructured query on one or more indexed attributes (resolution, organism, release date, ...) joined by a single logical_operator. Each condition supports exists, negation, case_sensitive; chemical_attributes=True selects the chemical-component catalog.
rcsb_query_sequenceMMseqs2 sequence-similarity query (BLAST-like), with identity / e-value cutoffs.
rcsb_query_chemicalChemical query by SMILES/InChI descriptor (whole-molecule or substructure) or molecular formula.
rcsb_query_structure3D shape-similarity query against a reference PDB assembly or chain.
rcsb_query_seqmotifShort sequence-motif query (PROSITE pattern, regex, or simple wildcards).
rcsb_query_strucmotif3D structural-motif query: a geometric arrangement of specific residues (e.g. a catalytic triad).
rcsb_query_composerJoin 2+ query documents with AND/OR — nested boolean logic, and the only way to combine different services in one search.

Run

ToolWhat it does
rcsb_search_requestExecute a query document and return matching identifiers only. Carries every output option: return_type, limit/offset, all_hits, facets, sort_by/sort_direction, group_by/group_by_ranking, include_computed_models.

Discover

ToolWhat it does
rcsb_list_pdb_search_attributesDiscover searchable attribute paths, types, and operators. schema="structure" (default, ~636) or schema="chemical" (~58: chem_comp.*, drugbank_info.*, ...). Records also carry enum (closed value sets) and nested_group (attributes stored in nested objects — see below).
rcsb_find_go_termsResolve a free-text molecular function / biological process / cellular component to Gene Ontology ids (via EBI QuickGO), annotated with PDB entry counts — then search by rcsb_polymer_entity_annotation.annotation_lineage.id.
rcsb_find_interpro_domainsResolve a free-text protein domain / family / fold to InterPro and Pfam ids (via EBI Search), annotated with PDB entry counts — then search by rcsb_polymer_entity_annotation.annotation_id.
rcsb_find_enzyme_classesResolve a free-text enzyme / reaction to Enzyme Commission (EC) numbers (via EBI Search/IntEnz), annotated with PDB entry counts — then search by rcsb_polymer_entity.rcsb_ec_lineage.id (hierarchical).
rcsb_find_disease_termsResolve a free-text disease / condition to MONDO ids (via EBI OLS), annotated with PDB entry counts — then search by rcsb_uniprot_annotation.annotation_lineage.id (hierarchical, UniProt-based).
rcsb_find_organismsResolve a free-text organism / common name / clade to NCBI Taxonomy ids (via UniProt taxonomy), annotated with PDB entry counts — then search by rcsb_entity_source_organism.taxonomy_lineage.id (hierarchical: a clade id matches every organism beneath it).

Both attribute catalogs are generated from the live metadata schemas by scripts/generate_search_attributes.py. To search chemical-component attributes, find the path with rcsb_list_pdb_search_attributes(schema="chemical"), pass chemical_attributes=True to rcsb_query_attribute, and usually set return_type="mol_definition".

Nested attributes. An object can hold many annotations, many binding affinities, many citations. For attributes carrying a nested_group, the query shape selects the semantics: conditions built in one rcsb_query_attribute call, with nothing else in it, must hold on the same record; conditions in separate calls are matched independently against any record. Both are valid and mean different things — type=Kd with value<1 describes one measurement, while an InterPro id and a GO type are necessarily two different annotations.

Counting and faceting are output options on rcsb_search_request, not separate tools: every response includes total_count (the full match count — for "how many ..." run the search with limit=1 and read it), and passing facets returns a breakdown (terms/histogram/date_histogram/range/cardinality) instead of hits. A terms facet also tells you what your hits share, which is how a handful of results becomes a re-searchable value.

Grouping. group_by returns one representative per cluster — seqid_30 … seqid_95 for sequence-identity clusters, or uniprot to collapse by accession — with group_by_ranking choosing the representative. Requires return_type="polymer_entity"; the response reports group_count alongside total_count.

Sorting. sort_by (an attribute path) + sort_direction (asc/desc) replaces the default score ordering (for similarity searches this overrides the similarity-ranked order). Only attributes indexed for sorting work — those exposing exact_match (strings) or equals (numbers/dates) in rcsb_list_pdb_search_attributes; sorting is not available for return_type="mol_definition".

Paging. rcsb_search_request accepts limit (1–100, default 10) and offset (default 0), and each response reports total_count, has_more, and next_offset — call again with the same query document and offset=next_offset. For an explicit "ALL ..." request, all_hits=True returns the complete set in one call (refused above 10,000 hits, and it cannot be combined with offset).

Data (data.rcsb.org/graphql)

There is one tool per Data API GraphQL root field. Each takes a list of IDs (singular lookups = a one-element list) plus an optional fields argument to override the curated default selection with your own GraphQL sub-selection. Unknown IDs are reported under not_found. Discover the paths to put in fields with rcsb_describe_data_object — browse a level, drill into a nested object with into=, or search the schema by keyword with query= + max_depth=. Every path it returns is verified against the live schema, so don't guess field names.

ToolObjectExample ID
rcsb_get_entriesPDB entries"4HHB"
rcsb_get_polymer_entitiesPolymer entities (protein/NA)"4HHB_1"
rcsb_get_nonpolymer_entitiesLigand/cofactor entities"4HHB_3"
rcsb_get_branched_entitiesCarbohydrate entities"5FMB_2"
rcsb_get_polymer_entity_instancesPolymer chains"4HHB.A"
rcsb_get_nonpolymer_entity_instancesBound-ligand instances"4HHB.E"
rcsb_get_branched_entity_instancesGlycan chains"5FMB.C"
rcsb_get_assembliesBiological assemblies"4HHB-1"
rcsb_get_interfacesAssembly interfaces"1BMV-1.1"
rcsb_get_chem_compsChemical components / ligands"HEM", "ATP"
rcsb_get_entry_groupsEntry groups"G_1002266"
rcsb_get_polymer_entity_groupsPolymer entity groups (seq. clusters)"85_70"
rcsb_get_nonpolymer_entity_groupsNon-polymer entity groups"ATP"
rcsb_get_uniprotUniProt record (single)"P69905"
rcsb_get_pubmedPubMed record (single, integer)6726807
rcsb_get_group_provenanceGrouping provenance (single)"provenance_sequence_identity"
rcsb_describe_data_objectIntrospect an object's live GraphQL schema to build a fields= selection: browse a level, drill into a nested object with into=, or search by keyword with query= + max_depth= (flat, incl. nested + cross-object paths). Returns verified dotted paths. The Data API analogue of rcsb_list_pdb_search_attributes.—

The Search API only returns identifiers, so a search is the first step: batch the returned ids into the matching rcsb_get_* tool to fetch titles, organisms, and other metadata (these tools query the GraphQL endpoint, batching every requested ID into one request). All 16 typed tools are generated from a single registry in queries.py (DATA_OBJECTS), so adding a field or endpoint is a one-line change.

Sequence Coordinates (sequence-coordinates.rcsb.org/graphql)

Maps alignments and positional annotations between sequence reference systems (UNIPROT, NCBI_PROTEIN, NCBI_GENOME, PDB_ENTITY, PDB_INSTANCE). Each tool takes an optional fields argument to override the default selection; use rcsb_describe_seqcoord_object to discover what fields are available.

This is the only RCSB API that cross-references NCBI (RefSeq protein / genome) — the Data API only knows UniProt. So "what NCBI proteins map to a PDB structure?" is answered by rcsb_seqcoord_alignments, not the Data API. PDB query ids must be entity-level (4HHB_1), not a bare entry (4HHB); for a whole entry, query each polymer entity.

ToolWhat it does
rcsb_seqcoord_alignmentsCross-reference a sequence across PDB / UniProt / NCBI with aligned ranges (e.g. 4HHB_1 → NCBI proteins NP_000508, NP_000549).
rcsb_seqcoord_annotationsPositional features of a PDB entity or instance (7CUT_1, 4HHB.A) from UniProt, the entity, its instances and their interfaces, optionally only some feature_types (ACTIVE_SITE); the sources follow from the types.
rcsb_describe_seqcoord_objectIntrospect the live schema to discover fields available on a seqcoord object (for use with fields=).

Report

ToolWhat it does
rcsb_render_reportRender a structured report of search results — title, columns, rows and evidence — into a formatted HTML document for the user.

Install

RCSB hosts the server, so most clients need no install — point them at https://mcp-beta.rcsb.org/mcp (see Connect an agent). Install only to run it yourself, pin a version, or develop against it:

bash
# run the published package without installing
uvx rcsb-mcp
# or install it
pip install rcsb-mcp

rcsb-mcp is listed in the Official MCP Registry as io.github.rcsb/rcsb-mcp, so registry-aware clients can discover it directly.

For local development, install from the project root instead:

Terminal
pip install -e .
# or with uv
uv pip install -e .

Run / test

bash
# unit tests (no network)
hatch test          # or: python tests/test_queries.py

# run the server over stdio
python -m rcsb_mcp.server
# or, after install:
rcsb-mcp

# inspect interactively
npx @modelcontextprotocol/inspector python -m rcsb_mcp.server

There are two evaluation suites (evals/): rcsb_pdb_eval.xml, 14 read-only, stable questions measuring how well an LLM can drive these tools to answer real PDB questions, and evals/tool_selection/, a first-tool-call A/B harness for catching routing regressions after a docstring edit. See evals/README.md to run either.

Connect an agent

Hosted (beta)

Code
https://mcp-beta.rcsb.org/mcp

Streamable HTTP, no install, no API key, no account. The deployment is stateless — any replica answers any request, so no session header is needed and there is nothing to keep alive between calls. It serves the same 36 tools and the rcsb_search_assistant prompt as a local run.

Claude Code

Terminal
claude mcp add --transport http rcsb-mcp https://mcp-beta.rcsb.org/mcp

Claude Desktop — Settings → Connectors → Add custom connector, and paste the URL.

Any client that takes a URL (.mcp.json, Cursor, VS Code, Zed, …):

config.json
{
  "mcpServers": {
    "rcsb-mcp": {
      "type": "http",
      "url": "https://mcp-beta.rcsb.org/mcp"
    }
  }
}

Stdio-only clients can bridge with mcp-remote:

config.json
{
  "mcpServers": {
    "rcsb-mcp": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp-beta.rcsb.org/mcp"]
    }
  }
}

Check it by hand — a bare initialize needs no session setup:

Terminal
curl -s https://mcp-beta.rcsb.org/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
        "protocolVersion":"2025-06-18","capabilities":{},
        "clientInfo":{"name":"curl","version":"0"}}}'

GET /healthz returns 200 for liveness checks. Opening the endpoint (or the site root) in a web browser shows a short page on how to connect a client; MCP clients are unaffected.

Beta. The endpoint, the tool surface and the tool descriptions may change without notice, and there is no stability guarantee — pin uvx rcsb-mcp==<version> and run it yourself if you need a fixed surface. When reporting a problem, include the serverInfo.version from the initialize response so the build is identifiable.

Local (stdio)

Run the server as a subprocess instead — for development, or to pin a version.

Edit claude_desktop_config.json:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
config.json
{
  "mcpServers": {
    "rcsb-mcp": {
      "command": "uvx",
      "args": ["rcsb-mcp"]
    }
  }
}

For a local source checkout, point at the module instead:

config.json
{
  "mcpServers": {
    "rcsb-mcp": {
      "command": "python",
      "args": ["-m", "rcsb_mcp.server"],
      "cwd": "/absolute/path/to/rcsb-mcp/src"
    }
  }
}

Restart Claude Desktop. The tools appear under the connectors (plug) icon.

Example prompts

  • "Find high-resolution human hemoglobin structures." → rcsb_query_fulltext + rcsb_query_attribute → rcsb_query_composer → rcsb_search_request
  • "Human hemoglobin structures better than 2 Å, best resolution first." → same, with sort_by on rcsb_search_request
  • "What PDB entries match this protein sequence: MTEY..." → rcsb_query_sequence → rcsb_search_request
  • "Find structures containing a ligand like this SMILES / with formula C8H9NO2." → rcsb_query_chemical → rcsb_search_request
  • "Which structures have a 3D fold similar to 4HHB?" → rcsb_query_structure → rcsb_search_request
  • "Find proteins with a zinc-finger motif." → rcsb_query_seqmotif → rcsb_search_request
  • "Structures of proteins with kinase activity / involved in DNA repair / in the mitochondrial membrane." → rcsb_find_go_terms → rcsb_query_attribute on rcsb_polymer_entity_annotation.annotation_lineage.id
  • "Structures containing an SH2 domain / immunoglobulin fold." → rcsb_find_interpro_domains → rcsb_query_attribute on rcsb_polymer_entity_annotation.annotation_id
  • "Alcohol dehydrogenase structures / any EC 3.4.21 serine protease." → rcsb_find_enzyme_classes → rcsb_query_attribute on rcsb_polymer_entity.rcsb_ec_lineage.id
  • "Structures of proteins associated with cystic fibrosis / breast cancer." → rcsb_find_disease_terms → rcsb_query_attribute on rcsb_uniprot_annotation.annotation_lineage.id
  • "Structures from mammals / from a particular organism or clade." → rcsb_find_organisms → rcsb_query_attribute on rcsb_entity_source_organism.taxonomy_lineage.id
  • "Non-redundant human kinase structures (90% identity clusters)." → rcsb_search_request with group_by="seqid_90", return_type="polymer_entity"
  • "How many human X-ray structures are there?" → rcsb_query_attribute → rcsb_search_request with limit=1 (read total_count)
  • "Break down ribosome structures by experimental method / by release year." → rcsb_search_request with facets
  • "Find structures with the same catalytic-site geometry as residues 162/193/219 of 2MNR." → rcsb_query_strucmotif → rcsb_search_request
  • "Find chemical components under 150 Da." → rcsb_list_pdb_search_attributes(schema="chemical") → rcsb_query_attribute with chemical_attributes=True → rcsb_search_request with return_type="mol_definition"
  • "Summarize PDB entries 4HHB, 1MBN and 6VXX." → rcsb_get_entries
  • "What's the sequence and organism of entity 4HHB_1?" → rcsb_get_polymer_entities
  • "Tell me about the ligand HEM." → rcsb_get_chem_comps
  • "What's the composition of the 4HHB biological assembly?" → rcsb_get_assemblies
  • "Which PDB entries does P69905 map to?" → rcsb_get_uniprot
  • "Which PDB entities align to UniProt P69905, and over what ranges?" → rcsb_seqcoord_alignments
  • "What NCBI proteins map to 4HHB?" → rcsb_seqcoord_alignments per entity (4HHB_1, 4HHB_2), to_ref=NCBI_PROTEIN
  • "Which binding sites map onto PDB entity 4HHB_1?" → rcsb_seqcoord_annotations with feature_types=["BINDING_SITE"]
  • "Pull a field the compact defaults don't include." → rcsb_describe_data_object to find the path, then the matching rcsb_get_* tool with fields=

Notes

  • Search endpoint: https://search.rcsb.org/rcsbsearch/v2/query (POST, JSON body).
  • Data endpoint: https://data.rcsb.org/graphql (POST, GraphQL). It returns HTTP 200 even for query errors, reporting them in an errors array.
  • Sequence Coordinates endpoint: https://sequence-coordinates.rcsb.org/graphql (POST, GraphQL; same HTTP-200-with-errors behavior).
  • The rcsb_find_* resolvers map free text to ontology ids via EBI services — the non-RCSB dependencies: GO via QuickGO (.../QuickGO/services/ontology/go/search), InterPro and Pfam via EBI Search (.../ebisearch/ws/rest/interpro7), EC via EBI Search/IntEnz (.../ebisearch/ws/rest/intenz), disease via OLS/MONDO (.../ols4/api/search?ontology=mondo), and organisms via UniProt (.../rest.uniprot.org/taxonomy/search). The resolved ids then drive RCSB annotation searches (rcsb_polymer_entity_annotation.*, rcsb_polymer_entity.rcsb_ec_lineage.id, rcsb_uniprot_annotation.annotation_lineage.id).
  • No API key required; the APIs are public. Be considerate with request volume.
  • Every outbound request sends User-Agent: rcsb-mcp/<version> (https://github.com/rcsb/rcsb-mcp), <version> being the installed package's (pyproject.toml's) version. Set RCSB_MCP_USER_AGENT to override it (printable ASCII; a {version} in it is filled in the same way); the Helm chart does, so the hosted service's traffic is distinguishable from local installs in upstream logs.
  • A full list of searchable attributes for rcsb_query_attribute is in the Search API attribute reference; the Data API schema is documented at data.rcsb.org/index.html#gql-api.

Prompt

The server exposes one MCP prompt, rcsb_search_assistant ("RCSB PDB search assistant") — the search requirements plus the HTML-report output format. Because it is served over the protocol's prompts capability, any MCP client can list and invoke it (Claude Desktop surfaces server prompts in the + / prompt menu); there's nothing to copy-paste. The text lives in src/rcsb_mcp/prompts/rcsb_search_assistant.md and ships with the package.

Invoke it when you want answers formatted as a PDB report. It is not required for the tools to work: every routing rule, gotcha and cross-reference lives on the tool descriptions themselves, which the protocol always delivers. That guidance used to live in two other places, both retired: the server instructions block (clients truncate or drop it) and a second rcsb_mcp_guide prompt (opt-in, so it may never be loaded). instructions now carries only a short map of the tool families, for clients that show tool names before loading their descriptions; every line restates a tool description, and nothing in it is needed to use the tools. prompts/rcsb_mcp_guide.md is kept on disk, unserved, as a source to rescue prose from.