Facebook Marketplace MCP 服务器:用 Chrome 会话自动化车源搜索
Facebook Marketplace Reaper Automate Marketplace Finder
一个 MCP 服务器通过现有 Chrome Facebook 登录会话访问 Facebook Marketplace,位置查询走 Facebook GraphQL API,列表搜索读取该会话的 Marketplace 搜索页。
一个 MCP 服务器,使用你现有的 Chrome Facebook 会话访问 Facebook Marketplace。位置查询使用 Facebook 的 GraphQL API。商品搜索读取该会话的 Marketplace 搜索页面。
前提条件
- macOS(Cookie 提取使用钥匙串)
- Google Chrome 并已登录 Facebook
- Python 3.11+
安装
cd server python3.12 -m venv .venv source .venv/bin/activate pip install -e .
macOS 上的 python3 通常低于 3.11。请使用 python3.12 或任何 Python 3.11+ 二进制文件。
设置
facebook-marketplace-mcp
或者将 MCP 客户端指向该模块:
{
"mcpServers": {
"facebook-marketplace": {
"command": "python",
"args": ["-m", "facebook_marketplace_mcp"],
"env": {
"CHROME_PROFILE": "Default"
}
}
}
}如果包不在默认的 PATH 中,请使用虚拟环境的 python。
CLI
facebook-marketplace 直接调用 Marketplace,无需 MCP 客户端或模型回合。每个命令都接受 --json(打印记录而非表格)和 --chrome-profile(Chrome 配置文件目录;默认为 CHROME_PROFILE 或 Default)。
里程从不需要,也不会打印。搜索页面使用已登录 Chrome 账户上的 Marketplace 城市。--latitude、--longitude 和 --radius-km 会随监视器一起存储,但不会改变该搜索。省略它们时,它们会保存为 0、0 和 50。
search
搜索商品并打印 slug、price、title、location、seller 和 url。
facebook-marketplace search "cr-v 2023" --min-price 20000 --max-price 26000 facebook-marketplace search "cr-v 2023" --province quebec facebook-marketplace search "crv 2023" "cr-v 2023" --province quebec
第一条命令查找 cr-v 2023,并保留价格从 CA$20,000 到 CA$26,000 的商品。第二条搜索魁北克省。Facebook 从魁北克城以 650 公里半径进行查询,然后丢弃魁北克省以外的商品。--province 也接受 QC 以及其他省份和地区。
卖家对同一辆车使用不同的措辞。传入多个名称,或用逗号分隔,命令会搜索每个名称,并为每个商品保留一行:
facebook-marketplace search "crv 2023, cr-v 2023" --province quebec每个名称最多返回 --limit 个商品。当 Facebook 报告还有下一页时,搜索最多读取 10 页。空页会被跳过,但仍会请求下一页。合并后的行保存在一个文件夹中,runs/crv 2023, cr-v 2023/。
| 标志 | 默认值 | 含义 |
|---|---|---|
--min-price |
无 | 最低价格(美元) |
--max-price |
无 | 最高价格(美元) |
--limit |
20 | 最大行数 |
--category |
无 | Marketplace 分类 ID |
--latitude |
0 | 仅存储;不作为搜索中心发送 |
--longitude |
0 | 仅存储;不作为搜索中心发送 |
--radius-km |
50 | 仅存储,除非设置了 --province |
--province |
无 | 加拿大省份或地区(quebec、QC)。搜索该省份并丢弃省外的商品 |
空结果会打印 No listings found 并以 0 退出。钥匙串、Cookie 或 HTTP 失败会打印到 stderr 并以 1 退出。
每个找到的商品都会获得一个稳定的 slug,slugified-title-<listing id>。首次看到某个商品 ID 时,该 slug 会保存在 ~/.fb-marketplace/catalog.json 中,即使之后标题发生变化也会复用。一个搜索名称对应一个文件夹。多个名称共享一个文件夹,文件夹名由这些名称用逗号连接而成:
server/runs/cr-v 2023/<slug>.json
server/runs/crv 2023, cr-v 2023/<slug>.json
每个商品存储 created_at、updated_at、original_price 和 price。打开商品链接时显示的照片会保存一次,为 <slug>.png,同一文件既是缩略图,也是 runs/index.html 中打开的图片。首次搜索将 created_at 和 updated_at 设为同一时间,并将 original_price 设为当时发现的价格。之后再次找到该商品的搜索会将 updated_at 设为该时间。更低的价格会保留 original_price,将更低的价格写入 price,并设置 price_dropped。
使用 facebook-marketplace serve 打开已保存的商品,然后转到 http://127.0.0.1:8767/index.html。页面读取每个商品的 JSON,并每 15 秒再次检查。搜索会更新 runs/index.json,即这些文件的列表。listing 和 monitor check 更新同一个商品文件。
列表显示每个搜索文件夹,然后是照片、价格、标题、地点和卖家。商品按最便宜优先排序。
点击一行,保存的 Marketplace 页面会在该行下方打开。再次点击可关闭。只有一行保持打开。
serve
在本机上提供 runs/,以便商品页面可以读取 JSON 文件。
facebook-marketplace serve
打开 http://127.0.0.1:8767/index.html。--port 选择另一个端口。进程会持续运行,直到被停止。
location
将城市或城镇解析为坐标。
facebook-marketplace location "Montreal"为每个匹配项打印 name、latitude 和 longitude,包括 Montreal、Quebec。使用诸如 Montreal 这样的城市名。Montreal QC 可能不返回任何行。
listing
通过搜索 URL 中的 id 打开一个商品列表(/marketplace/item/<id>/)。
facebook-marketplace listing 29168184989452025
打印标题、价格、成色、位置、卖家、描述和 URL。
monitor add
在 ~/.fb-marketplace/monitors.json 中保存搜索,以便后续检查只显示新的 id。每个 --query 值都作为独立的关键词存储。同名的监控会更新这些关键词,而不是创建第二个监控。
facebook-marketplace monitor add crv --query "crv 2023" --query "cr-v 2023" --min-price 20000 --max-price 26000
这会保存一个名为 crv 的监控,同时跟踪 crv 2023 和 cr-v 2023,然后合并这些行。--query 是必需的,且可以重复。用相同的名称再次运行 add 会更新这些关键词和价格范围。--limit 默认为 250。--category、--latitude、--longitude 和 --radius-km 匹配 search。该命令会打印监控名称、id 以及每个关键词。它此时还不会进行搜索。
monitor check
运行每个已保存的搜索,并打印之前未见过其 id 的商品列表。新见到的 id 会被存储,最多保留最近 500 个。
facebook-marketplace monitor check
检查每个监控。传入名称可只检查一个:
facebook-marketplace monitor check crv
facebook-marketplace monitor check "hrv, hr-v"每个块以 <name>: <count> new 开头,然后是跟 search 相同的列。缺少名称,或完全没有监控时,退出码为 1。
当该检查发现新商品列表时,它还会发送一条 Slack 消息。单独的 search 不会。没有新内容的检查也不会。消息内容是监控名称、新数量、最多五行价格、标题和地点,以及一个指向运行页面的链接。
每日检查
scripts/daily-monitors.sh 会为每个已保存的监控运行 monitor check。该检查会重写 runs/index.json。随后脚本会提交 runs/(包括 runs/index.html),并将该文件夹推送到 fb-marketplace main。index.html 会加载 index.json。推送到 main 会创建一个短期分支并将其合并到 gh-pages。GitHub Pages 从 gh-pages 构建站点,因此 Settings → Pages 必须使用 Deploy from a branch、gh-pages、/ (root)。没有商品列表变化的日子不会提交。没有新内容的日子不会发送 Slack。
用户 crontab 会在 Mac 本地时区的 9:00 运行它:
0 9 * * * /Users/poboisvert/Desktop/GIT/mrk-agent/server/scripts/daily-monitors.sh
届时 Mac 必须处于开机并已登录状态。该检查会从 Keychain 读取 Chrome 的 Facebook cookies,而 cron 不会唤醒睡眠中的 Mac。输出会追加到 ~/Library/Logs/fb-marketplace-daily.log。
通知
在 api.slack.com/apps 创建一个 Slack 应用。在 OAuth & Permissions 下,添加机器人作用域 chat:write,然后将该应用安装到工作区。复制 Bot User OAuth Token(xoxb-...)。邀请该机器人加入应接收提醒的频道,并从频道详情中复制频道 ID。
在运行 facebook-marketplace monitor check 或 facebook-marketplace-mcp 的 shell 中导出这些值:
export SLACK_BOT_TOKEN="xoxb-your-bot-token" export SLACK_CHANNEL="C0123456789"
SLACK_BOT_TOKEN 和 SLACK_CHANNEL 是必需的。SLACK_CHANNEL 是频道 ID。当机器人已在该频道中时,诸如 #marketplace 这样的名称也可以使用。
相同的名称可以写入 server/.env。复制 server/.env.example 以开始。该文件会被 git 忽略。shell 中已设置的值会保留。不要将 token 放入仓库或 ~/.fb-marketplace/monitors.json 中。如果任一值缺失,检查会打印 Slack skipped: set SLACK_BOT_TOKEN and SLACK_CHANNEL.,但仍会完成。Slack 错误也会以相同方式打印。not_in_channel 表示机器人尚未被邀请到该频道。
用以下命令确认 token 和频道:
pytest tests/test_slack_setup.py
该测试会向 Slack 验证机器人,然后向 SLACK_CHANNEL 发送一条消息。当任一值缺失时它会跳过。
monitor list
显示已保存的搜索,而不联系 Facebook。
facebook-marketplace monitor list
每个监控会打印其名称、设置时的价格范围、已见到的商品列表 id 数量以及上次检查时间。每个关键词会在名称下方单独一行打印:
crv 20000.0-26000.0 seen 0
crv 2023
cr-v 2023
monitor delete
移除一个已保存的搜索。该名称对应的已见 id 也会随之删除。
facebook-marketplace monitor delete crv
打印一条确认信息。如果 crv 不存在,错误会输出到 stderr,且命令退出码为 1。
工具
search_listings
按一个或多个名称和价格筛选条件搜索 Marketplace。
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
query |
string | yes | 一个或多个名称,用逗号分隔(crv 2023, cr-v 2023)。每个名称都会被搜索,结果行会被合并 |
latitude |
number | yes | 搜索中心的纬度 |
longitude |
number | yes | 搜索中心的经度 |
radius_km |
number | no | 搜索半径(默认:50)。保留给调用方;搜索页面使用 Chrome 账号的 Marketplace 城市 |
min_price |
number | no | 最低价格(美元) |
max_price |
number | no | 最高价格(美元) |
category |
string | no | 分类 ID |
limit |
number | no | 每个名称的最大结果数(默认:20) |
province |
string | no | 加拿大省份或地区(quebec、QC)。会剔除其以外的房源 |
里程在房源上可能缺失,且不是必需的。用逗号分隔的 query 会为每个名称运行一次 Marketplace 搜索,并按房源 id 保留一行。
get_listing
获取特定房源的完整详情。
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
listing_id |
string | yes | Marketplace 房源 ID |
search_location
查找城市或城镇并返回坐标。
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
query |
string | yes | 城市或城镇名称 |
monitor_search
将搜索保存为监控项。query 中的逗号是独立关键词,存储在监控项上,并在检查时合并。再次保存相同的 name 会替换这些关键词。
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
name |
string | yes | 监控项名称 |
query |
string | yes | 一个或多个名称,用逗号分隔。检查与合并方式与 search_listings 相同 |
latitude |
number | yes | 搜索中心纬度 |
longitude |
number | yes | 搜索中心经度 |
radius_km |
number | no | 半径(默认:50) |
min_price |
number | no | 最低价格 |
max_price |
number | no | 最高价格 |
province |
string | no | 加拿大省份或地区(quebec、QC) |
check_monitors
检查监控项自上次检查以来的新房源。
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
monitor_name |
string | no | 检查特定监控项,或省略以检查全部 |
list_monitors
列出已保存的监控项及其为每个名称存储的关键词。
delete_monitor
删除已保存的监控项。
监控项存储在 ~/.fb-marketplace/monitors.json 中。
配置
| 环境变量 | 默认值 | 描述 |
|---|---|---|
CHROME_PROFILE |
Default |
Chrome 配置文件目录名称 |
SLACK_BOT_TOKEN |
Slack 机器人令牌(xoxb-...)。在新监控项房源通知时必需 |
|
SLACK_CHANNEL |
Slack 频道 ID,或诸如 #marketplace 的名称。与 SLACK_BOT_TOKEN 一起使用时必需 |
速率限制
服务器自我限速为每分钟 3 次请求,并带有随机抖动。搜索需要几秒钟。
限制
- 仅限 macOS 用于自动提取 cookie
- 需要 Chrome 并保持活跃的 Facebook 会话
- Facebook 服务条款 — 自动化操作 Facebook 违反其服务条款
- 搜索城市 遵循已登录 Chrome 账号上的 Marketplace 位置
- 速率受限 — 过度使用可能触发 CAPTCHA 或账号标记
- 无写入操作 — 仅搜索/读取,不发送消息或创建房源
来源:Hacker News · github.com

