anilist_recommendations
Get community recommendations for anime or manga similar to a specific title. Returns ranked results with format, score, and genres.
Instructions
Get community recommendations for a specific anime or manga. Use when the user asks for shows similar to a specific title, or says "I liked X, what else should I watch?" Returns titles ranked by recommendation count with format, score, and genres.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | AniList media ID | |
| title | No | Search by title if no ID is known | |
| type | No | Media type. Defaults to ANIME. | ANIME |
| limit | No | Number of recommendations to return (default 10, max 25) |
Implementation Reference
- src/tools/search.ts:319-370 (handler)The execute handler for the anilist_recommendations tool. Queries the AniList API for community recommendations, filters by rating and NSFW status, and formats results with media summaries and recommendation counts.
execute: async (args) => { try { const variables: Record<string, unknown> = { type: args.type, perPage: args.limit, }; if (args.id) variables.id = args.id; if (args.title) variables.search = args.title; const data = await anilistClient.query<RecommendationsResponse>( RECOMMENDATIONS_QUERY, variables, { cache: "media" }, ); const source = data.Media; const sourceTitle = getTitle(source.title); const nsfw = isNsfwEnabled(); const recs = source.recommendations.nodes.filter( (n) => n.mediaRecommendation && n.rating > 0 && (nsfw || !n.mediaRecommendation.isAdult), ); if (!recs.length) { return `No community recommendations found for "${sourceTitle}".`; } const lines: string[] = [ `# Recommendations based on ${sourceTitle}`, `${recs.length} community suggestion${recs.length !== 1 ? "s" : ""}:`, "", ]; for (let i = 0; i < recs.length; i++) { const rec = recs[i]; const m = rec.mediaRecommendation; if (!m) continue; lines.push( `${i + 1}. ${formatMediaSummary(m)}`, ` Recommended by ${rec.rating} user${rec.rating !== 1 ? "s" : ""}`, "", ); } return lines.join("\n"); } catch (error) { return throwToolError(error, "fetching recommendations"); } }, - src/tools/search.ts:301-305 (registration)The tool registration using server.addTool() with name 'anilist_recommendations', description, schema, and execute handler.
}); // === Community Recommendations === server.addTool({ - src/schemas.ts:589-607 (schema)Zod schema defining input parameters: id (optional int), title (optional string), type (ANIME/MANGA, default ANIME), limit (1-25, default 10). Requires id or title.
export const RecommendationsInputSchema = z .object({ id: z.number().int().positive().optional().describe("AniList media ID"), title: z.string().optional().describe("Search by title if no ID is known"), type: z .enum(["ANIME", "MANGA"]) .default("ANIME") .describe("Media type. Defaults to ANIME."), limit: z .number() .int() .min(1) .max(25) .default(10) .describe("Number of recommendations to return (default 10, max 25)"), }) .refine((data) => data.id !== undefined || data.title !== undefined, { message: "Provide either an id or a title.", }); - src/api/queries.ts:223-239 (helper)GraphQL query (RECOMMENDATIONS_QUERY) used to fetch community recommendations from the AniList API, sorted by rating descending.
export const RECOMMENDATIONS_QUERY = ` query MediaRecommendations($id: Int, $search: String, $type: MediaType, $perPage: Int) { Media(id: $id, search: $search, type: $type) { id title { romaji english native } recommendations(sort: RATING_DESC, perPage: $perPage) { nodes { rating mediaRecommendation { ...MediaFields } } } } } ${MEDIA_FRAGMENT} `; - src/types.ts:141-156 (helper)TypeScript interface (RecommendationsResponse) defining the shape of the API response for recommendations.
export interface RecommendationsResponse { Media: { id: number; title: { romaji: string | null; english: string | null; native: string | null; }; recommendations: { nodes: Array<{ rating: number; mediaRecommendation: AniListMedia | null; }>; }; }; }