Media Scraper Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Media Scraper Mcp (MCP Server) 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.
TypeScript/Node implementation of the TMDB local media metadata tool described in docs/spec-tmdb-media.md.
Current status: iteration 1 (read-only pipeline) in progress, building on the parser benchmark spike. It does not write media metadata, rename files, move files, delete files, or touch a media library.
The iteration provides these read-only commands:
scan — discover media files under a configured library root.search — query TMDB for candidate matches.match — score and rank candidates against a parsed file.details — fetch canonical metadata for a chosen candidate.scrape --dry-run — run the full pipeline and report what would be written,without writing anything to the media library.
corepack pnpm install
corepack pnpm benchmark:parser
corepack pnpm test
corepack pnpm typecheckParse one filename or path:
corepack pnpm exec tsx src/cli.ts parse "/Volumes/Media/TV/庆余年/Season 1/第01集.mkv" --jsonThe fixture at tests/fixtures/parser-samples.json currently shows:
The enhanced parser layers Chinese season/episode handling and parent-directory title inference on top of parse-torrent-title. Known-hard cases are also tracked in the fixture but do not gate the command.
本项目有两种用法:CLI(你在终端手动跑)和 MCP(AI 客户端如 Claude Code / Codex 通过对话调用)。两者底层是同一套管线。
刮削分两种模式,区别在「动不动真实视频文件」:
| 模式 | 做什么 | 动视频吗 | CLI | MCP 工具 |
|---|---|---|---|---|
| ① 轻量 sidecar | 在视频旁边写 metadata.json / metadata.md | 不动,只新增旁车文件 | scrape | plan_scrape → write_artifacts |
| ② 完整 organize | tinyMediaManager / Jellyfin 式整理:重命名文件夹、把分集移进 Season N/、写 tvshow.nfo + 分集 NFO、下载 poster/fanart/剧照 | 会重命名/移动真实视频 | organize(+ undo) | plan_organize → apply_organize(+ undo_organize) |
两种模式都很保守:默认 dry-run、默认不覆盖、执行前需二次确认;organize 还可整次回滚。
CLI 既能用源码跑(corepack pnpm exec tsx src/cli.ts <cmd>),也能 build 后用 node dist/cli.js <cmd>。下面用配置示例里的库名 movies / tv 举例。
# 列出某库(或子目录)的视频文件(只读)
node dist/cli.js scan -l tv -s "庆余年"
# 搜 TMDB 候选
node dist/cli.js search "庆余年" -t tv
node dist/cli.js search "盗梦空间" -t movie -y 2010
# 取某 TMDB id 的规范元数据
node dist/cli.js details tv 272432
node dist/cli.js details movie 27205 --language zh-CN
# 发现/挑片(只读):趋势、推荐、相似
node dist/cli.js trending movie # 本周热门电影(默认 week)
node dist/cli.js trending tv -w day # 当日热门剧集
node dist/cli.js recommend movie 27205 # 与某电影相关的推荐
node dist/cli.js similar tv 272432 --language zh-CN # 与某剧集相似的作品
# 扫描 + 解析 + 匹配,看会命中什么(只读,不写)
node dist/cli.js match -l tv -s "庆余年"
node dist/cli.js match -l tv -s "某改名文件夹" --tmdb-id tv:272432 # 强制锁定作品
# 模式①:sidecar 刮削。默认 DRY-RUN,加 --yes 才真正写
node dist/cli.js scrape -l tv -s "庆余年" # dry-run,看会写什么
node dist/cli.js scrape -l tv -s "庆余年" --yes # 真正写出 metadata.json/.md
node dist/cli.js scrape -l tv -s "某文件夹" --tmdb-id tv:272432 --yes # 强制作品后写
node dist/cli.js scrape -l tv -s "庆余年" --yes --overwrite # 覆盖已有 sidecar(先备份 .bak.<ts>)
# 模式②:organize(Jellyfin 式整理,会重命名/移动真实视频)。默认 DRY-RUN
# 同时支持电影和剧集:--tmdb-id 接受 movie:603 / tv:272432 / 裸 id(默认 tv)
node dist/cli.js organize -l tv -s "低智商犯罪" --tmdb-id 272432 # 剧集 dry-run:打印改名 + 每集移动
node dist/cli.js organize -l tv -s "低智商犯罪" --tmdb-id 272432 --yes # 剧集真正执行,打印 run-id
node dist/cli.js organize -l tv -s "低智商犯罪" --tmdb-id 272432 --yes --no-images # 不下图片
node dist/cli.js organize -l tv -s "低智商犯罪" --tmdb-id 272432 --yes --overwrite # 覆盖已有 NFO/图片
node dist/cli.js organize -l movies -s "某电影文件夹" --tmdb-id movie:603 # 电影 dry-run
node dist/cli.js organize -l movies -s "某电影文件夹" --tmdb-id movie:603 --yes # 电影真正执行
# 回滚一次 organize(用 organize --yes 打印的 run-id)
node dist/cli.js undo <run-id>关键点:
scrape / organize 默认都是 dry-run,必须显式 --yes 才动磁盘。organize 同时支持电影和剧集;--tmdb-id 必填,接受 movie:603 / tv:272432 / 裸 272432(裸 id 默认按 tv 处理)。片名 (年份),每集移进 Season N/片名 - SxxExx - 标题,写 tvshow.nfo + 分集 NFO,下 poster/fanart/剧照。片名 (年份)(如 片名 (年份).mkv),写 movie.nfo,下 poster/fanart——没有 Season 文件夹、没有分集。organize --yes 都会落一个 run-id,可用 undo <run-id> 整次回滚(移回视频、删除新建的 Season 目录与 NFO/图片、把文件夹名改回去)。-l/--library 库名 + -s/--subpath 相对子路径。MCP server 跑的是编译后的 dist/cli.js mcp,共暴露 12 个工具:
| 工具 | 作用 | 破坏性 |
|---|---|---|
get_capabilities | 列出库、默认/回退语言、支持格式、minConfidence、视频扩展名、TMDB 署名 | 否(只读) |
scan_media_files | 分页列出某库的视频文件(含 existingArtifacts) | 否(只读) |
search_tmdb | 按标题(可带年份)搜 TMDB 候选 | 否(只读) |
get_tmdb_metadata | 取某 TMDB id 的规范元数据 | 否(只读) |
get_trending | 取趋势:{ type, window?(day/week,默认 week), language? },挑片/发现用 | 否(只读) |
get_recommendations | 取某 TMDB id 的推荐:{ type, tmdb_id, language? } | 否(只读) |
get_similar | 取某 TMDB id 的相似作品:{ type, tmdb_id, language? } | 否(只读) |
plan_scrape | 模式① 规划 sidecar 写入(不写),返回 plan_id + expected_plan_hash | 否(只读) |
write_artifacts | 模式① 按计划写出 sidecar,需 plan_id + expected_plan_hash | 是(destructive) |
plan_organize | 模式② 规划 Jellyfin 式整理(电影 / 剧集均可,tmdb_id 接受 movie:603 / tv:272432 / 裸 id),不动文件,返回 plan_id + expected_plan_hash | 否(只读) |
apply_organize | 模式② 执行整理:重命名/移动视频 + 写 NFO + 下图片,需 plan_id + expected_plan_hash,落 run_id | 是(destructive,动真实视频!) |
undo_organize | 按 run_id 整次回滚一次 apply_organize | 是(destructive) |
plan_scrape({ library, subpath?, tmdb_id?, ... }) 规划,返回 plan_id、expected_plan_hash 和 targets(将写哪些文件、命中哪部作品、置信度)。不写任何文件。targets 念给用户看,等用户核对。write_artifacts({ plan_id, expected_plan_hash }) 原子写出(hash 不符会报 PLAN_STALE,重新 plan 即可)。plan_organize({ library, subpath, tmdb_id, images?, overwrite? }) 规划,返回 plan_id、expected_plan_hash、show_folder_rename(文件夹改名)、seasons、moves(每集要移到哪)、NFO/图片数量、unmatched。不动任何文件。tmdb_id 同时支持电影和剧集,接受 movie:603 / tv:272432 / 裸 272432(裸 id 默认 tv);电影布局只把文件夹+主视频重命名为「片名 (年份)」并写 movie.nfo + poster/fanart(无 Season 文件夹、无分集)。apply_organize({ plan_id, expected_plan_hash }) 执行,返回一个 run_id。undo_organize({ run_id }) 整次回滚。安全红线:root 由配置固定,只传library+subpath,绝不传绝对路径;organize 因为动真实文件,必须 plan → 给用户看 → 确认 → apply,必要时 undo;纯数字集号 / 被改名的文件夹用tmdb_id(如"tv:272432")强制锁定作品。
# 1. 安装依赖并构建(MCP / dist 用法都需要先 build)
corepack pnpm install
corepack pnpm build
# 2. 配置 config.toml(参考 config.example.toml,填好每个库的 root 与 type)
cp config.example.toml config.toml
# 3. 设置 TMDB 凭据(环境变量,不要写进配置文件)
export TMDB_ACCESS_TOKEN="<your-tmdb-v4-read-access-token>"库根目录在配置里固定,AI / MCP 调用方只传库名 + 相对子路径,绝不传绝对路径。
方式 A:项目级 .mcp.json(已提供示例,把占位 token 换成你自己的):
{
"mcpServers": {
"tmdb-media": {
"command": "node",
"args": ["dist/cli.js", "mcp"],
"env": {
"TMDB_ACCESS_TOKEN": "<your-tmdb-v4-read-access-token>",
"TMDB_MEDIA_CONFIG": "config.toml"
}
}
}
}方式 B:命令行一键添加:
claude mcp add tmdb-media -- node dist/cli.js mcp随仓库还附带一个 Claude Code skill .claude/skills/tmdb-scrape/SKILL.md, 覆盖 sidecar 刮削和 organize 整理两套安全工作流,用户提到「刮削 / scrape / organize / Jellyfin / 重命名 / TMDB 元数据 / 识别媒体文件夹」等时会自动触发。
在 ~/.codex/config.toml 加:
[mcp_servers.tmdb-media]
command = "node"
args = ["dist/cli.js", "mcp"]
[mcp_servers.tmdb-media.env]
TMDB_ACCESS_TOKEN = "<your-tmdb-v4-read-access-token>"
TMDB_MEDIA_CONFIG = "config.toml"TMDB_ACCESS_TOKEN — TMDB v4 read access token(Bearer,优先)。TMDB_API_KEY — TMDB v3 api key(TMDB_ACCESS_TOKEN 缺失时的回退)。TMDB_MEDIA_CONFIG —(可选)config.toml 路径;不设则用 $XDG_CONFIG_HOME/tmdb-media/config.toml。TMDB_MEDIA_LOG_LEVEL —(可选)日志级别,默认 info。鉴权只走以上环境变量,不要写进配置文件,也不要在对话里打印 / 回显。
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.