mcpField
M
myfigurecollection-api

myfigurecollection-api

本地服务
github.com/ssskay游戏娱乐34 周前更新

关于 myfigurecollection-api

myfigurecollection-api 是 Python 库和本地 MCP 服务,用于读取 MyFigureCollection.net 的公开数据。它解析公开页面,让 Agent 搜索手办和商店、查条码与商品列表,并读取收藏、用户列表和俱乐部信息。

主要功能

  1. 01搜索手办并查询条码
  2. 02读取商品详情和商店列表
  3. 03浏览收藏和用户列表
  4. 04获取俱乐部详情与成员
  5. 05通过 Python 库和 CLI 访问数据
  6. 06可选归档公开商品页面

适用场景

  1. 01查询手办的发售资料和规格
  2. 02查看合作商店的商品价格
  3. 03通过 JAN 或 UPC 条码查找商品
  4. 04查看用户收藏或俱乐部成员名单

MCP 相关

通过 stdio 在本地运行,并向 MCP 客户端提供 12 个读取 MyFigureCollection.net 数据的工具。它解析公开 HTML,而非依赖公开 API。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"ssskay-myfigurecollection-api": {
"command": "uvx",
"args": [
"myfigurecollection-api"
]
}
}
}
启动命令uvx myfigurecollection-api

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypimyfigurecollection-api0.1.1

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

myfigurecollection-api

安装: pip install myfigurecollection-api · 所有格式和校验和

非官方的 MyFigureCollection.net API:一个 Python 库和本地 MCP 服务,让 Agent 能读取手办数据、收藏、列表和社团。

