diff --git a/packages/default.nix b/packages/default.nix index c89d7f3..5b87f22 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -24,5 +24,6 @@ transmission-mcp = pkgs.callPackage ./transmission-mcp/package.nix { }; sabnzbd-mcp = pkgs.callPackage ./sabnzbd-mcp/package.nix { }; jellyfin-mcp = pkgs.callPackage ./jellyfin-mcp/package.nix { }; + nextcloud-mcp-server = pkgs.callPackage ./nextcloud-mcp-server/package.nix { }; # example-mcp-server = pkgs.callPackage ./example-mcp-server/package.nix { }; } diff --git a/packages/nextcloud-mcp-server/package.nix b/packages/nextcloud-mcp-server/package.nix new file mode 100644 index 0000000..1e319e1 --- /dev/null +++ b/packages/nextcloud-mcp-server/package.nix @@ -0,0 +1,191 @@ +{ + lib, + python3Packages, + fetchFromGitHub, + fetchPypi, +}: + +let + # Helper: buildPythonPackage for a wheel fetched from PyPI + # CRITICAL: pname MUST use underscores, not hyphens, for PyPI wheel filenames + fetchWheel = { pname, version, hash, propagatedBuildInputs ? [ ], meta ? { } }: + python3Packages.buildPythonPackage { + inherit pname version; + format = "wheel"; + src = fetchPypi { + inherit pname version hash; + format = "wheel"; + dist = "py3"; + python = "py3"; + }; + inherit propagatedBuildInputs; + doCheck = false; + inherit meta; + }; + + pythonvcard4 = fetchWheel { + pname = "pythonvcard4"; version = "0.2.0"; hash = "sha256-3OMTVd1QruU3+Ig96G8wFRDkB7wXVaaOyNUFW2T1xmA="; + meta = with lib; { description = "vCard parsing"; homepage = "https://github.com/GNOME/python-vcard4"; license = licenses.gpl3Plus; }; + }; + prometheus-client = fetchWheel { + pname = "prometheus_client"; version = "0.25.0"; hash = "sha256-1a7InjSabsIwgF0N+ILzgH90/WwaL6hoZOPCJ5BZ/tE="; + meta = with lib; { description = "Prometheus client"; homepage = "https://github.com/prometheus/client_python"; license = licenses.asl20; }; + }; + python-json-logger = fetchWheel { + pname = "python_json_logger"; version = "4.1.0"; hash = "sha256-EymUdlz3W/RFVL6apJsG7yNF0jZhqWcgJicWQ4FBtrI="; + meta = with lib; { description = "JSON logger"; homepage = "https://github.com/nhairs/python-json-logger"; license = licenses.bsd2; }; + }; + importlib-metadata = fetchWheel { + pname = "importlib_metadata"; version = "8.7.1"; hash = "sha256-Wh+Avx2qSJSVBx77sJXXWmNM8oqLwplYEkQGO1MXYVE="; + propagatedBuildInputs = with python3Packages; [ zipp ]; + meta = with lib; { description = "Importlib metadata"; homepage = "https://github.com/python/importlib_metadata"; license = licenses.asl20; }; + }; + googleapis-common-protos = fetchWheel { + pname = "googleapis_common_protos"; version = "1.75.0"; hash = "sha256-lh7WA5nEV86w7o8oWoTIcKq8nGqDK503uygbW+veQ+0="; + propagatedBuildInputs = with python3Packages; [ protobuf ]; + meta = with lib; { description = "Common protos"; homepage = "https://github.com/googleapis/python-api-common-protos"; license = licenses.asl20; }; + }; + opentelemetry-api = fetchWheel { + pname = "opentelemetry_api"; version = "1.39.1"; hash = "sha256-Lt2EY0Mqf4RD7c6QlyFpsZXn1qBVAM0p5tE4mBh8mVA="; + propagatedBuildInputs = with python3Packages; [ deprecated ]; + meta = with lib; { description = "OpenTelemetry API"; homepage = "https://github.com/open-telemetry/opentelemetry-python"; license = licenses.asl20; }; + }; + opentelemetry-proto = fetchWheel { + pname = "opentelemetry_proto"; version = "1.39.1"; hash = "sha256-Is3Hjv07N2XQnmi/vQENT8JUyYGK/QtrQjOH2d7kYAc="; + propagatedBuildInputs = with python3Packages; [ protobuf ]; + meta = with lib; { description = "OpenTelemetry Proto"; homepage = "https://github.com/open-telemetry/opentelemetry-python"; license = licenses.asl20; }; + }; + opentelemetry-semantic-conventions = fetchWheel { + pname = "opentelemetry_semantic_conventions"; version = "0.60b1"; hash = "sha256-n6jIsMEQ2iiYCSkrBZEiDTp7U8FSaiMCHpd9aFl4k/s="; + propagatedBuildInputs = with python3Packages; [ deprecated ]; + meta = with lib; { description = "OTel semconv"; homepage = "https://github.com/open-telemetry/semantic-conventions"; license = licenses.asl20; }; + }; + opentelemetry-sdk = fetchWheel { + pname = "opentelemetry_sdk"; version = "1.39.1"; hash = "sha256-TVSCxHhRPssKXZONzGE5TmRwZuDMJna+6fOvPz9F8Bw="; + propagatedBuildInputs = with python3Packages; [ typing-extensions ]; + meta = with lib; { description = "OpenTelemetry SDK"; homepage = "https://github.com/open-telemetry/opentelemetry-python"; license = licenses.asl20; }; + }; + x-wr-timezone = fetchWheel { + pname = "x_wr_timezone"; version = "2.0.1"; hash = "sha256-50pTufT33vgThFXCQOZeR8Ikd4vOPAJPzW2iy+kcoDg="; + propagatedBuildInputs = with python3Packages; [ icalendar click ]; + meta = with lib; { description = "X-WR-TIMEZONE"; homepage = "https://github.com/niccokunzmann/x-wr-timezone"; license = licenses.lgpl3Plus; }; + }; + opentelemetry-util-http = fetchWheel { + pname = "opentelemetry_util_http"; version = "0.60b1"; hash = "sha256-ZjgbooVQyRvuFNy6iXms5ENESvHtYJImY0WWtLD68Zk="; + meta = with lib; { description = "OTel HTTP utils"; homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib"; license = licenses.asl20; }; + }; + opentelemetry-exporter-otlp-proto-common = fetchWheel { + pname = "opentelemetry_exporter_otlp_proto_common"; version = "1.39.1"; hash = "sha256-CPilhi1kzDQ1EFaG0CFsE2XcVwH4aESozVZZfQx2T94="; + meta = with lib; { description = "OTLP proto common"; homepage = "https://github.com/open-telemetry/opentelemetry-python"; license = licenses.asl20; }; + }; + opentelemetry-instrumentation = fetchWheel { + pname = "opentelemetry_instrumentation"; version = "0.60b1"; hash = "sha256-BEgNuVK0j7HtAHP4IvDuJgEre+fD6sGjeTEic3x4Yy0="; + propagatedBuildInputs = with python3Packages; [ wrapt packaging ]; + meta = with lib; { description = "OTel instrumentation"; homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib"; license = licenses.asl20; }; + }; + recurring-ical-events = fetchWheel { + pname = "recurring_ical_events"; version = "3.8.2"; hash = "sha256-mtYF4ntPvrcO4cZiBa3jJVC+FaV87cV5YGUi8cZ6720="; + propagatedBuildInputs = with python3Packages; [ icalendar python-dateutil ]; + meta = with lib; { description = "Recurring iCal events"; homepage = "https://github.com/niccokunzmann/python-recurring-ical-events"; license = licenses.lgpl3Plus; }; + }; + opentelemetry-exporter-otlp-proto-grpc = fetchWheel { + pname = "opentelemetry_exporter_otlp_proto_grpc"; version = "1.39.1"; hash = "sha256-+hwTagXH6bTAn3OUacvbkn6iCzQIirHZWahJtcxYnBg="; + propagatedBuildInputs = with python3Packages; [ grpcio deprecated ]; + meta = with lib; { description = "OTLP gRPC exporter"; homepage = "https://github.com/open-telemetry/opentelemetry-python"; license = licenses.asl20; }; + }; + qdrant-client = fetchWheel { + pname = "qdrant_client"; version = "1.18.0"; hash = "sha256-CTqoz4pCDuOtKmiwB+E3jXmSsmAOC1PBk/wXJnT2Wc0="; + propagatedBuildInputs = with python3Packages; [ grpcio httpx numpy portalocker protobuf pydantic urllib3 ]; + meta = with lib; { description = "Qdrant client"; homepage = "https://github.com/qdrant/qdrant-client"; license = licenses.asl20; }; + }; + opentelemetry-instrumentation-asgi = fetchWheel { + pname = "opentelemetry_instrumentation_asgi"; version = "0.60b1"; hash = "sha256-1I3vLb7RApTJnPz0HrvQxBTTkKEXc6QfRy0gAA/N3CU="; + propagatedBuildInputs = with python3Packages; [ asgiref ]; + meta = with lib; { description = "OTel ASGI"; homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib"; license = licenses.asl20; }; + }; + opentelemetry-instrumentation-httpx = fetchWheel { + pname = "opentelemetry_instrumentation_httpx"; version = "0.60b1"; hash = "sha256-83Y23XQq0q+D2Ja6aWAe0o2lH6TiXRq2L96JzkE+J1s="; + propagatedBuildInputs = with python3Packages; [ httpx wrapt ]; + meta = with lib; { description = "OTel HTTPX"; homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib"; license = licenses.asl20; }; + }; + opentelemetry-instrumentation-logging = fetchWheel { + pname = "opentelemetry_instrumentation_logging"; version = "0.60b1"; hash = "sha256-8uGMvH4d02KMgOMNJDiX/ck8W34MiuYKvSubapn4I0M="; + meta = with lib; { description = "OTel logging"; homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib"; license = licenses.asl20; }; + }; + langchain-text-splitters = fetchWheel { + pname = "langchain_text_splitters"; version = "1.1.2"; hash = "sha256-ot4NeZ/zGIZCn9bi4AMt8nW2DsgXwZBZp7RhgcwcLxA="; + propagatedBuildInputs = with python3Packages; [ langchain-core ]; + meta = with lib; { description = "LangChain text splitters"; homepage = "https://github.com/langchain-ai/langchain"; license = licenses.mit; }; + }; + mistralai = fetchWheel { + pname = "mistralai"; version = "2.4.7"; hash = "sha256-FjnL0tjxjHIqfm2Fl4PCAdUkC668MUkdJxWza8o9gK8="; + propagatedBuildInputs = with python3Packages; [ httpx pydantic python-dateutil ]; + meta = with lib; { description = "Mistral AI API client"; homepage = "https://github.com/mistralai/client-python"; license = licenses.asl20; }; + }; + caldav = fetchWheel { + pname = "caldav"; version = "3.2.0"; hash = "sha256-OTYfRgqWWZuOTvu91xE4Ktsbvo/CeOrEZQ8jy2FV7KU="; + propagatedBuildInputs = with python3Packages; [ httpx icalendar python-dateutil ]; + meta = with lib; { description = "CalDAV client"; homepage = "https://github.com/python-caldav/caldav"; license = licenses.asl20; }; + }; + +in +python3Packages.buildPythonApplication rec { + pname = "nextcloud-mcp-server"; + version = "0.89.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "cbcoutinho"; + repo = "nextcloud-mcp-server"; + rev = "v${version}"; + hash = "sha256-IDTSGsHQ8cCFvgSO7pDbSSHVNV0OIjjoEN9ZfkaPAvk="; + }; + + build-system = [ python3Packages.uv-build ]; + + dependencies = with python3Packages; [ + mcp httpx pillow icalendar pydantic click pyjwt + aiosqlite alembic authlib fastembed anthropic boto3 starlette + jinja2 markdownify pymupdf pymupdf4llm openai dynaconf sqlalchemy + + pythonvcard4 prometheus-client python-json-logger importlib-metadata + googleapis-common-protos opentelemetry-api opentelemetry-proto + opentelemetry-semantic-conventions opentelemetry-sdk + x-wr-timezone opentelemetry-util-http opentelemetry-exporter-otlp-proto-common + opentelemetry-instrumentation recurring-ical-events + opentelemetry-exporter-otlp-proto-grpc qdrant-client + opentelemetry-instrumentation-asgi opentelemetry-instrumentation-httpx + opentelemetry-instrumentation-logging langchain-text-splitters mistralai caldav + ]; + + postPatch = '' + substituteInPlace pyproject.toml \ + --replace-quiet '"uv_build>=0.11.5,<0.12.0"' '"uv_build"' \ + --replace-quiet '" (>=1.27,<1.28)"' '""' \ + --replace-quiet '" (>=0.28.1,<0.29.0)"' '""' \ + --replace-quiet '" (>=10.3.0,<12.0.0)"' '""' \ + --replace-quiet '" (>=7.1.0,<7.2.0)"' '""' \ + --replace-quiet '" (>=3.0.1,<4.0)"' '""' \ + --replace-quiet '" (>=1.28.2,<2.0.0)"' '""' \ + --replace-quiet '" (>=2.0.0,<3.0.0)"' '""' \ + --replace-quiet '">=3.0.1,<4.0"' '""' \ + --replace-quiet '">=3.8.0,<4.0"' '""' \ + --replace-quiet '">=3.2.13,<4.0"' '""' \ + --replace-quiet '">=1.28.2"' '""' \ + --replace-quiet '">=0.21.0"' '""' \ + --replace-quiet '">=3.2.0"' '""' \ + --replace-quiet '">=0.2.0"' '""' \ + --replace-quiet '">=2.4.5"' '""' + ''; + + dontCheckRuntimeDeps = true; + catchConflicts = false; + + meta = with lib; { + description = "MCP server for Nextcloud — files, calendar, contacts, notes, deck, talk, sharing"; + homepage = "https://github.com/cbcoutinho/nextcloud-mcp-server"; + license = licenses.agpl3Only; + mainProgram = "nextcloud-mcp-server"; + platforms = platforms.all; + }; +}