Production-quality MCP server exposing the UniProt REST API (search, entries, FASTA, ID mapping, taxonomy) to LLM clients over stdio.
Project description
uniprot-mcp
GitHub repo:
fzlzjerry/uniprot-mcp· PyPI package & command:uniprotkb-mcp(the Python import package isuniprot_mcp).
A production-quality MCP server that exposes the UniProt REST API
to LLM clients (Claude Code, Claude Desktop, …) over stdio. Built with
FastMCP and managed with uv.
Tools return compact, token-efficient summaries by default and full payloads only on request, with robust error handling and an embedded UniProt query cheat-sheet so the model writes valid queries.
Tools
| Tool | What it does |
|---|---|
search_uniprotkb |
Search UniProtKB with native query syntax. reviewed / organism_id filters are added for you. Summary, FASTA, or TSV output. |
get_entry |
One entry as a curated digest (function, names, organism, length, subcellular location, family/domains, key features, PTMs, keywords, PDB/AlphaFold/Ensembl/RefSeq/InterPro/GO cross-refs) or json/fasta/txt/gff. |
get_fasta |
Raw FASTA for one accession or a batch. |
map_ids |
Convert ids across databases via UniProt's async ID-mapping (e.g. RefSeq_Protein→UniProtKB, UniProtKB_AC-ID→PDB). Returns mapped pairs and unmapped ids; validates the db pair against the live config. |
get_taxonomy |
Resolve an organism name or taxon id → taxon id, names, rank, lineage. Turn "human" into organism_id:9606. |
search_uniref |
Search UniRef100/90/50 sequence-similarity clusters. |
search_proteomes |
Search proteomes (whole-organism protein sets); reference-proteome filter. |
Plus an MCP resource resource://uniprot/query-cheatsheet documenting the
UniProtKB query syntax (gene:, organism_id:, reviewed:true,
length:[X TO Y], keyword:, ec:, boolean AND/OR/NOT, …).
Requirements
- Python ≥ 3.10 (the repo pins 3.13 via
.python-version) uv
Install
git clone https://github.com/fzlzjerry/uniprot-mcp
cd uniprot-mcp
uv sync # creates .venv and installs fastmcp + httpx
Run
# stdio server (what MCP clients launch):
uv run uniprotkb-mcp
UniProt asks API clients to identify themselves with a contact address. Set one
via the UNIPROT_MCP_CONTACT environment variable (it goes into the
User-Agent); otherwise a placeholder is used.
UNIPROT_MCP_CONTACT="you@example.org" uv run uniprotkb-mcp
Run with uvx (no clone / no sync)
uvx (a.k.a. uv tool run) fetches, builds, and runs the console script in a
throwaway environment — nothing to install first. Pick whichever source you have:
# From PyPI (once published — see "Releasing" below):
uvx uniprotkb-mcp
# From a Git repo (note: repo is uniprot-mcp, command is uniprotkb-mcp):
uvx --from git+https://github.com/fzlzjerry/uniprot-mcp uniprotkb-mcp
# From a local checkout (this directory):
uvx --from /ABSOLUTE/PATH/TO/uniprot-mcp uniprotkb-mcp
# From a built wheel:
uvx --from ./dist/uniprotkb_mcp-0.1.0-py3-none-any.whl uniprotkb-mcp
Pin a version with uvx uniprotkb-mcp@0.1.0, or force a refresh of the cached
build with uvx --refresh --from <source> uniprotkb-mcp.
Register with Claude Desktop
Edit claude_desktop_config.json
(macOS: ~/Library/Application Support/Claude/claude_desktop_config.json,
Windows: %APPDATA%\Claude\claude_desktop_config.json) and add:
{
"mcpServers": {
"uniprot": {
"command": "uvx",
"args": ["--from", "git+https://github.com/fzlzjerry/uniprot-mcp", "uniprotkb-mcp"],
"env": { "UNIPROT_MCP_CONTACT": "you@example.org" }
}
}
}
Swap the --from source for a local path (/ABSOLUTE/PATH/TO/uniprot-mcp) or,
once published, drop --from entirely and use "args": ["uniprotkb-mcp"]. Make
sure uvx is on the PATH Claude Desktop sees (it ships with uv; give the
absolute path to uvx if needed, e.g. ~/.local/bin/uvx). Restart Claude Desktop
and the uniprot tools appear.
Prefer a cloned checkout instead of
uvx? Use"command": "uv", "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/uniprot-mcp", "uniprotkb-mcp"].
Register with Claude Code
Project-scoped via a .mcp.json in your project root (same shape):
{
"mcpServers": {
"uniprot": {
"command": "uvx",
"args": ["--from", "git+https://github.com/fzlzjerry/uniprot-mcp", "uniprotkb-mcp"],
"env": { "UNIPROT_MCP_CONTACT": "you@example.org" }
}
}
}
Or from the CLI:
# via uvx (published / git / local source):
claude mcp add uniprot -e UNIPROT_MCP_CONTACT=you@example.org -- uvx uniprotkb-mcp
# via a local checkout with uv:
claude mcp add uniprot -e UNIPROT_MCP_CONTACT=you@example.org \
-- uv run --directory /ABSOLUTE/PATH/TO/uniprot-mcp uniprotkb-mcp
Smoke test
Exercises every tool against the live API and prints the output:
UNIPROT_MCP_CONTACT="you@example.org" uv run python -m tests.smoke
Continuous integration
.github/workflows/ci.yml runs on every push / PR to main:
- structure (Python 3.10 & 3.13) — byte-compile + offline checks that all 7
tools register,
ctxstays out of the public schema, and the cheat-sheet resource is present (tests/check_structure.py). - smoke — the full live-API smoke test (
tests/smoke.py).
Releasing (PyPI Trusted Publishing — no token)
Publishing uses OIDC Trusted Publishing, PyPI's recommended method: GitHub
Actions proves its identity to PyPI directly, so no API token or secret is
stored anywhere. .github/workflows/publish.yml builds and publishes on a
version tag.
One-time PyPI setup — at https://pypi.org/manage/account/publishing/ add a pending publisher (pending because the project doesn't exist on PyPI yet; it becomes a normal trusted publisher after the first upload):
| Field | Value |
|---|---|
| PyPI Project Name | uniprotkb-mcp |
| Owner | fzlzjerry |
| Repository name | uniprot-mcp |
| Workflow name | publish.yml |
| Environment name | pypi |
Each release:
# bump `version` in pyproject.toml, commit, then tag:
git tag v0.1.0
git push origin v0.1.0
The tag triggers publish.yml, which checks the tag matches the pyproject
version, builds the sdist + wheel, and uploads via OIDC. After the first upload,
anyone can run uvx uniprotkb-mcp and the Claude config simplifies to
"command": "uvx", "args": ["uniprotkb-mcp"].
Prefer a manual one-off?
uv build && uv publish --token pypi-...still works, but Trusted Publishing is the recommended, token-free path.
Design notes
- Single shared
httpx.AsyncClientwith a descriptiveUser-Agentincluding your contact. - Retry/backoff on
429(honoringRetry-After) and5xx;400surfaces UniProt's own error message; no raw tracebacks reach the client (errors are raised asToolError). - Pagination via the
Linkheader /x-total-results; result sizes are capped (≤ 500) and the total is always reported so you can narrow or page. - ID mapping follows the real async flow:
POST /idmapping/run→ poll/idmapping/status/{job}(a303+Locationsignals completion) → fetch results, automatically choosing the enriched UniProtKB results endpoint vs. the simple-pair endpoint based on the target database.
Project layout
src/uniprot_mcp/
server.py # FastMCP instance, the 7 tools, cheat-sheet resource, main()
client.py # shared AsyncClient, retry/backoff, error mapping, header parsing
idmapping.py # async run/poll/results flow with target-aware routing
config.py # cached idmapping db config + from/to validation
formatting.py # JSON -> compact summary digests
cheatsheet.py # UniProt query cheat-sheet
tests/smoke.py # live-API smoke test
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uniprotkb_mcp-0.1.0.tar.gz.
File metadata
- Download URL: uniprotkb_mcp-0.1.0.tar.gz
- Upload date:
- Size: 118.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6748bf1cfcba907d35dea87fef73256b1189b708a46caa82c05d88db28f89ff8
|
|
| MD5 |
9a48f359e11eb1a64596ac0a0ad7d91a
|
|
| BLAKE2b-256 |
065ea9828d31cfb0bd9a0a8d283f01d992bb3531e6d53f25c036cff7da54fc86
|
Provenance
The following attestation bundles were made for uniprotkb_mcp-0.1.0.tar.gz:
Publisher:
publish.yml on fzlzjerry/uniprot-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uniprotkb_mcp-0.1.0.tar.gz -
Subject digest:
6748bf1cfcba907d35dea87fef73256b1189b708a46caa82c05d88db28f89ff8 - Sigstore transparency entry: 1817630501
- Sigstore integration time:
-
Permalink:
fzlzjerry/uniprot-mcp@025a7084f7a72c17951ff79babd0927a37975713 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fzlzjerry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@025a7084f7a72c17951ff79babd0927a37975713 -
Trigger Event:
push
-
Statement type:
File details
Details for the file uniprotkb_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: uniprotkb_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44b2b9fd9e37b4257c2d314f8f27dba450f1ad68d82667dbf37c5177a505c967
|
|
| MD5 |
7beecf1b3049840e23bbc53ee55f8807
|
|
| BLAKE2b-256 |
a1017aa5cf03df524ca395f0dbc4c3d247a41386b910b07f296d57a36be41420
|
Provenance
The following attestation bundles were made for uniprotkb_mcp-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on fzlzjerry/uniprot-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uniprotkb_mcp-0.1.0-py3-none-any.whl -
Subject digest:
44b2b9fd9e37b4257c2d314f8f27dba450f1ad68d82667dbf37c5177a505c967 - Sigstore transparency entry: 1817630627
- Sigstore integration time:
-
Permalink:
fzlzjerry/uniprot-mcp@025a7084f7a72c17951ff79babd0927a37975713 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fzlzjerry
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@025a7084f7a72c17951ff79babd0927a37975713 -
Trigger Event:
push
-
Statement type: