node-csfd-api 4.2.0-next.1 → 4.3.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  <div align="center">
8
8
 
9
- # CSFD API 🎬 2026
9
+ # CSFD API 🎬 + CSFD Export + MCP Server 🤖
10
10
 
11
- #### Modern TypeScript NPM library for scraping **Czech Movie Database (csfd.cz)** _(unofficial)_
11
+ #### Modern TypeScript NPM library for scraping **CSFD.CZ**. Scraper, API, Export and MCP Server in one package. _(unofficial)_
12
12
 
13
- [Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-usage-examples) • [Docker](#-docker-support)
13
+ [Features](#-features) • [Installation](#-installation) • [Quick Start](#-quick-start) • [API Reference](#-api-reference) • [Examples](#-usage-examples) • [MCP Server](#-mcp-server-model-context-protocol) • [Docker](#-docker-support)
14
14
 
15
15
  </div>
16
16
 
@@ -22,14 +22,16 @@
22
22
  - 🧪 **Well-tested** - ~100% code coverage
23
23
  - 🚀 **Universal** - Works in Node.js, browsers, and serverless environments
24
24
  - 🐳 **Docker ready** - Pre-built Docker images available
25
+ - 🤖 **MCP Server** - Use CSFD data directly within LLMs like Claude Desktop
25
26
  - 🔄 **Modern API** - Promise-based with async/await support
26
- - 📦 **One dependency** - Lightweight and efficient
27
+ - 📦 **Few dependencies** - Lightweight and efficient
27
28
 
28
29
  ### Supported Platforms
29
30
 
30
31
  - Node.js (ESM & CommonJS)
31
32
  - Browsers (with CORS considerations)
32
33
  - Docker containers
34
+ - MCP Server (Claude Desktop, etc.)
33
35
  - Serverless (Firebase Functions, AWS Lambda, CloudFlare Workers, etc.)
34
36
  - Chrome Extensions
35
37
  - React Native (Yes, with Expo too!)
@@ -75,6 +77,7 @@ console.log(reviews);
75
77
  - [Creators](#creators)
76
78
  - [User Ratings](#user-ratings)
77
79
  - [User Reviews](#user-reviews)
80
+ - [MCP Server](#-mcp-server-model-context-protocol)
78
81
  - [Docker Support](#-docker-support)
79
82
  - [Development](#-development)
80
83
 
@@ -517,6 +520,75 @@ const filtered = await csfd.userReviews(195357, {
517
520
 
518
521
  Same options as [UserRatingsOptions](#userrationsoptions).
519
522
 
523
+ ## 💻 CLI Tools
524
+
525
+ This library comes with a powerful CLI that exposes several tools.
526
+
527
+ ### 1. Export Ratings (CSV, JSON & Letterboxd)
528
+
529
+ > Backup your personal user ratings to CSV (default), JSON, or Letterboxd format. Use this tool just to keep a local copy of your data.
530
+
531
+ ```bash
532
+ # Export to CSV (default) -> saves as <userId>-ratings.csv
533
+ npx node-csfd-api export ratings 912
534
+
535
+ # Export to JSON -> saves as <userId>-ratings.json
536
+ npx node-csfd-api export ratings 912 --json
537
+
538
+ # Export to Letterboxd CSV -> saves as <userId>-for-letterboxd.csv
539
+ npx node-csfd-api export ratings 912 --letterboxd
540
+ ```
541
+
542
+ ### 2. REST API Server
543
+
544
+ Run a standalone REST API server.
545
+
546
+ ```bash
547
+ npx node-csfd-api server
548
+ # Server listening on port 3000
549
+ ```
550
+
551
+ ### 3. MCP Server
552
+
553
+ Run the Model Context Protocol server for AI agents.
554
+
555
+ ```bash
556
+ npx node-csfd-api mcp
557
+ ```
558
+
559
+ ## 🤖 MCP Server (Model Context Protocol)
560
+
561
+ This library includes a built-in [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server. This allows you to use ČSFD data directly within LLMs like **Claude Desktop**.
562
+
563
+ ### Features
564
+
565
+ - **Search**: Search for movies, TV series, and users.
566
+ - **Details**: Get comprehensive details about movies, creators, and users.
567
+ - **Reviews**: Read user reviews and ratings.
568
+
569
+ ### Usage with Claude Desktop
570
+
571
+ Add the following configuration to your `claude_desktop_config.json`:
572
+
573
+ ```json
574
+ {
575
+ "mcpServers": {
576
+ "csfd": {
577
+ "command": "npx",
578
+ "args": ["-y", "node-csfd-api", "mcp"]
579
+ }
580
+ }
581
+ }
582
+ ```
583
+
584
+ ### Supported Tools
585
+
586
+ - `search`: Search query (returns movies, series, users)
587
+ - `movie_details`: Get movie details by ID
588
+ - `creator_details`: Get creator details by ID
589
+ - `user_ratings`: Get user ratings
590
+ - `user_reviews`: Get user reviews
591
+
520
592
  ## 🐳 Docker Support
521
593
 
522
594
  Run the CSFD API as a standalone REST service using Docker.
@@ -0,0 +1,61 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { csfd } from "./../index.mjs";
3
+ async function runRatingsExport(userId, options) {
4
+ try {
5
+ if (options.format === "letterboxd") {
6
+ csfd.setOptions({ language: "en" });
7
+ }
8
+ console.log(`Fetching ratings for user ${userId} (${options.format.toUpperCase()})...`);
9
+ const ratings = await csfd.userRatings(userId, options.userRatingsOptions);
10
+ console.log(`Fetched ${ratings.length} ratings.`);
11
+ let content = "";
12
+ let fileName = "";
13
+ const escapeCsvField = (value) => {
14
+ const needsQuotes = /[",\n\r]/.test(value);
15
+ const escaped = value.replaceAll('"', '""');
16
+ return needsQuotes ? `"${escaped}"` : escaped;
17
+ };
18
+ if (options.format === "letterboxd") {
19
+ content = [
20
+ "Title,Year,Rating,WatchedDate",
21
+ ...ratings.map((r) => {
22
+ const title = escapeCsvField(r.title ?? "");
23
+ const year = r.year ?? "";
24
+ const rating = r.userRating ?? "";
25
+ const watchedDate = escapeCsvField(r.userDate ?? "");
26
+ return `${title},${year},${rating},${watchedDate}`;
27
+ })
28
+ ].join("\n");
29
+ fileName = `${userId}-for-letterboxd.csv`;
30
+ } else if (options.format === "json") {
31
+ content = JSON.stringify(ratings, null, 2);
32
+ fileName = `${userId}-ratings.json`;
33
+ } else {
34
+ const headers = ["id", "title", "year", "rating", "date", "type", "url", "colorRating"];
35
+ content = [
36
+ headers.join(","),
37
+ ...ratings.map((r) => {
38
+ return [
39
+ r.id,
40
+ escapeCsvField(r.title ?? ""),
41
+ r.year ?? "",
42
+ r.userRating ?? "",
43
+ escapeCsvField(r.userDate ?? ""),
44
+ escapeCsvField(r.type ?? ""),
45
+ escapeCsvField(r.url ?? ""),
46
+ escapeCsvField(r.colorRating ?? "")
47
+ ].join(",");
48
+ })
49
+ ].join("\n");
50
+ fileName = `${userId}-ratings.csv`;
51
+ }
52
+ await writeFile(fileName, content);
53
+ console.log("Saved in file:", `./${fileName}`);
54
+ } catch (error) {
55
+ console.error("Error exporting ratings:", error);
56
+ throw error;
57
+ }
58
+ }
59
+ export {
60
+ runRatingsExport
61
+ };
@@ -2,8 +2,8 @@
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { z } from "zod";
5
- import packageJson from "./package.json" with { type: "json" };
6
- import { csfd } from "./index.mjs";
5
+ import packageJson from "./../package.json" with { type: "json" };
6
+ import { csfd } from "./../index.mjs";
7
7
  const server = new McpServer({
8
8
  name: packageJson.name,
9
9
  version: packageJson.version
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import "dotenv/config";
3
3
  import express from "express";
4
- import packageJson from "./package.json" with { type: "json" };
5
- import { csfd } from "./index.mjs";
4
+ import packageJson from "./../package.json" with { type: "json" };
5
+ import { csfd } from "./../index.mjs";
6
6
  const LOG_COLORS = {
7
7
  info: "\x1B[36m",
8
8
  // cyan
package/cli.mjs ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = path.dirname(__filename);
6
+ async function main() {
7
+ const args = process.argv.slice(2);
8
+ const command = args[0];
9
+ switch (command) {
10
+ case "server":
11
+ case "api":
12
+ try {
13
+ await import(path.join(__dirname, "bin/server.mjs"));
14
+ } catch (error) {
15
+ console.error("Failed to start server:", error);
16
+ process.exit(1);
17
+ }
18
+ break;
19
+ case "mcp":
20
+ try {
21
+ await import(path.join(__dirname, "bin/mcp-server.mjs"));
22
+ } catch (error) {
23
+ console.error("Failed to start MCP server:", error);
24
+ process.exit(1);
25
+ }
26
+ break;
27
+ case "export":
28
+ if (args[1] === "ratings") {
29
+ const userIdRaw = args[2];
30
+ const userId = Number(userIdRaw);
31
+ if (!userIdRaw || isNaN(userId)) {
32
+ console.error("Error: Please provide a valid numeric User ID.");
33
+ console.log("Usage: npx node-csfd-api export ratings <userId> [options]");
34
+ process.exit(1);
35
+ }
36
+ const isLetterboxd = args.includes("--letterboxd");
37
+ const isJson = args.includes("--json");
38
+ const isCsv = args.includes("--csv");
39
+ let format = "csv";
40
+ if (isLetterboxd) {
41
+ format = "letterboxd";
42
+ } else if (isJson) {
43
+ format = "json";
44
+ } else if (isCsv) {
45
+ format = "csv";
46
+ }
47
+ try {
48
+ const modulePath = path.join(__dirname, "bin/export-ratings.mjs");
49
+ const { runRatingsExport } = await import(modulePath);
50
+ await runRatingsExport(userId, {
51
+ format,
52
+ userRatingsOptions: {
53
+ // Default behavior for Letterboxd (films only) if not overridden
54
+ includesOnly: isLetterboxd ? ["film"] : void 0,
55
+ allPages: true,
56
+ allPagesDelay: 1e3
57
+ }
58
+ });
59
+ } catch (error) {
60
+ console.error("Failed to run export:", error);
61
+ process.exit(1);
62
+ }
63
+ } else if (args[1] === "letterboxd") {
64
+ console.warn(
65
+ 'Deprecation Warning: "export letterboxd" is deprecated. Please use "export ratings <id> --letterboxd" instead.'
66
+ );
67
+ console.log("Usage: npx node-csfd-api export ratings <userId> --letterboxd");
68
+ process.exit(1);
69
+ } else {
70
+ console.error(`Unknown export target: ${args[1]}`);
71
+ printUsage();
72
+ process.exit(1);
73
+ }
74
+ break;
75
+ case "help":
76
+ case "--help":
77
+ case "-h":
78
+ default:
79
+ printUsage();
80
+ break;
81
+ }
82
+ }
83
+ function printUsage() {
84
+ console.log(`
85
+ Usage: npx node-csfd-api <command> [options]
86
+
87
+ Commands:
88
+ server, api Start the REST API server
89
+ mcp Start the MCP (Model Context Protocol) server for AI agents
90
+ export ratings <userId> Export user ratings to CSV (default), JSON, or Letterboxd format
91
+ Options:
92
+ --csv Export to CSV format (default)
93
+ --json Export to JSON format
94
+ --letterboxd Export to Letterboxd-compatible CSV format
95
+ help Show this help message
96
+ `);
97
+ }
98
+ main().catch((error) => {
99
+ console.error("Fatal error:", error);
100
+ process.exit(1);
101
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-csfd-api",
3
- "version": "4.2.0-next.1",
3
+ "version": "4.3.0-next.0",
4
4
  "description": "ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)",
5
5
  "author": "BART! <bart@bartweb.cz>",
6
6
  "publishConfig": {
@@ -10,9 +10,9 @@
10
10
  "dependencies": {
11
11
  "@modelcontextprotocol/sdk": "^1.26.0",
12
12
  "cross-fetch": "^4.1.0",
13
- "node-html-parser": "^7.0.2",
13
+ "dotenv": "^17.3.1",
14
14
  "express": "^5.2.1",
15
- "dotenv": "^17.2.4",
15
+ "node-html-parser": "^7.0.2",
16
16
  "zod": "^4.3.6"
17
17
  },
18
18
  "repository": {
@@ -51,8 +51,7 @@
51
51
  "./package.json": "./package.json"
52
52
  },
53
53
  "bin": {
54
- "csfd-mcp": "mcp-server.mjs",
55
- "csfd-server": "server.mjs"
54
+ "node-csfd-api": "cli.mjs"
56
55
  },
57
56
  "sideEffects": false
58
57
  }