Skip to main content
Glama
Ukenn2112

Bangumi TV MCP Service

by Ukenn2112

search_persons

Find individuals, corporations, or associations on Bangumi with specific career filters like producer, mangaka, or actor. Use pagination for precise results.

Instructions

Search for persons or companies on Bangumi.

Supported Person Types (integer enum in result):
1: Individual, 2: Corporation, 3: Association

Supported Career Filters (string enum):
'producer', 'mangaka', 'artist', 'seiyu', 'writer', 'illustrator', 'actor'

Args:
    keyword: The search keyword.
    limit: Pagination limit. Defaults to 30.
    offset: Pagination offset. Defaults to 0.
    career_filter: Optional filter by person career (list of strings from PersonCareer enum).

Returns:
    Formatted search results or an error message.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
career_filterNo
keywordYes
limitNo
offsetNo

Implementation Reference

  • The primary handler function implementing the 'search_persons' MCP tool. It performs a POST request to the Bangumi API /v0/search/persons endpoint with keyword and optional career filters, handles errors, formats results using format_person_summary helper, and returns a formatted string summary.
    @mcp.tool()
    async def search_persons(
        keyword: str,
        limit: int = 30,
        offset: int = 0,
        career_filter: Optional[List[PersonCareer]] = None,
    ) -> str:
        """
        Search for persons or companies on Bangumi.
    
        Supported Person Types (integer enum in result):
        1: Individual, 2: Corporation, 3: Association
    
        Supported Career Filters (string enum):
        'producer', 'mangaka', 'artist', 'seiyu', 'writer', 'illustrator', 'actor'
    
        Args:
            keyword: The search keyword.
            limit: Pagination limit. Defaults to 30.
            offset: Pagination offset. Defaults to 0.
            career_filter: Optional filter by person career (list of strings from PersonCareer enum).
    
        Returns:
            Formatted search results or an error message.
        """
        json_body = {"keyword": keyword, "filter": {}}
        if career_filter:
            # Ensure string values for the API call using the enum values
            formatted_careers = [
                c.value if isinstance(c, PersonCareer) else str(c) for c in career_filter
            ]
            json_body["filter"]["career"] = formatted_careers  # Filter is in JSON body
    
        params = {"limit": limit, "offset": offset}  # Query parameters for the POST request
    
        response = await make_bangumi_request(
            method="POST",
            path="/v0/search/persons",
            query_params=params,
            json_body=json_body,
        )
    
        error_msg = handle_api_error_response(response)
        if error_msg:
            return error_msg
    
        # Expecting a dictionary with 'data' and 'total'
        if not isinstance(response, dict) or "data" not in response:
            return f"Unexpected API response format for search_persons: {response}"
    
        persons = response.get("data", [])
        if not persons:
            return f"No persons found for keyword '{keyword}'."
    
        formatted_results = [format_person_summary(p) for p in persons]
        total = response.get("total", 0)
        results_text = (
            f"Found {len(persons)} persons (Total matched: {total}).\n"
            + "---\n".join(formatted_results)
        )
    
        return results_text
  • Helper function used by search_persons to format individual person data into a readable summary string, including type, career, summary, and image.
    def format_person_summary(person: Dict[str, Any]) -> str:
        """Formats a person dictionary into a readable summary string."""
        person_id = person.get("id")
        name = person.get("name")
        person_type = person.get("type")  # Integer enum
        career = person.get("career")  # List of string enums
        summary = person.get("short_summary") or person.get("summary", "")
    
        try:
            type_str = (
                PersonType(person_type).name if person_type is not None else "Unknown Type"
            )
        except ValueError:
            type_str = f"Unknown Type ({person_type})"
    
        formatted_string = f"[{type_str}] {name} (ID: {person_id})\n"
        if career:
            formatted_string += f"  Career: {', '.join(career)}\n"
        if summary:
            formatted_summary = summary  # [:200] + '...' if len(summary) > 200 else summary
            formatted_string += f"  Summary: {formatted_summary}\n"
    
        images = person.get("images")
        if images and images.get("common"):
            formatted_string += f"  Image: {images.get('common')}\n"
    
        return formatted_string
  • main.py:77-90 (schema)
    Enum defining supported career types used as input filter for search_persons tool, providing schema/validation for career_filter parameter.
    class PersonCareer(str, Enum):
        """
        Career of a person
        'producer', 'mangaka', 'artist', 'seiyu', 'writer', 'illustrator', 'actor'
        """
    
        PRODUCER = "producer"
        MANGAKA = "mangaka"
        ARTIST = "artist"
        SEIYU = "seiyu"
        WRITER = "writer"
        ILLUSTRATOR = "illustrator"
        ACTOR = "actor"
  • main.py:66-75 (schema)
    Enum defining person types returned by the API, used in formatting and validation within search_persons.
    class PersonType(IntEnum):
        """
        type of a person or company
        1 = 个人, 2 = 公司, 3 = 组合
        """
    
        INDIVIDUAL = 1
        CORPORATION = 2
        ASSOCIATION = 3
  • Core helper function used by search_persons to make authenticated HTTP requests to the Bangumi API, with comprehensive error handling.
    async def make_bangumi_request(
        method: str,
        path: str,
        query_params: Optional[Dict[str, Any]] = None,
        json_body: Optional[Dict[str, Any]] = None,
        headers: Optional[Dict[str, str]] = None,
    ) -> Any:
        """Make a request to the Bangumi API with proper headers and error handling."""
        request_headers = headers.copy() if headers else {}
        request_headers["User-Agent"] = USER_AGENT
        request_headers["Accept"] = "application/json"
    
        if BANGUMI_TOKEN:
            request_headers["Authorization"] = f"Bearer {BANGUMI_TOKEN}"
    
        url = f"{BANGUMI_API_BASE}{path}"
    
        async with httpx.AsyncClient() as client:
            try:
                print(
                    f"DEBUG: Making {method} request to {url} with params={query_params}, json={json_body}"
                )
                response = await client.request(
                    method=method,
                    url=url,
                    params=query_params,
                    json=json_body,
                    headers=request_headers,
                    timeout=30.0,
                )
                response.raise_for_status()
                # Return the raw JSON response, let the calling tool handle its structure (dict or list)
                json_response = response.json()
                print(
                    f"DEBUG: Received response (type: {type(json_response)}, keys/length: {list(json_response.keys()) if isinstance(json_response, dict) else len(json_response) if isinstance(json_response, list) else 'N/A'})"
                )
                return json_response
            except httpx.HTTPStatusError as e:
                error_msg = (
                    f"HTTP error occurred: {e.response.status_code} - {e.response.text}"
                )
                print(f"ERROR: {error_msg}")
                # Try to parse the error response body if it's JSON
                try:
                    error_details = e.response.json()
                    return {
                        "error": error_msg,
                        "status_code": e.response.status_code,
                        "details": error_details,
                    }
                except json.JSONDecodeError:
                    return {
                        "error": error_msg,
                        "status_code": e.response.status_code,
                        "details": e.response.text,
                    }
            except httpx.RequestError as e:
                error_msg = f"An error occurred while requesting {e.request.url!r}: {e}"
                print(f"ERROR: {error_msg}")
                return {"error": error_msg}
            except Exception as e:
                error_msg = f"An unexpected error occurred: {e}"
                print(f"ERROR: {error_msg}")
                return {"error": error_msg}
