Skip to main content

just-prs-mcp: Conversational and Programmatic Polygenic Risk Scores

PyPI version Python 3.13+ Claude Plugin MCP BioContextAI Registry Core library Research use only Not medical advice

just-prs-mcp brings the just-prs bioinformatics toolbox into Claude, Cursor, Codex, and any other Model Context Protocol client. It exposes typed tools for searching 5,000+ published polygenic scoring models, normalizing VCF and consumer-array data, computing PRS, comparing results with reference populations, estimating absolute risk, and assessing result quality.

It is useful whether you are:

  • a bioinformatician adding reproducible PRS operations to an MCP-enabled research environment;
  • a researcher or analyst who wants to inspect models and evidence through a conversational interface;
  • a Claude or Cursor user who wants to analyze a local genome without writing a pipeline; or
  • a developer embedding PRS tools in an agent, application, or internal system.

The server runs locally by default, needs no API key, and does not upload your genome. The underlying scoring, catalog, and reference-panel logic remains in just-prs; this repository provides the MCP tools, Claude plugin, packaging, prompts, and guided interpretation workflows.

The server is published in the BioContextAI Registry, a community registry for agentic biomedical systems, where researchers can discover its scientific scope, supported features, and registry metadata.

See the evidence, not just a score

Trait-level PRS report showing model percentiles, match rates, quality, and a consensus reference curve

Instead of hiding uncertainty behind one number, the server gives clients the evidence needed to judge a result: PGS IDs, variant-match rates, model quality, reference population, percentiles, absolute-risk context, and agreement or conflict across models for the same trait.

How it fits into your workflow

flowchart LR
    U["Researcher, bioinformatician,<br/>or genome owner"]
    C["Claude · Cursor · Codex<br/>or another MCP client"]
    M["just-prs-mcp<br/>typed tools + prompts + skill"]
    J["just-prs<br/>scoring and catalog engine"]
    V["Local VCF / array"]
    P["PGS Catalog metadata<br/>and reference distributions"]

    U --> C --> M --> J
    V --> J
    P --> J
    J --> M --> C
Use case Recommended interface
Ask questions and receive an evidence-aware interpretation Claude plugin
Add structured PRS tools to Claude, Cursor, Codex, or an internal system MCP server
Build scripts, notebooks, pipelines, or a browser UI directly just-prs
Evaluate quickly without personal genomic data Public test genomes

What can you ask?

These are queries an MCP client can resolve with the current tools. One genome is always a one-element samples list; two or more people use the same tools with a longer list. compute_prs_by_trait interprets percentiles by default.

"Search the PGS Catalog for type 2 diabetes and explain which models are best supported."

"Download Anton's public genome and compute PRS for type 2 diabetes.
Give me the HTML report link and say which models agree."

"What's Livia's genetic predisposition for venous thromboembolism? Include
absolute risk, not just a percentile."

"Compare Anton and Livia on intelligence. Show all associated models,
use the median, check whether a high percentile is favorable, and open
the overlay HTML report."

"Detect the build and ancestry of this VCF, then score coronary artery disease
with superpopulation=auto."

"Compute BMI PRS directly from ~/data/me.vcf.gz. Do not normalize it first;
if list_genomes already has a cached Parquet for this genome, reuse that path."

"I already have result JSON from a previous run — plot the trait panel and
build the Ask-AI write-up from those result_paths."

"Score this genome against PGS000337 only, then give the percentile and quality."

The tool always returns html_link: an HTTP URL over Streamable HTTP (GET /reports/<file> on the MCP origin) or a file:// URI over local stdio. The model must quote that exact target as a markdown link and tell the user to open the interactive report; it must not fetch or paste the HTML.

The client chooses the tools and keeps the provenance (PGS IDs, match rates, quality, ancestry). You can also call every tool from your own MCP application.

Connect Claude, Cursor, or another MCP client

Local use requires uv. uvx creates an isolated environment for the published package, so there is no repository clone or project-level installation step.

Claude Code

Add the MCP server:

claude mcp add just-prs -- uvx just-prs-mcp@latest stdio
claude mcp list

Use a pinned version in reproducible research environments:

claude mcp add just-prs -- uvx just-prs-mcp@0.5.0 stdio

For the MCP server plus the bundled trait-interpretation skill, use the Claude plugin.

Cursor

Add to .cursor/mcp.json (project) or your user MCP config (Cursor MCP docs):

