Files
mcp-servers/docs/adding-new-packages.md
MCP Packages e66a06afdf docs
2026-02-04 23:04:56 +01:00

4.6 KiB
Raw Blame History

Adding New Packages

Directory Structure

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

StepbyStep 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)

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

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.