循环 应用
MCP(模型上下文协议)服务器 继续 物业管理。允许人工智能助手(Claude等)通过浏览器自动化和直接API调用与DoorLoop交互。
特性
MCP工具
| 工具 | 说明 |
|---|---|
doorloop_login | 使用DoorLoop进行身份验证。如果需要,返回2FA状态。 |
doorloop_submit_2fa | 提交2FA验证码。 |
doorloop_list_properties | 列出所有具有地址、类型和单位计数的属性。 |
doorloop_list_units | 列出房产的单位及其状态和租金。 |
doorloop_list_tenants | 列出所有租户的联系方式、租约和余额。 |
doorloop_find_tenant | 通过姓名或电子邮件搜索租户。回到人工智能模糊匹配。 |
doorloop_list_leases | 列出租赁,可选择按属性或状态筛选。 |
doorloop_receive_payment | 为租户填写付款表格( 不 提交——用户评论并单击保存)。 |
doorloop_list_lease_transactions | 列出特定租赁的所有交易(需要 lease_id). |
数据检索策略
每个读取操作都使用三层回退:
- 直接API --最快。使用以前浏览器会话中缓存的令牌。
- 浏览器(剧作家) -在页面导航期间拦截DoorLoop XHR API响应。
- 人工智能视觉(克劳德) --作为最后手段,从页面文本中提取结构化数据。
所有提取的数据都缓存在本地SQLite数据库中(~/.doorloop-mcp/doorloop.sqlite3).
需求
- Ruby 3.4+
- Node.js(用于Playwright浏览器二进制文件)
- 一个DoorLoop账户
设置
# Install dependencies
bundle install
npx playwright install chromium
# Configure environment
cp .env.example .env.local
# Edit .env.local with your DoorLoop credentials环境变量
DOORLOOP_EMAIL=you@example.com
DOORLOOP_PASSWORD=yourpassword
DOORLOOP_URL=yourorg.app.doorloop.com # defaults to bansals.app.doorloop.com
# Optional
DOORLOOP_HEADLESS=true # set false to see the browser
# AgentMail — automatic 2FA retrieval + payment confirmation emails
AGENTMAIL_API_KEY=...
AGENTMAIL_INBOX_ID=...
DOORLOOP_CONFIRMATION_EMAIL_TO=you@example.com # enables post-payment email
# Claude AI — vision fallback + tenant fuzzy matching
ANTHROPIC_API_KEY=...
DOORLOOP_LLM_MODEL=claude-haiku-4-5-20251001 # model for tenant fuzzy matching
DOORLOOP_VISION_MODEL=claude-sonnet-4-20250514 # model for vision page extraction码头工人
快速启动
# Build the image
docker compose build
# Login once to persist the Chrome session
docker compose run --rm login
# Run as MCP server (used by Claude Desktop / MCP clients)
docker compose run --rm mcp该镜像捆绑了Ruby 4.0、Node.js 22、Chromium和所有Playwright依赖项。数据(Chrome配置文件+SQLite数据库)被持久化 ~/.doorloop-mcp 通过卷装载在主机上。
MCP客户端配置(Docker)
{
"mcpServers": {
"doorloop": {
"command": "docker",
"args": ["compose", "-f", "/path/to/doorloop-app/docker-compose.yml", "run", "--rm", "mcp"]
}
}
}图像细节
| 阶段 | 基础 | 目的 |
|---|---|---|
base | ruby:4.0.1-slim-bookworm | Ruby+Node.js 22+构建程序 |
gems | base | 捆绑安装(无开发组) |
playwright | gems | npm ci + playwright install chromium --with-deps |
app | playwright | 完整来源+ /data 音量 |
ENTRYPOINT:bundle exec bin/doorloopCMD:server- Chromium无头运行
--no-sandbox --disable-setuid-sandbox(容器中要求) /data音量:Chrome配置文件位于/data/chrome-profileSQLite位于/data/doorloop.sqlite3
______________________________________________________________________
用法
作为MCP服务器(适用于克劳德桌面/Claude代码)
bin/doorloop server添加到MCP配置中:
{
"mcpServers": {
"doorloop": {
"command": "/path/to/doorloop-app/bin/doorloop",
"args": ["server"]
}
}
}CLI命令
bin/doorloop version # Print version
bin/doorloop server # Start MCP stdio server
bin/doorloop login # Interactive login
bin/doorloop console # IRB/Pry console with DoorLoopApp loaded
bin/doorloop properties list # List all properties
bin/doorloop units list # List units
bin/doorloop tenants list # List all tenants
bin/doorloop leases list # List all leases
bin/doorloop leases transactions --tenant "Shital" # Fetch transactions by tenant name
bin/doorloop leases transactions --lease-id abc123 --raw # JSON output
bin/doorloop payment receive \
--tenant "Prayag Bansal" \
--amount 4500 \
--date 2026-03-01 \
--method EFT \
--memo "March rent" # Fill payment form (prompts to confirm after Save)控制台使用
# Load and authenticate
session = DoorLoopApp.session
session.start
session.ensure_authenticated!
# Fetch and cache data
DoorLoopApp.executor.call(:list_properties)
DoorLoopApp.executor.call(:list_tenants)
DoorLoopApp.executor.call(:list_leases)
# Query cached data
store = DoorLoopApp.store
store.all_tenants
store.find_tenant_by_name("Prayag")
store.active_leases
# Fill a payment form (does not submit)
payment_page = DoorLoopApp::Browser::Pages::PaymentPage.new(session)
payment_page.fill_payment(
tenant_name: "Prayag Bansal",
amount: "1200",
date: "2026-03-01",
payment_method: "EFT",
memo: "March rent"
)建筑
系统概述
graph TD
subgraph Clients["Clients"]
AI["AI Assistant\n(Claude, etc.)"]
CLI["bin/doorloop\nCLI"]
end
subgraph MCP["MCP Layer"]
SERVER["MCP Server\n(stdio transport)"]
TOOLS["9 MCP Tools\nlogin · list_properties · list_units\nlist_tenants · list_leases · find_tenant\nreceive_payment · list_lease_transactions\nsubmit_2fa"]
end
subgraph Executor["Data::Executor (3-layer fallback)"]
L1["Layer 1: Direct API\nHTTP + cached token"]
L2["Layer 2: Browser\nPlaywright XHR interception"]
L3["Layer 3: Vision\nClaude AI text extraction"]
end
subgraph External["External"]
DL["DoorLoop\nbansals.app.doorloop.com"]
AM["AgentMail\n2FA + email"]
CLAUDE_AI["Claude AI\ntenant matching · vision"]
end
subgraph Storage["Storage"]
DB["SQLite\n~/.doorloop-mcp/doorloop.sqlite3"]
CHROME["Chrome Profile\npersistent session"]
end
AI -->|"MCP JSON-RPC\n(stdio)"| SERVER
CLI --> TOOLS
SERVER --> TOOLS
TOOLS --> Executor
L1 -->|"REST"| DL
L2 -->|"Playwright"| DL
L3 --> CLAUDE_AI
Executor --> DB
L2 --> CHROME
AM -->|"OTP codes"| L2
AM -->|"confirmation\nemail"| CLI数据检索流程
flowchart LR
REQ["operation\ncall"] --> API
API{"Layer 1\nDirect API\ntoken valid?"}
API -->|yes| API_CALL["HTTP GET\n/api/..."]
API_CALL -->|success| STORE
API_CALL -->|fail / auth error| BROWSER
API -->|no token| BROWSER
BROWSER{"Layer 2\nBrowser\nXHR intercept"}
BROWSER --> NAV["navigate_to(path)\n+ expect_response(...)"]
NAV -->|success| STORE
NAV -->|timeout / error| VISION
VISION{"Layer 3\nVision\nANTHROPIC_API_KEY?"}
VISION -->|configured| EXTRACT["Claude reads\npage text"]
EXTRACT -->|success| STORE
EXTRACT -->|fail| EMPTY["return []"]
VISION -->|not configured| EMPTY
STORE["upsert_all\nSQLite"] --> RESULT["return data"]付款流程
sequenceDiagram
participant U as User / AI
participant CLI as CLI / MCP Tool
participant DB as SQLite
participant PW as Playwright Browser
participant DL as DoorLoop
participant AM as AgentMail
U->>CLI: payment receive --tenant X --amount Y
CLI->>DB: find_tenant_by_name(X)
alt not found in DB
CLI->>PW: list_tenants (refresh)
PW->>DL: navigate + intercept XHR
DL-->>PW: tenants JSON
PW-->>CLI: tenant list
CLI->>DB: upsert_all
end
CLI->>PW: fill_payment(lease_id, amount, date, method, memo)
PW->>DL: navigate to payment form
PW->>DL: fill form fields
PW-->>CLI: form ready (not submitted)
CLI-->>U: "Click Save in browser, then press Enter"
U->>CLI: [press Enter]
CLI->>PW: list_lease_transactions(lease_id)
PW->>DL: navigate + intercept XHR
DL-->>PW: transactions JSON
PW-->>CLI: transactions
CLI->>DB: upsert_lease_transactions
CLI-->>U: confirmed transaction details
opt AgentMail configured
CLI->>AM: send_message(to, subject, body)
AM-->>U: confirmation email
end文件结构
bin/doorloop CLI entry point (Thor)
lib/doorloop_app/
server.rb MCP server setup
tool.rb Base tool class
tools/ 9 MCP tools
browser/ Playwright session + page objects
pages/ PropertiesPage, UnitsPage, TenantsPage,
LeasesPage, LeaseTransactionsPage, PaymentPage
api/ REST API client (token-based, post-login)
endpoints/ Properties, Units, Tenants, Leases
models/ Sequel ORM models (SQLite)
json_backed.rb Shared upsert/find/stale logic
Property, Unit, Lease, Tenant, LeaseTransaction
data/executor.rb 3-layer fallback orchestrator
llm/tenant_matcher.rb Claude AI fuzzy tenant matching
vision/client.rb Claude AI page text extraction
agent_mail/client.rb AgentMail 2FA retrieval + email sending
notifications/ PaymentConfirmation (via AgentMail)
cli/ Thor CLI commands + subcommands测试
bundle exec rake test测试使用Minitest+Mocha和模拟浏览器会话。不需要活的DoorLoop连接。
许可证
麻省理工学院
