node-csfd-api 4.3.4 → 5.0.0-next-2
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 +11 -11
- package/bin/export-ratings.mjs +62 -58
- package/bin/mcp-server.mjs +274 -182
- package/bin/server.mjs +239 -281
- package/cli.mjs +74 -78
- package/dto/creator.d.mts +1 -1
- package/dto/creator.d.ts +1 -1
- package/dto/global.d.mts +1 -1
- package/dto/global.d.ts +1 -1
- package/dto/movie.d.mts +22 -1
- package/dto/movie.d.ts +22 -1
- package/dto/user-reviews.d.mts +1 -1
- package/dto/user-reviews.d.ts +1 -1
- package/helpers/creator.helper.js +2 -2
- package/helpers/creator.helper.js.map +1 -1
- package/helpers/creator.helper.mjs +3 -3
- package/helpers/creator.helper.mjs.map +1 -1
- package/helpers/global.helper.js +52 -0
- package/helpers/global.helper.js.map +1 -1
- package/helpers/global.helper.mjs +50 -1
- package/helpers/global.helper.mjs.map +1 -1
- package/helpers/movie.helper.js +87 -3
- package/helpers/movie.helper.js.map +1 -1
- package/helpers/movie.helper.mjs +84 -5
- package/helpers/movie.helper.mjs.map +1 -1
- package/helpers/search.helper.js +2 -1
- package/helpers/search.helper.js.map +1 -1
- package/helpers/search.helper.mjs +3 -2
- package/helpers/search.helper.mjs.map +1 -1
- package/helpers/user-ratings.helper.js +1 -1
- package/helpers/user-ratings.helper.js.map +1 -1
- package/helpers/user-ratings.helper.mjs +2 -2
- package/helpers/user-ratings.helper.mjs.map +1 -1
- package/helpers/user-reviews.helper.js +2 -2
- package/helpers/user-reviews.helper.js.map +1 -1
- package/helpers/user-reviews.helper.mjs +3 -3
- package/helpers/user-reviews.helper.mjs.map +1 -1
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/package.json +2 -4
- package/package.mjs +8 -0
- package/services/movie.service.js +15 -3
- package/services/movie.service.js.map +1 -1
- package/services/movie.service.mjs +16 -4
- package/services/movie.service.mjs.map +1 -1
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ console.log(results.users); // Array of users
|
|
|
223
223
|
title: 'Black Bart',
|
|
224
224
|
year: '1975',
|
|
225
225
|
url: 'https://www.csfd.cz/film/19653-black-bart/',
|
|
226
|
-
type: '
|
|
226
|
+
type: 'tv-film',
|
|
227
227
|
colorRating: 'bad',
|
|
228
228
|
poster: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
|
|
229
229
|
origins: ['USA'],
|
|
@@ -247,7 +247,7 @@ tvSeries: [
|
|
|
247
247
|
title: 'Království',
|
|
248
248
|
year: 1994,
|
|
249
249
|
url: 'https://www.csfd.cz/film/71924-kralovstvi/',
|
|
250
|
-
type: '
|
|
250
|
+
type: 'series',
|
|
251
251
|
colorRating: 'good',
|
|
252
252
|
poster: 'https://image.pmgstatic.com/cache/resized/w60h85/files/images/film/posters/166/708/166708064_2da697.jpg',
|
|
253
253
|
origins: ['Dánsko'],
|
|
@@ -398,7 +398,7 @@ const onlyMovies = await csfd.userRatings('912-bart', {
|
|
|
398
398
|
});
|
|
399
399
|
|
|
400
400
|
const excludeEpisodes = await csfd.userRatings('912-bart', {
|
|
401
|
-
exclude: ['
|
|
401
|
+
exclude: ['episode', 'season']
|
|
402
402
|
});
|
|
403
403
|
```
|
|
404
404
|
|
|
@@ -434,13 +434,13 @@ const excludeEpisodes = await csfd.userRatings('912-bart', {
|
|
|
434
434
|
|
|
435
435
|
#### UserRatingsOptions
|
|
436
436
|
|
|
437
|
-
| Option | Type | Default | Description
|
|
438
|
-
| --------------- | ----------------- | ------- |
|
|
439
|
-
| `includesOnly` | `CSFDFilmTypes[]` | `null` | Include only specific content types (e.g., `['film', '
|
|
440
|
-
| `exclude` | `CSFDFilmTypes[]` | `null` | Exclude specific content types (e.g., `['
|
|
441
|
-
| `allPages` | `boolean` | `false` | Fetch all pages of ratings
|
|
442
|
-
| `allPagesDelay` | `number` | `0` | Delay between page requests in milliseconds
|
|
443
|
-
| `page` | `number` | `1` | Fetch specific page number
|
|
437
|
+
| Option | Type | Default | Description |
|
|
438
|
+
| --------------- | ----------------- | ------- | -------------------------------------------------------------------- |
|
|
439
|
+
| `includesOnly` | `CSFDFilmTypes[]` | `null` | Include only specific content types (e.g., `['film', 'series']`) |
|
|
440
|
+
| `exclude` | `CSFDFilmTypes[]` | `null` | Exclude specific content types (e.g., `['episode']`) |
|
|
441
|
+
| `allPages` | `boolean` | `false` | Fetch all pages of ratings |
|
|
442
|
+
| `allPagesDelay` | `number` | `0` | Delay between page requests in milliseconds |
|
|
443
|
+
| `page` | `number` | `1` | Fetch specific page number |
|
|
444
444
|
|
|
445
445
|
> 📝 **Note**: `includesOnly` and `exclude` are mutually exclusive. If both are provided, `includesOnly` takes precedence.
|
|
446
446
|
>
|
|
@@ -476,7 +476,7 @@ const allReviews = await csfd.userReviews(195357, {
|
|
|
476
476
|
// Filter by content type
|
|
477
477
|
const filtered = await csfd.userReviews(195357, {
|
|
478
478
|
includesOnly: ['film'],
|
|
479
|
-
exclude: ['
|
|
479
|
+
exclude: ['episode']
|
|
480
480
|
});
|
|
481
481
|
```
|
|
482
482
|
|
package/bin/export-ratings.mjs
CHANGED
|
@@ -1,61 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { csfd } from "../index.mjs";
|
|
1
3
|
import { writeFile } from "node:fs/promises";
|
|
2
|
-
|
|
4
|
+
|
|
5
|
+
//#region src/tools/export-ratings.ts
|
|
6
|
+
/**
|
|
7
|
+
* Runs the ratings export process for a given user.
|
|
8
|
+
* @param userId - The CSFD user ID.
|
|
9
|
+
* @param options - Export options (format, filters, language).
|
|
10
|
+
*/
|
|
3
11
|
async function runRatingsExport(userId, options) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error("Error exporting ratings:", error);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
12
|
+
try {
|
|
13
|
+
if (options.format === "letterboxd") csfd.setOptions({ language: "en" });
|
|
14
|
+
console.log(`Fetching ratings for user ${userId} (${options.format.toUpperCase()})...`);
|
|
15
|
+
const ratings = await csfd.userRatings(userId, options.userRatingsOptions);
|
|
16
|
+
console.log(`Fetched ${ratings.length} ratings.`);
|
|
17
|
+
let content = "";
|
|
18
|
+
let fileName = "";
|
|
19
|
+
const escapeCsvField = (value) => {
|
|
20
|
+
const needsQuotes = /[",\n\r]/.test(value);
|
|
21
|
+
const escaped = value.replaceAll("\"", "\"\"");
|
|
22
|
+
return needsQuotes ? `"${escaped}"` : escaped;
|
|
23
|
+
};
|
|
24
|
+
if (options.format === "letterboxd") {
|
|
25
|
+
content = ["Title,Year,Rating,WatchedDate", ...ratings.map((r) => {
|
|
26
|
+
return `${escapeCsvField(r.title ?? "")},${r.year ?? ""},${r.userRating ?? ""},${escapeCsvField(r.userDate ?? "")}`;
|
|
27
|
+
})].join("\n");
|
|
28
|
+
fileName = `${userId}-for-letterboxd.csv`;
|
|
29
|
+
} else if (options.format === "json") {
|
|
30
|
+
content = JSON.stringify(ratings, null, 2);
|
|
31
|
+
fileName = `${userId}-ratings.json`;
|
|
32
|
+
} else {
|
|
33
|
+
content = [[
|
|
34
|
+
"id",
|
|
35
|
+
"title",
|
|
36
|
+
"year",
|
|
37
|
+
"rating",
|
|
38
|
+
"date",
|
|
39
|
+
"type",
|
|
40
|
+
"url",
|
|
41
|
+
"colorRating"
|
|
42
|
+
].join(","), ...ratings.map((r) => {
|
|
43
|
+
return [
|
|
44
|
+
r.id,
|
|
45
|
+
escapeCsvField(r.title ?? ""),
|
|
46
|
+
r.year ?? "",
|
|
47
|
+
r.userRating ?? "",
|
|
48
|
+
escapeCsvField(r.userDate ?? ""),
|
|
49
|
+
escapeCsvField(r.type ?? ""),
|
|
50
|
+
escapeCsvField(r.url ?? ""),
|
|
51
|
+
escapeCsvField(r.colorRating ?? "")
|
|
52
|
+
].join(",");
|
|
53
|
+
})].join("\n");
|
|
54
|
+
fileName = `${userId}-ratings.csv`;
|
|
55
|
+
}
|
|
56
|
+
await writeFile(fileName, content);
|
|
57
|
+
console.log("Saved in file:", `./${fileName}`);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error("Error exporting ratings:", error);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
export { runRatingsExport };
|
package/bin/mcp-server.mjs
CHANGED
|
@@ -1,192 +1,284 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { csfd } from "../index.mjs";
|
|
3
|
+
import { name, version } from "../package.mjs";
|
|
2
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
6
|
import { z } from "zod";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
//#region src/mcp-server/index.ts
|
|
7
9
|
const server = new McpServer({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
name,
|
|
11
|
+
version
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* TOOL 1: Search
|
|
15
|
+
* Description: Essential first step to get IDs for movies or creators.
|
|
16
|
+
*/
|
|
17
|
+
server.registerTool("search", {
|
|
18
|
+
title: "Search",
|
|
19
|
+
description: "Searches for a movie, TV series, or person on CSFD.cz. Returns a list of results with IDs. Use this tool FIRST to find the ID needed for other tools.",
|
|
20
|
+
inputSchema: { query: z.string().describe("Search query (movie title, series, or actor, director, etc. name)") },
|
|
21
|
+
annotations: {
|
|
22
|
+
readOnlyHint: true,
|
|
23
|
+
idempotentHint: true,
|
|
24
|
+
openWorldHint: false
|
|
25
|
+
}
|
|
26
|
+
}, async ({ query }) => {
|
|
27
|
+
try {
|
|
28
|
+
const results = await csfd.search(query);
|
|
29
|
+
return {
|
|
30
|
+
structuredContent: results,
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `Found ${results.movies.length} movies, ${results.tvSeries.length} TV series, and ${results.users.length} users.`
|
|
34
|
+
}]
|
|
35
|
+
};
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
content: [{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: `Error during search: ${error}`
|
|
41
|
+
}],
|
|
42
|
+
isError: true
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* TOOL 2: Movie Details
|
|
48
|
+
* Description: Returns detailed info about a specific movie/series.
|
|
49
|
+
*/
|
|
50
|
+
server.registerTool("get_movie", {
|
|
51
|
+
title: "Get Movie",
|
|
52
|
+
description: "Retrieves detailed information about a specific movie or series, including rating, plot, genres, and actors. Requires a numeric CSFD ID.",
|
|
53
|
+
inputSchema: { id: z.number().describe("CSFD Movie ID (found using the 'search' tool)") },
|
|
54
|
+
annotations: {
|
|
55
|
+
readOnlyHint: true,
|
|
56
|
+
idempotentHint: true,
|
|
57
|
+
openWorldHint: false
|
|
58
|
+
}
|
|
59
|
+
}, async ({ id }) => {
|
|
60
|
+
try {
|
|
61
|
+
const movie = await csfd.movie(id);
|
|
62
|
+
return {
|
|
63
|
+
structuredContent: movie,
|
|
64
|
+
content: [{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: `Movie ${movie.title} (${movie.year}) with rating ${movie.rating} retrieved successfully.`
|
|
67
|
+
}]
|
|
68
|
+
};
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
content: [{
|
|
72
|
+
type: "text",
|
|
73
|
+
text: `Error retrieving movie details: ${error}`
|
|
74
|
+
}],
|
|
75
|
+
isError: true
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* TOOL 3: Creator Details
|
|
81
|
+
* Description: Returns detailed info about a person (actor, director).
|
|
82
|
+
*/
|
|
83
|
+
server.registerTool("get_creator", {
|
|
84
|
+
title: "Get Creator",
|
|
85
|
+
description: "Retrieves information about a specific creator (actor, director, etc.), including their biography and filmography. Requires a numeric CSFD ID.",
|
|
86
|
+
inputSchema: { id: z.number().describe("CSFD Creator ID") },
|
|
87
|
+
annotations: {
|
|
88
|
+
readOnlyHint: true,
|
|
89
|
+
idempotentHint: true,
|
|
90
|
+
openWorldHint: false
|
|
91
|
+
}
|
|
92
|
+
}, async ({ id }) => {
|
|
93
|
+
try {
|
|
94
|
+
const creator = await csfd.creator(id);
|
|
95
|
+
return {
|
|
96
|
+
structuredContent: creator,
|
|
97
|
+
content: [{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Creator ${creator.name} retrieved successfully.`
|
|
100
|
+
}]
|
|
101
|
+
};
|
|
102
|
+
} catch (error) {
|
|
103
|
+
return {
|
|
104
|
+
content: [{
|
|
105
|
+
type: "text",
|
|
106
|
+
text: `Error retrieving creator details: ${error}`
|
|
107
|
+
}],
|
|
108
|
+
isError: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
/**
|
|
113
|
+
* TOOL 4: User Ratings
|
|
114
|
+
* Description: Returns ratings from a specific CSFD user.
|
|
115
|
+
*/
|
|
116
|
+
server.registerTool("get_user_ratings", {
|
|
117
|
+
title: "Get User Ratings",
|
|
118
|
+
description: "Retrieves movie ratings from a specific CSFD user. Returns a list of movies with their user rating (0-5 stars). Supports pagination and filtering by film type.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
|
|
121
|
+
page: z.number().optional().describe("Page number to fetch (default: 1)"),
|
|
122
|
+
allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
|
|
123
|
+
allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
|
|
124
|
+
excludes: z.array(z.string()).optional().describe("Film types to exclude (e.g. \"series\", \"tv-film\")"),
|
|
125
|
+
includesOnly: z.array(z.string()).optional().describe("Only include these film types (e.g. \"film\")")
|
|
126
|
+
},
|
|
127
|
+
annotations: {
|
|
128
|
+
readOnlyHint: true,
|
|
129
|
+
idempotentHint: true,
|
|
130
|
+
openWorldHint: false
|
|
131
|
+
}
|
|
132
|
+
}, async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
133
|
+
try {
|
|
134
|
+
const results = await csfd.userRatings(user, {
|
|
135
|
+
page,
|
|
136
|
+
allPages,
|
|
137
|
+
allPagesDelay,
|
|
138
|
+
excludes,
|
|
139
|
+
includesOnly
|
|
140
|
+
});
|
|
141
|
+
return {
|
|
142
|
+
structuredContent: { results },
|
|
143
|
+
content: [{
|
|
144
|
+
type: "text",
|
|
145
|
+
text: `Retrieved ${results.length} user ratings successfully.`
|
|
146
|
+
}]
|
|
147
|
+
};
|
|
148
|
+
} catch (error) {
|
|
149
|
+
return {
|
|
150
|
+
content: [{
|
|
151
|
+
type: "text",
|
|
152
|
+
text: `Error retrieving user ratings: ${error}`
|
|
153
|
+
}],
|
|
154
|
+
isError: true
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
/**
|
|
159
|
+
* TOOL 5: User Reviews
|
|
160
|
+
* Description: Returns reviews written by a specific CSFD user.
|
|
161
|
+
*/
|
|
162
|
+
server.registerTool("get_user_reviews", {
|
|
163
|
+
title: "Get User Reviews",
|
|
164
|
+
description: "Retrieves movie reviews written by a specific CSFD user. Returns a list of movies with their review text and rating.",
|
|
165
|
+
inputSchema: {
|
|
166
|
+
user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
|
|
167
|
+
page: z.number().optional().describe("Page number to fetch (default: 1)"),
|
|
168
|
+
allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
|
|
169
|
+
allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
|
|
170
|
+
excludes: z.array(z.string()).optional().describe("Film types to exclude (e.g. \"series\", \"tv-film\")"),
|
|
171
|
+
includesOnly: z.array(z.string()).optional().describe("Only include these film types (e.g. \"film\")")
|
|
172
|
+
},
|
|
173
|
+
annotations: {
|
|
174
|
+
readOnlyHint: true,
|
|
175
|
+
idempotentHint: true,
|
|
176
|
+
openWorldHint: false
|
|
177
|
+
}
|
|
178
|
+
}, async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
179
|
+
try {
|
|
180
|
+
const results = await csfd.userReviews(user, {
|
|
181
|
+
page,
|
|
182
|
+
allPages,
|
|
183
|
+
allPagesDelay,
|
|
184
|
+
excludes,
|
|
185
|
+
includesOnly
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
structuredContent: { results },
|
|
189
|
+
content: [{
|
|
190
|
+
type: "text",
|
|
191
|
+
text: `Retrieved ${results.length} user reviews successfully.`
|
|
192
|
+
}]
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
content: [{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: `Error retrieving user reviews: ${error}`
|
|
199
|
+
}],
|
|
200
|
+
isError: true
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
/**
|
|
205
|
+
* TOOL 6: Cinemas
|
|
206
|
+
* Description: Returns cinema screenings for a given district and time period.
|
|
207
|
+
*/
|
|
208
|
+
server.registerTool("get_cinemas", {
|
|
209
|
+
title: "Get Cinemas",
|
|
210
|
+
description: "Retrieves cinema screenings for a given district in Czech Republic. Returns a list of cinemas with their current screenings, showtimes, and movie names and ids.",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
district: z.union([z.number(), z.string()]).describe("District ID (numeric) or name"),
|
|
213
|
+
period: z.enum([
|
|
214
|
+
"today",
|
|
215
|
+
"tomorrow",
|
|
216
|
+
"weekend",
|
|
217
|
+
"week",
|
|
218
|
+
"month"
|
|
219
|
+
]).describe("Time period for screenings")
|
|
220
|
+
},
|
|
221
|
+
annotations: {
|
|
222
|
+
readOnlyHint: true,
|
|
223
|
+
idempotentHint: true,
|
|
224
|
+
openWorldHint: false
|
|
225
|
+
}
|
|
226
|
+
}, async ({ district, period }) => {
|
|
227
|
+
try {
|
|
228
|
+
const results = await csfd.cinema(district, period);
|
|
229
|
+
return {
|
|
230
|
+
structuredContent: { results },
|
|
231
|
+
content: [{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: `Retrieved ${results.length} cinema screenings successfully.`
|
|
234
|
+
}]
|
|
235
|
+
};
|
|
236
|
+
} catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
content: [{
|
|
239
|
+
type: "text",
|
|
240
|
+
text: `Error retrieving cinema data: ${error}`
|
|
241
|
+
}],
|
|
242
|
+
isError: true
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* PROMPT: Actor's Top Rated Works
|
|
248
|
+
* Example: "Find movies starring Mads Mikkelsen and give me the top 5 sorted by rating."
|
|
249
|
+
*/
|
|
250
|
+
server.registerPrompt("actor-top-rated", {
|
|
251
|
+
title: "Actor Top Rated",
|
|
252
|
+
description: "Finds and ranks the best movies of a specific actor or creator.",
|
|
253
|
+
argsSchema: { actorName: z.string().describe("Name of the actor or director") }
|
|
254
|
+
}, async ({ actorName }) => {
|
|
255
|
+
return { messages: [{
|
|
256
|
+
role: "user",
|
|
257
|
+
content: {
|
|
258
|
+
type: "text",
|
|
259
|
+
text: `First, search for the person "${actorName}" to get their ID. Then, retrieve their full profile to see their filmography. From the results, identify the top 5 highest-rated movies they acted in. Finally, provide a bulleted list with the movie titles, years, and their CSFD ratings.`
|
|
260
|
+
}
|
|
261
|
+
}] };
|
|
10
262
|
});
|
|
11
|
-
server.tool(
|
|
12
|
-
"search",
|
|
13
|
-
"Searches for a movie, TV series, or person on CSFD.cz. Returns a list of results with IDs. Use this tool FIRST to find the ID needed for other tools.",
|
|
14
|
-
{
|
|
15
|
-
query: z.string().describe("Search query (movie title, series, or actor name)")
|
|
16
|
-
},
|
|
17
|
-
async ({ query }) => {
|
|
18
|
-
try {
|
|
19
|
-
const results = await csfd.search(query);
|
|
20
|
-
return {
|
|
21
|
-
content: [
|
|
22
|
-
{
|
|
23
|
-
type: "text",
|
|
24
|
-
text: JSON.stringify(results, null, 2)
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
};
|
|
28
|
-
} catch (error) {
|
|
29
|
-
return {
|
|
30
|
-
content: [{ type: "text", text: `Error during search: ${error}` }],
|
|
31
|
-
isError: true
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
server.tool(
|
|
37
|
-
"get_movie",
|
|
38
|
-
"Retrieves detailed information about a specific movie or series, including rating, plot, genres, and actors. Requires a numeric CSFD ID.",
|
|
39
|
-
{
|
|
40
|
-
id: z.number().describe("CSFD Movie ID (found using the 'search' tool)")
|
|
41
|
-
},
|
|
42
|
-
async ({ id }) => {
|
|
43
|
-
try {
|
|
44
|
-
const movie = await csfd.movie(id);
|
|
45
|
-
return {
|
|
46
|
-
content: [
|
|
47
|
-
{
|
|
48
|
-
type: "text",
|
|
49
|
-
text: JSON.stringify(movie, null, 2)
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
};
|
|
53
|
-
} catch (error) {
|
|
54
|
-
return {
|
|
55
|
-
content: [{ type: "text", text: `Error retrieving movie details: ${error}` }],
|
|
56
|
-
isError: true
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
);
|
|
61
|
-
server.tool(
|
|
62
|
-
"get_creator",
|
|
63
|
-
"Retrieves information about a specific creator (actor, director, etc.), including their biography and filmography. Requires a numeric CSFD ID.",
|
|
64
|
-
{
|
|
65
|
-
id: z.number().describe("CSFD Creator ID (found using the 'search' tool)")
|
|
66
|
-
},
|
|
67
|
-
async ({ id }) => {
|
|
68
|
-
try {
|
|
69
|
-
const creator = await csfd.creator(id);
|
|
70
|
-
return {
|
|
71
|
-
content: [
|
|
72
|
-
{
|
|
73
|
-
type: "text",
|
|
74
|
-
text: JSON.stringify(creator, null, 2)
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
};
|
|
78
|
-
} catch (error) {
|
|
79
|
-
return {
|
|
80
|
-
content: [{ type: "text", text: `Error retrieving creator details: ${error}` }],
|
|
81
|
-
isError: true
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
server.tool(
|
|
87
|
-
"get_user_ratings",
|
|
88
|
-
"Retrieves movie ratings from a specific CSFD user. Returns a list of movies with their user rating (0-5 stars). Supports pagination and filtering by film type.",
|
|
89
|
-
{
|
|
90
|
-
user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
|
|
91
|
-
page: z.number().optional().describe("Page number to fetch (default: 1)"),
|
|
92
|
-
allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
|
|
93
|
-
allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
|
|
94
|
-
excludes: z.array(z.string()).optional().describe('Film types to exclude (e.g. "seri\xE1l", "TV film")'),
|
|
95
|
-
includesOnly: z.array(z.string()).optional().describe('Only include these film types (e.g. "film")')
|
|
96
|
-
},
|
|
97
|
-
async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
98
|
-
try {
|
|
99
|
-
const results = await csfd.userRatings(user, {
|
|
100
|
-
page,
|
|
101
|
-
allPages,
|
|
102
|
-
allPagesDelay,
|
|
103
|
-
excludes,
|
|
104
|
-
includesOnly
|
|
105
|
-
});
|
|
106
|
-
return {
|
|
107
|
-
content: [
|
|
108
|
-
{
|
|
109
|
-
type: "text",
|
|
110
|
-
text: JSON.stringify(results, null, 2)
|
|
111
|
-
}
|
|
112
|
-
]
|
|
113
|
-
};
|
|
114
|
-
} catch (error) {
|
|
115
|
-
return {
|
|
116
|
-
content: [{ type: "text", text: `Error retrieving user ratings: ${error}` }],
|
|
117
|
-
isError: true
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
);
|
|
122
|
-
server.tool(
|
|
123
|
-
"get_user_reviews",
|
|
124
|
-
"Retrieves movie reviews written by a specific CSFD user. Returns a list of movies with their review text and rating. Supports pagination and filtering by film type.",
|
|
125
|
-
{
|
|
126
|
-
user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
|
|
127
|
-
page: z.number().optional().describe("Page number to fetch (default: 1)"),
|
|
128
|
-
allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
|
|
129
|
-
allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
|
|
130
|
-
excludes: z.array(z.string()).optional().describe('Film types to exclude (e.g. "seri\xE1l", "TV film")'),
|
|
131
|
-
includesOnly: z.array(z.string()).optional().describe('Only include these film types (e.g. "film")')
|
|
132
|
-
},
|
|
133
|
-
async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
134
|
-
try {
|
|
135
|
-
const results = await csfd.userReviews(user, {
|
|
136
|
-
page,
|
|
137
|
-
allPages,
|
|
138
|
-
allPagesDelay,
|
|
139
|
-
excludes,
|
|
140
|
-
includesOnly
|
|
141
|
-
});
|
|
142
|
-
return {
|
|
143
|
-
content: [
|
|
144
|
-
{
|
|
145
|
-
type: "text",
|
|
146
|
-
text: JSON.stringify(results, null, 2)
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
};
|
|
150
|
-
} catch (error) {
|
|
151
|
-
return {
|
|
152
|
-
content: [{ type: "text", text: `Error retrieving user reviews: ${error}` }],
|
|
153
|
-
isError: true
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
server.tool(
|
|
159
|
-
"get_cinemas",
|
|
160
|
-
"Retrieves cinema screenings for a given district in Czech Republic. Returns a list of cinemas with their current screenings, showtimes, and movie details.",
|
|
161
|
-
{
|
|
162
|
-
district: z.union([z.number(), z.string()]).describe("District ID (numeric) or name"),
|
|
163
|
-
period: z.enum(["today", "tomorrow", "weekend", "week", "month"]).describe("Time period for screenings")
|
|
164
|
-
},
|
|
165
|
-
async ({ district, period }) => {
|
|
166
|
-
try {
|
|
167
|
-
const results = await csfd.cinema(district, period);
|
|
168
|
-
return {
|
|
169
|
-
content: [
|
|
170
|
-
{
|
|
171
|
-
type: "text",
|
|
172
|
-
text: JSON.stringify(results, null, 2)
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
};
|
|
176
|
-
} catch (error) {
|
|
177
|
-
return {
|
|
178
|
-
content: [{ type: "text", text: `Error retrieving cinema data: ${error}` }],
|
|
179
|
-
isError: true
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
);
|
|
184
263
|
async function main() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
264
|
+
const transport = new StdioServerTransport();
|
|
265
|
+
await server.connect(transport);
|
|
266
|
+
console.error(`--- CSFD MCP Server (v${version}) ---`);
|
|
267
|
+
console.error("Status: Running via Stdio");
|
|
268
|
+
console.error("\nTo use this server in Claude Desktop, add this to your config:");
|
|
269
|
+
console.error(JSON.stringify({ "node-csfd-api": {
|
|
270
|
+
command: "npx",
|
|
271
|
+
args: [
|
|
272
|
+
"-y",
|
|
273
|
+
"node-csfd-api",
|
|
274
|
+
"mcp"
|
|
275
|
+
]
|
|
276
|
+
} }, null, 2));
|
|
188
277
|
}
|
|
189
278
|
main().catch((error) => {
|
|
190
|
-
|
|
191
|
-
|
|
279
|
+
console.error("Fatal error in MCP server:", error);
|
|
280
|
+
process.exit(1);
|
|
192
281
|
});
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
export { };
|