From b467013c12bd918af75f49273293c0823d829dd7 Mon Sep 17 00:00:00 2001 From: MCP Packages Date: Wed, 4 Feb 2026 15:35:12 +0100 Subject: [PATCH] Initial commit: MCP server packages for Nix - Add flake structure with overlay and packages exports - Add manim-mcp-server as first packaged MCP server - Add README.org with usage instructions and package templates - Add packages/default.nix as package aggregator - Add overlays/default.nix for nixpkgs integration --- .envrc | 1 + .gitignore | 27 +++ README.org | 304 ++++++++++++++++++++++++++ flake.lock | 240 ++++++++++++++++++++ flake.nix | 67 ++++++ overlays/default.nix | 23 ++ packages/default.nix | 16 ++ packages/manim-mcp-server/package.nix | 54 +++++ 8 files changed, 732 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 README.org create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 overlays/default.nix create mode 100644 packages/default.nix create mode 100644 packages/manim-mcp-server/package.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..deed614 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +# Nix +result +result-* + +# direnv +.direnv/ + +# Editor files +*~ +\#*\# +.#* +*.swp +*.swo + +# macOS +.DS_Store + +# IDE +.idea/ +.vscode/ +*.code-workspace + +# Agent transcripts +.agent-shell/ + +# Local environment overrides +.envrc.local diff --git a/README.org b/README.org new file mode 100644 index 0000000..f8be219 --- /dev/null +++ b/README.org @@ -0,0 +1,304 @@ +#+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 | +|--------------------+------------------------------------------------------+----------| +| manim-mcp-server | Execute Manim animation code and return videos | 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 + +#+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 + +** 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. diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..aa29fbe --- /dev/null +++ b/flake.lock @@ -0,0 +1,240 @@ +{ + "nodes": { + "blueprint": { + "inputs": { + "nixpkgs": [ + "jailed-agents", + "llm-agents", + "nixpkgs" + ], + "systems": "systems_3" + }, + "locked": { + "lastModified": 1769353768, + "narHash": "sha256-zI+7cbMI4wMIR57jMjDSEsVb3grapTnURDxxJPYFIW0=", + "owner": "numtide", + "repo": "blueprint", + "rev": "c7da5c70ad1c9b60b6f5d4f674fbe205d48d8f6c", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "blueprint", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "jail-nix": { + "locked": { + "lastModified": 1765903853, + "narHash": "sha256-buoPpx7moJzAXbLuHAImn6x9fGRdk3x0T57goPv1vnc=", + "owner": "~alexdavid", + "repo": "jail.nix", + "rev": "bf9f49c8118e7a77b68a675dbe26e93e91412066", + "type": "sourcehut" + }, + "original": { + "owner": "~alexdavid", + "repo": "jail.nix", + "type": "sourcehut" + } + }, + "jailed-agents": { + "inputs": { + "flake-utils": "flake-utils_2", + "jail-nix": "jail-nix", + "llm-agents": "llm-agents", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1770196904, + "narHash": "sha256-nV2Sq7+y9ocPln5+zLVjV5cvE4E4i7J6TR88OnIPQdA=", + "path": "/conf/jailed-agents", + "type": "path" + }, + "original": { + "path": "/conf/jailed-agents", + "type": "path" + } + }, + "llm-agents": { + "inputs": { + "blueprint": "blueprint", + "nixpkgs": "nixpkgs", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1769813338, + "narHash": "sha256-IlRKon8+bfoi/uOa8CUPAAWW0Pv6AHBSF1jVSD4QO8U=", + "owner": "numtide", + "repo": "llm-agents.nix", + "rev": "58939415e56d01c30d429cf0c49a9d8e2a6a07c3", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "llm-agents.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1769740369, + "narHash": "sha256-xKPyJoMoXfXpDM5DFDZDsi9PHArf2k5BJjvReYXoFpM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6308c3b21396534d8aaeac46179c14c439a89b8a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1770115704, + "narHash": "sha256-KHFT9UWOF2yRPlAnSXQJh6uVcgNcWlFqqiAZ7OVlHNc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e6eae2ee2110f3d31110d5c222cd395303343b08", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "jailed-agents": "jailed-agents", + "nixpkgs": "nixpkgs_3" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "jailed-agents", + "llm-agents", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769691507, + "narHash": "sha256-8aAYwyVzSSwIhP2glDhw/G0i5+wOrren3v6WmxkVonM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..659921d --- /dev/null +++ b/flake.nix @@ -0,0 +1,67 @@ +{ + nixConfig = { + extra-substituters = [ + "https://nix-community.cachix.org" + ]; + extra-trusted-public-keys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + + description = "MCP Server Packages for Nix"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + jailed-agents.url = "path:/conf/jailed-agents"; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + jailed-agents, + ... + }: + { + # Overlay that adds all MCP packages to nixpkgs + overlays.default = import ./overlays/default.nix; + } + // flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ self.overlays.default ]; + }; + + # Import all MCP packages + mcpPackages = import ./packages { inherit pkgs; }; + + # List of all MCP server packages (for devShell) + allMcpServers = builtins.attrValues mcpPackages ++ [ pkgs.mcp-nixos ]; + in + { + # Export all packages + packages = mcpPackages // { + default = pkgs.symlinkJoin { + name = "mcp-servers"; + paths = builtins.attrValues mcpPackages; + }; + }; + + devShells.default = pkgs.mkShell { + packages = + allMcpServers + ++ [ + pkgs.git + (jailed-agents.lib.${system}.makeJailed system { + agentTool = "opencode"; + extraPkgs = allMcpServers; + }) + ]; + }; + } + ); +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..5f658ab --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,23 @@ +# MCP Servers Overlay +# +# This overlay adds all MCP server packages to nixpkgs. +# +# Usage in a flake: +# { +# inputs.mcp.url = "github:your-user/mcp"; +# +# outputs = { nixpkgs, mcp, ... }: { +# # Apply the overlay +# pkgs = import nixpkgs { +# system = "x86_64-linux"; +# overlays = [ mcp.overlays.default ]; +# }; +# # Now pkgs.manim-mcp-server is available +# }; +# } +# +final: prev: +let + mcpPackages = import ../packages { pkgs = final; }; +in +mcpPackages diff --git a/packages/default.nix b/packages/default.nix new file mode 100644 index 0000000..f88a31a --- /dev/null +++ b/packages/default.nix @@ -0,0 +1,16 @@ +# MCP Server Packages +# +# This file aggregates all MCP server packages in this repository. +# To add a new package: +# 1. Create a directory: packages// +# 2. Create package.nix in that directory +# 3. Add an entry below using callPackage +# +{ pkgs }: + +{ + manim-mcp-server = pkgs.callPackage ./manim-mcp-server/package.nix { }; + + # Add new packages here: + # example-mcp-server = pkgs.callPackage ./example-mcp-server/package.nix { }; +} diff --git a/packages/manim-mcp-server/package.nix b/packages/manim-mcp-server/package.nix new file mode 100644 index 0000000..bb3c7fb --- /dev/null +++ b/packages/manim-mcp-server/package.nix @@ -0,0 +1,54 @@ +{ + lib, + stdenv, + fetchFromGitHub, + makeWrapper, + python3, + manim, +}: + +let + python = python3.withPackages ( + ps: with ps; [ + mcp + fastmcp + ] + ); +in +stdenv.mkDerivation rec { + pname = "manim-mcp-server"; + version = "0.0.1-unstable"; + + src = fetchFromGitHub { + owner = "abhiemj"; + repo = "manim-mcp-server"; + rev = "da23214426a56ce3ba4da39b0718d64cf97cd23c"; + hash = "sha256-orR3CtFiSucErPJzIF0Si4s16LH1d+ZhyUKo6PC966I="; + }; + + nativeBuildInputs = [ makeWrapper ]; + + dontBuild = true; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin $out/lib/manim-mcp-server + cp src/manim_server.py $out/lib/manim-mcp-server/ + + makeWrapper ${python}/bin/python $out/bin/manim-mcp-server \ + --add-flags "$out/lib/manim-mcp-server/manim_server.py" \ + --set MANIM_EXECUTABLE "${manim}/bin/manim" + + runHook postInstall + ''; + + meta = with lib; { + description = "MCP server that executes Manim animation code and returns generated videos"; + homepage = "https://github.com/abhiemj/manim-mcp-server"; + license = licenses.mit; + maintainers = [ ]; + mainProgram = "manim-mcp-server"; + platforms = platforms.all; + }; +}