protein-mcp-server
Allows using Cloudflare KV, R2, and D1 as storage backends for the MCP server.
Supports OpenTelemetry tracing for observability.
Allows using Supabase as a storage backend for the MCP server.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@protein-mcp-serverList SARS-CoV-2 spike protein cryo-EM structures"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Public Hosted Server: https://protein.caseyjhand.com/mcp
Overview
Experimental (PDB) and predicted (AlphaFold) protein structures behind one surface. Search, fetch, align, and annotate structures and their ligands across RCSB, AlphaFold DB, 3D-Beacons, UniProt, InterPro, and Foldseek, all keyless. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Tool | Description |
| Search experimental and predicted structures by text, sequence, or organism/method/resolution, with optional facets |
| Fetch metadata and coordinate URLs for experimental, predicted, or best-available structures |
| Find sequence homologs (RCSB mmseqs2) or fold homologs (Foldseek) |
| Resolve ligands to component IDs, find structures containing one, or map its binding site |
| Align structures with TM-align or jFATCAT, against a reference or all pairs |
| Profile the PDB as counts, histograms, timelines, and cross-tabs |
| Fetch UniProt features and variants plus InterPro domains with GO terms |
Resources
Resource | Description |
| Experimental structure summary for a PDB entry |
| AlphaFold DB predicted-structure summary for a UniProt accession |
Both resources are also reachable through protein_get_structure, for clients that don't surface resources.
Related MCP server: UniProt MCP Server
Capability reference
protein_search_structures tool
At least one of
query,sequence(an mmseqs2 search;min_identity/max_evalueapply only with it),organism,method, ormax_resolution;content_typeisexperimental,predicted, orall(default); up to 100 hits per page (default 25) vialimit/startEach hit names its
sourceand a chainable entryid(sequence hits addentityId); experimental hits carry title, method, resolution, and organism, AlphaFold models theiruniprotAccessionOptional
facets(method,organism,polymer_type,resolution,release_year,molecular_weight) add a flat breakdown capped atPROTEIN_FACET_BUCKET_CAPbuckets per dimension; for non-sequence searches,protein_analyze_collectionreaches the long tail
protein_get_structure tool
source: experimental(default) takes PDB entry IDs and theAF_*/MA_*computed-model IDs search returns (these come back assource: predicted);predictedtakes UniProt accessions for AlphaFold models with pLDDT/PAE;best_availabletakes UniProt accessions and returns the highest-resolution experimental structure, else the best prediction. Up toPROTEIN_MAX_BATCH_IDSIDs per call (default 25)Unresolved IDs land in
failed[], andrequested/processedshow IDs dropped past the cap; the call fails asall_failedwhen nothing resolves andmixed_id_typeswhen the IDs don't fitsource. Experimental-source records addpolymerEntities,ligands,molecularWeight, andreleaseDate, andcoordinateUrlslists only files that existinclude_coordsinlines coordinate text within a response budget; an over-budget batch returns anoverflowsize outline to re-call withsections: [ids], and a lone oversized file is withheld in favor of itscoordinateUrls
protein_find_similar tool
by: sequenceruns a synchronous RCSB mmseqs2 search fromsequence,pdb_id, oruniprot, filtered bymax_evalue/min_identity;by: structureruns an async Foldseek search frompdb_idoruniprotagainstpdb100+afdb50unlessdatabasessays otherwise. A field only the other mode reads fails asmode_mismatched_field; up to 100 hits per page (default 25)Hits name their
sourceand, for structure hits, thedatabase, ranked byscoreacross all searched databases; responses reporttotalCountandnextStartA structure job still running at the poll budget returns
status: computingwith aticketId; re-call withticket_idto resume it or re-page a finished job. A multichain structure is one query per chain: each response coversquery(0-based, default 0) out ofqueryCount
protein_track_ligands tool
modeisfind_ligand(query: a name or formula),structures_with_ligand(comp_id), orbinding_site(pdb_id, optionalcomp_id); a missing mode input fails asmissing_param.limitis 1–100 (default 25), andstartpages the last two modesfind_ligandreturns component IDs with formula, weight, SMILES, and InChIKey, ranked bydepositionCount, withtotalCountandcandidatesConsideredshowing when the candidate pool was cut short;structures_with_ligandlists entries highest resolution firstbinding_sitereturns pocket residues with contact distances, numbered in both label (asymId,seqId) and author (authAsymId,authSeqId) namespaces; it works on experimental structures only
protein_compare_structures tool
2 structures up to
PROTEIN_MAX_COMPARE_STRUCTURES(default 10, max 25), each apdb_idwith an optional label-namespacechain;methodistm-align(default),fatcat-rigid, orfatcat-flexible;referenceisfirst(default) orall_pairs;timeout_s(5–120) sets the per-pair poll budgetEach pair row has a
status(complete,computing,failed),tmScore,rmsd,alignedResidues, and[a, b]-orderedmodeledResiduesandcoverage; TM-score is normalized bya's length, so reversing a pair changes itA computing pair returns its job
uuid; re-call with{ a, b, uuid }inresume[]to poll it instead of resubmitting. A resume under a differentmethodor for another pair fails asresume_method_mismatchorresume_job_mismatch
protein_analyze_collection tool
group_bytakes one ofmethod,organism,polymer_type,resolution,release_year,molecular_weight, or two distinct ones for a cross-tab; scope withquery,organism,method,max_resolution, andcontent_type(defaultexperimental).intervalsets a numeric bin width forresolution/molecular_weightor"year"forrelease_yearReturns
totalandbucketsReturned; buckets carrylabelandcount(numeric bins addrangeFrom/rangeTo), and every dimension reportsmissingValueCountbucket_limit(1–500, defaultPROTEIN_FACET_BUCKET_CAP) caps each dimension level separately, so a cross-tab can returnbucket_limit × (1 + bucket_limit)buckets;truncatedandnoticename the capped positions
protein_get_annotations tool
A
uniprotaccession, or apdb_idresolved through its UniProt cross-reference (authorchainpicks one accession);includeisfeatures,domains,variants, orall(default);limitcaps each class separately (1–200, default 50)Returns UniProt features and natural variants plus InterPro domains with GO terms; a PDB entry mapping to several accessions defaults to the lowest author chain and lists the rest in
ambiguityCapped classes set
truncatedand are named innotice; failures are typed asmissing_identifier,invalid_accession,no_uniprot_mapping, orchain_not_found
pdb://{entry_id} resource
entry_idis a PDB entry ID (e.g.4HHB); returnsapplication/jsonwith title, methods, resolution, organisms, ligands, andpolymerEntitiescarrying bothauthAsymIdsandlabelAsymIdsSame data as
protein_get_structurewithsource: experimental
af://{uniprot} resource
uniprotis a UniProt accession or an AlphaFold DB entry ID (e.g.AF-P69905-F1); returnsapplication/jsonwithmeanPlddt,confidenceBuckets,cifUrl/pdbUrl/bcifUrl, andmodelVersionSame data as
protein_get_structurewithsource: predicted
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
PDB / AlphaFold-specific:
Search, fetch, and comparison treat experimental (PDB) and predicted (AlphaFold DB, ModelArchive, 3D-Beacons providers) structures the same way
Keyless across RCSB, AlphaFold DB, 3D-Beacons, UniProt, InterPro, and Foldseek
Collection analytics run on RCSB's facet engine and return bucket counts, not matching entries
Foldseek and alignment jobs poll for up to
PROTEIN_ASYNC_POLL_TIMEOUT_MS(default 30 s), then hand back a resume handle (ticketId, per-pairuuid) instead of blockingChain namespaces stay separate:
authAsymIdsfeedprotein_get_annotationschain,labelAsymIdsfeedprotein_compare_structureschain
Agent-friendly output:
Provenance: every hit names its
source(experimental/predicted) and the engine or database behind it, andprotein_get_structureandprotein_get_annotationscarry anattributionblock (see Upstream data licensing)Graceful partial failure:
failed[]rows and per-pairstatuskeep one bad ID or pair from failing the requestPaging and advisories: paged tools return
totalCountandnextStart, astartpast the end is flagged innoticeseparately from zero matches, and every advisory joins into that onenotice
Getting started
Public Hosted Instance
A public instance is available at https://protein.caseyjhand.com/mcp, no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"protein-mcp-server": {
"type": "streamable-http",
"url": "https://protein.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Add the following to your MCP client configuration file. No API key is needed.
{
"mcpServers": {
"protein-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/protein-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"protein-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/protein-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"protein-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/protein-mcp-server:latest"]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
No accounts or API keys: every upstream is public.
Installation
Clone the repository:
git clone https://github.com/cyanheads/protein-mcp-server.gitNavigate into the directory:
cd protein-mcp-serverInstall dependencies:
bun installConfigure environment (optional):
cp .env.example .env
# every variable has a working defaultConfiguration
Every variable is optional.
Variable | Description | Default |
| Poll budget for an async alignment or Foldseek job before it returns |
|
| Max IDs per |
|
| Max structures per |
|
| Buckets per dimension for |
|
| Max concurrent upstream requests for per-ID and per-pair fan-out (1–16). |
|
| Transport: |
|
| HTTP server port. |
|
| HTTP session mode: |
|
| Authentication: |
|
| Log level (RFC 5424). |
|
| Enable OpenTelemetry. |
|
Each upstream's base URL can also be pointed at a mirror: RCSB_SEARCH_BASE_URL, RCSB_DATA_BASE_URL, RCSB_FILES_BASE_URL, RCSB_MODELS_BASE_URL, RCSB_ALIGNMENT_BASE_URL, BEACONS_BASE_URL, ALPHAFOLD_BASE_URL, MODELARCHIVE_BASE_URL, FOLDSEEK_BASE_URL, UNIPROT_BASE_URL, INTERPRO_BASE_URL. See .env.example for their defaults and the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t protein-mcp-server .
docker run --rm -p 3010:3010 protein-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/protein-mcp-server. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Upstream clients: |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageExport new definitions from the barrels in
src/mcp-server/*/definitions/index.tsand register them in thecreateApp()arrays insrc/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Upstream data licensing
Structure and annotation data comes from public databases, each under its own license. protein_get_structure and protein_get_annotations return an attribution block with the license, citation, and homepage of every source that contributed to that response. CC BY and CC BY-SA sources require attribution on redistribution; CC0 sources ask only for citation.
Source | Contributes to | License |
| CC0 1.0 Universal | |
| CC BY 4.0 | |
| CC BY 4.0 | |
| CC BY-SA 4.0 | |
| CC BY 4.0 | |
| CC BY 4.0 | |
| CC0 1.0 Universal | |
| CC BY 4.0 |
best_available models arrive through 3D-Beacons, so the block credits the provider that actually supplied the model; a provider with no curated entry gets a See provider terms fallback instead of a guessed license. InterPro and GO are credited separately, each only when it contributes. This table covers upstream data; the server's own code is licensed separately (see License).
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
RCSB PDB MCP — experimentally determined macromolecular structures.
Agent-to-Agent (A2A) + Model Context Protocol (MCP) hub for peptides.
Model Context Protocol server for Studex tools, notifications, and profile integrations
Official STRING database MCP server. Query for protein-protein interactions, enrichment, annotations, homology, and PPI networks.
Related MCP Servers
- FlicenseBqualityDmaintenanceA Model Context Protocol server that enhances language models with protein structure analysis capabilities, enabling detailed active site analysis and disease-related protein searches through established protein databases.219-
- FlicenseCqualityDmaintenanceA comprehensive Model Context Protocol (MCP) server providing advanced access to the UniProt protein database.2620-
- FlicenseAqualityFmaintenanceA Model Context Protocol (MCP) server that provides access to the Protein Data Bank (PDB) - the worldwide repository of information about the 3D structures of proteins, nucleic acids, and complex assemblies.527-
- FlicenseBqualityDmaintenanceA comprehensive Model Context Protocol (MCP) server that provides access to the AlphaFold Protein Structure Database through a rich set of tools and resources for protein structure prediction analysis.1935-