#+TITLE: MCP Server Packages for Nix #+AUTHOR: #+DESCRIPTION: Nix derivations for Model Context Protocol (MCP) servers * Overview This repository provides Nix derivations for MCP (Model Context Protocol) servers that are not yet available in nixpkgs. * Available Packages | Package | Description | Language | |----------------------------+----------------------------------------------------------+------------| | academic-search-mcp-server | Search academic papers via Semantic Scholar and Crossref | Python | | manim-mcp-server | Execute Manim animation code and return videos | Python | | pdf-reader-mcp | Production-ready PDF processing with parallel processing | TypeScript | | zotero-mcp | Connect Zotero research library with AI assistants | Python | * Usage ** Using the Overlay (Recommended) Add this flake to your inputs and apply the overlay: #+begin_src nix { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; mcp.url = "github:YOUR-USERNAME/mcp"; # Update with your repo }; outputs = { nixpkgs, mcp, ... }: { # Apply the overlay to get packages in pkgs nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ { nixpkgs.overlays = [ mcp.overlays.default ]; } # Now you can use pkgs.manim-mcp-server ]; }; }; } #+end_src ** Using Packages Directly Access packages without the overlay: #+begin_src nix { inputs.mcp.url = "github:YOUR-USERNAME/mcp"; outputs = { mcp, ... }: { # Access directly myPackage = mcp.packages.x86_64-linux.manim-mcp-server; }; } #+end_src ** In a Development Shell #+begin_src nix { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; mcp.url = "github:YOUR-USERNAME/mcp"; }; outputs = { nixpkgs, mcp, ... }: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; overlays = [ mcp.overlays.default ]; }; in { devShells.${system}.default = pkgs.mkShell { packages = [ pkgs.manim-mcp-server ]; }; }; } #+end_src * Adding New Packages ** Directory Structure #+begin_example packages/ ├── default.nix # Package aggregator └── / └── package.nix # Package derivation #+end_example ** Step-by-Step Guide 1. *Create the package directory* #+begin_src bash mkdir -p packages/ #+end_src 2. *Create =package.nix=* using the appropriate builder for the language: - Python (with pyproject.toml): =python3Packages.buildPythonApplication= - Python (script only): wrapper approach with =stdenv.mkDerivation= - Go: =buildGoModule= - Node.js: =buildNpmPackage= - Rust: =rustPlatform.buildRustPackage= 3. *Register in =packages/default.nix=* #+begin_src nix { pkgs }: { manim-mcp-server = pkgs.callPackage ./manim-mcp-server/package.nix { }; # Add your new package here: new-mcp-server = pkgs.callPackage ./new-mcp-server/package.nix { }; } #+end_src 4. *Build and test* #+begin_src bash nix build .# ./result/bin/ #+end_src ** Package Templates *** Python (with pyproject.toml) #+begin_src nix { lib, python3Packages, fetchFromGitHub }: python3Packages.buildPythonApplication rec { pname = "example-mcp-server"; version = "1.0.0"; pyproject = true; src = fetchFromGitHub { owner = "owner"; repo = "repo"; rev = "v${version}"; hash = "sha256-AAAA..."; # Use lib.fakeHash first, then update }; build-system = [ python3Packages.hatchling ]; dependencies = with python3Packages; [ mcp fastmcp ]; meta = with lib; { description = "Description of the MCP server"; homepage = "https://github.com/owner/repo"; license = licenses.mit; mainProgram = "example-mcp-server"; }; } #+end_src *** Python (script only, like manim-mcp-server) #+begin_src nix { lib, stdenv, fetchFromGitHub, makeWrapper, python3 }: let python = python3.withPackages (ps: with ps; [ mcp fastmcp # other dependencies ]); in stdenv.mkDerivation rec { pname = "example-mcp-server"; version = "0.0.1-unstable"; src = fetchFromGitHub { owner = "owner"; repo = "repo"; rev = "commit-hash"; hash = "sha256-AAAA..."; }; nativeBuildInputs = [ makeWrapper ]; dontBuild = true; installPhase = '' runHook preInstall mkdir -p $out/bin $out/lib/${pname} cp src/server.py $out/lib/${pname}/ makeWrapper ${python}/bin/python $out/bin/${pname} \ --add-flags "$out/lib/${pname}/server.py" runHook postInstall ''; meta = with lib; { description = "Description"; homepage = "https://github.com/owner/repo"; license = licenses.mit; mainProgram = pname; }; } #+end_src *** Go #+begin_src nix { lib, buildGoModule, fetchFromGitHub }: buildGoModule rec { pname = "example-mcp-server"; version = "1.0.0"; src = fetchFromGitHub { owner = "owner"; repo = "repo"; rev = "v${version}"; hash = "sha256-AAAA..."; }; vendorHash = "sha256-BBBB..."; # Use lib.fakeHash first ldflags = [ "-s" "-w" "-X main.version=${version}" ]; meta = with lib; { description = "Description"; homepage = "https://github.com/owner/repo"; license = licenses.mit; mainProgram = pname; }; } #+end_src *** Node.js (with package-lock.json) #+begin_src nix { lib, buildNpmPackage, fetchFromGitHub }: buildNpmPackage rec { pname = "example-mcp-server"; version = "1.0.0"; src = fetchFromGitHub { owner = "owner"; repo = "repo"; rev = "v${version}"; hash = "sha256-AAAA..."; }; npmDepsHash = "sha256-BBBB..."; # Use lib.fakeHash first dontNpmBuild = true; # If pre-built or no build step needed meta = with lib; { description = "Description"; homepage = "https://github.com/owner/repo"; license = licenses.mit; mainProgram = pname; }; } #+end_src *** Node.js (wrapper for npm packages without package-lock.json) Use this approach when the upstream project uses bun.lock or yarn.lock instead of package-lock.json: #+begin_src nix { lib, stdenvNoCC, nodejs_22, makeWrapper }: stdenvNoCC.mkDerivation rec { pname = "example-mcp-server"; version = "1.0.0"; # No source needed - npx fetches the package dontUnpack = true; nativeBuildInputs = [ makeWrapper ]; installPhase = '' runHook preInstall mkdir -p $out/bin makeWrapper ${nodejs_22}/bin/npx $out/bin/${pname} \ --add-flags "--yes" \ --add-flags "@scope/package-name@${version}" runHook postInstall ''; meta = with lib; { description = "Description"; homepage = "https://github.com/owner/repo"; license = licenses.mit; mainProgram = pname; }; } #+end_src Note: This approach requires network access on first run as npx downloads the package. ** Calculating Hashes When adding a new package, use =lib.fakeHash= initially: #+begin_src nix hash = lib.fakeHash; #+end_src Then run =nix build= and copy the correct hash from the error message. * Development ** Enter Development Shell #+begin_src bash nix develop #+end_src ** Build a Specific Package #+begin_src bash nix build .#manim-mcp-server #+end_src ** Build All Packages #+begin_src bash nix build .#default #+end_src ** List Available Packages #+begin_src bash nix flake show #+end_src * License Each packaged MCP server retains its original license. The Nix expressions in this repository are provided as-is.