protein-mcp-server

v0.9.0 pre-1.0

Federated protein structure & annotation across experimental (PDB) and predicted (AlphaFold) models via MCP. STDIO or Streamable HTTP.

protein.caseyjhand.com/mcp
claude mcp add --transport http protein-mcp-server https://protein.caseyjhand.com/mcp
codex mcp add protein-mcp-server --url https://protein.caseyjhand.com/mcp
{
  "mcpServers": {
    "protein-mcp-server": {
      "url": "https://protein.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http protein-mcp-server https://protein.caseyjhand.com/mcp
{
  "mcpServers": {
    "protein-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://protein.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "protein-mcp-server": {
      "type": "http",
      "url": "https://protein.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://protein.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

protein_search_structures

open-world

Search experimental (PDB) and predicted (computed-model) protein structures by free text, protein sequence (triggers an mmseqs2 similarity search), and/or organism, method, resolution, and bound-ligand filters. Returns ranked hits; the experimental page is enriched with title, method, resolution, and source organisms (for a sequence hit, those of the matched entity), and every sequence hit carries its identity, E-value, bit score, and aligned range against the query. Chain hit IDs into protein_get_structure. Optionally returns a facet breakdown (counts by method / organism / release year / …) alongside the hits in the same response. Facets count the filtered result set, so an active organism or method filter also constrains its own facet: the facet lists only the values found in the matching entries (other organisms in the same complexes, other methods deposited with the same entries), never the alternatives the filter excluded. Numeric histogram buckets (resolution, molecular weight) carry explicit rangeFrom/rangeTo bounds so a boundary label is unambiguous.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_search_structures",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "description": "Free-text query (protein name, gene, keyword, PDB title terms).",
      "type": "string"
    },
    "sequence": {
      "description": "Protein sequence for RCSB mmseqs2: at least 10 residues in A–I or K–Z (J excluded; B/O/U/X/Z accepted). Whitespace is removed and ASCII lowercase normalized.",
      "type": "string"
    },
    "organism": {
      "description": "Filter by source organism: a scientific name (\"Homo sapiens\"), an NCBI common name (\"human\", \"E. coli\"), or an NCBI taxon ID (\"9606\"), in any letter case. Matches that taxon and every taxon under it (strains, subspecies); a multi-word name also matches scientific names that contain it, such as \"Escherichia coli (strain K12)\". A word fragment (\"coli\") matches nothing.",
      "type": "string"
    },
    "method": {
      "description": "Filter by experimental method: X-RAY DIFFRACTION, ELECTRON MICROSCOPY, SOLUTION NMR, SOLID-STATE NMR, ELECTRON CRYSTALLOGRAPHY, NEUTRON DIFFRACTION, FIBER DIFFRACTION, POWDER DIFFRACTION, SOLUTION SCATTERING, EPR, FLUORESCENCE TRANSFER, INFRARED SPECTROSCOPY, THEORETICAL MODEL (any letter case), or an alias: cryo-EM / cryoEM / EM → ELECTRON MICROSCOPY; X-ray / xray → X-RAY DIFFRACTION; NMR → SOLUTION NMR + SOLID-STATE NMR. Any other value is rejected. Computed models carry no method, so under content_type \"predicted\" this filter matches nothing.",
      "type": "string"
    },
    "max_resolution": {
      "description": "Maximum resolution in Å (lower is sharper); applies to experimental structures.",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "ligand": {
      "description": "Filter by bound ligand: an exact chemical component ID (e.g. \"STI\" for imatinib, \"HEM\"), in any letter case. Keeps structures holding the component as a bound (non-polymer) copy, not as a residue inside a polymer chain. Resolve a ligand name to its ID with protein_track_ligands mode \"find_ligand\". Computed models carry no ligands, so under content_type \"predicted\" this filter matches nothing.",
      "type": "string"
    },
    "min_identity": {
      "description": "Minimum sequence identity (0–1) for a sequence search. Requires sequence — supplying it without one is rejected, since the threshold filters only a sequence search. Default 0.",
      "type": "number",
      "minimum": 0,
      "maximum": 1
    },
    "max_evalue": {
      "description": "Maximum E-value for a sequence search. Requires sequence — supplying it without one is rejected, since the threshold filters only a sequence search. Default 1.",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "content_type": {
      "default": "all",
      "description": "Which structure universe to search: experimental (PDB), predicted (computed models), or all.",
      "type": "string",
      "enum": [
        "experimental",
        "predicted",
        "all"
      ]
    },
    "facets": {
      "description": "Optional dimensions to summarize as a facet breakdown alongside the hits. Each dimension at most once; repeating one is rejected.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "method",
          "organism",
          "polymer_type",
          "resolution",
          "release_year",
          "molecular_weight"
        ]
      }
    },
    "limit": {
      "default": 25,
      "description": "Maximum hits to return (1–100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "start": {
      "default": 0,
      "description": "Zero-based result offset. Combine with limit to retrieve later pages.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "content_type",
    "limit",
    "start"
  ],
  "additionalProperties": false
}
view source ↗

protein_get_structure

open-world

Fetch structures with metadata and coordinate-file URLs. source "experimental" takes PDB entry IDs, and also resolves the computed-model IDs protein_search_structures returns (AF_*/MA_*), which come back marked source "predicted" with their modelling provider; "predicted" takes UniProt accessions, isoform accessions (P04637-2), or AlphaFold DB entry IDs (AF-P04637-2-F1) (AlphaFold, with pLDDT/PAE confidence); "best_available" takes the same identifiers, an entry ID reduced to its accession, and returns the top federated model — the PDB entry with the widest UniProt coverage, ties going to the finest resolution (coverage measures the mapped span, so the pick can be an engineered mutant over the wild-type entry), else the model with the highest confidence on the lDDT scale (pLDDT/100 or QMEANDisCo), unscored models last, which can include an experimental model outside the PDB such as a SASBDB fit; best_available records carry coverage and the UniProt span. Under predicted and best_available, a UniProt accession merged into another entry resolves to its successor's model with a notice naming the merge, and a demerged or deleted accession lands in failed[] with its replacements. Records fetched under source "experimental", computed models included, also carry polymer entities with both chain namespaces (labelAsymIds for protein_compare_structures, authAsymIds for protein_get_annotations), bound ligands, molecular weight, and release date. Resolves up to the configured batch cap per call with per-ID partial success: IDs are trimmed and repeats looked up once, missed IDs are listed in failed[] with their reasons, and IDs beyond the cap are listed in ignored, never looked up. Upstream lookups share one time budget per call; under predicted and best_available, an ID not finished within it, or whose upstream lookup failed, lands in failed[] with a reason to re-call it. Set include_coords to inline coordinate text, held to 24000 characters per response on both surfaces: a lone selected file arrives in 24000-character windows, each giving coordinatesNextOffset to pass back as coords_offset; several selected files inline whole when they total 24000 characters or fewer, and otherwise overflow lists each file's length — re-call with sections naming one structure to page through its file. coordinateUrls always link the complete files.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_get_structure",
    "arguments": {
      "ids": "<ids>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "ids": {
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "description": "PDB entry IDs or computed-model IDs such as AF_AFP69905F1 (source experimental); UniProt accessions, isoform accessions such as P04637-2, or AlphaFold DB entry IDs such as AF-P04637-2-F1 (predicted / best_available). Trimmed, and a repeat (case-insensitive) is looked up once."
    },
    "source": {
      "default": "experimental",
      "description": "Where to fetch: experimental (PDB), predicted (AlphaFold), or best_available (federated pick).",
      "type": "string",
      "enum": [
        "experimental",
        "predicted",
        "best_available"
      ]
    },
    "include_coords": {
      "default": false,
      "description": "Inline coordinate text for every resolved structure — mmCIF, or PDB format when no mmCIF URL is available; coordinateFormat names which. A lone file arrives in 24000-character windows. Off by default — URLs are always returned.",
      "type": "boolean"
    },
    "sections": {
      "description": "Structure IDs to inline coordinates for, in place of include_coords — from an overflow outline, or one ID to page through its file with coords_offset. Each must match the id of a structure this call resolves.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "coords_offset": {
      "default": 0,
      "description": "Character offset of the window to return when exactly one structure is selected (sections naming one ID, or include_coords on a one-ID call): the window is characters [coords_offset, coords_offset + 24000). Pass the coordinatesNextOffset a previous window returned.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "ids",
    "source",
    "include_coords",
    "coords_offset"
  ],
  "additionalProperties": false
}
view source ↗

protein_find_similar

open-world

Find structurally or evolutionarily related proteins. by:"sequence" runs an RCSB mmseqs2 sequence-similarity search (synchronous; experimental PDB entries only — protein_search_structures with a sequence also reaches computed models) over a sequence — supplied directly, taken from one protein entity of a PDB entry (chain picks it; by default the lowest-numbered protein entity of at least 10 residues; queryEntityId names it), or pulled from a UniProt accession (isoforms included) or entry name (HBA_HUMAN); each hit carries its identity, E-value, bit score, and aligned range. by:"structure" runs a Foldseek fold-similarity search (asynchronous) against experimental and predicted databases, uploading the PDB entry's mmCIF file or the accession's AlphaFold DB model, up to 16,000,000 characters; if the job is still computing when the poll budget elapses, or the call's 50 s budget runs out after Foldseek accepted the job, the response reports status "computing" with a ticket — re-call with ticket_id set to that value to resume the same job instead of resubmitting, and a complete response carries the same ticket so a finished job can be re-paged with a different start. Foldseek searches each chain of a multichain structure as its own query: a response covers one query (query, default 0), reports queryCount, and ranks that query's hits by score across all searched databases. Each mode reads only its own controls: sequence, chain, max_evalue and min_identity belong to by:"sequence"; ticket_id, databases and query belong to by:"structure"; pdb_id, uniprot, start and limit are shared. A field the selected mode cannot consume is rejected rather than silently ignored. A UniProt accession merged into another entry answers for its successor with a notice; a demerged or deleted one fails with its replacements. Output names the engine and database each hit came from; a structure hit also carries its Foldseek target name, and an id only where that name maps to a PDB entry or UniProt accession that protein_get_structure resolves.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_find_similar",
    "arguments": {
      "by": "<by>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "by": {
      "type": "string",
      "enum": [
        "sequence",
        "structure"
      ],
      "description": "Similarity axis: sequence (mmseqs2) or structure (Foldseek)."
    },
    "sequence": {
      "description": "Protein sequence for by:sequence: at least 10 residues in A–I or K–Z (J excluded; B/O/U/X/Z accepted). Whitespace is removed and ASCII lowercase normalized.",
      "type": "string"
    },
    "pdb_id": {
      "description": "PDB entry ID to derive the query from. by:\"sequence\" searches one of its protein entities (see chain); by:\"structure\" uploads its mmCIF file, up to 16,000,000 characters.",
      "type": "string"
    },
    "chain": {
      "description": "Author chain ID (auth_asym_id, case-sensitive) of pdb_id selecting the protein entity whose sequence by:\"sequence\" searches, e.g. \"B\" for the beta chain of 4HHB. Requires pdb_id. Default: the lowest-numbered protein entity of at least 10 residues; DNA and RNA chains never qualify.",
      "type": "string"
    },
    "uniprot": {
      "description": "UniProt identifier to derive the query from: a canonical accession (e.g. P69905), an isoform accession (e.g. P04637-2), or a UniProtKB entry name (e.g. HBA_HUMAN), which resolves to its entry’s accession. by:\"sequence\" searches its UniProt sequence, by:\"structure\" its AlphaFold DB model. A merged accession answers for its successor, with a notice.",
      "type": "string"
    },
    "ticket_id": {
      "description": "Foldseek ticket ID from a prior by:structure response whose status was \"computing\". When set, polls that existing job instead of submitting a new search (by:structure only) — pdb_id/uniprot/databases are ignored.",
      "type": "string"
    },
    "databases": {
      "description": "Foldseek target databases (by:structure), by exact name. Default pdb100 + afdb50. pdb100: experimental PDB entries; afdb50, afdb-swissprot, afdb-proteome: AlphaFold DB models; cath50: CATH domains of PDB chains and AlphaFold models; bfvd_v3: predicted viral proteins; mgnify_esm30, gmgcl_id: predicted metagenomic proteins; bfmd: predicted complexes.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "afdb50",
          "afdb-swissprot",
          "afdb-proteome",
          "bfvd_v3",
          "cath50",
          "mgnify_esm30",
          "pdb100",
          "gmgcl_id",
          "bfmd"
        ]
      }
    },
    "query": {
      "description": "Zero-based Foldseek query index (by:structure). Default 0. Foldseek splits a multichain structure into one query per chain, in file order; queryCount in the response says how many the job holds. Pass the same value with ticket_id to resume or re-page that query.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "max_evalue": {
      "description": "Maximum E-value (by:sequence). Default 1.",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "min_identity": {
      "description": "Minimum sequence identity 0–1 (by:sequence). Default 0.",
      "type": "number",
      "minimum": 0,
      "maximum": 1
    },
    "limit": {
      "default": 25,
      "description": "Maximum hits to return (1–100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "start": {
      "default": 0,
      "description": "Zero-based result offset. Pages a by:sequence search, and a completed by:structure job when re-called with its ticket_id.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "by",
    "limit",
    "start"
  ],
  "additionalProperties": false
}
view source ↗