Behavior3/5

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

With no annotations provided, the description carries full burden. It discloses that the tool returns formatted search results or error messages, and mentions pagination behavior through limit/offset parameters. However, it doesn't cover important behavioral aspects like rate limits, authentication requirements, or what happens with invalid inputs.

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

Conciseness4/5

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

The description is well-structured with clear sections for purpose, supported types, career filters, arguments, and returns. It's appropriately sized with no wasted sentences, though the career filter list could be slightly more concise.

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

Completeness3/5

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

For a search tool with 4 parameters, no annotations, and no output schema, the description provides good parameter documentation but lacks important context. It doesn't explain result format details, error conditions, or how results are ordered. The mention of 'formatted search results' is vague without an output schema.

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

Parameters5/5

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

The description adds significant value beyond the input schema, which has 0% description coverage. It explains the meaning of career_filter with a complete list of valid values, clarifies that keyword is the search term, and explains that limit/offset are for pagination with their defaults. This fully compensates for the schema's lack of descriptions.

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

Purpose4/5

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

The description clearly states the tool searches for persons or companies on Bangumi, providing a specific verb ('search') and resource ('persons or companies'). However, it doesn't explicitly differentiate from sibling tools like search_characters or search_subjects, which search different entity types.

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

Usage Guidelines2/5

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

No guidance is provided about when to use this tool versus alternatives like search_characters or search_subjects. The description mentions what the tool does but offers no context about appropriate use cases or exclusions.

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

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ukenn2112/BangumiMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server