tmdb-scrape — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited tmdb-scrape (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
用这个 skill 通过 tmdb-media MCP server 给本地影视库处理 TMDB 元数据。整体体验类似 tinyMediaManager(tmm),但更保守:默认 dry-run、默认不覆盖、执行前必须经用户二次确认。
有两种模式,区别在「动不动真实视频文件」——务必先想清楚用户要哪种:
metadata.json / metadata.md,不动视频。工具:plan_scrape → write_artifacts。见下面〈sidecar 工作流〉。
Season N/、写tvshow.nfo + 分集 NFO、下载 poster/fanart/剧照,会重命名/移动真实视频。 工具:plan_organize → apply_organize(+ undo_organize 回滚)。见下面〈organize 工作流〉。
这个 MCP server 暴露 12 个工具:get_capabilities、scan_media_files、search_tmdb、 get_tmdb_metadata、get_trending、get_recommendations、get_similar、plan_scrape、 write_artifacts、plan_organize、apply_organize、undo_organize。其中 write_artifacts / apply_organize / undo_organize 是破坏性(destructive)操作;其余 均为只读。
get_trending、get_recommendations、get_similar 是只读的「发现/挑片」工具,不动任何文件:
get_trending({ type, window?, language? }) — 趋势(window 为 day / week,默认 week)。get_recommendations({ type, tmdb_id, language? }) — 某作品的推荐。get_similar({ type, tmdb_id, language? }) — 与某作品相似的作品。用户问「最近有什么好看的 / 帮我挑片 / 和这部类似的还有啥」时用它们浏览候选;要继续刮削或 整理某部具体作品时,再走下面的 sidecar / organize 工作流。
选哪种模式? 用户说「写元数据 / sidecar / metadata.json / 不要动我的文件」→ 模式①。 用户说「整理 / organize / 像 Jellyfin/Kodi/tmm 那样 / 重命名 / 分季文件夹 / 生成 NFO」 → 模式②。拿不准就直接问用户要不要重命名/移动视频。
library(库名)+ 可选 subpath(相对路径),绝不传绝对路径。绝对路径既不需要也不被接受。
plan_*(只规划、不动磁盘)→ 把计划讲给用户看 →用户确认后 → write_artifacts / apply_organize(都需 plan_id + expected_plan_hash)。
run_id,可用undo_organize 整次回滚。
get_capabilities不带参数调用。它会告诉你:
libraries — 有哪些库可用、各自类型(movie / tv)。这是唯一可写的根。defaultLanguage / fallbackLanguage — 默认语言(通常 zh-CN)。formats — 支持的 sidecar 格式(json、markdown)。minConfidence — 自动写入所需的最低置信度阈值。videoExtensions — 识别为视频的扩展名(.mkv、.mp4、.avi、.mov、.m4v、.wmv、.ts)。attribution — TMDB 署名文本(展示数据时应保留)。不知道库名时不要瞎猜——先看这里。
scan_media_files 列文件(分页)参数:{ library, subpath?, cursor?, limit? }。
cursor(默认 0)+ limit(默认 200,最大 1000)分页;返回里有 nextCursor /hasMore,据此翻页。
existingArtifacts:已有 sidecar 的文件默认不会被覆盖。warnings。relPath 与父目录名做初步判断。search_tmdb({ title, type, year?, language? }) 找候选;type 为 movie 或 tv。get_tmdb_metadata({ type, tmdb_id, language? })核对简介、年份、原名,或者直接问用户。不要在不确定时硬猜。
像 01.mp4、E01.mkv、被改过名的文件夹这种情况,自动匹配会失败或不可靠。 此时:先让用户确认这是哪部作品,拿到 TMDB id 后,用 plan_scrape 的 tmdb_id 参数强制匹配,例如 "tv:272432"(也接受纯 "272432")。这就是「强制锁定作品」的做法。
plan_scrape(只规划,不写)参数:{ library, subpath?, tmdb_id?, formats?, min_confidence?, overwrite?, language? }。
返回 { plan_id, expected_plan_hash, matched_files, targets, skipped, note }。其中 targets 列出每条计划:写到哪个目录 dir、命中作品 title / year / tmdb_id、 confidence、是否人工 overridden,以及 files(含 existsBefore 表示是否已存在)。
把 targets 完整讲给用户看:将写哪些文件、各自命中哪部作品、置信度多少、有没有 已存在文件会被影响。让用户核对无误。
write_artifacts参数:{ plan_id, expected_plan_hash },必须用上一步返回的那一对。
PLAN_STALE——说明计划已过期,重新 plan_scrape 即可。plan_scrape 时显式传了 overwrite: true,否则绝不覆盖已有 sidecar。何时用:用户想把一个电影或剧集文件夹整理成 tinyMediaManager / Jellyfin / Kodi 那种规整布局 ——重命名文件夹为 <title> (<year>),按类型生成 NFO + 下载 poster/fanart(剧集还会把每集移进 Season N/、生成 tvshow.nfo + 分集 NFO + 剧照)。关键词:整理、organize、Jellyfin、Kodi、tmm、 重命名、分季文件夹、NFO、海报。
最高优先级红线:organize 会重命名文件夹、移动并重命名真实视频文件。plan_organize只是规划、不动磁盘;真正动文件的是apply_organize。绝不在没把计划念给用户、没拿到 用户明确确认之前调用apply_organize。
organize 同时支持电影和剧集。tmdb_id必填,接受movie:603/tv:272432/ 裸272432(裸 id 默认按 tv 处理): - 剧集:文件夹改名为<title> (<year>),每集移进Season N/<title> - SxxExx - <标题>, 写tvshow.nfo+ 分集 NFO,下 poster/fanart/剧照。 - 电影:把文件夹和主视频都重命名为<title> (<year>)(如片名 (年份).mkv),写movie.nfo,下 poster/fanart——没有 Season 文件夹、没有分集。
get_capabilities + scan_media_files和 sidecar 一样:先 get_capabilities 确认库与语言,再 scan_media_files 列出该文件夹的视频文件。
search_tmdb / get_tmdb_metadata 找到正确作品,拿到其 TMDB id;电影用 movie:<id>、剧集用 tv:<id>(裸 id 默认按 tv 处理,电影务必加 movie: 前缀)。
organize 不做自动匹配,tmdb_id 本来就必填,所以务必确认正确。
plan_organize(只规划,不动文件)参数:{ library, subpath, tmdb_id, language?, images?, overwrite? }。tmdb_id 用 movie:603(电影)或 tv:272432(剧集);裸 id 默认按 tv 处理。 (images 默认 true 会下图;overwrite 默认 false 不覆盖已有 NFO/图片。)
返回 { plan_id, expected_plan_hash, show_folder_rename, seasons, moves, nfo_count, image_count, unmatched, note }:
show_folder_rename — 文件夹将从 from 改名成 to(如 低智商犯罪 → 低智商犯罪 (2024))。seasons / moves — 会建哪些季目录、每集视频将移动/重命名到哪个新路径(电影没有季目录,moves 仅把主视频重命名为 片名 (年份).<ext>)。
nfo_count / image_count — 将写多少 NFO、下多少图片(电影是 movie.nfo,剧集是 tvshow.nfo + 分集 NFO)。unmatched — 没能对上分集的文件(不会被移动)。把文件夹改名和每集移动一条条讲给用户,并明确说明这会重命名 / 移动真实视频文件, 不是只写旁车。让用户核对 show_folder_rename、moves、unmatched 后明确同意再继续。
apply_organize参数:{ plan_id, expected_plan_hash },必须用第 3 步返回的那一对。
PLAN_STALE——计划过期,重新 plan_organize。run_id——记下来,用于回滚。undo_organize 回滚参数:{ run_id },用上一步返回的 run_id。会把视频移回原名、删除新建的 Season 目录与 写入的 NFO/图片、把文件夹名改回去。出问题或用户反悔时用它整次回滚。
library + subpath,绝不传绝对路径。plan_organize → 把改名/移动念给用户 → 用户明确确认 → apply_organize;出问题用 undo_organize 整次回滚。绝不未经 确认直接 apply_organize。
overwrite: true。tmdb_id 强制锁定作品。plan_scrape→write_artifacts 或plan_organize→apply_organize)。
TMDB_ACCESS_TOKEN / TMDB_API_KEY),不要打印或回显。示例 1:常规刮削一个剧集文件夹
用户:帮我刮削 tv 库里的《庆余年》文件夹。
get_capabilities 确认有 tv 库、默认语言。scan_media_files({ library: "tv", subpath: "庆余年" }) 列文件,看 existingArtifacts。search_tmdb({ title: "庆余年", type: "tv" }) 找候选;必要时 get_tmdb_metadata 核对。plan_scrape({ library: "tv", subpath: "庆余年" }),把 targets 念给用户听。write_artifacts({ plan_id, expected_plan_hash })。示例 2:混淆名 / 纯数字集号,强制锁定作品
用户:这个全是 01.mp4 02.mp4 的文件夹是《低智商犯罪》,tmdb id 272432,帮我写元数据。get_capabilities 看一眼库与语言。plan_scrape({ library: "tv", subpath: "<那个文件夹>", tmdb_id: "tv:272432" })——用 tmdb_id 强制,绕过不可靠的自动匹配。
write_artifacts({ plan_id, expected_plan_hash })。示例 3:识别 / 修正错配的文件夹
用户:我 movie 库里有个文件夹不知道是啥,也可能配错了,帮我看看。
get_capabilities + scan_media_files 列出文件。search_tmdb 找候选;用 get_tmdb_metadata 比对简介、年份。plan_scrape(必要时用 tmdb_id 强制正确作品;要覆盖旧 sidecar 才传overwrite: true)→ 复述 targets → write_artifacts。
示例 4:organize——把剧集文件夹整理成 Jellyfin 式(会动真实视频)
用户:把 tv 库里的《低智商犯罪》文件夹整理成 Jellyfin 格式,tmdb 272432。
get_capabilities 确认 tv 库与语言,scan_media_files({ library: "tv", subpath: "低智商犯罪" }) 列文件。plan_organize({ library: "tv", subpath: "低智商犯罪", tmdb_id: "272432" })。低智商犯罪 → 低智商犯罪 (2024),每集移到 Season 1/低智商犯罪 - S01E01 - ….mkv 等,将写 N 个 NFO、下 M 张图——并明确告诉用户这会重命名、移动真实视频文件。列出 unmatched(如有)。
apply_organize({ plan_id, expected_plan_hash }),记下返回的 run_id。undo_organize({ run_id }) 整次回滚。示例 5:organize——把电影文件夹整理成 Jellyfin 式(会动真实视频)
用户:把 movie 库里这个《搏击俱乐部》文件夹整理成 Jellyfin 格式,tmdb 603。
get_capabilities 确认 movie 库与语言,scan_media_files({ library: "movies", subpath: "<那个文件夹>" }) 列文件。movie: 前缀:plan_organize({ library: "movies", subpath: "<那个文件夹>", tmdb_id: "movie:603" })。搏击俱乐部 (1999)(如 搏击俱乐部 (1999).mkv),写 movie.nfo、下 poster/fanart,没有季目录、没有分集——并明确告诉用户这会重命名/移动真实视频文件。
apply_organize({ plan_id, expected_plan_hash }),记下返回的 run_id。undo_organize({ run_id }) 整次回滚。示例 6:挑片/发现(只读,不动文件)
用户:最近有什么热门电影?和《盗梦空间》类似的还有啥?
get_trending({ type: "movie" }) 看本周热门(要当日热度就 window: "day")。get_similar({ type: "movie", tmdb_id: "27205" }) 或 get_recommendations(...) 取相似/推荐候选,念给用户挑。~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.