Skip to main content
Glama
Ukenn2112

Bangumi TV MCP Service

by Ukenn2112

get_subject_persons

Retrieve a formatted list of staff and cast members linked to a specific subject on Bangumi TV using its subject ID. Ideal for quickly accessing key contributors in anime, manga, music, or game content.

Instructions

List persons (staff, cast) related to a subject. Args: subject_id: The ID of the subject. Returns: Formatted list of related persons or an error message.

Input Schema

NameRequiredDescriptionDefault
subject_idYes

Input Schema (JSON Schema)

{ "properties": { "subject_id": { "title": "Subject Id", "type": "integer" } }, "required": [ "subject_id" ], "title": "get_subject_personsArguments", "type": "object" }

Implementation Reference

  • main.py:599-649 (handler)
    The core handler function decorated with @mcp.tool(), which registers and implements the get_subject_persons tool. It makes an API request to fetch related persons for a subject, processes the response using PersonType enum for typing, formats the output as a string list, and handles errors.
    @mcp.tool() async def get_subject_persons(subject_id: int) -> str: """ List persons (staff, cast) related to a subject. Args: subject_id: The ID of the subject. Returns: Formatted list of related persons or an error message. """ response = await make_bangumi_request( method="GET", path=f"/v0/subjects/{subject_id}/persons" ) error_msg = handle_api_error_response(response) if error_msg: return error_msg # Expecting a list of persons if not isinstance(response, list): return f"Unexpected API response format for get_subject_persons: {response}" persons = response if not persons: return f"No persons found related to subject ID {subject_id}." formatted_results = [] for person in persons: name = person.get("name") person_id = person.get("id") relation = person.get("relation") # e.g., "导演", "动画制作", "声优" career = ", ".join( person.get("career", []) or [] ) # person.get('career') could be None or empty list eps = person.get("eps") # Participation in episodes/tracks for THIS subject # Safely get person type name if available and is valid enum value person_type_int = person.get("type") person_type_str = "Unknown Type" if person_type_int is not None: try: person_type_str = PersonType(person_type_int).name except ValueError: person_type_str = f"Unknown Type ({person_type_int})" formatted_results.append( f"Person ID: {person_id}, Name: {name}, Type: {person_type_str}, Relation (in subject): {relation}, Overall Career: {career}, Participating Episodes/Tracks: {eps}" ) return "Related Persons:\n" + "\n---\n".join(formatted_results)
  • main.py:66-74 (schema)
    IntEnum defining PersonType used in the handler to categorize and label persons in the output (e.g., Individual, Corporation, Association). Serves as type definition/schema for output formatting.
    class PersonType(IntEnum): """ type of a person or company 1 = 个人, 2 = 公司, 3 = 组合 """ INDIVIDUAL = 1 CORPORATION = 2 ASSOCIATION = 3
  • MCP prompt that references and utilizes the 'get_subject_persons' tool as part of fetching full subject information.
    def get_subject_full_info(subject_id: int) -> str: """ Get detailed information, related persons, characters, and relations for a subject. Args: subject_id: The ID of the subject to get information for. """ return f"Get the full details for subject ID {subject_id} using 'get_subject_details'. Also get related persons using 'get_subject_persons', related characters using 'get_subject_characters', and other related subjects using 'get_subject_relations'. Summarize the key information from all these tool outputs."
  • Core helper function called by the handler to make authenticated HTTP requests to Bangumi API.
    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}
  • Helper function used by the handler to detect and format API errors into user-friendly strings.
    def handle_api_error_response(response: Any) -> Optional[str]: """ Checks if the API response indicates an error and returns a formatted error message. Handles both dictionary-based errors and returns from make_bangumi_request on failure. """ # Check for error structure returned by make_bangumi_request on HTTPStatusError or RequestError if isinstance(response, dict) and ( "error" in response or "status_code" in response ): # This is an error dictionary created by our helper status_code = response.get("status_code", "N/A") error_msg = response.get("error", "Unknown error during request.") details = response.get("details", "") return f"Bangumi API Request Error (Status {status_code}): {error_msg}. Details: {details}".strip() # Check for error structure returned by Bangumi API itself (often dictionaries) # Safely check if the response is a dictionary before accessing its keys if isinstance(response, dict): if "title" in response and "description" in response: # This looks like a common Bangumi error response structure error_title = response.get("title", "API Error") error_description = response.get("description", "No description provided.") # The API might return a status code in the body too, or rely on HTTP status return f"Bangumi API Error: {error_title}. {error_description}".strip() # Check if it's a dictionary but *not* empty and *doesn't* look like a success response from list endpoints # Check for specific error fields if structure varies # Add more checks here if other error dictionary formats are observed # Example: if "message" in response and "code" in response: return f"API Error {response['code']}: {response['message']}" pass # If it's a dictionary but doesn't match known error formats, assume it's a valid data response for now # If it's not a dictionary, or it's a dictionary that doesn't match known error formats, assume it's not an error return None

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