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.
@@ -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.tool("search", "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.", { query: z.string().describe("Search query (movie title, series, or actor name)") }, async ({ query }) => {
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 { content: [{
21
- type: "text",
22
- text: JSON.stringify(results, null, 2)
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.tool("get_movie", "Retrieves detailed information about a specific movie or series, including rating, plot, genres, and actors. Requires a numeric CSFD ID.", { id: z.number().describe("CSFD Movie ID (found using the 'search' tool)") }, async ({ id }) => {
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 { content: [{
42
- type: "text",
43
- text: JSON.stringify(movie, null, 2)
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.tool("get_creator", "Retrieves information about a specific creator (actor, director, etc.), including their biography and filmography. Requires a numeric CSFD ID.", { id: z.number().describe("CSFD Creator ID (found using the 'search' tool)") }, async ({ id }) => {
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 { content: [{
63
- type: "text",
64
- text: JSON.stringify(creator, null, 2)
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.tool("get_user_ratings", "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.", {
81
- user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
82
- page: z.number().optional().describe("Page number to fetch (default: 1)"),
83
- allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
84
- allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
85
- excludes: z.array(z.string()).optional().describe("Film types to exclude (e.g. \"series\", \"tv-film\")"),
86
- includesOnly: z.array(z.string()).optional().describe("Only include these film types (e.g. \"film\")")
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 { content: [{
97
- type: "text",
98
- text: JSON.stringify(results, null, 2)
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.tool("get_user_reviews", "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.", {
115
- user: z.union([z.string(), z.number()]).describe("CSFD User ID (numeric) or username"),
116
- page: z.number().optional().describe("Page number to fetch (default: 1)"),
117
- allPages: z.boolean().optional().describe("Fetch all pages at once (use wisely, may be slow)"),
118
- allPagesDelay: z.number().optional().describe("Delay in ms between page requests when using allPages"),
119
- excludes: z.array(z.string()).optional().describe("Film types to exclude (e.g. \"series\", \"tv-film\")"),
120
- includesOnly: z.array(z.string()).optional().describe("Only include these film types (e.g. \"film\")")
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 { content: [{
131
- type: "text",
132
- text: JSON.stringify(results, null, 2)
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.tool("get_cinemas", "Retrieves cinema screenings for a given district in Czech Republic. Returns a list of cinemas with their current screenings, showtimes, and movie details.", {
149
- district: z.union([z.number(), z.string()]).describe("District ID (numeric) or name"),
150
- period: z.enum([
151
- "today",
152
- "tomorrow",
153
- "weekend",
154
- "week",
155
- "month"
156
- ]).describe("Time period for screenings")
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 { content: [{
161
- type: "text",
162
- text: JSON.stringify(results, null, 2)
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("CSFD MCP Server running on stdio...");
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-csfd-api",
3
- "version": "5.0.0-next.0",
3
+ "version": "5.0.0-next.1",
4
4
  "description": "ČSFD API in JavaScript. Amazing NPM library for scrapping csfd.cz :)",
5
5
  "author": "BART! <bart@bartweb.cz>",
6
6
  "publishConfig": {
package/package.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  //#region package.json
3
3
  var name = "node-csfd-api";
4
- var version = "5.0.0-next.0";
4
+ var version = "5.0.0-next.1";
5
5
  var homepage = "https://github.com/bartholomej/node-csfd-api#readme";
6
6
 
7
7
  //#endregion