uniprot-mcp-server

v0.2.1 pre-1.0

Search UniProtKB by protein function, fetch curated records, map IDs across databases, and pull reference proteomes, taxonomy, and sequences via MCP. STDIO or Streamable HTTP.

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

Tools

6

uniprot_search_proteins

open-world

Search UniProtKB and return curated protein records. Pass text_search for a plain-language query (the 80% case) or query for the full Lucene field syntax (gene:TP53 AND organism_id:9606 AND reviewed:true) — exactly one is required. Reviewed (Swiss-Prot) entries are manually curated; unreviewed (TrEMBL) are computationally predicted and ~30x more numerous, so reviewed defaults to true to avoid drowning in predictions — set it false to include TrEMBL. Request facets (e.g. reviewed, model_organism) for server-side count breakdowns. Results page forward with an opaque cursor; UniProtKB has no offset paging. This is the discovery entry point — chain results[].accession into uniprot_get_entry for full records, or uniprot_get_sequence for FASTA.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_search_proteins",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "text_search": {
      "description": "Plain-language search across protein names, gene names, and function, e.g. \"kinase apoptosis\". Provide this OR query, not both.",
      "type": "string"
    },
    "query": {
      "description": "UniProtKB Lucene query with field prefixes — gene, organism_id, keyword (KW-xxxx), go (GO id), reviewed, protein_name, family, length, existence, accession. Example: \"gene:BRCA1 AND organism_id:9606 AND reviewed:true\". Provide this OR text_search, not both.",
      "type": "string"
    },
    "reviewed": {
      "default": true,
      "description": "Restrict to reviewed Swiss-Prot entries. Defaults to true (curated only); set false to include unreviewed TrEMBL. Ignored when query already pins a reviewed: clause.",
      "type": "boolean"
    },
    "organism_id": {
      "description": "Restrict to an NCBI taxon ID, e.g. 9606 for human. A convenience filter ANDed onto the query; resolve names with uniprot_get_taxonomy.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "fields": {
      "description": "Comma-separated UniProtKB field names to project, e.g. \"accession,gene_names,cc_function\". Omit for a sensible default set covering name, gene, organism, length, reviewed, score, and a function snippet.",
      "type": "string"
    },
    "facets": {
      "description": "Comma-separated upstream facet names for count breakdowns, e.g. \"reviewed,model_organism,proteins_with\". Returns a facets array alongside the hits.",
      "type": "string"
    },
    "size": {
      "description": "Number of hits per page (max 500). Omit for the server default.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 500
    },
    "cursor": {
      "description": "Opaque forward-pagination cursor from a prior response. Walk pages with this; random access to page N is not supported.",
      "type": "string"
    }
  },
  "required": [
    "reviewed"
  ],
  "additionalProperties": false
}
view source ↗

uniprot_get_entry

open-world

Fetch full curated UniProtKB entries by accession in one batch (up to 20). Each entry carries function, catalytic activity, cofactors, subcellular location, disease involvement, PTMs, natural variants, isoforms, domains, GO terms, keywords, and cross-references. Partial failures do not abort the batch — resolved entries land in succeeded[] and unknown/withdrawn accessions in failed[]. Pass fields to trim the upstream projection. A single oversized record returns kind: "outline" (a section listing with byte sizes) instead of overflowing context — re-call the same accession with sections:[...] (e.g. ["disease","variants"]) to pull only those. This tool does not search: accessions come from uniprot_search_proteins.results[].accession or uniprot_map_ids. Strip any isoform suffix (P04637-2 to P04637) before calling.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_get_entry",
    "arguments": {
      "accessions": "<accessions>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "accessions": {
      "minItems": 1,
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^(?:[OPQ][0-9][A-Z0-9]{3}[0-9]|[A-NR-Z][0-9](?:[A-Z][A-Z0-9]{2}[0-9]){1,2})$",
        "description": "A UniProtKB primary accession, e.g. \"P04637\". Canonical form only — strip any \"-N\" isoform suffix."
      },
      "description": "Accessions to fetch (1–20). From uniprot_search_proteins or uniprot_map_ids."
    },
    "fields": {
      "description": "Comma-separated UniProtKB field names to project, e.g. \"accession,gene_names,cc_function,ft_variant\". Omit for the full curated default set. Use this on the initial call to trim payload.",
      "type": "string"
    },
    "sections": {
      "description": "Only used to re-call after a kind: \"outline\" response — pass a subset of the outlined section keys to fetch just those sections. Do not pass on the initial call.",
      "type": "array",
      "items": {
        "type": "string",
        "description": "A section key from a prior outline response, e.g. \"disease\", \"variants\", \"function\", \"xrefs\"."
      }
    }
  },
  "required": [
    "accessions"
  ],
  "additionalProperties": false
}
view source ↗

