19 Commits

Author SHA1 Message Date
hermes-agent 8dc25624ff add: annas-mcp package (Go, fakeHash placeholders)
NixOS Configuration CI / Nix Flake Check (pull_request) Failing after 20s
2026-07-12 18:58:19 +00:00
hermes-agent 676d06f8ca audiobookshelf-mcp: fix vendorHash (from CI)
NixOS Configuration CI / Nix Flake Check (pull_request) Successful in 46s
2026-07-12 11:16:46 +00:00
hermes-agent 4856b98429 fix: remove committed pyc, add to gitignore
NixOS Configuration CI / Nix Flake Check (pull_request) Failing after 14s
2026-07-12 11:14:52 +00:00
hermes-agent d009717854 audiobookshelf-mcp: fix src hash (from CI), still need vendorHash
NixOS Configuration CI / Nix Flake Check (pull_request) Failing after 14s
2026-07-12 11:14:43 +00:00
hermes-agent 617bb9cab5 pinchflat-mcp: add pagination, downloaded filter, and delete_media tool
NixOS Configuration CI / Nix Flake Check (pull_request) Failing after 21s
- list_media: add offset and downloaded params for API pagination
- delete_media: new tool to delete downloaded files (with prevent_download option)
- Bump timeout on delete to 120s
2026-07-12 11:09:19 +00:00
hermes-agent 15906893c0 Add audiobookshelf-mcp package
Go binary from michaeldvinci/audiobookshelf-mcp (v0.0.5).
Covers libraries, audiobooks, podcasts, authors, collections,
playlists, and users. Uses buildGoModule with fakeHash placeholders
to be filled on first nix build.
2026-07-04 22:24:46 +00:00
hermes-agent dc23a30013 Add pinchflat-mcp package
NixOS Configuration CI / Nix Flake Check (pull_request) Successful in 26s
Python MCP server (fastmcp + httpx) that exposes the Pinchflat REST API
as MCP tools. Covers sources, media items, media profiles, tasks, and
settings endpoints.

Tested against live Pinchflat instance — 28 sources, search, app info
all working via stdio transport.
2026-07-04 22:05:12 +00:00
hermes-agent ac60ea8712 fix: correct SRI hash for applemusic-mcp source
NixOS Configuration CI / Nix Flake Check (push) Successful in 17s
2026-06-25 16:12:48 +02:00
hermes-agent 87e2b844e8 fix: use fetchFromGitHub instead of fetchPypi for applemusic-mcp
NixOS Configuration CI / Nix Flake Check (push) Failing after 17s
fetchPypi with pyproject format was causing "Unsupported format pyproject"
error. Switched to fetchFromGitHub to match the pattern used by other
packages in this repo (e.g. zotero-mcp).

Note: the SRI hash is a placeholder — run `nix build .#applemusic-mcp`
and replace with the correct hash from the error output on first build.
2026-06-25 16:11:06 +02:00
hermes-agent c86bd93348 docs: add applemusic-mcp to README
NixOS Configuration CI / Nix Flake Check (push) Failing after 7s
2026-06-25 16:07:16 +02:00
hermes-agent 4d88ebc184 feat: register applemusic-mcp in default.nix
NixOS Configuration CI / Nix Flake Check (push) Failing after 9s
2026-06-25 16:06:44 +02:00
hermes-agent 8a362abe52 feat: add applemusic-mcp package
NixOS Configuration CI / Nix Flake Check (push) Successful in 18s
Cross-platform Apple Music MCP server supporting playlist management,
library search, and catalog access via media-user-token (no Apple
Developer account required).

https://github.com/epheterson/applemusic-mcp
2026-06-25 16:06:32 +02:00
hermes-agent 28997eb625 zotero-mcp: add semantic search dependencies (chromadb, sentence-transformers, openai, google-genai, tiktoken)
NixOS Configuration CI / Nix Flake Check (push) Successful in 43s
2026-06-22 11:42:13 +02:00
hermes-agent 90c942e4bb update: bump 6 MCP packages + nixpkgs flake
NixOS Configuration CI / Nix Flake Check (push) Successful in 1m23s
- flake.lock: nixpkgs 2026-05-31 → 2026-06-16
- zotero-mcp: v0.2.2 → v0.5.0
- duckduckgo-mcp-server: 0.1.1-unstable → v0.4.0
- kindly-web-search-mcp-server: bump to latest commit + add trafilatura dep
- sabnzbd-mcp: pin to specific commit instead of refs/heads/main
- jellyfin-mcp: v2026.318.7 → v2026.604.2 (remove go.mod patch)
- nextcloud-mcp-server: v0.89.0 → v0.121.3

