Nix flake for Claude Code with MCP servers and plugins.
- Installs Claude Code CLI via claude-code-nix
- Installs dependencies: bun, uv, nodejs, jq
- Configures MCP servers (Azure DevOps) - merges into existing
~/.claude.json - Installs plugins (claude-mem)
- Nix with flakes enabled
- Docker CLI available (
dockercommand)- Docker Desktop, Rancher Desktop, Colima, or Podman with Docker CLI
Use the pre-configured module that includes the Claude Code package:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager";
nix-mcp-setup.url = "github:helgeu/nix-mcp-setup";
};
outputs = { nixpkgs, home-manager, nix-mcp-setup, ... }: {
homeConfigurations."youruser" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.aarch64-darwin;
modules = [
# Use system-specific module with package included
nix-mcp-setup.homeManagerModulesWithPackage.aarch64-darwin.default
{
programs.claude-code = {
enable = true;
mcp.azure-devops.work = {
enable = true;
organizationUrl = "https://dev.azure.com/myorg";
};
# plugins.claude-mem.enable = true; # Optional
};
}
];
};
};
}For more control, pass the flake via extraSpecialArgs:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager";
nix-mcp-setup.url = "github:helgeu/nix-mcp-setup";
};
outputs = { nixpkgs, home-manager, nix-mcp-setup, ... }: {
homeConfigurations."youruser" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.aarch64-darwin;
extraSpecialArgs = {
inherit nix-mcp-setup;
};
modules = [
nix-mcp-setup.homeManagerModules.default
{
programs.claude-code = {
enable = true;
mcp.azure-devops.work = {
enable = true;
organizationUrl = "https://dev.azure.com/myorg";
};
# plugins.claude-mem.enable = true; # Optional
};
}
];
};
};
}Then run:
home-manager switchInstall Claude Code only (no MCP config):
nix profile install github:helgeu/nix-mcp-setup| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable Claude Code |
package |
package | claude-code | Claude Code package |
containerCommand |
string | "docker" |
Container runtime (docker, podman, etc.) |
validateContainerRuntime |
bool | true |
Warn if container runtime not found |
Multiple Azure DevOps instances can be configured. Each <name> becomes part of the MCP server name (e.g., work → ado-mcp-work).
| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable this ADO MCP server instance |
organizationUrl |
string | required | ADO organization URL |
image |
string | pinned digest | Docker image (pinned for reproducibility) |
patEnvVar |
string | "AZURE_DEVOPS_PAT_<NAME>" |
PAT environment variable (auto-generated from instance name) |
prePull |
bool | true |
Pre-pull image during activation |
Example with multiple instances:
programs.claude-code.mcp.azure-devops = {
work = {
enable = true;
organizationUrl = "https://dev.azure.com/work-org";
# patEnvVar defaults to "AZURE_DEVOPS_PAT_WORK"
};
client-acme = {
enable = true;
organizationUrl = "https://dev.azure.com/acme-corp";
patEnvVar = "ADO_PAT_ACME"; # Override default
};
};| Option | Type | Default | Description |
|---|---|---|---|
installGhCli |
bool | true |
Install GitHub CLI (gh) for PAT management |
Multiple GitHub instances can be configured (github.com + GitHub Enterprise). Each <name> becomes part of the MCP server name (e.g., personal → github-mcp-personal).
| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable this GitHub MCP server instance |
image |
string | pinned digest | Docker image (pinned for reproducibility) |
patEnvVar |
string | "GITHUB_PAT_<NAME>" |
PAT environment variable (auto-generated from instance name) |
host |
string | null |
GitHub Enterprise host URL (null for github.com) |
toolsets |
list | [] |
Limit tools: repos, issues, pull_requests, actions, etc. |
prePull |
bool | true |
Pre-pull image during activation |
Example with multiple instances:
programs.claude-code.mcp.github.instances = {
personal = {
enable = true;
# patEnvVar defaults to "GITHUB_PAT_PERSONAL"
};
work-ghe = {
enable = true;
host = "https://github.mycompany.com";
patEnvVar = "GH_PAT_WORK";
toolsets = [ "repos" "issues" "pull_requests" ];
};
};| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable Context7 MCP server |
image |
string | pinned digest | Docker image (pinned for reproducibility) |
serverName |
string | "context7-mcp" |
MCP server name in config |
prePull |
bool | true |
Pre-pull image during activation |
| Option | Type | Default | Description |
|---|---|---|---|
enable |
bool | false |
Enable claude-mem plugin |
autoInstall |
bool | true |
Auto-install on activation |
Set PATs as environment variables (one per instance):
# For instance "work" → env var AZURE_DEVOPS_PAT_WORK
export AZURE_DEVOPS_PAT_WORK="your-work-pat"
export AZURE_DEVOPS_PAT_CLIENT_ACME="your-acme-pat"Use the helper script to set up PATs:
# Interactive mode
./scripts/create-ado-pat.sh
# Or specify instance directly
./scripts/create-ado-pat.sh --instance work --org "https://dev.azure.com/work-org"Set PATs as environment variables (one per instance):
# For instance "personal" → env var GITHUB_PAT_PERSONAL
export GITHUB_PAT_PERSONAL="ghp_xxxxxxxxxxxx"
export GH_PAT_WORK="ghp_yyyyyyyyyyyy" # Custom env var for work-ghe instanceUse the helper script to set up PATs:
# Interactive mode
./scripts/create-github-pat.sh
# Set up PAT for specific instance
./scripts/create-github-pat.sh --instance personal
# Set up PAT for GitHub Enterprise instance
./scripts/create-github-pat.sh --instance work-ghe --host "https://github.mycompany.com"Or create manually at: https://github.com/settings/tokens
The module merges MCP servers into your existing ~/.claude.json. It won't overwrite your other settings.
If autoInstall = false, install manually:
./scripts/setup-claude-plugins.sh claude-memDocker images are pinned by digest for reproducibility. To update to latest:
# Pull latest and get new digest
docker pull ghcr.io/metorial/mcp-container--vortiago--mcp-azure-devops--mcp-azure-devops:latest
docker inspect ghcr.io/metorial/mcp-container--vortiago--mcp-azure-devops--mcp-azure-devops:latest \
--format='{{index .RepoDigests 0}}'
# Use the output in your config:
mcp.azure-devops.image = "ghcr.io/...@sha256:abc123...";| Server | Docker Image | Status |
|---|---|---|
| Azure DevOps | ghcr.io/metorial/mcp-container--vortiago--mcp-azure-devops--mcp-azure-devops |
✅ Implemented |
| GitHub | ghcr.io/github/github-mcp-server |
✅ Implemented |
| Context7 | mcp/context7 |
✅ Implemented |
nix-mcp-setup/
├── flake.nix # Main entry point
├── modules/
│ ├── home-manager.nix # Home Manager module
│ ├── mcp-servers/
│ │ ├── azure-devops-mcp.nix # ADO MCP config
│ │ ├── github-mcp.nix # GitHub MCP config
│ │ └── context7-mcp.nix # Context7 MCP config
│ └── plugins/
│ └── claude-mem.nix # claude-mem plugin
├── scripts/
│ ├── create-ado-pat.sh # Generate ADO PAT (multi-instance)
│ ├── create-ado-pat.ps1 # Generate ADO PAT (PowerShell, legacy)
│ ├── create-github-pat.sh # Generate GitHub PAT
│ └── setup-claude-plugins.sh # Manual plugin install
├── examples/
│ └── claude.json # Example config
└── docs/
├── ROADMAP.md
├── PLAN-NIX-MODULE.md
└── PLUGIN-DEPENDENCIES.md
Create a test directory and flake:
mkdir /tmp/nix-mcp-test && cd /tmp/nix-mcp-testCreate flake.nix (see examples/test-flake.nix), then:
# Dry run - see what would be generated
home-manager build --flake .#test
# Check generated config
cat result/home-path/etc/profile.d/hm-session-vars.sh
# Actually apply (modifies your home)
home-manager switch --flake .#testAfter setup:
# Check Claude Code
claude --version
# Check MCP servers
claude mcp list
# Check plugins
claude plugin list
# Check config was merged
cat ~/.claude.json | jq '.mcpServers'MIT