{
  "mcpServers": {
    "just-prs": {
      "command": "uvx",
      "args": ["just-prs-mcp@latest", "stdio"],
      "env": { "PRS_MCP_MODE": "essentials" }
    }
  }
}

From a checkout, uv run just-prs-mcp stdio is the same server. File log: <cache>/logs/mcp.log. HTTP (just-prs-mcp http, then "url": "http://127.0.0.1:3011/mcp") is optional if you want a process that outlives the Cursor session.

Codex

Install the native plugin from the shared DNA Seq marketplace to get both the MCP server and the evidence-aware trait-interpretation skill:

codex plugin marketplace add dna-seq/dna-seq-claude-marketplace

In Codex Desktop, open Plugins, choose DNA Seq Genomics, and install just-prs: Polygenic Risk Scores. If no Codex CLI is installed, clone the marketplace repository and open that checkout in Codex Desktop; its repository marketplace is discovered automatically.

For a tools-only configuration, add this to ~/.codex/config.toml:

[mcp_servers.just-prs]
command = "uvx"
args = ["just-prs-mcp@latest", "stdio"]

Other MCP clients and internal systems

Use the same local stdio process:

{
  "command": "uvx",
  "args": ["just-prs-mcp@latest", "stdio"],
  "env": {
    "PRS_MCP_MODE": "essentials"
  }
}

The server is built with FastMCP and returns structured Pydantic outputs, so it can be used interactively or orchestrated by your own MCP client.

Claude plugin

The repository is also packaged as a Claude Code / Cowork plugin. .claude-plugin/plugin.json registers the prs-trait-interpretation skill, while .mcp.json launches the MCP server through uvx. The skill guides Claude through model selection, quality filtering, percentile interpretation, model agreement, and research-use caveats rather than treating the first available score as definitive.

Install it from the shared marketplace:

claude plugin marketplace add dna-seq/dna-seq-claude-marketplace
claude plugin install just-prs@dna-seq

Or use the working tree directly during development:

claude plugin validate .
claude --plugin-dir .

Or build the minimal ZIP for manual upload in Claude Desktop / Cowork:

uv run pack plugin
# dist/just-prs-claude-plugin-<version>.zip

The ZIP contains only the plugin manifest, MCP configuration, skill, README, and license. See the official Claude plugin documentation.

Claude Desktop (.mcpb extension)

If you only need the MCP tools, package a Claude Desktop extension:

uv run pack mcpb
# dist/just-prs-mcp-<version>.mcpb

Double-click the .mcpb or drag it into Claude Desktop. The extension still runs the server locally. Metadata and configurable options are declared in manifest.json.

Version pinning tip

uvx caches the first version it resolves for a bare package name. Prefer just-prs-mcp@latest or just-prs-mcp@<version> — avoid the bare name.

Use --mode extended or PRS_MCP_MODE=extended for bulk downloads, HuggingFace upload, prevalence priors, multi-method absolute risk, and reference-panel scoring.

From a clone (development)

The plugin's .mcp.json launches the pinned PyPI release. To run the working tree while developing:

[mcp_servers.just-prs]
command = "uv"
args = ["run", "just-prs-mcp", "stdio"]

What is a PRS?

Many traits and common diseases — type 2 diabetes, coronary artery disease, height, longevity — are polygenic: influenced by thousands of small genetic effects. A Polygenic Risk Score adds those effects and places the result relative to a reference population. It is not a diagnosis; it can visualize inherited predisposition and, where evidence allows, translate a percentile into an absolute-risk estimate.

What is MCP?

The Model Context Protocol lets AI assistants and applications call external tools through a shared protocol. Here, MCP turns the just-prs Python API into discoverable, typed operations with structured inputs and outputs. A chat client can use them conversationally; a bioinformatics platform can orchestrate the same operations programmatically.

Contents

Quickstart (developers)

uv sync                                    # deps (incl. dev)
uv sync --extra reference                  # + pgenlib (Linux/WSL)

uv run just-prs-mcp stdio                  # stdio for MCP clients
uv run just-prs-mcp stdio --mode extended  # full tool surface
uv run just-prs-mcp http                   # HTTP (default :3011)
uv run fastmcp dev fastmcp.json            # MCP Inspector

uv run pytest
uv run ruff check .
uv run pyright

The server boots with no environment configured — every setting is optional.