MFC 没有可用的公共 API。它自己的 API 社团(#349) 八年来一直承诺“API v4 即将推出”。这个软件包改为读取公开的 HTML,并将其转换为类型化模型。

刚接触?简而言之

MyFigureCollection 是互联网上最大的动漫手办和周边目录,多年来一直没有方便程序读取它的好方法。 这个项目让你可以在自己的电脑上解决这个问题。安装一次后,Claude 这样的 AI 助手就能帮你在 MFC 上查找信息:“AmiAmi 上这个手办多少钱?”或“列出 10 月发售的所有 Chiikawa 商品。”

sequenceDiagram
    participant You
    participant Claude
    participant api as mfc-api, on your computer
    participant MFC as myfigurecollection.net
    You->>Claude: How much is the Alice Carroll figure?
    Claude->>api: get_partner_listings(287)
    api->>MFC: fetch the item's Buy window
    MFC-->>api: HTML
    api-->>Claude: AmiAmi · Available · ¥11,980
    Claude-->>You: AmiAmi has it in stock for ¥11,980

什么是 MCP? Model Context Protocol 是一种标准接口,用于赋予 AI 助手新的能力。MCP 服务是你电脑上的一个小程序,助手可以调用它。这个服务为你的助手提供 12 种 MFC 能力,从商品搜索到条码查询。只需在配置文件中添加一段代码即可接入,详见将其用作 MCP 服务。

为什么不使用 MFC 的官方 API? 因为它并不存在。该网站自己的 API 社团从 2018 年起就在等它推出。

为什么这不是一个可以访问的网站? Cloudflare 会守护 MFC,并根据 IP 信誉等因素决定谁能访问。它信任来自家用电脑的连接,却不信任服务器,因此托管版本会在几天内被拦截,而在你自己的电脑上运行的副本则能继续工作。整个设计都受这一限制影响。

我需要懂 Python 吗? 安装只需两条终端命令(如下)。之后就由你的助手来操作。

为什么要做这个项目(以及为什么显而易见的方法行不通)

MFC 位于 Cloudflare 之后,它会根据 TLS 指纹拦截请求,而不是根据 user-agent。 无论发送什么请求头,requests、httpx 和 aiohttp 都会收到 403 “Just a moment...” 挑战。 这就是较早的 tenji 抓取工具停止工作的原因:它的解析器甚至没有收到 HTML。

这个软件包使用 curl_cffi,并设置 impersonate="chrome",以重现真实的 Chrome 握手并获得 200 响应。这个选择至关重要。 换成普通的 HTTP 客户端会导致一切无法运行。

这也是它作为本地工具而非托管服务发布的原因: Cloudflare 会衡量 IP 信誉,因此运行在数据中心 IP 上的抓取工具会触发验证,并连带影响所有人共用的 IP 地址。请在自己的电脑上运行它。

flowchart LR
    A["requests / httpx / aiohttp<br/>(any headers you like)"] -->|"403 Just a moment..."| CF{Cloudflare}
    B["Your browser"] -->|200| CF
    C["mfc-api via curl_cffi<br/>(Chrome TLS handshake)"] -->|200| CF
    CF --> MFC[("myfigurecollection.net")]

安装

需要 Python 3.10+。该软件包已发布到 PyPI:

pip install myfigurecollection-api

在 Mac 上,python3 通常是 Xcode 自带的 3.9,无法运行此代码,因此请明确指定解释器(例如 pip3.12)。如果直接使用克隆的仓库,请运行 pip3.12 install -e .。

然后检查是否安装成功:

mfc-api item 287

如果找不到 mfc-api,说明 shell 的 python3 bin 目录不在 PATH 中。使用 python3.12 -c "import sysconfig; print(sysconfig.get_path('scripts'))" 查找脚本,然后使用该绝对路径。

将其用作 MCP 服务

不带参数运行 mfc-api 会通过 stdio 启动 MCP 服务。将以下内容添加到 MCP 配置中 — Claude Desktop 的 ~/Library/Application Support/Claude/claude_desktop_config.json,或 Claude Code 项目中的 .mcp.json:

{
  "mcpServers": {
    "myfigurecollection": {
      "command": "uvx",
      "args": ["myfigurecollection-api"]
    }
  }
}

这需要安装 uv;首次运行时,uvx 会从 PyPI 获取该软件包,因此无需进行其他设置。

没有 uv?将 command 指向已安装脚本的绝对路径,例如 /Library/Frameworks/Python.framework/Versions/3.12/bin/mfc-api。路径必须是 绝对路径,因为 MCP 客户端启动服务时使用的 PATH 非常精简,不包含 shell 的 Python bin 目录 — 即使 "command": "mfc-api" 在终端中能正常运行,也会失败。

工具
工具返回内容
get_item(item_id)完整条目:类别、图片、来源、角色、公司、艺术家、发售记录(日期/版本/价格/条形码)、比例、高度、评分、拥有者数量
search_items(query, page, category_id)每页 50 个条目,支持分页
search_by_barcode(barcode)按 JAN/UPC 查找条目 — 用于跨商店匹配条目的连接键
get_partner_listings(item_id)哪些合作商店在售该条目,以及库存情况和价格
get_shop(shop_id)主页、位置、配送、评分、评论和条目数量
search_shops(keywords, page, average_score, partners_only)商店目录,每页 10 家
get_profile(username)加入日期、访问量、等级、简介字段、各类别收藏数量
get_collection(username, status, page)每页 50 个条目;status 为 owned、ordered、wished 或 favorites
get_user_lists(username, page)用户发布的条目列表
get_list(list_id, page)列表的所有者、描述、标签和条目
get_club(club_id)描述、主题、近期评论、工作人员、成员
get_club_members(club_id, page)完整成员名单

get_club 是新增功能 — tenji 从未提供过此功能。

关于商店数据的两点说明

只有 MFC 记录了条形码的条目才有价格。 get_partner_listings 会返回所有合作商店,但 MFC 只能查询已记录 JAN 的条目的实际库存。对于没有条形码的条目,32 家合作商店都会返回 maybe_available,且没有价格。 这表示“未查询”,不是“有库存”。 请按 availability == "available" 进行筛选。

search_by_barcode 是查找功能,不是搜索功能。 已知条形码会在 item 下返回完整条目,并带有 matched: true。未知条形码会返回 matched: false — 其中也包括真实存在但 MFC 从未记录过的条形码,西方发行版本中这种情况很常见。

配置
环境变量默认值含义
MFC_API_RATE_LIMIT1.0请求间隔秒数
MFC_API_CACHE_TTL3600缓存有效期(秒);0 表示禁用
MFC_API_CACHE_DIR~/.cache/mfc-api缓存页面的存放位置
MFC_API_LOG_LEVELWARNING服务日志级别(日志输出到 stderr)

将其用作库

from mfc_api import MFCClient, CollectionStatus

with MFCClient() as mfc:
    item = mfc.get_item(287)
    print(item.name)                       # Aria - Alice Carroll - Maa - 1/6 (Toy's Works)
    print(item.releases[0].price)          # 6980.0
    print([c.name for c in item.characters])  # ['Alice Carroll', 'Maa']

    collection = mfc.get_collection("Climbatize", status=CollectionStatus.OWNED)
    print(collection.stats.owned, collection.pagination.total_pages)

    # Walk every page, politely (one request per second)
    for page in mfc.iter_collection("Climbatize", max_pages=3):
        print(page.pagination.current_page, len(page.items))

查询某个来源或角色下的所有内容(仅限库和 CLI — 不是 MCP 工具):

with MFCClient() as mfc:
    page = mfc.get_entry_items(237138)          # Chiikawa, oldest first, 50 per page
    print(page.pagination.total_items)          # 7247
    item = mfc.get_item(page.items[0].id)
    print(item.picture_large)                   # full-size upload/items/2/ picture

Item.picture 是 256px 预览图;Item.picture_large 是原始上传图片。 transport.get_bytes(url) 会通过同一个速率限制器获取图片,遇到 429 时会抛出携带 retry_after 的 MFCRateLimitedError,而不是重试。

输入条形码,获取价格:

from mfc_api import MFCClient

with MFCClient() as mfc:
    match = mfc.search_by_barcode("4543341130624")
    if match.matched:
        for listing in mfc.get_partner_listings(match.item.id).available:
            print(listing.shop_name, listing.price, listing.currency)  # AmiAmi 11980.0 JPY

从 shell 中使用

mfc-api item 287
mfc-api barcode 4543341130624
mfc-api listings 287
mfc-api shops Japan --partners
mfc-api collection Climbatize --status owned --page 2

所有内容都会以 JSON 格式输出到 stdout;日志输出到 stderr。mfc-api --help 会列出所有子命令。mfc-api-cli 仍作为别名保留。

将条目页存档到 Wayback Machine

今天读到的价格或商品列表,明天可能就无法引用了:页面会发生变化,而且没人必须相信你所说的内容。archive=True 会将公开条目页提交给 Internet Archive 的 Save Page Now,并将结果附加到条目上。

with MFCClient() as mfc:
    item = mfc.get_item(287, archive=True)
    print(item.releases[0].price, item.archive.wayback_url)
    # 6980.0 https://web.archive.org/web/20260903081500/https://myfigurecollection.net/item/287

一个钩子带来三项收获:价格历史序列会在日常读取中逐渐累积,每一行都可由不信任你的人审计,而且数据能留存下来。最后一点并非假设——tenji 已停运,Mandarake 于 2026 年 9 月陷入瘫痪。

绝不会影响读取。 失败会记录为一行,而不是抛出异常:item.archive.status 的值为 success、already(近期已有快照,因此 Archive 拒绝再次创建——这仍算成功保存)、skipped、pending 或 failed,并附带 reason。即使 Internet Archive 宕机,你仍然能获取条目。

绝不存档任何个人信息

MFC 上大多数内容都与个人有关。is_public_item_url 是针对 /item/<id> 的白名单,且 URL 不得带有查询字符串,因此个人资料、收藏集、用户列表和社团名册都会在发出任何请求之前被拒绝:

mfc.snapshot("https://myfigurecollection.net/item/287")       # captured
mfc.snapshot("https://myfigurecollection.net/profile/someone")  # skipped, never sent

特意使用白名单而非黑名单:这样,新增的个人 URL 格式不会因为规则只列出需要保留的内容而意外泄露。

这是有原因的选择加入功能

读取默认使用 archive=False。存档应当作为一个独立、审慎的流程,用于处理你真正关心的条目,而不是放在对延迟敏感的循环中执行:

  • 每周一次。 JSON 账本会记录每个 URL 上次存档的时间;最近 7 天内存档过的内容会跳过,不发出请求。每周一次足以追踪价格曲线,也能减少对 Archive 和 MFC 的影响。提交时还会附带 if_not_archived_within=7d,因此即使账本丢失,Archive 也会执行同样的时间间隔限制。
  • 串行处理,每 6 秒一次,每次运行最多 50 个,并遵循 429 响应中的 Retry-After。
设置作用
MERCH_ARCHIVE=0紧急开关——禁用进程中的所有快照。与同系列的 merch 客户端共享,因此一次批量运行中只需设置一个变量,即可关闭所有存档。
MERCH_ARCHIVE_LEDGER账本路径,与同系列的客户端共享,使一次流程能为每个 URL 保持统一可靠的存档间隔。
MFC_ARCHIVE_LEDGER仅供此软件包使用的账本路径。默认值:<cache dir>/archive-ledger.json。
IA_ACCESS_KEY / IA_SECRET_KEYInternet Archive S3 密钥。可从 archive.org/account/s3.php 免费获取。在 macOS 上,也会从 Keychain 服务 ia-s3-access / ia-s3-secret 中读取。

缺少凭据时,结果会是 status="failed",并附带说明如何修复的原因——不会崩溃,也不会静默地什么都不做。

每次处理流程创建一个 Archiver 并重复使用(客户端会替你完成此操作),这样速率限制器和每次运行的数量上限就会应用于整个批次,而不会在每次处理时重置。

做一个守规矩的用户

  • 默认在整个进程范围内限制为每秒 1 个请求。
  • 响应会在磁盘缓存一小时,因此重复的 Agent 调用不会产生额外开销。
  • 只读。没有登录、写入或投票操作,也不计划添加这些功能。
  • Wayback 快照需主动选择启用,每个 URL 每周最多一次,每次运行设有数量上限,且仅限 /item/<id> 页面——绝不存档个人资料、收藏集、列表或社团页面。

如果你对 MFC 的抓取频率高到引人注意,Cloudflare 就会开始质询你的 IP,而你会让所有人的使用体验都变差。不要这样做。

测试

python3 -m pytest

默认测试完全离线——解析器测试会读取于 2026 年 7 月 30 日保存的 HTML 样例。访问线上站点的测试标记为 live,默认不运行:

python3 -m pytest -m live

当 MFC 的标记可能发生变化时运行这些测试;它们是预警信号。

致谢

解析器架构——每个页面对应一个解析器类,接收 HTML 并返回一个 模型——移植自 Nate Shoffner(MIT)开发的 tenji。选择器并非如此:自 tenji 上次发布以来,MFC 的模板已发生变化。tenji 使用的两个端点已彻底失效 (itemlists.v4.php 现在会返回 404),而收藏、个人资料、列表和商店页面的标记也都与它预期的不同。

tenji 有一项内容原样保留了下来:Buy 窗口仍然是向 /item/{id} 发送带有 commit=loadWindow&window=buyItem 的表单 POST 请求,并以 JSON 作答。这个发现来自 tenji,到 2026 年仍然有效。

tenji 的 MIT 声明全文收录于 NOTICE,并附有对哪些内容源自 tenji、哪些没有的准确说明。

免责声明

非官方项目。与 MyFigureCollection.net 或 Tsuki Board 无关,也未获其认可或支持。 本项目会抓取公开页面,MFC 一旦更改 HTML,本项目就可能失效。物品数据归 MFC 及其贡献者所有。

采用 MIT 许可证,详见 LICENSE。

由 Sara Kay 开发。

mcp-name: io.github.ssskay/myfigurecollection-api

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。