Skip to main content
Glama
Grinv

AniList MCP Server

Search anime/manga

search_media
Read-only

Find anime or manga on AniList by title and filters such as genre, format, status, season/year, or length, or browse rankings by score, popularity, or trend. Returns AniList IDs for other tools.

Instructions

Search AniList for anime or manga by title and/or filters (genre, tag, format, status, season/year, country, length — most with an exclusion variant), or browse term-less by ranking (top-rated, most popular, trending — see the sort parameter) when you don't have a title to search for. Adult (NSFW) results are included unless you set sfw: true (or isAdult: false); isAdult: true returns adult titles only. Returns AniList IDs to use with get_media and other ID-based tools.

Input Schema

NameRequiredDescriptionDefault
sfwNoSet true to exclude adult (isAdult) entries — same as `isAdult: false`. Adult results are NOT filtered by default.
pageNoPage number for pagination. AniList's paginated connections (search results, a title's characters/staff/reviews, activity feeds, forum comments) reject a page whose page × perPage exceeds ~5000 entries with an upstream error, so paging that deep fails rather than returning more results.
sortNoSort order, most-significant key first (e.g. ["SCORE_DESC"] for highest-rated first, ["POPULARITY_DESC"] for most popular, ["TRENDING_DESC"] for what's hot right now). Defaults to relevance-ranked SEARCH_MATCH when a `term` is given; with no term and no explicit sort, results come back in AniList's own default order. Set an explicit sort for a term-less ranking/browse query (e.g. top-rated or most-popular).
termNoFree-text search term (matches title). Omit to only filter.
typeYesWhether to search anime or manga.
genresNoRestrict to entries matching ALL of these genre names (see get_genres for valid names) — an unrecognized genre name doesn't error, it just filters out all results, same silent-mismatch behavior as `format_in`/`tag_in` below.
onListNo[Requires login] Restrict to (true) or exclude (false) entries already on the authenticated user's own list. Omit to ignore list status entirely. Errors if not logged in (confirmed live: AniList would otherwise silently ignore it and return unfiltered results).
seasonNoRestrict to this airing season. Works alone — matches every year's occurrence of that season, NOT just the current year (unlike anilist.co's own season filter UI, which implicitly assumes the current year when you don't also pick one). Combine with `seasonYear` for one specific season+year.
tag_inNoRestrict to entries matching ALL of these exact tag names (see get_media_tags for valid names — unlike `genres`, tag names are case-sensitive and more specific, e.g. "Time Loop" or "Tragedy"). An unrecognized tag name doesn't error, it just silently matches nothing (same behavior as `genres`/`format_in` above, confirmed live).
isAdultNoAniList's own adult-content filter: true returns ONLY adult (18+) entries, false excludes them (same as `sfw: true`). Omit to include both. No login or account setting is needed for adult results. `sfw: true` with `isAdult: true` contradict each other and are rejected.
perPageNoResults per page (max 50, AniList's own ceiling — it silently clamps anything higher).
format_inNoRestrict to these formats. Only formats valid for the `type` you're searching match anything — e.g. NOVEL/ONE_SHOT with type: ANIME, or TV/OVA/ONA with type: MANGA, will just filter out all results, not error.
source_inNoRestrict to entries adapted from these source material types.
status_inNoRestrict to these release statuses.
seasonYearNoRestrict to this airing/release year (matches any season within it). Works alone or combined with `season` for one specific season+year — neither requires the other.
tag_not_inNoExclude entries having ANY of these exact tag names (see `tag_in`).
genre_not_inNoExclude entries having ANY of these genres. Unlike `genres`, an unrecognized name excludes nothing (no-op, confirmed live).
format_not_inNoExclude these formats.
licensedBy_inNoRestrict to entries licensed/streamed by ANY of these sites (names as in get_media's `externalLinks[].site`, e.g. "Crunchyroll", "Netflix"; case-insensitive). An unrecognized site name matches nothing.
status_not_inNoExclude these release statuses.
endDate_lesserNoRestrict to entries whose end date is strictly BEFORE this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means "up to 2019-12-31".
minimumTagRankNoOnly count a tag in `tag_in`/`tag_not_in` when its relevance rank (0-100, as in get_media's `tags[].rank`) is at least this — e.g. 90 for titles where the tag is central, not incidental. Applies to both lists (confirmed live).
volumes_lesserNoManga only: fewer volumes than this (see above).
chapters_lesserNoManga only: fewer chapters than this (same column as `episodes_lesser`).
countryOfOriginNoRestrict to this country of origin, as an uppercase ISO 3166-1 alpha-2 code (e.g. "JP", "KR" for manhwa, "CN" for manhua/donghua, "TW"). An unused code matches nothing.
duration_lesserNoAnime only: episode length strictly less than this, in minutes (see above).
endDate_greaterNoRestrict to entries whose end date is strictly AFTER this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means "from 2020-01-01 on".
episodes_lesserNoRestrict to entries with fewer episodes/chapters than this.
volumes_greaterNoManga only: more volumes than this. With type: ANIME AniList silently applies it to episode duration instead (shared column, confirmed live).
chapters_greaterNoManga only: more chapters than this. Same underlying column as `episodes_greater` — with type: ANIME it filters episode count (confirmed live).
duration_greaterNoAnime only: episode length strictly greater than this, in minutes. With type: MANGA AniList silently applies it to volume count instead (shared column, confirmed live).
episodes_greaterNoRestrict to entries with more episodes/chapters than this.
startDate_lesserNoRestrict to entries whose start date is strictly BEFORE this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means "up to 2019-12-31".
popularity_lesserNoRestrict to entries with fewer list-adds than this.
startDate_greaterNoRestrict to entries whose start date is strictly AFTER this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means "from 2020-01-01 on".
includeDescriptionNoAlso fetch each result's full synopsis (`description`). Kept off by default — with up to 50 results per call, always including it would burn tokens on text you may not need; use get_media for a single title's full synopsis instead.
popularity_greaterNoRestrict to entries with more list-adds than this.
averageScore_lesserNoRestrict to entries with an average score strictly less than this (0-100).
averageScore_greaterNoRestrict to entries with an average score strictly greater than this (0-100).

Output Schema

NameRequiredDescriptionDefault
resultsYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed23 schema fields changedv0.11.0
    • addedInput schema / additionalProperties
      Added value: +false
    • addedInput schema / properties / chapters_greater
      Added value: +{
      +  "description": "Manga only: more chapters than this. Same underlying column as `episodes_greater` — with type: ANIME it filters episode count (confirmed live).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / chapters_lesser
      Added value: +{
      +  "description": "Manga only: fewer chapters than this (same column as `episodes_lesser`).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / countryOfOrigin
      Added value: +{
      +  "description": "Restrict to this country of origin, as an uppercase ISO 3166-1 alpha-2 code (e.g. \"JP\", \"KR\" for manhwa, \"CN\" for manhua/donghua, \"TW\"). An unused code matches nothing.",
      +  "pattern": "^[A-Z]{2}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / duration_greater
      Added value: +{
      +  "description": "Anime only: episode length strictly greater than this, in minutes. With type: MANGA AniList silently applies it to volume count instead (shared column, confirmed live).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / duration_lesser
      Added value: +{
      +  "description": "Anime only: episode length strictly less than this, in minutes (see above).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedInput schema / properties / endDate_greater / description
      Previous value: -"Restrict to entries whose end date is on or after this date."New value: +"Restrict to entries whose end date is strictly AFTER this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means \"from 2020-01-01 on\"."
    • changedInput schema / properties / endDate_lesser / description
      Previous value: -"Restrict to entries whose end date is on or before this date."New value: +"Restrict to entries whose end date is strictly BEFORE this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means \"up to 2019-12-31\"."
    • addedInput schema / properties / format_not_in
      Added value: +{
      +  "description": "Exclude these formats.",
      +  "items": {
      +    "enum": [
      +      "TV",
      +      "TV_SHORT",
      +      "MOVIE",
      +      "SPECIAL",
      +      "OVA",
      +      "ONA",
      +      "MUSIC",
      +      "MANGA",
      +      "NOVEL",
      +      "ONE_SHOT"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / genre_not_in
      Added value: +{
      +  "description": "Exclude entries having ANY of these genres. Unlike `genres`, an unrecognized name excludes nothing (no-op, confirmed live).",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / isAdult
      Added value: +{
      +  "description": "AniList's own adult-content filter: true returns ONLY adult (18+) entries, false excludes them (same as `sfw: true`). Omit to include both. No login or account setting is needed for adult results. `sfw: true` with `isAdult: true` contradict each other and are rejected.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / licensedBy_in
      Added value: +{
      +  "description": "Restrict to entries licensed/streamed by ANY of these sites (names as in get_media's `externalLinks[].site`, e.g. \"Crunchyroll\", \"Netflix\"; case-insensitive). An unrecognized site name matches nothing.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / minimumTagRank
      Added value: +{
      +  "description": "Only count a tag in `tag_in`/`tag_not_in` when its relevance rank (0-100, as in get_media's `tags[].rank`) is at least this — e.g. 90 for titles where the tag is central, not incidental. Applies to both lists (confirmed live).",
      +  "maximum": 100,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedInput schema / properties / onList / description
      Previous value: -"[Requires login] Restrict to (true) or exclude (false) entries already on the authenticated user's own list. Omit to ignore list status entirely. Confirmed live: silently no-ops (identical results for true/false/omitted) if not logged in, since there's no list to check against — same behavior as get_recommendations_for_media's `excludeInList`."New value: +"[Requires login] Restrict to (true) or exclude (false) entries already on the authenticated user's own list. Omit to ignore list status entirely. Errors if not logged in (confirmed live: AniList would otherwise silently ignore it and return unfiltered results)."
    • changedInput schema / properties / sfw / description
      Previous value: -"Set true to exclude adult (isAdult) entries. Adult results are NOT filtered by default."New value: +"Set true to exclude adult (isAdult) entries — same as `isAdult: false`. Adult results are NOT filtered by default."
    • addedInput schema / properties / sort / minItems
      Added value: +1
    • changedInput schema / properties / startDate_greater / description
      Previous value: -"Restrict to entries whose start date is on or after this date."New value: +"Restrict to entries whose start date is strictly AFTER this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means \"from 2020-01-01 on\"."
    • changedInput schema / properties / startDate_lesser / description
      Previous value: -"Restrict to entries whose start date is on or before this date."New value: +"Restrict to entries whose start date is strictly BEFORE this date (the bound date itself is excluded). An omitted month/day counts as 0, so {year: 2020} here means \"up to 2019-12-31\"."
    • addedInput schema / properties / status_not_in
      Added value: +{
      +  "description": "Exclude these release statuses.",
      +  "items": {
      +    "enum": [
      +      "FINISHED",
      +      "RELEASING",
      +      "NOT_YET_RELEASED",
      +      "CANCELLED",
      +      "HIATUS"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / tag_not_in
      Added value: +{
      +  "description": "Exclude entries having ANY of these exact tag names (see `tag_in`).",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / term / minLength
      Added value: +1
    • addedInput schema / properties / volumes_greater
      Added value: +{
      +  "description": "Manga only: more volumes than this. With type: ANIME AniList silently applies it to episode duration instead (shared column, confirmed live).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / volumes_lesser
      Added value: +{
      +  "description": "Manga only: fewer volumes than this (see above).",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
  2. Changed5 schema fields changedv0.9.0
    • changedInput schema / properties / includeDescription / description
      Previous value: -"Also fetch each result's full synopsis (`description`). Kept off by default — with up to 25 results per call, always including it would burn tokens on text you may not need; use get_media for a single title's full synopsis instead."New value: +"Also fetch each result's full synopsis (`description`). Kept off by default — with up to 50 results per call, always including it would burn tokens on text you may not need; use get_media for a single title's full synopsis instead."
    • changedInput schema / properties / perPage / description
      Previous value: -"Results per page (max 25)."New value: +"Results per page (max 50, AniList's own ceiling — it silently clamps anything higher)."
    • changedInput schema / properties / perPage / maximum
      Previous value: -25New value: +50
    • removedOutput schema / properties / results / properties / pageInfo / properties / hasNextPage / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / results / properties / pageInfo / properties / hasNextPage / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
  3. Changed18 schema fields changedv0.7.1
    • addedInput schema / properties / endDate_greater / properties / year / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / endDate_greater / properties / year / minimum
      Removed value: --9007199254740991
    • addedInput schema / properties / endDate_lesser / properties / year / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / endDate_lesser / properties / year / minimum
      Removed value: --9007199254740991
    • changedInput schema / properties / onList / description
      Previous value: -"[Requires login] Restrict to (true) or exclude (false) entries already on the authenticated user's own list. Omit to ignore list status entirely."New value: +"[Requires login] Restrict to (true) or exclude (false) entries already on the authenticated user's own list. Omit to ignore list status entirely. Confirmed live: silently no-ops (identical results for true/false/omitted) if not logged in, since there's no list to check against — same behavior as get_recommendations_for_media's `excludeInList`."
    • changedInput schema / properties / page / description
      Previous value: -"Page number for pagination."New value: +"Page number for pagination. AniList's paginated connections (search results, a title's characters/staff/reviews, activity feeds, forum comments) reject a page whose page × perPage exceeds ~5000 entries with an upstream error, so paging that deep fails rather than returning more results."
    • addedInput schema / properties / perPage / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / perPage / minimum
      Removed value: -1
    • addedInput schema / properties / seasonYear / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / seasonYear / minimum
      Removed value: --9007199254740991
    • changedInput schema / properties / sort / description
      Previous value: -"Sort order, most-significant key first (e.g. [\"SCORE_DESC\"] for highest-rated first, [\"POPULARITY_DESC\"] for most popular, [\"TRENDING_DESC\"] for what's hot right now). Defaults to relevance-ranked SEARCH_MATCH, which only makes sense when `term` is also given — set an explicit sort for a term-less browse/ranking query."New value: +"Sort order, most-significant key first (e.g. [\"SCORE_DESC\"] for highest-rated first, [\"POPULARITY_DESC\"] for most popular, [\"TRENDING_DESC\"] for what's hot right now). Defaults to relevance-ranked SEARCH_MATCH when a `term` is given; with no term and no explicit sort, results come back in AniList's own default order. Set an explicit sort for a term-less ranking/browse query (e.g. top-rated or most-popular)."
    • addedInput schema / properties / startDate_greater / properties / year / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / startDate_greater / properties / year / minimum
      Removed value: --9007199254740991
    • addedInput schema / properties / startDate_lesser / properties / year / exclusiveMinimum
      Added value: +0
    • removedInput schema / properties / startDate_lesser / properties / year / minimum
      Removed value: --9007199254740991
    • addedOutput schema / properties / results / properties / media / items / properties / id / exclusiveMinimum
      Added value: +0
    • changedOutput schema / properties / results / properties / media / items / properties / id / maximum
      Previous value: -9007199254740991New value: +2147483647
    • removedOutput schema / properties / results / properties / media / items / properties / id / minimum
      Removed value: --9007199254740991
  4. Changed3 schema fields changedv0.4.0
    • changedInput schema / properties / genres / description
      Previous value: -"Restrict to entries matching ALL of these genre names (see get_genres)."New value: +"Restrict to entries matching ALL of these genre names (see get_genres for valid names) — an unrecognized genre name doesn't error, it just filters out all results, same silent-mismatch behavior as `format_in`/`tag_in` below."
    • changedInput schema / properties / tag_in / description
      Previous value: -"Restrict to entries matching ALL of these exact tag names (see get_media_tags for valid names — unlike `genres`, tag names are case-sensitive and more specific, e.g. \"Time Loop\" or \"Tragedy\")."New value: +"Restrict to entries matching ALL of these exact tag names (see get_media_tags for valid names — unlike `genres`, tag names are case-sensitive and more specific, e.g. \"Time Loop\" or \"Tragedy\"). An unrecognized tag name doesn't error, it just silently matches nothing (same behavior as `genres`/`format_in` above, confirmed live)."
    • addedOutput schema / properties / results / properties / media / items / description
      Added value: +"Only `id` is guaranteed here — the real object has more fields, but their shape depends on which variant of an underlying union type this is (e.g. which activity type), so only the field common to every variant is declared."
  5. Addedv0.3.0
  6. Removedv0.2.0
  7. Addedv0.2.0

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds behavior annotations don't carry: adult/NSFW results are included by default unless `sfw: true` or `isAdult: false`, and `isAdult: true` inverts it — a genuine safety and result-set fact. It also notes exclusion-variant filters and the ranking browse mode, all beyond readOnly/openWorld hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the primary search mode, then the browse fallback, then the adult-content default, then the return type. The parentheticals are dense but each clause carries a distinct decision-relevant fact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 39 parameters, a full input schema, an output schema, and annotations, the description covers the decisions the schema can't: which mode to use, what the safety default is, and what the tool hands back. Nothing an agent needs before calling is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description still adds value by tying `sort` to the term-less browse case and explaining the sfw/isAdult equivalence, which spans two parameters. It doesn't survey the other 35 filter params, but the schema already documents those thoroughly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ("Search AniList for anime or manga") and covers both modes: title/filter search and term-less ranking browse. It also distinguishes itself from the ID-based siblings by noting it returns AniList IDs consumed by get_media, so an agent can place it in the workflow without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to browse term-less via `sort` when you have no title, and points to get_media for a single title's synopsis and get_genres/get_media_tags for valid filter names. What's missing is a direct statement of when to prefer search_media over get_media for a lookup, but the routing is otherwise clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.