Test genomes (quick play)

Two public WGS datasets from just-dna-lite are built in:

Sample Zenodo VCF Size License Parameter
Anton Kulaga 18370498 antonkulaga.vcf ~482 MB CC0 sample="anton"
Livia Zaharia 19487816 SIMHIFQTILQ.hard-filtered.vcf.gz ~349 MB CC-BY-4.0 sample="livia"
"Download Anton's sample genome and compute the PRS for type 2 diabetes."

Typical tool chain: download_sample_genome → (auto-normalize) → compute_prs_by_trait → percentile → absolute_risk → optional plot_trait_panel / build_prs_prompt. Download both anton and livia for a two-person comparison.

Tools

Essentials (always available)

Tool Description
search_scores Search the PGS Catalog by free text
score_info Cleaned metadata for one PGS ID
best_performance Best evaluation metrics (OR / HR / AUROC / C-index)
search_traits REST trait search with synonym retry
trait_info Trait by EFO / MONDO ID + associated PGS IDs
list_genomes Inventory of downloaded and normalized genomes in the cache
download_sample_genome Fetch a public sample WGS VCF from Zenodo (auto-normalizes by default; can take several minutes)
normalize_vcf Optional VCF → reusable genotype Parquet preprocessing; never required before compute
vcf_metainfo Detect build, WGS/array/gVCF, and inferred ancestry; recommends restoration + superpopulation
compute_prs Score one genome against one PGS model (reference_restoration="auto")
compute_prs_batch Score one genome against many PGS models
compute_prs_by_trait Score raw VCFs or Parquets for 1+ genomes (samples=["Label=path", ...]); profile="all" by default (curated is the shortlist); returns a PRSJob
prs_job_status Poll a long scoring/download job (wait_seconds=25) until done / failed
list_prs_jobs Recover a job_id after a client timeout
percentile Population percentile (reference panel / theoretical / AUROC fallback)
absolute_risk Absolute disease risk from a PRS z-score + prevalence
assess_quality Quality label + interpretation (pure logic, no I/O)
compare_genomes Cross-genome comparison + optional just-prs LLM prompt
build_prs_prompt Reusable prs prompt / Ask-AI text from saved reports (one or many genomes)
plot_trait_panel just-prs trait HTML report; always returns html_link (HTTP URL or local file:// URI)

Extended (opt-in via --mode extended)

Tool Description
normalize_array 23andMe / AncestryDNA → Parquet
download_scoring_file One harmonized scoring file from EBI FTP
list_pgs_ids All PGS IDs on EBI FTP
download_all_metadata All metadata sheets as Parquet
bulk_download_scores Many/all scoring files
prevalence_info Population prevalence priors for a score or trait
absolute_risk_bundle Multi-method absolute-risk estimation
push_catalog_to_hf Upload cleaned catalog to HuggingFace (needs token)
download_reference_panel Fetch 1000G / HGDP+1kGP panel
reference_score / reference_score_batch Score against a reference panel (needs pgenlib)
pgen_read_pvar / pgen_read_psam / pgen_score PLINK2 binary ops (needs pgenlib)

File paths: computation tools take local paths on the server filesystem. Over stdio that is your machine. Reference / pgen tools need uv sync --extra reference (Linux/WSL).

Prompts and resources

Prompt Description
compute_prs_for_trait Step-by-step: search → score raw VCF/Parquet inputs directly → interpret
interpret_prs_for_trait End-to-end trait read (optional multi-genome compare)
interpret_prs_result Interpret a single PGS result (prefer build_prs_prompt when you have a report)
interpret_trait_results Interpret combined results across models / people
Resource Description
resource://prs/panels Reference panels, genome builds, and the active cache directory
resource://prs/genomes JSON catalog of cached VCFs / Parquets (same as list_genomes)

Typical MCP workflow

1. search_traits("venous thromboembolism")     → trait ID (e.g. EFO_0001645)
2. download_sample_genome(sample="anton")       → VCF (+ optional cached Parquet)
3. vcf_metainfo(vcf_path=...)                    → optional: build + ancestry
4. compute_prs_by_trait(trait_id, samples=["Anton=<raw VCF path>"],
     superpopulation="auto")                    → TraitPRSReports
5. absolute_risk / assess_quality               → as needed
6. build_prs_prompt(result_paths=...)           → reusable LLM write-up
7. plot_trait_panel(result_paths=...)           → html_link (HTTP or file://)

Same tools for a two-person (or family) comparison — samples and result_paths are always lists:

2. download_sample_genome("anton"); download_sample_genome("livia")
3. compute_prs_by_trait(trait_id,
     samples=["Anton=<anton VCF>", "Livia=<livia VCF>"],
     superpopulation="auto")
4. compare_genomes(result_paths=...)            → 2+ genomes (median, not "best")
5. build_prs_prompt(result_paths=...)           → comparison-first prompt
6. plot_trait_panel(result_paths=...)           → overlay HTML (or html_link from step 3)

compute_prs_by_trait returns a PRSJob immediately. Poll prs_job_status(job_id, wait_seconds=25) until done. Then result is TraitPRSReports (reports, result_paths, sample_labels, html_link, plus transport-specific html_path / html_url). The job also copies html_link onto the top-level record. One genome is n_samples=1. There is no vcf_path argument — always samples. interpret defaults to True; profile defaults to all (every associated score). Pass profile="curated" only for the shortlist. Pass interpret=False only for raw scores.

Raw VCF input is first-class: do not call normalize_vcf as a prerequisite. Normalization is only an optional optimization for intentional repeated reuse. If a normalized Parquet already exists, list_genomes exposes it. normalize_vcf, download_sample_genome, and compute_prs_batch are the same job+poll pattern. Do not start a second identical compute after a timeout — call prs_job_status or list_prs_jobs instead.

Modes

PRS_MCP_MODE (env) or --mode (CLI), default essentials:

Mode What's registered
essentials Catalog + core compute/analyze + comparison. Smaller tool list for clients.
extended Batch downloads, HF upload, prevalence, multi-method risk, reference/pgen.

Configuration

All settings are optional. See .env.example and settings.py.

Variable Description
PRS_MCP_MODE essentials (default) or extended
PRS_MCP_CACHE_DIR Cache for catalog data, scoring files, panels, results
PRS_MCP_DEFAULT_GENOME_BUILD Default genome build (GRCh38)
PRS_MCP_DEFAULT_PANEL Default reference panel (1000g)
PRS_MCP_DUCKDB_MEMORY_LIMIT DuckDB memory for batch scoring (e.g. 8GB)
PRS_MCP_HF_TOKEN HuggingFace token for push_catalog_to_hf (also HF_TOKEN)
PRS_MCP_TRANSPORT stdio / http / sse
PRS_MCP_HOST / PRS_MCP_PORT Bind address for HTTP/SSE (default 127.0.0.1:3011)
PRS_MCP_PUBLIC_BASE_URL Optional public origin for trait HTML (/reports/<file>). http/sse fill this from the bind address; set only behind a reverse proxy.
PRS_MCP_AUTO_CACHE_VCF_FOR_BATCH Transparently normalize/cache raw VCFs once for multi-score tools (default true)
PRS_MCP_ISOLATE_NATIVE_SCORING Run VCF normalization and multi-score DuckDB/Polars work in python -m just_prs_mcp.native_worker so a native crash does not kill MCP (default true). Worker failures are classified as exception / protocol / signal / timeout; only a confirmed native/signal scoring exit bisects the PGS batch. Stderr lands in <cache>/logs/mcp.log.
PRS_MCP_MAX_CONCURRENT_SCORING_JOBS Native genomic workloads allowed per server process (default 1; job tools and remaining blocking native tools share this slot)
PRS_MCP_JOB_GRACE_SECONDS How long a submitting tools/call waits for a fast job before returning running (default 2)
PRS_MCP_LOG_LEVEL Logging level (info by default)
PRS_MCP_LOG_FILE Rotating file log (default <cache>/logs/mcp.log). Set off to disable.

Methodology

Percentile estimation

Percentiles use the 1000 Genomes Project phase 3 panel (2,504 individuals; AFR, AMR, EAS, EUR, SAS) on GRCh38 harmonized scoring files. PRS is Σ(effect_weight × dosage) for matched variants; the user sample is placed on the same distribution.

Quality scoring

Synthetic quality score (0–100) from four tiers:

  • T1a: AUROC / C-index (strongest)
  • T1b: Beta only (0.95×)
  • T2: OR / HR only (0.90×; probit transform)
  • T3: No performance metric (0.6× floor)

Also factors cohort size, coverage, and harmonized-score penalty. Labels: High (≥70), Normal (≥50), Moderate (≥30), Low (<30).

Absolute risk

For disease traits, absolute_risk converts a z-score into lifetime probability and risk ratio vs population average. risk_ratio 1.0 = average; >1 elevated; <1 reduced. If prevalence data is unavailable, the tool reports that explicitly.

Interpreting results

Built-in instructions guide agents to:

  • Present PRS as predisposition, not a trait measurement
  • Call absolute_risk after percentile for disease traits
  • Respect trait directionality
  • Flag ancestry mismatches, low coverage, and model disagreement
  • Cite PGS IDs with links to the PGS Catalog

See the just-prs interpretation guide.

Research use only

PRS results are for research and educational purposes only and do not constitute medical advice.

  • PRS models are statistical proxies, not causal readouts.
  • Catalog listing does not mean clinical readiness.
  • Environment, lifestyle, age, sex, and biomarkers often matter as much as or more than common-variant signal.
  • Low match rates (common with consumer arrays) mean a noisier, less informative score.
  • Ancestry matters: accuracy often drops outside the training population.

A high PRS is not a diagnosis; a low PRS is not a guarantee.

Privacy

Genomic computation is designed to stay local:

  • Over stdio / Claude Desktop / the Claude plugin, tools read paths on your machine. VCFs are not uploaded to a third-party API by this server.
  • There is deliberately no client-to-server VCF upload or remote-fetch tool.
  • Optional HuggingFace upload (push_catalog_to_hf, extended mode) sends catalog metadata, not personal genotype files, and only when you invoke it with a token.

Deployment

  • Docker: docker build -t just-prs-mcp . && docker run -p 3011:3011 just-prs-mcp
  • Smithery (GitHub connect): repo is ready — smithery.yaml (runtime: python)
    • [tool.smithery] pointing at just_prs_mcp.server:start_mcp_smithery.
    1. Push this repo to GitHub.
    2. Follow the current Smithery publishing guide.
    3. Optional: set PRS_MCP_MODE=extended (or other PRS_MCP_*) in the Smithery project env if you want the full tool surface on the hosted instance. Local smoke-test of the same entrypoint: uv run smithery dev / uv run playground / uv run start.
  • Declarative: fastmcp.json for fastmcp run / fastmcp dev

Project layout

src/just_prs_mcp/
  server.py          build_server(), CLI, graceful shutdown, Smithery entrypoint
  settings.py        pydantic-settings (PRS_MCP_*), safe defaults
  client.py          shared PRSCatalog / REST-client construction + adapters
  models.py          Pydantic tool I/O models (+ reused just-prs models)
  jobs.py            PRSJob store, submit/poll, scoring semaphore
  native_worker.py   isolated native scoring / normalize subprocess
  plugin_package.py  minimal Claude plugin ZIP builder
  logging_setup.py   stdlib logging → stderr + `<cache>/logs/mcp.log`
  tools/
    catalog.py         essentials — PGS Catalog search and lookup
    compute.py         essentials — normalize, compute, compare, prompts
    extended.py        extended — batch downloads, HF upload, prevalence, multi-risk
    reference.py       extended — reference-panel / pgen scoring (pgenlib)
tests/               in-memory client tests (wiring + logic, no network)

License

MIT — see LICENSE.

Metadata

Release files for just-prs-mcp 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for just-prs-mcp 0.5.0
File Size Uploaded
just_prs_mcp-0.5.0.tar.gz 83.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for just-prs-mcp 0.5.0
File Interpreter ABI Platform
just_prs_mcp-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 176.0 kB

Release files / just_prs_mcp-0.5.0.tar.gz

Download URL just_prs_mcp-0.5.0.tar.gz
Size 83.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3877cda36c24520306d4c7f2a439ae1797359eadb81027a76a1791b890bd46a1
BLAKE2b-256 checksum
How to use checksums
bbafbc53f970ef3b4ca333b1748d243ff2f304075a9b3678d5934de4e05248b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / just_prs_mcp-0.5.0-py3-none-any.whl

Download URL just_prs_mcp-0.5.0-py3-none-any.whl
Size 92.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e64cd7413b720adaa3e325c2862f72bbef1f7cd9540587d2b5458816ead48b6
BLAKE2b-256 checksum
How to use checksums
fdba49c30bca2cdd6372e06df111c5fa80bb023a2c9251ff50a5fcca9908f756
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page