n8n-mcp, mcp-arr-server, pdf-reader-mcp held back:
upstream npm packages require @modelcontextprotocol/sdk versions
not yet published to npm registry
2026-06-20 13:55:06 +02:00
luis 6d1df19b13 mcp server
NixOS Configuration CI / Nix Flake Check (push) Successful in 44s
2026-06-14 23:16:03 +02:00
luis f4b66744ad fixes
NixOS Configuration CI / Nix Flake Check (push) Successful in 52s
2026-06-03 23:54:11 +02:00
hermes-agent b17a484806 nextcloud-mcp-server: add missing icalendar-searcher dependency
CI / Flake Check (push) Successful in 46s
CI / Build Individual Packages (academic-search-mcp-server) (push) Successful in 59s
CI / Build Individual Packages (duckduckgo-mcp-server) (push) Successful in 52s
CI / Build Individual Packages (kindly-web-search-mcp-server) (push) Successful in 1m35s
CI / Build Individual Packages (manim-mcp-server) (push) Successful in 1m7s
CI / Build Individual Packages (rust-research-mcp) (push) Failing after 52s
CI / Build Individual Packages (pdf-reader-mcp) (push) Successful in 1m7s
CI / Build Individual Packages (zotero-mcp) (push) Successful in 1m35s
2026-05-28 20:40:20 +02:00
luis 55344ed9ef Merge pull request 'fix: unset PYTHONPATH to prevent Python 3.12 ABI contamination' (#3) from hermes-agent/mcp-servers:main into main
CI / Flake Check (push) Successful in 42s
CI / Build Individual Packages (academic-search-mcp-server) (push) Successful in 56s
CI / Build Individual Packages (duckduckgo-mcp-server) (push) Successful in 50s
CI / Build Individual Packages (kindly-web-search-mcp-server) (push) Successful in 1m30s
CI / Build Individual Packages (manim-mcp-server) (push) Successful in 1m2s
CI / Build Individual Packages (rust-research-mcp) (push) Failing after 48s
CI / Build Individual Packages (pdf-reader-mcp) (push) Successful in 1m3s
CI / Build Individual Packages (zotero-mcp) (push) Successful in 1m36s
Reviewed-on: #3
2026-05-28 09:34:02 +02:00
hermes-agent 9c01a07231 fix: unset PYTHONPATH in nextcloud-mcp-server wrapper
CI / Flake Check (pull_request) Has been cancelled
CI / Build Individual Packages (academic-search-mcp-server) (pull_request) Has been cancelled
CI / Build Individual Packages (duckduckgo-mcp-server) (pull_request) Has been cancelled
CI / Build Individual Packages (kindly-web-search-mcp-server) (pull_request) Has been cancelled
CI / Build Individual Packages (manim-mcp-server) (pull_request) Has been cancelled
CI / Build Individual Packages (pdf-reader-mcp) (pull_request) Has been cancelled
CI / Build Individual Packages (rust-research-mcp) (pull_request) Has been cancelled
CI / Build Individual Packages (zotero-mcp) (pull_request) Has been cancelled
Prevents Python 3.12 site-packages (from host env like mautrix bridge) from contaminating the Python 3.13 wrapper, causing C extension ABI mismatches (e.g. PIL._imaging).
2026-05-28 09:15:30 +02:00
20 changed files with 599 additions and 222 deletions
+13 -54
View File
@@ -1,63 +1,22 @@
name: CI name: NixOS Configuration CI
on: on:
push: push:
branches: [ main, master ] branches:
- main
- master
pull_request: pull_request:
branches: [ main, master ] branches:
- main
- master
jobs: jobs:
flake-check: check:
name: Flake Check name: Nix Flake Check
runs-on: ubuntu-latest runs-on: nixos
steps: steps:
- name: Checkout code - name: Checkout Repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Run nix flake check
uses: https://github.com/cachix/install-nix-action@v26 run: nix flake check --show-trace
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
- name: Validate flake
run: nix flake check --print-build-logs
build-individual:
name: Build Individual Packages
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package:
- academic-search-mcp-server
- duckduckgo-mcp-server
- kindly-web-search-mcp-server
- manim-mcp-server
- pdf-reader-mcp
- rust-research-mcp
- zotero-mcp
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Nix
uses: https://github.com/cachix/install-nix-action@v26
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
- name: Build ${{ matrix.package }}
run: nix build .#${{ matrix.package }} --print-build-logs
- name: Test executable exists
run: |
if [ -e "./result/bin/${{ matrix.package }}" ]; then
echo "✓ Executable found: ${{ matrix.package }}"
./result/bin/${{ matrix.package }} --help || true
else
echo "⚠ No executable found at ./result/bin/${{ matrix.package }}"
ls -la ./result/bin/ || echo "No bin directory"
fi
+1
View File
@@ -27,3 +27,4 @@ result-*
# Local environment overrides # Local environment overrides
.envrc.local .envrc.local
/.dir-locals.el /.dir-locals.el
__pycache__/
+23 -17
View File
@@ -6,21 +6,27 @@ This repository provides Nix derivations for MCP (Model Context Protocol) server
## Available Packages ## Available Packages
| Package | Description | Language | | Package | Description | Language |
|------------------------------|---------------------------------------------------------------|------------| | -------------------------------- | -------------------------------------------------------------------- | ---------- |
| academic-search-mcp-server | Search academic papers via Semantic Scholar and Crossref | Python | | academic-search-mcp-server | Search academic papers via Semantic Scholar and Crossref | Python |
| duckduckgo-mcp-server | Web search and content fetching via DuckDuckGo | Python | | annas-mcp | Anna's Archive MCP server | Python |
| kindly-web-search-mcp-server | Web search + content retrieval via Serper, Tavily, or SearXNG | Python | | applemusic-mcp | Apple Music — manage playlists, search catalog, browse library | Python |
| manim-mcp-server | Execute Manim animation code and return videos | Python | | duckduckgo-mcp-server | Web search and content fetching via DuckDuckGo | Python |
| n8n-mcp | AI access to n8n node docs and workflow management | TypeScript | | jellyfin-mcp | MCP server for Jellyfin media server | Python |
| pdf-reader-mcp | Productionready PDF processing with parallel processing | TypeScript | | kindly-web-search-mcp-server | Web search + content retrieval via SearxNG, Tavily, or SearXNG | Python |
| rust-research-mcp | Accumulate and organize academic knowledge | Rust | | manim-mcp-server | Execute Manim animation code and return videos | Python |
| simple-web-search-mcp | Zero-config web search and page reading for LLMs | TypeScript | | mcp-arr-server | MCP server for *arr suite — Sonarr, Radarr, Lidarr, Prowlarr | TypeScript |
| mcp-arr-server | MCP server for *arr suite — Sonarr, Radarr, Lidarr, Prowlarr | TypeScript | | mcp-score | AI-driven music score generation and MuseScore live control | Python |
| transmission-mcp | MCP server for the Transmission BitTorrent client | Python | | n8n-mcp | AI access to n8n node docs and workflow management | TypeScript |
| sabnzbd-mcp | MCP server for SABnzbd download management | Python | | nextcloud-mcp-server | Nextcloud MCP server (files, calendar, contacts, deck, etc.) | Python |
| jellyfin-mcp | MCP server for Jellyfin — search, playback, metadata, admin | Go | | pdf-reader-mcp | Productionready PDF processing with parallel processing | TypeScript |
| zotero-mcp | Connect Zotero research library with AI assistants | Python | | rust-research-mcp | Accumulate and organize academic knowledge | Rust |
| simple-web-search-mcp | Zero-config web search and page reading for LLMs | TypeScript |
| transmission-mcp | MCP server for the Transmission BitTorrent client | Python |
| sabnzbd-mcp | MCP server for SABnzbd download management | Python |
| jellyfin-mcp | MCP server for Jellyfin — search, playback, metadata, admin | Go |
| zotero-mcp | Connect Zotero research library with AI assistants | Python |
| mcp-score | AI-driven music score generation and MuseScore live control | Python |
## Usage ## Usage
@@ -35,7 +41,7 @@ Add this flake to your inputs and apply the overlay:
mcp-servers.url = "git+ssh://gitea@gitea.bueso.eu/luis/mcp-servers"; mcp-servers.url = "git+ssh://gitea@gitea.bueso.eu/luis/mcp-servers";
}; };
outputs = { nixpkgs, mcp-servers, ... }: { outputs = { self, nixpkgs, ... }: {
# Apply the overlay to get packages in pkgs # Apply the overlay to get packages in pkgs
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
@@ -66,4 +72,4 @@ Access packages without the overlay:
``` ```
## License ## License
Each packaged MCP server retains its original license. The Nix expressions in this repository are provided asis. Each packaged MCP server retains its original license. The Nix expressions in this repository are provided as-is.
Generated
+3 -37
View File
@@ -1,30 +1,12 @@
{ {
"nodes": { "nodes": {
"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"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1770181073, "lastModified": 1781577229,
"narHash": "sha256-ksTL7P9QC1WfZasNlaAdLOzqD8x5EPyods69YBqxSfk=", "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "bf922a59c5c9998a6584645f7d0de689512e444c", "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -36,24 +18,8 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",
+43 -36
View File
@@ -12,52 +12,59 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
}; };
outputs = outputs =
{ self, nixpkgs, ... }:
let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
in
{ {
self,
nixpkgs,
flake-utils,
...
}:
{
# Overlay that adds all MCP packages to nixpkgs
overlays.default = import ./overlays/default.nix; overlays.default = import ./overlays/default.nix;
} }
// flake-utils.lib.eachDefaultSystem ( // {
system: packages = forAllSystems (
let system:
pkgs = import nixpkgs { let
inherit system; pkgs = import nixpkgs {
overlays = [ self.overlays.default ]; inherit system;
}; overlays = [ self.overlays.default ];
};
# Import all MCP packages mcpPackages = import ./packages { inherit pkgs; };
mcpPackages = import ./packages { inherit pkgs; }; in
mcpPackages // {
# List of all MCP server packages (for devShell)
allMcpServers = builtins.attrValues mcpPackages ++ [ pkgs.mcp-nixos ];
in
{
# Export all packages
packages = mcpPackages // {
default = pkgs.symlinkJoin { default = pkgs.symlinkJoin {
name = "mcp-servers"; name = "mcp-servers";
paths = builtins.attrValues mcpPackages; paths = builtins.attrValues mcpPackages;
}; };
}; }
);
devShells.default = pkgs.mkShell { devShells = forAllSystems (
packages = allMcpServers ++ [ system:
pkgs.git let
]; pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlays.default ];
};
mcpPackages = import ./packages { inherit pkgs; };
in
{
default = pkgs.mkShell {
packages = builtins.attrValues mcpPackages ++ [ pkgs.mcp-nixos pkgs.git ];
shellHook = ''
export SEARXNG_BASE_URL="https://search.bueso.eu"
'';
};
}
);
shellHook = '' checks.x86_64-linux = builtins.removeAttrs self.packages.x86_64-linux [ "default" ];
export SEARXNG_BASE_URL="https://search.bueso.eu" };
'';
};
}
);
} }
+5
View File
@@ -91,6 +91,11 @@
"JELLYFIN_URL": "PLACEHOLDER", "JELLYFIN_URL": "PLACEHOLDER",
"JELLYFIN_API_KEY": "PLACEHOLDER" "JELLYFIN_API_KEY": "PLACEHOLDER"
} }
},
"mcp-score": {
"type": "local",
"command": ["mcp-score", "serve"],
"enabled": true
} }
} }
} }
+36
View File
@@ -0,0 +1,36 @@
{
lib,
buildGoModule,
fetchFromGitHub,
makeWrapper,
}:
buildGoModule rec {
pname = "annas-mcp";
version = "0.1.0-unstable-2026-06-26";
src = fetchFromGitHub {
owner = "iosifache";
repo = "annas-mcp";
rev = "c095963ad5d10d33da3c614495246b6ec7f680d4";
hash = lib.fakeHash;
};
vendorHash = lib.fakeHash;
nativeBuildInputs = [ makeWrapper ];
# The MCP server mode is invoked with "mcp" subcommand
postInstall = ''
wrapProgram $out/bin/annas-mcp \
--add-flags "mcp"
'';
meta = with lib; {
description = "MCP server and CLI tool for searching and downloading documents from Anna's Archive";
homepage = "https://github.com/iosifache/annas-mcp";
license = licenses.mit;
mainProgram = "annas-mcp";
platforms = platforms.linux;
};
}
+40
View File
@@ -0,0 +1,40 @@
{
lib,
python3Packages,
fetchFromGitHub,
}:
python3Packages.buildPythonApplication rec {
pname = "applemusic-mcp";
version = "0.15.1";
pyproject = true;
src = fetchFromGitHub {
owner = "epheterson";
repo = "applemusic-mcp";
rev = "v${version}";
hash = "sha256-N97bZyT8TWOrt1WS7W31OJaICwoUxFfcDDuRs+TweTQ=";
};
build-system = with python3Packages; [
hatchling
];
dependencies = with python3Packages; [
mcp
pyjwt
requests
cryptography
playwright
];
pythonImportsCheck = [ "applemusic_mcp" ];
meta = with lib; {
description = "MCP server for Apple Music manage playlists, search catalog, browse library";
homepage = "https://github.com/epheterson/applemusic-mcp";
license = licenses.mit;
mainProgram = "applemusic-mcp";
platforms = platforms.all;
};
}
+27
View File
@@ -0,0 +1,27 @@
{
lib,
buildGoModule,
fetchFromGitHub,
}:
buildGoModule rec {
pname = "audiobookshelf-mcp";
version = "unstable-2026-06-27";
src = fetchFromGitHub {
owner = "michaeldvinci";
repo = "audiobookshelf-mcp";
rev = "e790d9c75085772180c95f2ec1376acc98e9282c";
hash = "sha256-vQR+Ej3Qtg8ehIUWnXkSayNYpqnOZPWV0TpTVPYh+io=";
};
vendorHash = "sha256-W8hlCGf4QdFbKc3QFc9pa4MWBhnp5A5GvWFNzg0BEhw=";
meta = with lib; {
description = "MCP server for Audiobookshelf libraries, audiobooks, podcasts, authors, collections, playlists";
homepage = "https://github.com/michaeldvinci/audiobookshelf-mcp";
license = licenses.gpl3Only;
mainProgram = "abs-mcp";
platforms = platforms.all;
};
}
+5 -9
View File
@@ -1,11 +1,3 @@
# MCP Server Packages
#
# This file aggregates all MCP server packages in this repository.
# To add a new package:
# 1. Create a directory: packages/<package-name>/
# 2. Create package.nix in that directory
# 3. Add an entry below using callPackage
#
{ pkgs }: { pkgs }:
{ {
@@ -16,7 +8,6 @@
zotero-mcp = pkgs.callPackage ./zotero-mcp/package.nix { }; zotero-mcp = pkgs.callPackage ./zotero-mcp/package.nix { };
pdf-reader-mcp = pkgs.callPackage ./pdf-reader-mcp/package.nix { }; pdf-reader-mcp = pkgs.callPackage ./pdf-reader-mcp/package.nix { };
kindly-web-search-mcp-server = pkgs.callPackage ./kindly-web-search-mcp-server/package.nix { }; kindly-web-search-mcp-server = pkgs.callPackage ./kindly-web-search-mcp-server/package.nix { };
rust-research-mcp = pkgs.callPackage ./rust-research-mcp/package.nix { };
duckduckgo-mcp-server = pkgs.callPackage ./duckduckgo-mcp-server/package.nix { }; duckduckgo-mcp-server = pkgs.callPackage ./duckduckgo-mcp-server/package.nix { };
n8n-mcp = pkgs.callPackage ./n8n-mcp/package.nix { }; n8n-mcp = pkgs.callPackage ./n8n-mcp/package.nix { };
simple-web-search-mcp = pkgs.callPackage ./simple-web-search-mcp/package.nix { }; simple-web-search-mcp = pkgs.callPackage ./simple-web-search-mcp/package.nix { };
@@ -25,5 +16,10 @@
sabnzbd-mcp = pkgs.callPackage ./sabnzbd-mcp/package.nix { }; sabnzbd-mcp = pkgs.callPackage ./sabnzbd-mcp/package.nix { };
jellyfin-mcp = pkgs.callPackage ./jellyfin-mcp/package.nix { }; jellyfin-mcp = pkgs.callPackage ./jellyfin-mcp/package.nix { };
nextcloud-mcp-server = pkgs.callPackage ./nextcloud-mcp-server/package.nix { }; nextcloud-mcp-server = pkgs.callPackage ./nextcloud-mcp-server/package.nix { };
annas-mcp = pkgs.callPackage ./annas-mcp/package.nix { };
mcp-score = pkgs.callPackage ./mcp-score/package.nix { };
applemusic-mcp = pkgs.callPackage ./applemusic-mcp/package.nix { };
pinchflat-mcp = pkgs.callPackage ./pinchflat-mcp/package.nix { };
audiobookshelf-mcp = pkgs.callPackage ./audiobookshelf-mcp/package.nix { };
# example-mcp-server = pkgs.callPackage ./example-mcp-server/package.nix { }; # example-mcp-server = pkgs.callPackage ./example-mcp-server/package.nix { };
} }
+3 -3
View File
@@ -6,14 +6,14 @@
python3Packages.buildPythonApplication rec { python3Packages.buildPythonApplication rec {
pname = "duckduckgo-mcp-server"; pname = "duckduckgo-mcp-server";
version = "0.1.1-unstable"; version = "0.4.0";
pyproject = true; pyproject = true;
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "nickclyde"; owner = "nickclyde";
repo = "duckduckgo-mcp-server"; repo = "duckduckgo-mcp-server";
rev = "d198a2f0e8bd7c862d87d8517e1518aa295f8348"; rev = "v${version}";
hash = "sha256-aoWU5AVErAt73V+BgveEmVnjNh/cteS+A9AIFLylOsw="; hash = "sha256-g1mpBrhuCt3g/XnUfHoY8lJDMizINypikj8Lqk2LVuE=";
}; };
build-system = [ python3Packages.hatchling ]; build-system = [ python3Packages.hatchling ];
+3 -8
View File
@@ -6,21 +6,16 @@
buildGoModule rec { buildGoModule rec {
pname = "jellyfin-mcp"; pname = "jellyfin-mcp";
version = "2026.318.7"; version = "2026.604.2";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "jaredtrent"; owner = "jaredtrent";
repo = "jellyfin-mcp"; repo = "jellyfin-mcp";
tag = "v${version}"; tag = "v${version}";
hash = "sha256-/6Sy8C5+/x90ZTo74qX0agTHybsWw+Vg416GBM1PS7k="; hash = "sha256-Ks54txfOAkNEWfhl5ZXEIaFzAbmCnwhHtN1+FIa7dgo=";
}; };
# go.mod requires 1.25.6 but nixpkgs has 1.25.5; patch to relax vendorHash = "sha256-cDy+PpZM6xL7ur/xq81y4vlyaDnSOpGkyVV2hh8qI7o=";
postPatch = ''
substituteInPlace go.mod --replace-fail "go 1.25.6" "go 1.25.5"
'';
vendorHash = "sha256-WYb+BpnKUUrgcJ0zChdTb1oB99R8bTgpSXUtjPKhL6M=";
meta = with lib; { meta = with lib; {
description = "MCP server for Jellyfin media server search, playback, metadata, admin"; description = "MCP server for Jellyfin media server search, playback, metadata, admin";
@@ -77,8 +77,8 @@ python313Packages.buildPythonApplication rec {
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "Shelpuk-AI-Technology-Consulting"; owner = "Shelpuk-AI-Technology-Consulting";
repo = "kindly-web-search-mcp-server"; repo = "kindly-web-search-mcp-server";
rev = "2fd83d28710cce335f610e3d5ed0b403250ab1ba"; rev = "2b76afb37bf311facbde6750d0a0c0cbdfb8fec2";
hash = "sha256-sOLx87p+w51wuBOItDdzrsrgItNZ92WivZAv3Zzp16o="; hash = "sha256-90QHr2FPiMSwKXmjlZ2W9NIQvj3LDXzYIq6m/Z+sJMw=";
}; };
build-system = with python313Packages; [ build-system = with python313Packages; [
@@ -94,6 +94,7 @@ python313Packages.buildPythonApplication rec {
nodriver nodriver
pymupdf pymupdf
fastmcp fastmcp
trafilatura
]; ];
nativeBuildInputs = [ makeWrapper ]; nativeBuildInputs = [ makeWrapper ];
+76
View File
@@ -0,0 +1,76 @@
{
lib,
python313Packages,
fetchFromGitHub,
fetchPypi,
}:
let
# music21 is not in nixpkgs; vendor it (upstream mcp-score pins >=9.0,<10)
music21 = python313Packages.buildPythonPackage rec {
pname = "music21";
version = "9.9.2";
format = "wheel";
src = fetchPypi {
inherit pname version;
format = "wheel";
dist = "py3";
python = "py3";
hash = "sha256-ZIAQq40TKNCxB0bO8UV+hLEidM0xYkgifpbSHielGMo=";
};
propagatedBuildInputs = with python313Packages; [
chardet
joblib
jsonpickle
matplotlib
more-itertools
numpy
requests
webcolors
];
doCheck = false;
pythonImportsCheck = [ "music21" ];
meta = with lib; {
description = "Toolkit for computer-aided musicology";
homepage = "https://github.com/cuthbertLab/music21";
license = licenses.bsd3;
};
};
in
python313Packages.buildPythonApplication rec {
pname = "mcp-score";
version = "0.1.0-unstable";
pyproject = true;
src = fetchFromGitHub {
owner = "tskovlund";
repo = "mcp-score";
rev = "3ff9d4b6504fcee5032c44fdcf7dc1d7a21a4b5d";
hash = "sha256-zrpvzxi8AbF5/etuvMZLni4HSFBYGRe55rpKJJEAg60=";
};
build-system = with python313Packages; [
hatchling
];
dependencies = with python313Packages; [
mcp
music21
websockets
];
pythonImportsCheck = [ "mcp_score" ];
meta = with lib; {
description = "MCP server for AI-driven music score generation and manipulation via MusicXML and MuseScore";
homepage = "https://github.com/tskovlund/mcp-score";
license = licenses.mit;
mainProgram = "mcp-score";
platforms = platforms.all;
};
}
+10 -3
View File
@@ -20,6 +20,7 @@ let
}; };
inherit propagatedBuildInputs; inherit propagatedBuildInputs;
doCheck = false; doCheck = false;
dontCheckRuntimeDeps = true;
inherit meta; inherit meta;
}; };
@@ -131,14 +132,14 @@ let
in in
python3Packages.buildPythonApplication rec { python3Packages.buildPythonApplication rec {
pname = "nextcloud-mcp-server"; pname = "nextcloud-mcp-server";
version = "0.89.0"; version = "0.121.3";
pyproject = true; pyproject = true;
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "cbcoutinho"; owner = "cbcoutinho";
repo = "nextcloud-mcp-server"; repo = "nextcloud-mcp-server";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-IDTSGsHQ8cCFvgSO7pDbSSHVNV0OIjjoEN9ZfkaPAvk="; hash = "sha256-U6BG5anTEllNnJzta4VV6QOfn86+N15q6v/SfLGM7mc=";
}; };
build-system = [ python3Packages.uv-build ]; build-system = [ python3Packages.uv-build ];
@@ -152,7 +153,7 @@ python3Packages.buildPythonApplication rec {
googleapis-common-protos opentelemetry-api opentelemetry-proto googleapis-common-protos opentelemetry-api opentelemetry-proto
opentelemetry-semantic-conventions opentelemetry-sdk opentelemetry-semantic-conventions opentelemetry-sdk
x-wr-timezone opentelemetry-util-http opentelemetry-exporter-otlp-proto-common x-wr-timezone opentelemetry-util-http opentelemetry-exporter-otlp-proto-common
opentelemetry-instrumentation recurring-ical-events opentelemetry-instrumentation recurring-ical-events icalendar-searcher
opentelemetry-exporter-otlp-proto-grpc qdrant-client opentelemetry-exporter-otlp-proto-grpc qdrant-client
opentelemetry-instrumentation-asgi opentelemetry-instrumentation-httpx opentelemetry-instrumentation-asgi opentelemetry-instrumentation-httpx
opentelemetry-instrumentation-logging langchain-text-splitters mistralai caldav opentelemetry-instrumentation-logging langchain-text-splitters mistralai caldav
@@ -178,6 +179,12 @@ python3Packages.buildPythonApplication rec {
--replace-quiet '">=2.4.5"' '""' --replace-quiet '">=2.4.5"' '""'
''; '';
# PYTHONPATH from the host environment (e.g., mautrix bridge injecting
# Python 3.12 site-packages) causes C extension ABI mismatches on NixOS.
# The wrapper's own sys.path has the correct closure packages, so we
# unset the external PYTHONPATH to prevent contamination.
makeWrapperArgs = [ "--unset" "PYTHONPATH" ];
dontCheckRuntimeDeps = true; dontCheckRuntimeDeps = true;
catchConflicts = false; catchConflicts = false;
+42
View File
@@ -0,0 +1,42 @@
{
lib,
stdenv,
makeWrapper,
python3,
}:
let
python = python3.withPackages (
ps: with ps; [
fastmcp
httpx
]
);
in
stdenv.mkDerivation {
pname = "pinchflat-mcp";
version = "0.1.0";
src = ./server.py;
nativeBuildInputs = [ makeWrapper ];
dontUnpack = true;
installPhase = ''
mkdir -p $out/lib/pinchflat-mcp $out/bin
cp $src $out/lib/pinchflat-mcp/server.py
makeWrapper ${python}/bin/python $out/bin/pinchflat-mcp \
--add-flags "$out/lib/pinchflat-mcp/server.py" \
--set-default PINCHFLAT_MCP_TRANSPORT stdio
'';
meta = with lib; {
description = "MCP server for Pinchflat media downloader";
homepage = "https://gitea.bueso.eu/hermes-agent/pinchflat";
license = licenses.mit;
mainProgram = "pinchflat-mcp";
platforms = platforms.all;
};
}
+257
View File
@@ -0,0 +1,257 @@
#!/usr/bin/env python3
"""Pinchflat MCP server — exposes the Pinchflat REST API as MCP tools."""
import os
import sys
from typing import Any, Optional
import httpx
from fastmcp import FastMCP
PINCHFLAT_URL = os.environ.get("PINCHFLAT_URL", "http://localhost:8945")
PINCHFLAT_TOKEN = os.environ.get("PINCHFLAT_API_TOKEN", "")
if not PINCHFLAT_TOKEN:
print("PINCHFLAT_API_TOKEN environment variable is required", file=sys.stderr)
sys.exit(1)
BASE = f"{PINCHFLAT_URL.rstrip('/')}/api/v1"
HEADERS = {"Authorization": f"Bearer {PINCHFLAT_TOKEN}", "Content-Type": "application/json"}
mcp = FastMCP("pinchflat")
def _get(path: str, params: Optional[dict] = None) -> Any:
"""Make a GET request to the Pinchflat API."""
with httpx.Client(timeout=30) as client:
r = client.get(f"{BASE}{path}", headers=HEADERS, params=params)
r.raise_for_status()
return r.json()
def _post(path: str, json: Optional[dict] = None) -> Any:
"""Make a POST request to the Pinchflat API."""
with httpx.Client(timeout=30) as client:
r = client.post(f"{BASE}{path}", headers=HEADERS, json=json)
r.raise_for_status()
return r.json()
def _put(path: str, json: dict) -> Any:
"""Make a PUT request to the Pinchflat API."""
with httpx.Client(timeout=30) as client:
r = client.put(f"{BASE}{path}", headers=HEADERS, json=json)
r.raise_for_status()
return r.json()
def _delete(path: str) -> Any:
"""Make a DELETE request to the Pinchflat API."""
with httpx.Client(timeout=30) as client:
r = client.delete(f"{BASE}{path}", headers=HEADERS)
r.raise_for_status()
return r.json()
# --- Sources ---
@mcp.tool()
def list_sources() -> dict:
"""List all configured media sources (YouTube channels, playlists, etc.)."""
return _get("/sources")
@mcp.tool()
def get_source(source_id: int) -> dict:
"""Get details of a specific source by ID, including its pending tasks."""
return _get(f"/sources/{source_id}")
@mcp.tool()
def create_source(
original_url: str,
media_profile_id: int,
collection_type: str = "channel",
custom_name: Optional[str] = None,
download_cutoff_date: Optional[str] = None,
) -> dict:
"""Create a new media source (e.g. add a YouTube channel to monitor).
Args:
original_url: URL of the channel/playlist to monitor
media_profile_id: ID of the media profile to use for downloads
collection_type: 'channel', 'playlist', or 'video'
custom_name: Optional custom name for the source
download_cutoff_date: Only download media after this date (YYYY-MM-DD)
"""
source = {
"media_profile_id": media_profile_id,
"collection_type": collection_type,
"original_url": original_url,
}
if custom_name:
source["custom_name"] = custom_name
if download_cutoff_date:
source["download_cutoff_date"] = download_cutoff_date
return _post("/sources", json={"source": source})
@mcp.tool()
def update_source(
source_id: int,
custom_name: Optional[str] = None,
download_cutoff_date: Optional[str] = None,
enabled: Optional[bool] = None,
index_frequency_minutes: Optional[int] = None,
) -> dict:
"""Update an existing source. Only provided fields will be changed."""
updates = {}
if custom_name is not None:
updates["custom_name"] = custom_name
if download_cutoff_date is not None:
updates["download_cutoff_date"] = download_cutoff_date
if enabled is not None:
updates["enabled"] = enabled
if index_frequency_minutes is not None:
updates["index_frequency_minutes"] = index_frequency_minutes
return _put(f"/sources/{source_id}", json={"source": updates})
@mcp.tool()
def delete_source(source_id: int) -> dict:
"""Delete a source (marks it for deletion)."""
return _delete(f"/sources/{source_id}")
@mcp.tool()
def force_download_pending(source_id: int) -> dict:
"""Force download of all pending media items for a source."""
return _post(f"/sources/{source_id}/force_download_pending")
@mcp.tool()
def force_redownload(source_id: int) -> dict:
"""Force re-download of all existing media for a source."""
return _post(f"/sources/{source_id}/force_redownload")
@mcp.tool()
def force_index(source_id: int) -> dict:
"""Force re-index of a source."""
return _post(f"/sources/{source_id}/force_index")
@mcp.tool()
def force_metadata_refresh(source_id: int) -> dict:
"""Force metadata refresh for a source."""
return _post(f"/sources/{source_id}/force_metadata_refresh")
# --- Media Items ---
@mcp.tool()
def list_media(
source_id: Optional[int] = None,
limit: int = 50,
offset: int = 0,
downloaded: Optional[bool] = None,
) -> dict:
"""List media items with pagination. Optionally filter by source_id or download status.
Args:
source_id: Filter to a specific source
limit: Max items to return (default 50)
offset: Skip first N items for pagination (default 0)
downloaded: If True, only return downloaded media; if False, only undownloaded
"""
params = {"limit": limit, "offset": offset}
if source_id:
params["source_id"] = source_id
if downloaded is not None:
params["downloaded"] = "true" if downloaded else "false"
return _get("/media", params=params)
@mcp.tool()
def search_media(query: str) -> dict:
"""Search media items by title or description."""
return _get("/media/search", params={"q": query})
@mcp.tool()
def get_media(media_id: int) -> dict:
"""Get details of a specific media item."""
return _get(f"/media/{media_id}")
@mcp.tool()
def force_download_media(media_id: int) -> dict:
"""Force download of a specific media item."""
return _post(f"/media/{media_id}/force_download")
@mcp.tool()
def delete_media(media_id: int, prevent_download: bool = False) -> dict:
"""Delete a media item's downloaded files from disk.
Args:
media_id: The media item ID to delete
prevent_download: If True, prevent the item from being re-downloaded in the future
"""
params = {}
if prevent_download:
params["prevent_download"] = "true"
with httpx.Client(timeout=120) as client:
r = client.delete(f"{BASE}/media/{media_id}", headers=HEADERS, params=params)
r.raise_for_status()
return r.json()
# --- Media Profiles ---
@mcp.tool()
def list_media_profiles() -> dict:
"""List all media profiles (download quality/container settings)."""
return _get("/media_profiles")
@mcp.tool()
def get_media_profile(profile_id: int) -> dict:
"""Get details of a specific media profile."""
return _get(f"/media_profiles/{profile_id}")
# --- Tasks ---
@mcp.tool()
def list_tasks(source_id: Optional[int] = None) -> dict:
"""List all tasks. Optionally filter by source_id."""
params = {}
if source_id:
params["source_id"] = source_id
return _get("/tasks", params=params)
@mcp.tool()
def get_task(task_id: int) -> dict:
"""Get details of a specific task."""
return _get(f"/tasks/{task_id}")
# --- Settings & Info ---
@mcp.tool()
def get_settings() -> dict:
"""Get current Pinchflat settings."""
return _get("/settings")
@mcp.tool()
def get_app_info() -> dict:
"""Get Pinchflat app info (version, environment, etc.)."""
return _get("/app_info")
if __name__ == "__main__":
transport = os.environ.get("PINCHFLAT_MCP_TRANSPORT", "stdio")
mcp.run(transport=transport if transport in ("stdio", "http") else "stdio")
-50
View File
@@ -1,50 +0,0 @@
{
lib,
rustPlatform,
fetchFromGitHub,
pkg-config,
openssl,
}:
rustPlatform.buildRustPackage rec {
pname = "rust-research-mcp";
version = "0.6.7-unstable";
src = fetchFromGitHub {
owner = "Ladvien";
repo = "research_hub_mcp";
rev = "3335c118da9e7a9e9e7f2e608989fbe35557f3c5";
hash = "sha256-KkIVeFQ8hEL82ZtC+Tie+8T/eZcEoWyq5cRVgdinQEc=";
};
cargoHash = "sha256-zwhQ2ksFbedeuzTaJI+9t9of6es7RJa6JwRHQRznqBY=";
nativeBuildInputs = [
pkg-config
];
buildInputs = [
openssl
];
doCheck = false;
# The build.rs uses vergen to embed git info, which fails without a git repo.
# Set environment variables to satisfy vergen during build.
env = {
VERGEN_GIT_BRANCH = "main";
VERGEN_GIT_COMMIT_DATE = "2025-09-25";
VERGEN_GIT_COMMIT_TIMESTAMP = "2025-09-25T19:35:10Z";
VERGEN_GIT_SHA = "3335c118da9e7a9e9e7f2e608989fbe35557f3c5";
VERGEN_BUILD_DATE = "2025-09-25";
VERGEN_BUILD_TIMESTAMP = "2025-09-25T19:35:10Z";
};
meta = with lib; {
description = "MCP server for accumulating and organizing academic knowledge";
homepage = "https://github.com/Ladvien/research_hub_mcp";
license = licenses.gpl3Only;
mainProgram = pname;
platforms = platforms.all;
};
}
+1 -1
View File
@@ -23,7 +23,7 @@ stdenv.mkDerivation {
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "jmagar"; owner = "jmagar";
repo = "sabnzbd-mcp"; repo = "sabnzbd-mcp";
rev = "refs/heads/main"; rev = "9d691ed70b72397fddec03ca4ec68c81b30c79c3";
hash = "sha256-1sEnHH40cDVT5oiZD2Xywl7S9vJThii/ce+6r+XmpSw="; hash = "sha256-1sEnHH40cDVT5oiZD2Xywl7S9vJThii/ce+6r+XmpSw=";
}; };
+8 -2
View File
@@ -39,14 +39,14 @@ let
in in
python3Packages.buildPythonApplication rec { python3Packages.buildPythonApplication rec {
pname = "zotero-mcp"; pname = "zotero-mcp";
version = "0.2.2"; version = "0.5.0";
pyproject = true; pyproject = true;
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "54yyyu"; owner = "54yyyu";
repo = "zotero-mcp"; repo = "zotero-mcp";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-GZkzABsUh6qua66K4URPq0InLgs6cqLgKEXm7wzT+s8="; hash = "sha256-ioy6bdP+jFioUGBKiiYtD4nbdFe6v2E3nCi6s9+dTT0=";
}; };
build-system = with python3Packages; [ build-system = with python3Packages; [
@@ -67,6 +67,12 @@ python3Packages.buildPythonApplication rec {
pymupdf pymupdf
ebooklib ebooklib
pdfplumber pdfplumber
# Semantic search
chromadb
sentence-transformers
openai
google-genai
tiktoken
]; ];
# Optional: semantic search dependencies # Optional: semantic search dependencies