bwa-mcp

Local

A Model Context Protocol (MCP) server that exposes BWA (Burrows-Wheeler Aligner) tools for use with Claude or any MCP-compatible client.

Add to your MCP Client

LocalWindowsmacOSLinux

Add the following to your claude_desktop_config.json (or equivalent MCP config file):

{
  "mcpServers": {
    "bwa-mcp": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/bwa-mcp",
        "main.py"
      ]
    }
  }
}

BWA MCP Server

A Model Context Protocol (MCP) server that exposes BWA (Burrows-Wheeler Aligner) tools for use with Claude or any MCP-compatible client.


Tools

ToolDescription
check_bwa_installedCheck whether BWA is on PATH and return its version
install_bwaClone BWA from GitHub, build from source, and install to /usr/local/bin (macOS and Linux)
install_bwa_windowsInstall BWA on Windows via WSL
bwa_indexIndex a reference FASTA with bwa index (background)
bwa_memAlign reads to a reference with bwa mem (background)
check_job_statusPoll the status of a background bwa_index or bwa_mem job
list_jobsList all background jobs submitted in the current session

Background execution: bwa_index and bwa_mem return immediately with a job_id. Long-running alignment and indexing jobs will not time out the MCP connection. Call check_job_status(job_id) to poll until the job is "completed" or "failed".


Requirements

  • Python 3.13+
  • uv
  • macOS: Xcode Command Line Tools — xcode-select --install
  • Linux: sudo apt-get install gcc make zlib1g-dev git
  • Windows: WSL — run wsl --install in PowerShell as Administrator, then restart your computer

Local Setup

1. Clone the repository

git clone https://github.com/JesKwek/BWA-MCP.git
cd bwa-mcp

2. Add to Claude Desktop

Open your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add the following — replace the path with the actual location where you cloned the repo:

{
  "mcpServers": {
    "bwa-mcp": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/bwa-mcp",
        "main.py"
      ]
    }
  }
}

Save the file and restart Claude Desktop. The BWA tools will be available in your next conversation.


Usage Examples

1. Check if BWA is installed

"Is BWA installed on my system?"

Claude will tell you whether BWA is found, where it lives, and which version is installed.

See JSON output

Found:

{
  "installed": true,
  "path": "/usr/local/bin/bwa",
  "version": "Program: bwa (alignment via Burrows-Wheeler Aligner)",
  "error": null
}

Not found:

{
  "installed": false,
  "path": null,
  "version": null,
  "error": null
}

2. Install BWA on macOS or Linux

"Install BWA on my Mac."

"Install BWA on my Linux machine."

Claude will check for the required build tools (git, make, clang/gcc), clone BWA from GitHub, compile it, and install the binary to /usr/local/bin/bwa. If the install step needs admin access, it will print the exact sudo cp command to run in your terminal.

If any build tools are missing, Claude will tell you the exact command to install them:

  • macOS: xcode-select --install
  • Linux: sudo apt-get install gcc make zlib1g-dev git
See JSON output

Success:

{
  "success": true,
  "message": "BWA installed successfully to /usr/local/bin/bwa.",
  "binary_path": "/usr/local/bin/bwa",
  "error": null
}

Compiled but needs manual copy (permission denied):

{
  "success": true,
  "message": "BWA compiled successfully but could not be copied to /usr/local/bin/bwa (permission denied). Run manually:\n  sudo cp /tmp/bwa_build_xxx/bwa/bwa /usr/local/bin/bwa",
  "binary_path": "/tmp/bwa_build_xxx/bwa/bwa",
  "error": "Permission denied when copying to /usr/local/bin"
}

3. Install BWA on Windows

"Install BWA on Windows."

BWA is installed on Windows through WSL (Windows Subsystem for Linux). Claude will check if WSL is set up and, if so, install BWA inside the WSL environment automatically.

If WSL is not installed

Claude will return the following steps:

  1. Open PowerShell or Command Prompt as Administrator
  2. Run:
    wsl --install
    
  3. Restart your computer when prompted
  4. After restart, WSL will finish setting up and ask you to create a Linux username and password
  5. Once WSL is ready, ask Claude to install BWA again

If WSL is already installed

Claude will install the required build tools, clone BWA from GitHub, compile it, and place the binary at /usr/local/bin/bwa inside WSL — no manual steps needed.

See JSON output

WSL not installed:

