Sift MCP (Docker edition)
Sift MCP ā Docker edition š³
An MCP server that exposes the SANS SIFT digital-forensics toolkit as tools an LLM can call. Drive it from Claude Desktop, Ollama Desktop, or any MCP client.
This edition runs the whole toolchain as a self-contained Docker container ā no SIFT VM required, works anywhere Docker runs. If you'd rather run on an existing SANS SIFT install, see the VM edition (separate repo): sift-mcp-vm.
It wraps standard DFIR command-line programs (The Sleuth Kit, Volatility 3, Plaso, exiftool, YARA, etc.) behind a safe, allowlisted interface. This is a defensive / investigative tool ā it does not generate exploits or malware.
Contents
sift-mcp-docker/
āāā server.py # the MCP server
āāā requirements.txt # Python dependencies
āāā Dockerfile # Ubuntu 24.04 + forensic toolchain + server
āāā docker-compose.yml # service, mounts, ports, healthcheck
āāā healthcheck.py # container liveness probe
āāā .env.example # host bind address, port, timeouts
āāā .dockerignore
āāā clients/ # example client configs (Claude Desktop, Ollama)
āāā README.mdThe image is Ubuntu 24.04 with The Sleuth Kit, foremost, exiftool, binwalk, yara, and Plaso (from the GIFT PPA), plus Volatility 3 and python-evtx (via pip). It runs as a non-root user and serves MCP over HTTP on port 8000.
Quick start
git clone <your-repo-url> sift-mcp-docker
cd sift-mcp-docker
cp .env.example .env # optional: tweak ports/limits
mkdir -p cases/output # evidence goes in ./cases
docker compose up -d --build # build + start
docker compose logs -f # watch startupThe endpoint is now http://localhost:8000/mcp. Put evidence in ./cases
(e.g. ./cases/case01/disk.E01); recovered/carved files and timelines appear in
./cases/output.
How the mounts work
./casesā mounted read-only at/cases; the container can never alter your original evidence../cases/outputā mounted writable at/cases/outputfor results.
If the container can't write to cases/output (a bind-mount permission
mismatch), either chmod 777 cases/output on the host, or add
user: "${UID}:${GID}" to the service in docker-compose.yml and run
UID=$(id -u) GID=$(id -g) docker compose up -d.
Without compose
docker build -t sift-mcp:latest .
docker run -d --name sift-mcp -p 127.0.0.1:8000:8000 \
-v "$PWD/cases:/cases:ro" -v "$PWD/cases/output:/cases/output" \
sift-mcp:latestCommon commands
docker compose ps # status + health
docker compose logs -f # logs
docker compose restart # restart after editing .env
docker compose down # stop and remove
docker compose up -d --build # rebuild after changing server.pyThe tools
Disk / file analysis ā sift_disk_partitions (mmls), sift_image_info
(img_stat), sift_filesystem_info (fsstat), sift_list_files (fls),
sift_extract_file (icat, returns SHA-256), sift_carve_files (foremost),
sift_file_type (file), sift_hash_file (md5/sha1/sha256).
Memory forensics ā sift_volatility (any Volatility 3 plugin).
Timeline & artifacts ā sift_create_timeline (log2timeline),
sift_export_timeline (psort), sift_parse_evtx.
Metadata & strings ā sift_exiftool, sift_strings, sift_binwalk,
sift_hexdump, sift_yara_scan.
Housekeeping ā sift_list_evidence, sift_server_info (shows which
binaries are installed). Call sift_server_info after startup to confirm the
toolchain inside the container.
Connecting clients
Both configs are in clients/. Use http://localhost:8000/mcp as the URL.
Claude Desktop
Claude Desktop speaks MCP over stdio, so bridge to the HTTP endpoint with
mcp-remote (needs Node.js on the host). Edit
%APPDATA%\Claude\claude_desktop_config.json (Windows) or
~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"sift": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8000/mcp", "--transport", "http-only"]
}
}
}Ollama Desktop
Use mcphost to bridge an Ollama model
to MCP:
go install github.com/mark3labs/mcphost@latest
mcphost -m ollama:qwen2.5 --config clients/ollama_mcphost_config.example.jsonUse a tool-calling model (e.g. qwen2.5, llama3.1).
Quick check
curl -i http://localhost:8000/mcpA 406 Not Acceptable is expected and good ā it means the server is up (it only
accepts proper MCP POSTs, not bare GETs).
Configuration (environment variables)
Set host-side values in .env; container-internal paths are fixed by compose.
Variable | Default | Purpose |
|
| Host address to publish on ( |
|
| Host port mapped to the container |
|
| Default per-command timeout (s) |
|
| Output truncation limit |
Security model
Each tool runs one fixed, allowlisted binary via
execā never a shell.File paths are resolved (symlinks included) and confined to
/cases(read) and/cases/output(write); anything outside is rejected.Plugin names, carve types, inode addresses, and parser names are shape-validated. Every command runs under a timeout with truncated output.
The server has no authentication ā by default it publishes only on
127.0.0.1. If you setHOST_BIND=0.0.0.0, keep it on a trusted/private network, never the public internet.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Sidera-Labs/SiftDockerMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server