node-csfd-api 5.0.0-next.0 → 5.0.0-next.1
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/bin/mcp-server.mjs +150 -51
- package/package.json +1 -1
- package/package.mjs +1 -1
package/bin/mcp-server.mjs
CHANGED
|
@@ -14,13 +14,25 @@ const server = new McpServer({
|
|
|
14
14
|
* TOOL 1: Search
|
|
15
15
|
* Description: Essential first step to get IDs for movies or creators.
|
|
16
16
|
*/
|
|
17
|
-
server.
|
|
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 }) => {
|
|
18
27
|
try {
|
|
19
28
|
const results = await csfd.search(query);
|
|
20
|
-
return {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
+
};
|
|
24
36
|
} catch (error) {
|
|
25
37
|
return {
|
|
26
38
|
content: [{
|
|
@@ -35,13 +47,25 @@ server.tool("search", "Searches for a movie, TV series, or person on CSFD.cz. Re
|
|
|
35
47
|
* TOOL 2: Movie Details
|
|
36
48
|
* Description: Returns detailed info about a specific movie/series.
|
|
37
49
|
*/
|
|
38
|
-
server.
|
|
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 }) => {
|
|
39
60
|
try {
|
|
40
61
|
const movie = await csfd.movie(id);
|
|
41
|
-
return {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
};
|
|
45
69
|
} catch (error) {
|
|
46
70
|
return {
|
|
47
71
|
content: [{
|
|
@@ -56,13 +80,25 @@ server.tool("get_movie", "Retrieves detailed information about a specific movie
|
|
|
56
80
|
* TOOL 3: Creator Details
|
|
57
81
|
* Description: Returns detailed info about a person (actor, director).
|
|
58
82
|
*/
|
|
59
|
-
server.
|
|
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 }) => {
|
|
60
93
|
try {
|
|
61
94
|
const creator = await csfd.creator(id);
|
|
62
|
-
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
return {
|
|
96
|
+
structuredContent: creator,
|
|
97
|
+
content: [{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Creator ${creator.name} retrieved successfully.`
|
|
100
|
+
}]
|
|
101
|
+
};
|
|
66
102
|
} catch (error) {
|
|
67
103
|
return {
|
|
68
104
|
content: [{
|
|
@@ -77,13 +113,22 @@ server.tool("get_creator", "Retrieves information about a specific creator (acto
|
|
|
77
113
|
* TOOL 4: User Ratings
|
|
78
114
|
* Description: Returns ratings from a specific CSFD user.
|
|
79
115
|
*/
|
|
80
|
-
server.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
+
}
|
|
87
132
|
}, async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
88
133
|
try {
|
|
89
134
|
const results = await csfd.userRatings(user, {
|
|
@@ -93,10 +138,13 @@ server.tool("get_user_ratings", "Retrieves movie ratings from a specific CSFD us
|
|
|
93
138
|
excludes,
|
|
94
139
|
includesOnly
|
|
95
140
|
});
|
|
96
|
-
return {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
141
|
+
return {
|
|
142
|
+
structuredContent: { results },
|
|
143
|
+
content: [{
|
|
144
|
+
type: "text",
|
|
145
|
+
text: `Retrieved ${results.length} user ratings successfully.`
|
|
146
|
+
}]
|
|
147
|
+
};
|
|
100
148
|
} catch (error) {
|
|
101
149
|
return {
|
|
102
150
|
content: [{
|
|
@@ -111,13 +159,22 @@ server.tool("get_user_ratings", "Retrieves movie ratings from a specific CSFD us
|
|
|
111
159
|
* TOOL 5: User Reviews
|
|
112
160
|
* Description: Returns reviews written by a specific CSFD user.
|
|
113
161
|
*/
|
|
114
|
-
server.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
+
}
|
|
121
178
|
}, async ({ user, page, allPages, allPagesDelay, excludes, includesOnly }) => {
|
|
122
179
|
try {
|
|
123
180
|
const results = await csfd.userReviews(user, {
|
|
@@ -127,10 +184,13 @@ server.tool("get_user_reviews", "Retrieves movie reviews written by a specific C
|
|
|
127
184
|
excludes,
|
|
128
185
|
includesOnly
|
|
129
186
|
});
|
|
130
|
-
return {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
187
|
+
return {
|
|
188
|
+
structuredContent: { results },
|
|
189
|
+
content: [{
|
|
190
|
+
type: "text",
|
|
191
|
+
text: `Retrieved ${results.length} user reviews successfully.`
|
|
192
|
+
}]
|
|
193
|
+
};
|
|
134
194
|
} catch (error) {
|
|
135
195
|
return {
|
|
136
196
|
content: [{
|
|
@@ -145,22 +205,34 @@ server.tool("get_user_reviews", "Retrieves movie reviews written by a specific C
|
|
|
145
205
|
* TOOL 6: Cinemas
|
|
146
206
|
* Description: Returns cinema screenings for a given district and time period.
|
|
147
207
|
*/
|
|
148
|
-
server.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
+
}
|
|
157
226
|
}, async ({ district, period }) => {
|
|
158
227
|
try {
|
|
159
228
|
const results = await csfd.cinema(district, period);
|
|
160
|
-
return {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
229
|
+
return {
|
|
230
|
+
structuredContent: { results },
|
|
231
|
+
content: [{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: `Retrieved ${results.length} cinema screenings successfully.`
|
|
234
|
+
}]
|
|
235
|
+
};
|
|
164
236
|
} catch (error) {
|
|
165
237
|
return {
|
|
166
238
|
content: [{
|
|
@@ -171,10 +243,37 @@ server.tool("get_cinemas", "Retrieves cinema screenings for a given district in
|
|
|
171
243
|
};
|
|
172
244
|
}
|
|
173
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
|
+
}] };
|
|
262
|
+
});
|
|
174
263
|
async function main() {
|
|
175
264
|
const transport = new StdioServerTransport();
|
|
176
265
|
await server.connect(transport);
|
|
177
|
-
console.error(
|
|
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));
|
|
178
277
|
}
|
|
179
278
|
main().catch((error) => {
|
|
180
279
|
console.error("Fatal error in MCP server:", error);
|
package/package.json
CHANGED