uniprot_map_ids

open-world

Translate identifiers across databases via UniProt's ID-mapping service — gene names to accessions, accession to PDB / Ensembl / RefSeq / ChEMBL / GeneID, and back. The job runs asynchronously; this tool submits it and polls within a budget. If it finishes in time you get status "finished" with the mappings; if it runs long you get status "running" with a ticket — re-call with that ticket (and no other inputs) to fetch the result without re-submitting. A gene name often maps to one reviewed Swiss-Prot accession plus dozens of unreviewed TrEMBL ones, so target UniProtKB-Swiss-Prot (reviewed only) for the usual intent, or UniProtKB / UniProtKB_AC-ID to include TrEMBL. Pair a gene-symbol from_db with tax_id to disambiguate species. Chain the resulting accessions into uniprot_get_entry.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_map_ids",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "from_db": {
      "description": "Source database. Gene_Name = HGNC symbol (pair with tax_id); UniProtKB_AC-ID = accession or entry name; Ensembl/Ensembl_Protein = ENSG/ENSP; PDB; RefSeq_Nucleotide/RefSeq_Protein = NM_/NP_; ChEMBL; GeneID = NCBI Gene. Required unless resuming with a ticket.",
      "type": "string",
      "enum": [
        "UniProtKB_AC-ID",
        "Gene_Name",
        "GeneID",
        "Ensembl",
        "Ensembl_Protein",
        "PDB",
        "RefSeq_Nucleotide",
        "RefSeq_Protein",
        "ChEMBL",
        "PomBase",
        "WormBase_Protein"
      ]
    },
    "to_db": {
      "description": "Target database. UniProtKB-Swiss-Prot = reviewed accessions only (the usual intent); UniProtKB / UniProtKB_AC-ID also include unreviewed TrEMBL. Required unless resuming with a ticket.",
      "type": "string",
      "enum": [
        "UniProtKB",
        "UniProtKB-Swiss-Prot",
        "UniProtKB_AC-ID",
        "Gene_Name",
        "GeneID",
        "Ensembl",
        "Ensembl_Protein",
        "PDB",
        "RefSeq_Nucleotide",
        "RefSeq_Protein",
        "ChEMBL",
        "PomBase",
        "WormBase_Protein"
      ]
    },
    "ids": {
      "description": "Identifiers to translate. Required unless resuming with a ticket.",
      "maxItems": 100000,
      "type": "array",
      "items": {
        "type": "string",
        "description": "A source identifier in the from_db namespace, e.g. \"TP53\" for Gene_Name."
      }
    },
    "tax_id": {
      "description": "NCBI taxon ID to disambiguate ambiguous source IDs (e.g. a gene symbol across species). Recommended with Gene_Name; e.g. 9606 for human.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "ticket": {
      "description": "A ticket from a prior status \"running\" response. Pass this alone (no from_db/to_db/ids) to fetch the completed result.",
      "type": "string"
    }
  },
  "additionalProperties": false
}
view source ↗

uniprot_get_proteome

open-world

