mal-mcp

mal-mcp

A Model Context Protocol server that provides access to MyAnimeList's API for anime and manga data. It enables users to search, view rankings, manage their personal lists, and get recommendations through Claude and other MCP clients.

Category
Visit Server

README

mal-mcp

A Model Context Protocol server that exposes the MyAnimeList v2 API to Claude and other MCP-compatible clients. Written in TypeScript, runs locally via Bun over stdio or deploys to Cloudflare Workers as a hosted multi-user server.

Tools

Setup

  • configurestdio only — store the user's MyAnimeList client_id (and client_secret if issued). Must be called before any other tool. Not registered on the Worker; on the Worker, each user signs in through the MCP OAuth flow when they add the server to their client.
  • authenticatestdio only (meaningful) — start the MAL OAuth flow; opens a browser and waits for the local callback. On the Worker this is a no-op kept for compatibility — auth happens automatically on connect via MCP OAuth.
  • get_auth_status — check whether credentials and user tokens are available.

Public (Client ID only)

  • search_anime — search anime by title
  • get_anime_details — full details for an anime ID
  • get_anime_ranking — ranked lists (all, airing, upcoming, tv, ova, movie, special, bypopularity, favorite)
  • get_seasonal_anime — anime by year + season
  • search_manga — search manga by title
  • get_manga_details — full details for a manga ID
  • get_manga_ranking — ranked lists (all, manga, novels, oneshots, doujin, manhwa, manhua, bypopularity, favorite)

User-scoped (OAuth2 access token required)

  • get_current_user — profile + anime statistics for the authenticated user
  • get_anime_suggestions — personalized anime recommendations
  • get_user_anime_list — read any user's public anime list (or @me)
  • update_anime_list_status — add / update list status, score, episodes watched, etc.
  • delete_anime_list_item — remove an anime from your list
  • get_user_manga_list — read any user's public manga list (or @me)
  • update_manga_list_status — add / update list status, score, chapters read, etc.
  • delete_manga_list_item — remove a manga from your list

Option 1: Run locally over stdio

1. Install

bun install

2. Wire it up to your MCP client

Add to claude_desktop_config.json (Windows: %APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "mal": {
      "command": "bun",
      "args": ["C:\\BrunoLM\\Projects\\mal-mcp\\src\\index.ts"]
    }
  }
}

For Claude Code, use claude mcp add or drop the equivalent block into .claude/mcp.json.

3. Configure your MAL credentials

Create an API client at https://myanimelist.net/apiconfig:

  • App Type: other / web
  • App Redirect URL: http://localhost:8765/callback

Then, from your MCP client, call the configure tool with your client_id (and client_secret if MAL issued one). Credentials are persisted to ~/.mal-mcp-config.json.

4. (Optional) Authorize for user-scoped tools

Call authenticate from your MCP client. A browser opens, you approve the request, the local server on port 8765 catches the redirect, and tokens land in ~/.mal-mcp-tokens.json. The server refreshes them automatically from there.

If you prefer a CLI:

$env:MAL_CLIENT_ID = "your-client-id"
# $env:MAL_CLIENT_SECRET = "your-client-secret"   # only if issued
bun run auth

Option 2: Host on Cloudflare Workers (multi-user, MCP OAuth)

A single Worker serves every user behind standard MCP OAuth 2.1 (Dynamic Client Registration). One URL for everyone: https://mal-mcp.<account>.workers.dev/mcp. During sign-in each user supplies their own MAL client_id (and client_secret if issued); per-user state lives in a Durable Object keyed by a hash of those credentials.

1. Operator setup (once)

bun install
bunx wrangler login
bunx wrangler kv namespace create OAUTH_KV

Paste the returned namespace id into wrangler.jsonc (replace REPLACE_WITH_KV_ID), then deploy:

bun run worker:deploy

For local development:

bunx wrangler kv namespace create OAUTH_KV --preview
bun run worker:dev