{
  "success": false,
  "message": "WSL (Windows Subsystem for Linux) is not installed.\n\nTo install WSL:\n1. Open PowerShell or Command Prompt as Administrator\n2. Run: wsl --install\n3. Restart your computer when prompted\n4. After restart, WSL will finish setting up and ask you to create a username and password\n5. Once WSL is ready, run this tool again to install BWA",
  "error": "WSL not installed"
}

Success:

{
  "success": true,
  "message": "BWA installed successfully inside WSL at /usr/local/bin/bwa.",
  "error": null
}

4. Index a reference genome

"Index the reference genome at /data/hg38.fasta"

bwa_index launches in the background and returns immediately with a job_id.
Indexing a large genome (e.g. hg38) can take several minutes — use check_job_status to poll.

See JSON output

Job started:

{
  "job_id": "a3f72b1c",
  "pid": 48201,
  "status": "running",
  "message": "Indexing started in the background. Call check_job_status('a3f72b1c') to monitor progress.",
  "via_wsl": false,
  "error": null
}

Polling — still running:

{
  "job_id": "a3f72b1c",
  "status": "running",
  "pid": 48201,
  "operation": "bwa_index",
  "started_at": "2024-06-01T12:00:00",
  "reference_fasta": "/data/hg38.fasta",
  "via_wsl": false,
  "stderr": null,
  "error": null
}

Polling — complete:

{
  "job_id": "a3f72b1c",
  "status": "completed",
  "pid": 48201,
  "operation": "bwa_index",
  "started_at": "2024-06-01T12:00:00",
  "reference_fasta": "/data/hg38.fasta",
  "via_wsl": false,
  "stderr": "[bwa_index] Pack FASTA... ...",
  "error": null
}

5. Align reads with BWA-MEM

Paired-end:

"Align my paired-end reads sample_R1.fastq.gz and sample_R2.fastq.gz to hg38.fasta and save the output to /data/output.sam"

Hi-C data (with special flags):

"Align my Hi-C reads using BWA-MEM. R1 is /data/input_R1.fastq, R2 is /data/input_R2.fastq, reference is /data/hg38.fasta, output to /data/output.sam, use 8 threads and flags -SP5M"

Single-end:

"Align single-end reads at /data/reads.fastq to /data/ref.fasta and write to /data/out.sam"

bwa_mem launches in the background and returns immediately. Use check_job_status to monitor progress. The reference FASTA does not need to be present on disk if the index files already exist.

See JSON output

Job started:

{
  "job_id": "d9e14c82",
  "pid": 48350,
  "status": "running",
  "message": "Alignment started in the background. Call check_job_status('d9e14c82') to monitor progress.",
  "output_sam": "/data/output.sam",
  "via_wsl": false,
  "error": null
}

Polling — complete:

{
  "job_id": "d9e14c82",
  "status": "completed",
  "pid": 48350,
  "operation": "bwa_mem",
  "started_at": "2024-06-01T12:05:00",
  "output_sam": "/data/output.sam",
  "reference_fasta": "/data/hg38.fasta",
  "via_wsl": false,
  "stderr": "[M::bwa_idx_load_from_disk] ...",
  "error": null
}

6. List all background jobs

"Show me all running BWA jobs."

See JSON output
{
  "jobs": [
    {
      "job_id": "d9e14c82",
      "status": "running",
      "operation": "bwa_mem",
      "pid": 48350,
      "started_at": "2024-06-01T12:05:00",
      "output_sam": "/data/output.sam",
      "reference_fasta": "/data/hg38.fasta",
      "via_wsl": false
    },
    {
      "job_id": "a3f72b1c",
      "status": "completed",
      "operation": "bwa_index",
      "pid": 48201,
      "started_at": "2024-06-01T12:00:00",
      "output_sam": null,
      "reference_fasta": "/data/hg38.fasta",
      "via_wsl": false
    }
  ],
  "total": 2
}

Background Job Workflow

bwa_index / bwa_mem
        │
        ▼
   returns job_id   ←── no timeout risk
        │
        ▼
check_job_status(job_id)
        │
   status = "running"?  ──► poll again later
        │
   status = "completed"  ──► result is ready
   status = "failed"     ──► check stderr field

Note: The job registry is in-memory. Jobs are lost if the MCP server process restarts. Always check check_job_status in the same session that launched the job.


Platform Support

PlatformStatus
macOSTested — builds from source and installs to /usr/local/bin
WindowsSupported via WSL — tested on Windows 10/11 with WSL2
LinuxSupported (same build steps as macOS) — not yet tested