protein_track_ligands

open-world

Ligand discovery and binding-site analysis across the PDB. mode "find_ligand" resolves a name or formula to chemical component IDs with metadata (formula, weight, SMILES), ranked by deposition frequency — most-deposited component first, so the top hit is the most common match for the name, not necessarily an exact name-string match. The ranking covers a bounded candidate pool; totalCount and candidatesConsidered report how many components matched and how many were ranked. mode "structures_with_ligand" returns PDB entries holding a bound copy of a ligand (by exact component ID — get the ID from find_ligand first), highest-resolution first, each with its resolution in Å, title, method, and the polymer entities whose chains carry the ligand. This mode and find_ligand's depositionCount count bound copies only: a component present only as a residue inside a polymer chain (e.g. MSE in a selenomethionine protein) or a sugar inside a branched glycan is not counted. mode "binding_site" returns the protein residues lining a ligand's pocket in a given structure, with contact distances, each numbered in both the mmCIF label namespace (asymId, seqId) and the author namespace (authAsymId, authSeqId) used by deposited coordinates and most literature. Binding sites are experimental-only (computed from deposited coordinates; predicted models carry no bound ligands).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_track_ligands",
    "arguments": {
      "mode": "<mode>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "mode": {
      "type": "string",
      "enum": [
        "find_ligand",
        "structures_with_ligand",
        "binding_site"
      ],
      "description": "Operation: resolve a ligand, find structures containing it, or analyze its binding site."
    },
    "query": {
      "description": "Ligand name or formula (mode find_ligand).",
      "type": "string"
    },
    "comp_id": {
      "description": "Exact chemical component ID (modes structures_with_ligand and binding_site).",
      "type": "string"
    },
    "pdb_id": {
      "description": "PDB entry ID (mode binding_site).",
      "type": "string"
    },
    "limit": {
      "default": 25,
      "description": "Maximum results to return (1–100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "start": {
      "default": 0,
      "description": "Zero-based result offset (modes structures_with_ligand and binding_site; binding_site pages ligand instances).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "mode",
    "limit",
    "start"
  ],
  "additionalProperties": false
}
view source ↗