2. Each user connects

  1. Create a MAL API client at https://myanimelist.net/apiconfig (App Type: other). Set App Redirect URL to:

    https://mal-mcp.<account>.workers.dev/mal/callback
    

    (This exact URL — same for every user of a given deployment.)

  2. Add the MCP server to your client:

    claude mcp add --transport http mal https://mal-mcp.<account>.workers.dev/mcp
    

    Or equivalently in config:

    {
      "mcpServers": {
        "mal": {
          "url": "https://mal-mcp.<account>.workers.dev/mcp"
        }
      }
    }
    
  3. Your MCP client will pop a browser tab on first connect. The Worker's authorize page asks for your MAL client_id (and client_secret if issued), redirects you to MyAnimeList to approve, then returns you to your MCP client — now signed in. Access and refresh tokens are persisted in your Durable Object; the MAL access token is refreshed automatically.

Security notes for hosted deployments

  • The Worker is its own OAuth 2.1 authorization server for MCP. Bearer tokens issued to your MCP client are scoped to you; leaking one lets the bearer call MAL on your behalf until the token expires.
  • Different MAL credentials → different Durable Object → fully separate state. There is no cross-user shared state.
  • The Worker holds no MAL credentials of its own; each user supplies their own MAL API client.

Data storage

stdio

Two plaintext JSON files in your home directory, created with mode 0600 (owner read/write only):

File Contents
~/.mal-mcp-config.json Your MAL client_id and (if issued) client_secret.
~/.mal-mcp-tokens.json MAL access_token, refresh_token, and expires_at after authenticate.

Delete either file to reset the corresponding state. Nothing is sent anywhere besides myanimelist.net and api.myanimelist.net.

Hosted Worker

Two Cloudflare storage surfaces:

OAUTH_KV (Workers KV namespace) — used by @cloudflare/workers-oauth-provider and by the MAL authorize relay:

  • Registered OAuth clients (Dynamic Client Registration), authorization grants, and access/refresh tokens. The provider stores grant props encrypted; the encryption key is wrapped into the issued token itself, so KV snapshots alone are not enough to recover props.
  • Short-lived (10-minute TTL) pending-MAL-auth records keyed by a random state string. Each record holds the pending authorize URL, your MAL client_id/client_secret, the PKCE verifier, and the callback URL. Entries are deleted as soon as the MAL callback consumes them, or expire automatically otherwise. They are stored as plaintext JSON in KV.

MAL_SESSION (Durable Object, one per user) — keyed by u:<32-hex> where the hex is the first 32 chars of sha256("v1:" + mal_client_id + ":" + (mal_client_secret ?? "")). Stored as plaintext in the DO's SQLite storage (Cloudflare encrypts DO storage at rest on disk):

  • config: your MAL client_id and (if issued) client_secret.
  • tokens: MAL access_token, refresh_token, expires_at.

Two different MAL credential pairs produce two different hashes → two fully separate Durable Objects with no shared state.

What is not stored: anime/manga lists, user profile data, search results, or anything else returned from MAL — those flow straight through the request on demand. No analytics, no logs of request contents beyond standard Cloudflare observability metrics.

What travels over the wire: MAL client_id/client_secret are submitted as form fields from your browser to the authorize page over HTTPS. MAL access tokens are forwarded as Authorization: Bearer … to api.myanimelist.net.

Resetting a user's state: revoke the grant from your MCP client (or reconnect), or contact the operator to delete the matching Durable Object. Re-authorizing with the same MAL credentials will reuse the same DO and its existing tokens.

Environment variables (stdio only)

Variable Required Purpose
MAL_CLIENT_ID no Seeds the stdio config store on first boot if nothing is saved yet.
MAL_CLIENT_SECRET no Same, for clients that were issued a secret.
MAL_AUTH_PORT no Port the one-shot OAuth callback listens on (default 8765).

On hosted Worker deployments these env vars are not used; each end user supplies their own MAL credentials through the Worker's authorize page during MCP OAuth sign-in.

Development

bun run dev              # stdio, watch mode
bun run worker:dev       # Worker, local (miniflare)
bun run typecheck        # tsc --noEmit

All tools take an optional fields string that passes straight through to MAL — see the field spec if you need to override the defaults.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured