discover_movies
Find movies by genre, minimum rating, year, and sort order. Genre names are resolved automatically.
Instructions
Discover movies by genre name, minimum rating, year, and sort order. Genre is resolved by name (e.g. 'Action').
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| genre | No | ||
| min_rating | No | ||
| year | No | ||
| sort_by | No |
Implementation Reference
- src/index.ts:183-208 (handler)The async handler function for the discover_movies tool. It resolves genre name to ID, fetches /discover/movie from TMDB with optional filters (genre, min_rating, year, sort_by), and returns a summarized list of results.
async ({ genre, min_rating, year, sort_by }) => { try { let with_genres: number | undefined; if (genre) { const id = await resolveGenreId(genre); if (id === null) { return errorResult( new TmdbError( `Unknown genre '${genre}'. Try one of: Action, Adventure, Animation, Comedy, Crime, Documentary, Drama, Family, Fantasy, History, Horror, Music, Mystery, Romance, Science Fiction, TV Movie, Thriller, War, Western.` ) ); } with_genres = id; } const data = await tmdbFetch<{ results: any[] }>("/discover/movie", { with_genres, "vote_average.gte": min_rating, primary_release_year: year, sort_by: sort_by ?? "popularity.desc", include_adult: "false", }); return jsonResult({ results: summarizeList(data.results) }); } catch (err) { return errorResult(err); } } - src/index.ts:166-182 (schema)Input schema for discover_movies: optional genre (string), min_rating (0-10 number), year (1800-2100 integer), and sort_by (enum of TMDB sort values like popularity.desc).
{ genre: z.string().optional(), min_rating: z.number().min(0).max(10).optional(), year: z.number().int().min(1800).max(2100).optional(), sort_by: z .enum([ "popularity.desc", "popularity.asc", "vote_average.desc", "vote_average.asc", "primary_release_date.desc", "primary_release_date.asc", "revenue.desc", "revenue.asc", ]) .optional(), }, - src/index.ts:163-209 (registration)Registration of the discover_movies tool on the MCP server via server.tool(), including name, description, schema, and handler.
server.tool( "discover_movies", "Discover movies by genre name, minimum rating, year, and sort order. Genre is resolved by name (e.g. 'Action').", { genre: z.string().optional(), min_rating: z.number().min(0).max(10).optional(), year: z.number().int().min(1800).max(2100).optional(), sort_by: z .enum([ "popularity.desc", "popularity.asc", "vote_average.desc", "vote_average.asc", "primary_release_date.desc", "primary_release_date.asc", "revenue.desc", "revenue.asc", ]) .optional(), }, async ({ genre, min_rating, year, sort_by }) => { try { let with_genres: number | undefined; if (genre) { const id = await resolveGenreId(genre); if (id === null) { return errorResult( new TmdbError( `Unknown genre '${genre}'. Try one of: Action, Adventure, Animation, Comedy, Crime, Documentary, Drama, Family, Fantasy, History, Horror, Music, Mystery, Romance, Science Fiction, TV Movie, Thriller, War, Western.` ) ); } with_genres = id; } const data = await tmdbFetch<{ results: any[] }>("/discover/movie", { with_genres, "vote_average.gte": min_rating, primary_release_year: year, sort_by: sort_by ?? "popularity.desc", include_adult: "false", }); return jsonResult({ results: summarizeList(data.results) }); } catch (err) { return errorResult(err); } } ); - src/tmdb.ts:81-89 (helper)Helper function resolveGenreId() used by the handler to convert a genre name string to a TMDB genre ID, with caching.
export async function resolveGenreId(name: string): Promise<number | null> { if (!genreCache) { const data = await tmdbFetch<{ genres: { id: number; name: string }[] }>( "/genre/movie/list" ); genreCache = new Map(data.genres.map((g) => [g.name.toLowerCase(), g.id])); } return genreCache.get(name.toLowerCase()) ?? null; } - src/shape.ts:32-34 (helper)Helper function summarizeList() used by the handler to format and limit the list of results returned from TMDB.
export function summarizeList(items: RawMovie[] | undefined, limit = 20) { return (items ?? []).slice(0, limit).map(summarizeMovie); }