Files
mcp-servers/README.org
MCP Packages 04ea0f69ae pdf-reader-mcp
2026-02-04 22:26:10 +01:00

7.5 KiB

MCP Server Packages for Nix

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:

{
  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
      ];
    };
  };
}

Using Packages Directly

Access packages without the overlay:

{
  inputs.mcp.url = "github:YOUR-USERNAME/mcp";

  outputs = { mcp, ... }: {
    # Access directly
    myPackage = mcp.packages.x86_64-linux.manim-mcp-server;
  };
}

In a Development Shell

{
  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
        ];
      };
    };
}

Adding New Packages

Directory Structure

packages/
├── default.nix              # Package aggregator
└── <package-name>/
    └── package.nix          # Package derivation

Step-by-Step Guide

  1. Create the package directory

    mkdir -p packages/<package-name>
  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

    { 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 { };
    }
  4. Build and test

    nix build .#<package-name>
    ./result/bin/<package-name>

Package Templates

Python (with pyproject.toml)

{ 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";
  };
}

Python (script only, like manim-mcp-server)

{ 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;
  };
}

Go

{ 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;
  };
}

Node.js (with package-lock.json)

{ 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;
  };
}

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:

{ 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;
  };
}

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:

hash = lib.fakeHash;

Then run nix build and copy the correct hash from the error message.

Development

Enter Development Shell

nix develop

Build a Specific Package

nix build .#manim-mcp-server

Build All Packages

nix build .#default

List Available Packages

nix flake show

License

Each packaged MCP server retains its original license. The Nix expressions in this repository are provided as-is.