Fetch the reference proteome for an organism by UPID (e.g. "UP000005640") or NCBI taxon ID (e.g. 9606) — provide exactly one. Returns metadata inline: proteome type, total protein count, BUSCO completeness (score, complete/fragmented/missing counts, lineage dataset), and the genome assembly accession. The protein set is opt-in via include_proteins (it is large — human is ~147,506) and returns a capped page with a forward cursor; narrow it with the query filter (UniProtKB Lucene syntax) for a subset. Resolve an organism name to a taxon ID first with uniprot_get_taxonomy.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_get_proteome",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "upid": {
      "description": "Proteome UPID. Provide this OR taxon_id, not both.",
      "anyOf": [
        {
          "type": "string",
          "const": ""
        },
        {
          "type": "string",
          "pattern": "^UP[0-9]{9}$",
          "description": "Proteome identifier, e.g. \"UP000005640\"."
        }
      ]
    },
    "taxon_id": {
      "description": "NCBI taxon ID, e.g. 9606 for human. Resolves to the reference proteome. Provide this OR upid, not both.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "include_proteins": {
      "default": false,
      "description": "When true, also return a capped, cursor-paginated page of the proteome's proteins. Defaults to false — metadata alone is the common case.",
      "type": "boolean"
    },
    "query": {
      "description": "Optional UniProtKB Lucene filter to narrow the protein list, e.g. \"reviewed:true AND keyword:KW-0067\". Only applies when include_proteins is true.",
      "type": "string"
    },
    "size": {
      "description": "Proteins per page when include_proteins is true (max 500). Omit for the server default.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 500
    },
    "cursor": {
      "description": "Forward-pagination cursor from a prior protein page. Only meaningful with include_proteins.",
      "type": "string"
    }
  },
  "required": [
    "include_proteins"
  ],
  "additionalProperties": false
}
view source ↗

uniprot_get_taxonomy

open-world

Resolve a taxonomy record by NCBI taxon ID (e.g. 9606) or scientific name (e.g. "Homo sapiens") — provide exactly one. Returns the scientific and common name, mnemonic, rank, parent, and the full lineage. Set include_children to also fetch immediate child taxa (a separate lookup — not inline on the record). Use this to turn an organism name into the taxon ID that uniprot_search_proteins (organism_id) and uniprot_get_proteome (taxon_id) expect.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_get_taxonomy",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "taxon_id": {
      "description": "NCBI taxonomy ID, e.g. 9606. Provide this OR name, not both.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "name": {
      "description": "Organism scientific name, e.g. \"Homo sapiens\". Provide this OR taxon_id, not both. Matched against the scientific name.",
      "type": "string"
    },
    "include_children": {
      "default": false,
      "description": "When true, also fetch the immediate child taxa via a follow-up search. Defaults to false.",
      "type": "boolean"
    }
  },
  "required": [
    "include_children"
  ],
  "additionalProperties": false
}
view source ↗

uniprot_get_sequence

open-world

Fetch the canonical amino-acid sequence (FASTA) for a UniProtKB accession, with length and the parsed header. Set include_isoforms to also return the alternatively-spliced isoform sequences. This is the cheap sequence-only path — for the full functional record use uniprot_get_entry. Accessions come from uniprot_search_proteins or uniprot_map_ids; strip any "-N" isoform suffix (P04637-2 to P04637) before calling.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uniprot_get_sequence",
    "arguments": {
      "accession": "<accession>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "accession": {
      "type": "string",
      "pattern": "^(?:[OPQ][0-9][A-Z0-9]{3}[0-9]|[A-NR-Z][0-9](?:[A-Z][A-Z0-9]{2}[0-9]){1,2})$",
      "description": "UniProtKB primary accession, e.g. \"P04637\". Canonical form only — strip any \"-N\" isoform suffix."
    },
    "include_isoforms": {
      "default": false,
      "description": "When true, also return the isoform sequences. Defaults to false (canonical only).",
      "type": "boolean"
    }
  },
  "required": [
    "accession",
    "include_isoforms"
  ],
  "additionalProperties": false
}
view source ↗

Resources

2

A curated UniProtKB entry by accession — function, catalytic activity, disease, variants, GO terms, and cross-references. The resource mirror of uniprot_get_entry for a single accession. An annotation-heavy entry over the outline budget returns a bounded identity summary plus a section outline (names + byte sizes) instead of the full record — fetch specific sections with the uniprot_get_entry tool (sections:[...]).

uri uniprot://entry/{accession} mime application/json

A taxonomy record by NCBI taxon ID — scientific/common name, rank, parent, and full lineage. The resource mirror of uniprot_get_taxonomy by ID.

uri uniprot://taxonomy/{taxonId} mime application/json

Prompts

1

Guided protein-research workflow over UniProt — resolve an identifier to a UniProtKB accession, fetch the curated entry, pull disease and variant detail, and surface cross-references for structure, citations, and bioactivity.

  • identifierrequired — A gene name (e.g. "TP53"), UniProtKB accession (e.g. "P04637"), or protein name to research.
  • organism — Optional organism scientific name or NCBI taxon ID to disambiguate (e.g. "Homo sapiens" or "9606").