Usage
Pick Your Poison
We've got five ways to run this thing. They all do the same thing, so just pick based on what tools you already have installed. Or try all five. We don't judge.
No Nix Required
This tool works on any system — Windows, macOS, Linux. You're just querying web APIs. Yes, even you, Windows users.
Option 1: uvx
Recommended for most humans
The civilized approach. If you've got Python and can install things like a normal person, this is for you.
{
"mcpServers": {
"nixos": {
"command": "uvx",
"args": ["mcp-nixos"]
}
}
}Pro tip: this installs nothing permanently. It's like a one-night stand with software.
Option 2: Nix
For the enlightened
You're already using Nix, so you probably think you're better than everyone else. And you know what? You might be right.
{
"mcpServers": {
"nixos": {
"command": "nix",
"args": ["run", "github:utensils/mcp-nixos", "--"]
}
}
}Bonus: this method makes you feel superior at developer meetups.
Option 2b: Declarative Nix
The true Nix way
mcp-nixos ships in nixpkgs. Add it to your config like everything else you've spent 400 hours perfecting.
# NixOS (configuration.nix)
environment.systemPackages = [ pkgs.mcp-nixos ];
# Home Manager (home.nix)
home.packages = [ pkgs.mcp-nixos ];
# nix-darwin (darwin-configuration.nix)
environment.systemPackages = [ pkgs.mcp-nixos ];Or consume the flake directly via the provided overlay:
# flake.nix
{
inputs.mcp-nixos.url = "github:utensils/mcp-nixos";
outputs = { nixpkgs, mcp-nixos, ... }: {
nixpkgs.overlays = [ mcp-nixos.overlays.default ];
# pkgs.mcp-nixos is now available everywhere
};
}Finally, a package that slots into your 3,000-line flake.nix without drama.
Option 3: Docker
Container enthusiasts unite
Because why install software directly when you can wrap it in 17 layers of abstraction? At least it's reproducible. Probably.
{
"mcpServers": {
"nixos": {
"command": "docker",
"args": ["run", "--rm", "-i", "ghcr.io/utensils/mcp-nixos"]
}
}
}Multi-arch images (amd64 + arm64) on both GHCR and Docker Hub:
ghcr.io/utensils/mcp-nixosutensils/mcp-nixos
May consume 500MB of disk for a 10MB Python script. But hey, it's "isolated"!
Option 4: HTTP Transport (Remote MCP)
For grown-up deployments
Run the server over HTTP instead of STDIO. Great for shared setups, remote hosts, or when you want one server instance serving multiple clients like a responsible adult.
# Start with defaults: http://127.0.0.1:8000/mcp
MCP_NIXOS_TRANSPORT=http mcp-nixos
# Custom host, port, and path
MCP_NIXOS_TRANSPORT=http \
MCP_NIXOS_HOST=0.0.0.0 \
MCP_NIXOS_PORT=9090 \
MCP_NIXOS_PATH=/api/mcp \
mcp-nixos
# Stateless mode — no per-client sessions
MCP_NIXOS_TRANSPORT=http MCP_NIXOS_STATELESS_HTTP=1 mcp-nixosDefaults to 127.0.0.1:8000/mcp. Works with any MCP client that speaks HTTP.
Option 5: Pi Coding Agent
For Pi users
Pi doesn't speak MCP natively. Two supported paths:
A. pi-mcp-adapter (recommended — single source of truth):
pi install npm:pi-mcp-adapterThen add to ~/.pi/agent/mcp.json:
{
"mcpServers": {
"nixos": {
"command": "uvx",
"args": ["mcp-nixos"],
"lifecycle": "lazy"
}
}
}B. Project-local extension: the repo ships .pi/extensions/mcp-nixos.ts, auto-loaded when you run pi inside the cloned repo. Optional: cd .pi && npm install for editor type resolution. Pi runs it either way.
Pi doesn't speak MCP natively, so we meet it halfway.
The Tools
Just two. We consolidated 17 tools into 2 because your AI's context window isn't infinite. ~1,030 tokens total. You're welcome.
nix — Unified Query Tool
One tool to rule them all:
nix(action, query, source, type, channel, limit, version, system)version and system are only used by action="cache".
| Action | What it does |
|---|---|
search | Search packages, options, programs, flakes, wiki, docs |
info | Get detailed info about a package, option, or function |
stats | Counts, channels, categories |
browse | Browse Home Manager, Darwin, Nixvim, NVF, or Noogle by prefix (alias: options) |
channels | List available NixOS channels |
flake-inputs | Explore local flake inputs from the Nix store |
cache | Check binary cache status for packages |
store | Read files directly from /nix/store |
| Source | What it queries |
|---|---|
nixos | Packages, options, programs (search.nixos.org) |
home-manager | Home Manager options |
darwin | nix-darwin options |
flakes | Community flakes (search.nixos.org) |
flakehub | FlakeHub registry (flakehub.com) |
nixvim | Nixvim Neovim configuration options |
nvf | NVF Neovim configuration options (latest unstable docs) |
noogle | Nix function signatures & docs (noogle.dev) |
wiki | NixOS Wiki articles (wiki.nixos.org) |
nix-dev | Official Nix docs (nix.dev) |
nixhub | Package metadata & store paths (nixhub.io) |
NVF returns canonical vim.* option paths. It also accepts the shorthand programs.nvf.vim.* and the actual NixOS/Home Manager module path programs.nvf.settings.vim.* as input aliases.
Examples
# Search NixOS packages
nix(action="search", query="firefox", source="nixos", type="packages")
# Get package info
nix(action="info", query="firefox", source="nixos", type="package")
# Search Home Manager options
nix(action="search", query="git", source="home-manager")
# Browse darwin options by prefix
nix(action="browse", source="darwin", query="system.defaults")
# Search Nixvim options
nix(action="search", query="telescope", source="nixvim")
# Search NVF options
nix(action="search", query="vim.languages.nix", source="nvf")
# Inspect an NVF option through its Home Manager/NixOS wrapper path
nix(action="info", query="programs.nvf.settings.vim.languages.nix.enable", source="nvf")
# Browse an NVF prefix (the shorter wrapper alias is accepted too)
nix(action="browse", query="programs.nvf.vim.languages.nix", source="nvf")
# Search FlakeHub
nix(action="search", query="nixpkgs", source="flakehub")
# Noogle function lookup
nix(action="info", query="lib.attrsets.mapAttrs", source="noogle")
# NixOS Wiki
nix(action="search", query="nvidia", source="wiki")
# nix.dev tutorials
nix(action="search", query="packaging tutorial", source="nix-dev")
# NixHub rich metadata
nix(action="info", query="python", source="nixhub")
# Stats
nix(action="stats", source="nixos", channel="stable")
# Local flake inputs (requires Nix installed locally)
nix(action="flake-inputs", type="list")
nix(action="flake-inputs", type="ls", query="nixpkgs:pkgs/by-name")
nix(action="flake-inputs", type="read", query="nixpkgs:flake.nix")nix_versions — Package Version History
Historical package versions with nixpkgs commit hashes. Output includes:
- Package metadata (license, homepage, programs) when available
- Platform availability per version (Linux / macOS)
- nixpkgs commit hash for reproducible builds
- Attribute path for Nix expressions
nix_versions(package, version, limit)# List recent versions with metadata
nix_versions(package="python", limit=5)
# Find a specific version
nix_versions(package="nodejs", version="20.0.0")Binary Cache & NixHub
Two crowd-pleasers worth calling out separately.
Check the binary cache before you commit to a three-hour build:
# Is hello cached?
nix(action="cache", query="hello")
# Specific version
nix(action="cache", query="python", version="3.12.0")
# Specific system
nix(action="cache", query="firefox", system="x86_64-linux")Shows download size, unpacked size, compression method, and availability per platform.
Grab rich metadata from NixHub.io:
# Search packages with metadata
nix(action="search", source="nixhub", query="nodejs")
# Detailed info — license, homepage, programs, store paths
nix(action="info", source="nixhub", query="python")Environment Variables
| Variable | Purpose | Default |
|---|---|---|
MCP_NIXOS_TRANSPORT | stdio or http | stdio |
MCP_NIXOS_HOST | HTTP bind address | 127.0.0.1 |
MCP_NIXOS_PORT | HTTP bind port | 8000 |
MCP_NIXOS_PATH | HTTP MCP endpoint path | /mcp |
MCP_NIXOS_STATELESS_HTTP | Set to 1 to disable per-client session state | unset |
ELASTICSEARCH_URL | Override the NixOS search backend (for local testing) | unset |
What Happens Next?
Once you've picked your configuration method and added it to your MCP client:
- Your AI assistant stops making up NixOS package names
- You get actual, real-time information about 130K+ packages
- Configuration options that actually exist (shocking, we know)
- Version history that helps you find that one specific Ruby version from 2019
- Binary cache status so you know if you'll be waiting three hours to build Firefox
That's it. No complex setup. No 47-step installation guide. No sacrificing a USB stick to the Nix gods. Just paste, reload, and enjoy an AI that actually knows what it's talking about.
Still confused?
Good news: that's what the AI is for. Just ask it.