Skip to main content
Glama
README.md
# Ziroom MCP

这是一个自如租房 MCP 服务:既支持有状态的房源筛选,也支持无会话地抓取单个详情页 URL。搜索时 Agent 在同一个 `session_id` 中连续调用工具,服务端保持浏览器页面、筛选状态、版本号和回退检查点。

## 工具

- `create_search_session`:根据城市打开对应自如页面。
- `get_filter_schema`:读取当前字段、选项、控件类型和已选状态。
- `search_location`:搜索小区、商圈或地铁站。
- `select_filter_option`:选择单选或多选标签。
- `set_filter_range`:设置租金范围。
- `set_sort`:设置价格、面积等排序。
- `get_results`:返回房源名称、URL、当前全部条件及验证结果。
- `get_listing_detail`:通过一个 `/x/{listing-id}.html` URL 返回结构化详情和中文 Markdown 报告。
- `restore_checkpoint`:恢复某次操作前的完整状态。
- `reset_filter`:将指定字段整体恢复为默认值。
- `close_search_session`:关闭页面并释放资源。

## 安装

```powershell
cd C:\path\to\ziroom-mcp
python -m venv .venv
.venv\Scripts\python.exe -m pip install -e ".[test]"
```

服务会优先使用 Windows 上已经安装的 Chrome 或 Edge。如果没有可用浏览器,再安装 Playwright Chromium:

```powershell
.venv\Scripts\python.exe -m playwright install chromium
```

详情抓取与搜索共用同一个 Playwright 浏览器进程。每次 `get_listing_detail` 调用会创建独立 BrowserContext,读取完成后立即关闭,不会污染已有搜索会话。价格数字精灵图通过 Playwright 请求上下文下载并解码。

## 启动

```powershell
.venv\Scripts\ziroom-mcp.exe
```

服务默认使用 stdio,日志不得写入 stdout。

使用 Streamable HTTP:

```powershell
$env:ZIROOM_TRANSPORT="streamable-http"
$env:ZIROOM_HOST="127.0.0.1"
$env:ZIROOM_PORT="8000"
.venv\Scripts\ziroom-mcp.exe
```

HTTP MCP 端点为 `http://127.0.0.1:8000/mcp`,并使用兼容 Cloudflare Quick Tunnel 的 JSON 响应模式。

通过会转发公网 Host 的反向代理时,再设置 `$env:ZIROOM_BEHIND_PROXY="1"`。启用后必须保持 `ZIROOM_HOST=127.0.0.1`,避免直接监听公网网卡。

自如当前会对无界面 Chrome 返回空正文,因此服务默认启动可见浏览器。仅在目标页面确认支持时再启用无界面模式:

```powershell
$env:ZIROOM_HEADLESS="1"
.venv\Scripts\ziroom-mcp.exe
```

也可通过 `ZIROOM_CHROME_PATH` 指定 Chrome/Edge 可执行文件。

同一搜索会话始终复用同一个浏览器 Tab。筛选链接导航后,服务会保留现有查询参数并将 `isOpen` 恢复为 `1`,再重新定位下一项;若网站仍将目标链接隐藏在 DOM 中,则使用 DOM click 作为兜底。

## Agent 调用约定

抓取单个详情页时,直接调用一次 `get_listing_detail`,不需要创建或关闭搜索会话:

```json
{
  "url": "https://wh.ziroom.com/x/123456.html",
  "timeout_seconds": 30,
  "retries": 4,
  "include_report": true
}
```

返回值包含 `listing_id`、`url`、`fetched_at`、结构化的 `listing`,以及可选的 `report_markdown`。

筛选房源时遵循以下顺序:

1. 调用 `create_search_session`。
2. 调用 `get_filter_schema`,只选择页面当前返回的标签。
3. `location`、`area`、`metro` 是互斥的找房方式,只保留一个;按 `location` → `area` → `metro` 建立兜底队列,首选项报错、未保留或零结果时,确认页面已恢复后再尝试下一项。
4. 所有修改工具使用同一个 `session_id`,并传入上一步返回的 `state_version`。
5. 每次修改后检查 `has_results`。
6. 若为 `false`,使用本次返回的 `checkpoint` 调用 `restore_checkpoint`,并将 `reason` 设为 `empty_results`。
7. 若返回 `skipped=true` 和 `reason=page_did_not_retain_option`,说明页面没有保留本次标签且工具已恢复原状态;不得调用 `restore_checkpoint`,应刷新 schema 后记录为不可用或按业务规则有限重试。其他修改工具对应返回 `reason=page_did_not_retain_change`。
8. 最终调用 `get_results`,通过 `expected_filters` 校验所有应保留的条件。
9. 完成后调用 `close_search_session`。

可预期的筛选冲突不会作为工具错误返回。当前页面没有选项、选项已经应用、页面没有保留变更,或 `location`/`area`/`metro` 冲突时,修改工具返回 `skipped=true`、`state_changed=false`,保持原 `state_version` 和全部已选条件;Agent 应记录原因并继续下一项。真正的版本冲突、会话失效、站点故障和内部错误仍会作为工具错误返回。

## 测试

全部 MCP 工具都有离线协议层测试:

```powershell
.venv\Scripts\python.exe -m pytest -m "not live" -v
```

测试还会启动一个使用假网页后端的 stdio 服务器子进程,验证 MCP 初始化、工具发现和工具调用。`ZIROOM_BACKEND=fake` 仅供自动化测试使用。

真实网页冒烟测试:

```powershell
$env:ZIROOM_LIVE_TEST="1"
.venv\Scripts\python.exe -m pytest -m live -v
```

TDQS

B3.1/5.0

Scored across 11 tools

Disambiguation5/5

每个工具都有明确的职责:会话管理(创建/关闭)、搜索(位置、筛选选项、范围、排序)、结果获取、详情抓取、状态恢复/重置。工具之间没有明显重叠,边界清晰,代理可以准确选择所需工具。

Naming Consistency5/5

所有工具名称均采用一致的动词_名词的snake_case模式,如create_search_session、get_filter_schema、select_filter_option等,命名风格统一,可预测性强。

Tool Count5/5

11个工具完整覆盖了浏览器搜索会话的整个生命周期,从创建、配置、执行到关闭,每个工具都有其存在的价值,数量合理,既不冗余也不单薄。

Completeness4/5

覆盖了搜索流程的主要环节:会话管理、位置搜索、筛选和排序、结果获取、详情查看、状态恢复和重置。缺少一些如取消特定筛选选项之类的边缘操作,但核心工作流完整,代理可以正常完成任务。

Maintenance

ActivityMaintained
ResponsivenessNo issues