JMComic Skill
This skill enables you to interact with JMComic (18comic), a popular manga platform, to search, browse, and download manga content.
When to Use This Skill
Activate this skill when the user wants to:
- Search for manga by keyword or category
- Browse popular manga rankings (daily, weekly, monthly)
- Read album-specific or site-wide comments and nested replies, including spoiler flags
- List favorite folders, browse saved albums, add an album to favorites, or delete an album from favorites
- Download entire albums or specific chapters (Returns structured dict with status, paths, and metadata)
- Get detailed information about a manga album
- Configure download settings (paths, concurrency, proxies)
- Post-process downloaded content (Zip, PDF, LongImage) with native parameters or
dir_rule - Download the latest Android APK published by
hect0x7/JMComic-APK - Run
jms --helpto obtain the current upstream options, then invokejmsdirectly for an existing or newly downloaded manga directory
For APK download, local-reader startup, LAN safety, and download-to-read continuation rules, read
references/ecosystem.md before acting.
📥 Download Tools Return Structured Data
Both download_album and download_photo return structured dictionaries:
download_album(album_id: str, ctx: Context = None) returns:
{
"status": "success" | "failed",
"album_id": str,
"title": str,
"download_path": str, # Absolute path to download directory
"duration": float | None, # Total elapsed time in seconds
"image_paths": list[str], # Actual downloaded or cached image paths
"export_files": dict[str, list[str]], # Plugin outputs grouped by suffix
"task_id": str, # Dedicated ID for this download invocation
"log_path": str, # Absolute path to this task's log file
"error": str | None
}
download_photo(photo_id: str, ctx: Context = None) returns:
{
"status": "success" | "failed",
"photo_id": str,
"image_count": int, # Number of actual image paths in this result
"download_path": str, # Absolute path to download directory
"duration": float | None, # Total elapsed time in seconds
"image_paths": list[str], # Actual downloaded or cached image paths
"export_files": dict[str, list[str]], # Plugin outputs grouped by suffix
"task_id": str, # Dedicated ID for this download invocation
"log_path": str, # Absolute path to this task's log file
"error": str | None
}
Real-time Progress Tracking: Both methods accept an optional ctx: Context parameter (automatically injected by FastMCP). When provided, progress updates are sent via MCP notifications in real-time, allowing AI agents to monitor download progress.
Persistent Task Logs: Every download invocation creates an isolated log file and returns its task_id and log_path, including failed downloads. Logs default to ~/.jmcomic-ai/logs; set JM_TASK_LOG_DIR to use another directory.
Artifact Handoff: Use image_paths and export_files for packaging, sending, or cleanup instead of rescanning the configured directory. download_path comes from the completed upstream download result rather than a pre-download path prediction.
File-only Logging: Regular jmcomic, jmcomic_ai, and MCP runtime logs share ~/.jmcomic-ai/jmcomic_ai.log and are not emitted to stdout or stderr. Set JM_LOG_PATH to override the global log file. MCP protocol messages and explicit CLI result output are unaffected.
Upstream Rich Terminal Progress: jmcomic 2.7.4 adds the optional download_progress plugin with log_file and terminal_log_lines. Recommend it only when the user explicitly wants Rich progress in an interactive terminal. Do not enable it for jmai MCP/stdio downloads, which already use MCP Context notifications and isolated task logs.
Album Comments
Use get_album_comments(album_id: str, page: int = 1) to read one page of comments. This is a read-only tool; it does not post comments or replies.
{
"album_id": str,
"page": int,
"page_size": int,
"total": int | None,
"page_count": int | None,
"comment_count": int,
"comments": [
{
"comment_id": str | None,
"album_id": str | None,
"user_id": str | None,
"parent_comment_id": str | None,
"content": str,
"username": str,
"nickname": str,
"is_spoiler": bool,
"created_at": object,
"likes": int | None,
"replies": [...] # Recursive nested replies
}
]
}
Use get_forum_comments(page: int = 1) for the latest site-wide comments. It returns the same comment objects and pagination fields without an album_id filter; each comment's own album_id identifies its source album. This is also read-only.
Favorites
All favorite tools require an authenticated client. Call login in the same MCP session or configure
valid cookies. For HTML queries authenticated only by Cookie, pass username; after login, it can
be omitted. The API client ignores username and always queries the current account. Separate script
processes need authentication in their configuration; they do not inherit an MCP session's login.
get_favorite_folders(username: str = "") returns:
{"folders": [{"id": str, "name": str}]}
The directory can be empty. Use folder_id="0" to browse all favorites even if this ID is absent
from the returned directory.
browse_favorite_albums(folder_id: str = "0", page: int = 1, order_by: str = "favorite_time", username: str = "") returns:
{
"albums": [{"id": str, "title": str, "tags": list, "cover_url": str}],
"total_count": int,
"page": int,
"folder_id": str,
"error": str # Present only for invalid page, folder ID, or sort parameters
}
Pagination starts at 1; folder_id="0" means all favorites. An empty result retains pagination and
folder metadata. order_by accepts favorite_time (default) and update_time; the favorites list has
its own upstream sort vocabulary, which differs from browse_albums. The service does not sort a page
locally. Invalid arguments return an empty list with error; authentication and request failures
propagate as tool errors, not empty collections.
add_favorite_album(album_id: str) returns:
{
"status": "success" | "error",
"album_id": str,
"title": str, # Album title
"message": str
}
album_id accepts a numeric ID, a JM-prefixed ID, or an album URL and is normalized when parsing
succeeds. The album is saved to the account's default favorites placement.
Adding an album that is already saved returns status="error" and leaves the saved state unchanged.
delete_favorite_album(album_id: str) returns the same fields and takes the same album_id forms.
Deleting an album that is not saved returns status="error" and leaves the saved state unchanged.
Both tools behave identically whichever client implementation the configuration selects, and both return
the album title. Name every affected album as title (ID); when title is empty or absent, reuse an
earlier search, browse, or detail result, or fetch the name with get_album_detail(album_id) or
python scripts/album_info.py --id ID.
Core Capabilities
🛠️ Post-Processing
This skill supports advanced post-processing of downloaded manga. It returns structured data including the output path of the generated file.
- 📦 Zip Compression: Pack an entire album or individual chapters into a ZIP file.
- 📄 PDF Conversion: Merge all images of an album into a single PDF document.
- 🖼️ Long Image Merging: Combine all pages of a chapter into one continuous long image.
post_process(album_id: str, process_type: str, params: dict = None) returns:
{
"status": "success" | "error",
"process_type": str, # Process type used
"album_id": str, # Album ID processed
"output_path": str, # Absolute path to generated file/directory (empty string on error)
"output_paths": list[str], # All files actually registered by the upstream plugin
"is_directory": bool, # True if output is a directory (e.g., photo-level zip), False on error
"message": str # Success/error message
}
All fields are always present. On error, output_path is empty, output_paths is empty, and is_directory is False.
Output Control: Use dir_rule (a {"rule": "DSL_STRING", "base_dir": "BASE_PATH"} dict) for custom output paths. If omitted, files are saved in the configured default directory. The DSL supports Bd (base_dir), Axxx/Pxxx album/photo attributes, and {attr} Python format placeholders. When looping over albums into one base_dir, include {Aid} or {Atitle} to avoid overwrites.
For the full set of ZIP/PDF/LongImg × album/photo dir_rule examples, see references/post_process.md.
This skill provides command-line utilities for JMComic operations. All utilities are Python scripts located in the scripts/ directory and should be executed using Python.
Data Structure Notes
Most search and browsing tools (e.g., search_album, browse_albums) return a consistent structure that supports pagination:
{
"albums": [ ... ],
"total_count": 1234
}
total_count provides the total number of items available across all pages, allowing you to calculate the number of remaining pages and decide if further searching is needed.
Important: Browse Albums Data Limitations
browse_albums is the unified tool for browsing albums by category, time_range, and order_by (ranking + category browsing in one interface). Its response is lightweight — each album has only id, title, tags, and cover_url, and no stats (likes/views/author). To get those, call get_album_detail(album_id) per album.
order_by accepts: latest (default), likes, views, pictures, score, comments. For the full enumeration, use-case recipes (rankings, category browsing, combined queries), and the "top 10 with details" workflow, see references/browse_albums.md.
Configuration Reference
For detailed configuration options, refer to:
references/reference.md: Human-readable configuration guideassets/option_schema.json: JSON Schema for validation
Common configuration examples:
# Change download directory
dir_rule:
base_dir: "/path/to/downloads"
rule: "Bd / Ptitle"
# Adjust concurrency
download:
threading:
image: 30 # Max concurrent image downloads
photo: 5 # Max concurrent chapter downloads
# Set proxy
client:
async_impl: async_api # Used by jmcomic native async APIs
cache: level_option # Reuse metadata across clients from this option
postman:
meta_data:
proxies:
http: "http://proxy.example.com:8080"
https: "https://proxy.example.com:8080"
# Or use system proxy
client:
postman:
meta_data:
proxies: system
# Configure login cookies
client:
postman:
meta_data:
cookies:
AVS: "your_avs_cookie_value"
# Use plugins
plugins:
after_album:
- plugin: zip
kwargs:
level: photo
suffix: zip
delete_original_file: true
Available Command-Line Tools
The scripts/ directory provides utility tools for common tasks. All tools support the --help flag for detailed usage. The table below summarizes each script; for full per-script examples and feature lists, see references/scripts.md.
| Script | Purpose |
|---|---|
doctor.py |
Environment diagnostics: Python version, deps, config status, network/domain checks. |
batch_download.py |
Download multiple albums from a list of IDs (CLI or file) with progress/error summary. |
download_photo.py |
Download specific chapters/photos without fetching whole albums. |
validate_config.py |
Validate option.yml and convert between YAML and JSON. |
search_export.py |
Search by keyword/ranking/category and export to CSV or JSON (multi-page). |
album_info.py |
Query detailed metadata for one or many albums; print or export to JSON. |
album_comments.py |
Fetch one page of album comments and recursive replies; print or export to JSON. |
forum_comments.py |
Fetch one page of site-wide comments with source album IDs; print or export to JSON. |
favorite_folders.py |
List favorite folders as JSON; supports --username, --output, and --option. |
favorite_albums.py |
Browse one page of favorites as JSON; supports folder, page, sort, and username filters. |
add_favorite_album.py |
Add one favorite and print its structured result as JSON; failures exit non-zero. |
delete_favorite_album.py |
Delete one favorite and print its structured result as JSON; failures exit non-zero. |
download_covers.py |
Batch download album cover images to a custom output directory. |
ranking_tracker.py |
Track day/week/month rankings over time; export snapshots with timestamps. |
post_process.py |
Convert downloads to ZIP/PDF/LongImg, with optional encryption and dir_rule DSL. |
download_latest_apk.py |
Download the latest APK published by hect0x7/JMComic-APK; supports optional output_dir, --force, and --json (run --help for current usage). |
Script Parameters ↔ MCP Tools Mapping
The following table clarifies how script CLI parameters map to MCP tools.
| Script | Target Tool | Mapping Level | Notes |
|---|---|---|---|
search_export.py |
search_album / browse_albums |
Partial | --keyword maps to search_album; --ranking / --category maps to browse_albums. Ranking is a convenience mode based on time_range + configurable sort, not a separate backend API. |
post_process.py |
post_process |
High | --id→album_id, --type→process_type, optional flags to params. --dir-rule + --base-dir map to params.dir_rule. |
album_info.py |
get_album_detail |
Partial | Batch wrapper over repeated single-album calls; output format is script-defined. |
album_comments.py |
get_album_comments |
High | --id maps to album_id, --page maps to page, and the JSON response preserves the MCP result shape. |
forum_comments.py |
get_forum_comments |
High | --page maps to page, and each returned comment preserves its source album_id. |
favorite_folders.py |
get_favorite_folders |
High | --username maps to username; JSON preserves the MCP result shape. |
favorite_albums.py |
browse_favorite_albums |
High | --folder-id, --page, --order-by, --username map to the corresponding tool arguments. |
add_favorite_album.py |
add_favorite_album |
High | --id maps to album_id; an error result exits non-zero. |
delete_favorite_album.py |
delete_favorite_album |
High | --id maps to album_id; an error result exits non-zero. |
download_covers.py |
download_cover |
Partial | Batch wrapper over repeated cover calls. |
ranking_tracker.py |
browse_albums |
Partial | Uses time-range/category browse semantics and exports snapshots. |
batch_download.py |
download_album |
Partial | Batch wrapper over repeated calls; prints each result's download path and dedicated log path. |
download_photo.py |
download_photo |
Partial | Batch wrapper over repeated calls; prints each result's download path and dedicated log path. |
validate_config.py |
update_option (adjacent) |
None | Validation/format conversion utility; not a direct MCP tool wrapper. |
download_latest_apk.py |
None | None | Reads the public hect0x7/JMComic-APK GitHub Release API directly. |
Mapping Policy
- MCP tools are the source of truth for agent-facing contracts (name, args, return structure).
- Scripts are operational helpers for local package workflows and may expose different output formatting.
- If strict schema guarantees are required, prefer calling MCP tools directly instead of scripts.
Important Notes
- Legal Compliance: Ensure you have the right to download content
- Rate Limiting: The platform may rate-limit requests; adjust threading if needed
- Storage: Downloads can be large; ensure sufficient disk space
- Configuration: Default config is at
~/.jmcomic/option.yml - Next action: After a successful manga download, offer to start the local reader for the returned
download_path. Start it automatically only when the user also asked to open, read, or view the result.
Troubleshooting
- Connection errors: Try updating the domain list in client config
- Slow downloads: Reduce threading concurrency
- Scrambled images: Ensure
download.image.decodeis set totrue