protein_compare_structures

open-world

Structurally align multiple structures (up to the configured batch cap; structures past it are returned in ignored) via the RCSB Structural Comparison service (TM-align / jFATCAT). reference:"first" aligns every structure to the first; reference:"all_pairs" computes the full pairwise matrix. Each pair is an independent async alignment job with per-pair partial success — a pair still computing when the budget elapses returns status "computing" with its job UUID, and a failed pair degrades its row without sinking the others. Re-call with a matching entry in resume[] to poll a computing pair's UUID instead of resubmitting; a resumed pair reports a and b in the order its job was submitted, and a resume under a different method is rejected. Returns TM-score, RMSD, and aligned-residue count per pair, plus each structure's modeled-residue count and alignment coverage. TM-score is length-normalized and can shift sharply between structures that differ only by a terminal residue or two — the greedy superposition can settle into a worse local optimum — so read tmScore alongside rmsd, alignedResidues, modeledResidues and coverage, the columns that make such cases diagnosable.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_compare_structures",
    "arguments": {
      "structures": "<structures>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "structures": {
      "minItems": 2,
      "maxItems": 25,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "pdb_id": {
            "type": "string",
            "minLength": 1,
            "description": "PDB entry ID."
          },
          "chain": {
            "description": "mmCIF label_asym_id restricting the alignment to a single chain. Read it from polymerEntities[].labelAsymIds on protein_get_structure (source experimental) or the pdb://{entry_id} resource. Author chain IDs are a different namespace — polymerEntities[].authAsymIds, what protein_get_annotations.chain takes — and are not interchangeable with this one. Case-sensitive.",
            "type": "string"
          }
        },
        "required": [
          "pdb_id"
        ],
        "additionalProperties": false,
        "description": "A structure to align, by PDB entry ID with optional chain."
      },
      "description": "The structures to compare, up to the configured batch cap; structures past it are returned in ignored and not compared. A structure repeated here is compared once."
    },
    "reference": {
      "default": "first",
      "description": "Align all to the first structure, or compute the full pairwise matrix.",
      "type": "string",
      "enum": [
        "first",
        "all_pairs"
      ]
    },
    "method": {
      "default": "tm-align",
      "description": "Alignment algorithm: tm-align, fatcat-rigid, or fatcat-flexible.",
      "type": "string",
      "enum": [
        "tm-align",
        "fatcat-rigid",
        "fatcat-flexible"
      ]
    },
    "timeout_s": {
      "description": "Poll budget per pair in seconds before returning \"computing\". Defaults to the server setting.",
      "type": "integer",
      "minimum": 5,
      "maximum": 120
    },
    "resume": {
      "description": "Resume tickets from a prior call: for each pair whose labels match an entry here, poll the existing UUID instead of submitting a new alignment job. Copy a, b, and uuid verbatim from a prior response's pairs[]; keep structures, reference, and method unchanged. The order of structures may change — a resumed pair keeps the orientation its job was submitted in.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "a": {
            "type": "string",
            "minLength": 1,
            "description": "First structure label (entry or entry.chain) of a pair from a prior response."
          },
          "b": {
            "type": "string",
            "minLength": 1,
            "description": "Second structure label (entry or entry.chain) of a pair from a prior response."
          },
          "uuid": {
            "type": "string",
            "minLength": 1,
            "description": "Alignment job UUID returned for that pair by a prior call."
          }
        },
        "required": [
          "a",
          "b",
          "uuid"
        ],
        "additionalProperties": false,
        "description": "A prior pair to resume by UUID instead of resubmitting."
      }
    }
  },
  "required": [
    "structures",
    "reference",
    "method"
  ],
  "additionalProperties": false
}
view source ↗

protein_analyze_collection

open-world

Profile the PDB into distributions and trends over an optional scoping query: counts by method, organism, or polymer composition; resolution and molecular-weight histograms; release-year timelines; and multidimensional cross-tabs (e.g. method × release_year). Aggregation runs at RCSB, so the response carries compact counts per bucket rather than the matching entries. Pass one group_by dimension for a single breakdown, or two distinct dimensions for a cross-tab (the first nests the second). bucket_limit caps each dimension level separately rather than the response, so a cross-tab returns up to that many nested buckets under each of its capped parent buckets; bucketsReturned reports the realized total.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_analyze_collection",
    "arguments": {
      "group_by": "<group_by>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "group_by": {
      "minItems": 1,
      "maxItems": 2,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "method",
          "organism",
          "polymer_type",
          "resolution",
          "release_year",
          "molecular_weight"
        ]
      },
      "description": "1 dimension for a breakdown, or 2 distinct dimensions for a cross-tab (the first nests the second). Repeating a dimension is rejected."
    },
    "query": {
      "description": "Optional free-text scope (e.g. \"kinase\"); omit to profile the whole PDB.",
      "type": "string"
    },
    "organism": {
      "description": "Optional source-organism scope: a scientific name (\"Homo sapiens\"), an NCBI common name (\"human\"), or an NCBI taxon ID (\"9606\"), in any letter case. Matches that taxon and every taxon under it; a multi-word name also matches scientific names that contain it. A word fragment (\"coli\") matches nothing.",
      "type": "string"
    },
    "method": {
      "description": "Optional experimental-method scope: X-RAY DIFFRACTION, ELECTRON MICROSCOPY, SOLUTION NMR, SOLID-STATE NMR, ELECTRON CRYSTALLOGRAPHY, NEUTRON DIFFRACTION, FIBER DIFFRACTION, POWDER DIFFRACTION, SOLUTION SCATTERING, EPR, FLUORESCENCE TRANSFER, INFRARED SPECTROSCOPY, THEORETICAL MODEL (any letter case), or an alias: cryo-EM / cryoEM / EM → ELECTRON MICROSCOPY; X-ray / xray → X-RAY DIFFRACTION; NMR → SOLUTION NMR + SOLID-STATE NMR. Any other value is rejected.",
      "type": "string"
    },
    "max_resolution": {
      "description": "Optional maximum-resolution scope (Å).",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "content_type": {
      "default": "experimental",
      "description": "Which structure universe to profile. Default experimental. Computed models carry no experimental metadata, so method and resolution return nothing under \"predicted\".",
      "type": "string",
      "enum": [
        "experimental",
        "predicted",
        "all"
      ]
    },
    "interval": {
      "description": "Bin width for a histogram dimension (a number, for resolution or molecular_weight) or period for a date histogram (\"year\", for release_year). Applies to whichever requested group_by dimension can consume that value type — primary or nested child — so a cross-tab like [\"method\",\"resolution\"] bins its nested resolution child. When both requested dimensions can consume it the primary takes it and the child keeps its default. When neither can, the call is rejected rather than silently ignoring the override.",
      "anyOf": [
        {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Numeric bin width for a value histogram (e.g. resolution Å)."
        },
        {
          "type": "string",
          "enum": [
            "year"
          ],
          "description": "Period granularity for a date histogram. Only \"year\"."
        }
      ]
    },
    "bucket_limit": {
      "description": "Max buckets per dimension level, not per response. A cross-tab applies the cap separately to the parent dimension and to the nested child inside each parent bucket, so up to bucket_limit × (1 + bucket_limit) buckets can come back — 2550 at the default 50. The realized count comes back as bucketsReturned. Defaults to the configured server cap.",
      "type": "integer",
      "minimum": 1,
      "maximum": 500
    }
  },
  "required": [
    "group_by",
    "content_type"
  ],
  "additionalProperties": false
}
view source ↗

protein_get_annotations

open-world

Sequence and functional annotation for a protein: UniProt positional features (domains, binding and active sites, PTMs including cross-links and lipidation, topology, DNA binding, processing products such as chains and signal peptides, mutagenesis), natural variants, and InterPro domain/family memberships (Pfam, PROSITE, …) with GO terms. Provide a canonical UniProt accession directly, or a PDB ID — it is resolved to its UniProt accession via the structure's sequence cross-reference. A multi-chain PDB entry can map to several accessions; the default pick is deterministic (lowest author chain ID) and the alternatives are listed in "ambiguity" — pass "chain" to select a specific one. An accession UniProt merged into another entry answers for that successor with a notice; a demerged or deleted one fails with its replacement accessions. Use "include" to scope which annotation classes are fetched. Every response carries an "attribution" block with the upstream data licenses and citations.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "protein_get_annotations",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "uniprot": {
      "description": "Canonical UniProt accession (e.g. P69905). Isoform accessions (e.g. P04637-2) are rejected; UniProt annotates the canonical entry. Takes precedence over pdb_id.",
      "type": "string"
    },
    "pdb_id": {
      "description": "PDB entry ID; resolved to a UniProt accession via cross-reference.",
      "type": "string"
    },
    "chain": {
      "description": "Author chain ID (auth_asym_id, e.g. \"A\") that disambiguates a multi-chain PDB entry to a specific UniProt accession. Case-sensitive — must match the author chain ID exactly (large structures can carry distinct \"A\" and \"a\" chains). Only applies with pdb_id; ignored when uniprot is supplied directly. See polymerEntities[].authAsymIds in the pdb://{entry_id} resource for an entry's author chain IDs.",
      "type": "string"
    },
    "include": {
      "default": "all",
      "description": "Which annotation classes to fetch: features, domains (InterPro), variants, or all.",
      "type": "string",
      "enum": [
        "features",
        "domains",
        "variants",
        "all"
      ]
    },
    "limit": {
      "default": 50,
      "description": "Per-class page size (1–200, default 50). Continue each class independently with features_offset, variants_offset, or domains_offset; the notice gives the next offset.",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "features_offset": {
      "default": 0,
      "description": "Zero-based offset into functional features; independent of variants and domains.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "variants_offset": {
      "default": 0,
      "description": "Zero-based offset into natural variants; independent of features and domains.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "domains_offset": {
      "default": 0,
      "description": "Zero-based offset into InterPro memberships; independent of features and variants.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "include",
    "limit",
    "features_offset",
    "variants_offset",
    "domains_offset"
  ],
  "additionalProperties": false
}
view source ↗

Resources

2

Experimental structure summary for a PDB entry: title, method, resolution, source organisms, bound ligands, and per-entity chain IDs in both the author (auth_asym_id) and mmCIF label (label_asym_id) namespaces.

uri pdb://{entry_id} mime application/json

Predicted-structure summary from AlphaFold DB for a UniProt accession, isoform accession, or AlphaFold DB entry ID: mean pLDDT, confidence-band fractions, model URLs, and version. A UniProt accession merged into another entry answers with the successor’s model and a notice; a demerged or deleted one fails with its replacements.

uri af://{uniprot} mime application/json

Extensions

1

io.modelcontextprotocol/skills

{
  "directoryRead": true
}