Aizex MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Aizex MCPSend a message to GPT-4 explaining the theory of relativity"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Aizex MCP
通过 Playwright 浏览器自动化控制 Aizex 号池(ChatGPT/Claude 共享账号平台), 以 MCP (Model Context Protocol) 协议暴露为工具,让 agent 能操控aizex界面获取高级模型的回复,也可以写脚本批量自动生成内容。
架构概览
Mac (本机) VPS (远程)
┌─────────────────────┐ ┌──────────────┐
│ Chrome (非headless) │ │ nanobot │
│ ↑ │ │ ↑ │
│ Playwright 控制 │ │ MCP Client │
│ ↑ │ │ ↑ │
│ BrowserEngine │ SSH隧道 │ 127.0.0.1 │
│ ↑ │ ◄────────► │ :8000 │
│ AizexService │ └──────────────┘
│ ↑ │
│ FastMCP Server │
│ (port 8000) │
└─────────────────────┘Related MCP server: mcp-browser
核心组件
浏览器层 (src/browser/)
engine.py — BrowserEngine:管理 Playwright persistent context 的生命周期。 非 headless 模式启动(headless 被 Cloudflare 拦截)。支持
adopt_context()用于 session 恢复后接管新浏览器。auth.py — LoginManager:处理 Authing 登录流程。 检测是否已登录、处理登录表单、等待跳转完成。支持 session 未过期时直接跳过登录。
actions.py — BrowserActions:所有浏览器原子操作。 包括发送消息、获取回复、检测生成状态、切换模型、管理对话列表、文件上传下载等。 所有操作通过 CSS 选择器(配置在 aizex.yaml)定位页面元素。
recovery.py — SessionRecovery:号池 session 恢复。 当 session 被踢(其他用户登录同一账号)时,打开新浏览器重新走 Authing → 选号池 → 进入聊天的完整流程。恢复后通过
engine.adopt_context()替换主浏览器。selectors.py — SelectorManager:从 YAML 加载 CSS 选择器,支持 primary/fallback。
state.py — StateMachine:服务状态管理(READY/BUSY/ERROR/SESSION_KICKED/LOGIN_REQUIRED)。
service.py — AizexService:编排层。 协调 engine、auth、actions,提供锁机制(
run_locked)保证操作串行化。 实现wait_and_get的短锁轮询模式:短暂获取锁检查状态 → 释放锁等待 → 再次获取锁确认稳定。page_sentinel.py — PageSentinel:页面健康监控。 在每次操作前后检查页面状态,检测异常(如被踢、登录过期、网络错误)。
MCP 服务层 (src/mcp_server/)
server.py — FastMCP 服务端,注册 13 个工具。 包含服务端防护:send_message 3 秒冷却期、浏览器单例(多 session 共享)。 使用统一的结果工厂模式(
_build_success_response和_build_error_response)处理所有工具响应。 工具 docstring 使用中文,通过 tools/list 传递给 AI 客户端作为使用规则。schemas.py — Pydantic 数据模型,定义每个工具的输入输出结构。
核心层 (src/core/)
settings.py — Pydantic Settings,从
.env加载配置。 关键配置:browser_headless(默认 False)、poll_interval_ms、text_stability_window_ms。 遵循单一职责原则,只管理静态配置。session_store.py — SessionStore:运行时会话状态管理。 管理聊天URL和cookies的持久化,与Settings类分离,遵守单一职责原则。
errors.py — 自定义异常类,包含标准化的错误字段提取(
error_fields_from_exception)。
MCP 工具列表
工具 | 用途 |
| 检查服务状态(READY/SESSION_KICKED) |
| 新建对话 |
| 发送消息(3秒冷却) |
| 等待回复完成并获取(默认超时900秒) |
| 获取最后一条回复 |
| 检查是否正在生成 |
| 列出可用模型(支持SVG检测当前选中模型) |
| 切换模型 |
| 列出对话列表 |
| 切换对话 |
| 上传文件到当前对话 |
| 检查当前页面可下载的文件 |
| 下载文件(index=-1下载全部) |
| 刷新当前页面(处理生成卡住或页面异常) |
| 恢复被踢的 session(弹窗操作) |
最新功能更新
0. 教材批量生成系统(新增)
功能:基于 batch 系统的教材自动生成工具
组件:
textbook/prepare.py:读取 config.yaml,生成 job.json 和课程提示词textbook/run.sh:一键运行脚本(自动 prepare + batch run)textbook/chapters/:参考教材内容目录textbook/runs/:运行配置目录textbook/output/:生成结果目录
特点:
多轮共享会话:每 N 轮自动开新会话,上传参考文件
支持 system_prompt + 每课 prompt 的组合
自动检测错误回复(请求过于频繁、登录态异常等)
读回验证:生成 job.json 后立即验证关键字段
使用示例:
# 一键运行教材生成 ./textbook/run.sh textbook/runs/calculus_v1 # 续跑失败的任务 ./textbook/run.sh textbook/runs/calculus_v1 resume # 手动运行 prepare python3 textbook/prepare.py textbook/runs/calculus_v1
1. SessionStore 重构
问题:Settings类同时管理静态配置和运行时状态,违反单一职责原则
解决方案:新建
SessionStore类专门管理运行时状态功能:
保存/加载聊天URL(
.last_chat_url)保存/加载会话cookies(
.last_cookies.json)检查当前页面是否正确
获取导航URL
2. 统一结果工厂模式
问题:server.py中每个工具函数都有重复的try-except模板
解决方案:提取
_build_success_response和_build_error_response辅助函数优势:
代码更简洁,减少重复
错误处理标准化
统一的响应格式
3. 智能模型检测
问题:
is_current字段检测不准确,文本匹配容易出错解决方案:使用SVG检测代替文本匹配
实现:
当前选中的模型有checkmark图标(SVG子元素)
使用
await item.locator('svg').count() > 0检测分组入口(有展开箭头SVG)通过
_is_group_entry过滤
4. 文件管理功能
上传:支持上传任意文件到当前对话
下载:自动检测AI生成的可下载文件
特性:
智能文件路径提取
支持批量下载
安全的文件操作
5. 页面刷新功能
新增工具:
aizex_refresh_page用于处理页面状态异常使用场景:
AI 生成卡住不动时
页面状态异常时
wait_and_get超时后需要重置页面状态
特性:刷新后可能需要重新发送消息
6. 下载功能增强
URL 解码:自动解码下载链接中的编码文件名
智能文件名选择:优先使用从 URL path 参数提取的文件名,避免使用 Playwright 的 UUID 文件名
批量下载支持:支持逗号和连接号组合的索引表达式(如 "0,2-4,7")
全面消息扫描:
aizex_check_downloads支持扫描所有对话消息,而不仅仅是最后一条
7. 会话状态跟踪
新增响应字段:所有工具响应现在包含
session_model和session_conversation_id字段实时状态反馈:AI agent 每次操作后都能看到当前会话状态
智能提取:从页面 URL 自动提取对话 ID,从快照中获取当前模型
8. 使用规则优化
模型选择规则:明确禁止在已有消息的对话中切换模型,尤其是 Claude 对话
正确使用顺序:
aizex_new_chat→aizex_select_model→aizex_send_message文档更新:更新相关工具的 docstring 以提供更清晰的使用指导
9. 多实例隔离支持
问题:多个实例共用同一个 Chromium profile 目录导致 SingletonLock 冲突
解决方案:按
instance_id隔离所有浏览器相关路径核心修改:
Settings 配置扩展:新增
instance_id和pool_index字段,支持环境变量配置路径隔离:浏览器 profile、下载目录、artifacts 目录按 instance_id 添加后缀
SessionStore 隔离:URL 和 cookies 文件按 instance_id 添加后缀
端口隔离:Server 端口支持
AIZEX_PORT环境变量配置启动策略:非默认实例(instance_id != "0")启动时强制走 recovery 进入指定号池
管理脚本:新增
aizex-multi.sh脚本支持多实例生命周期管理使用示例:
# 启动 2 个实例,分别进 0 号和 3 号池 ./aizex-multi.sh start 2 0,3 # 查看状态 ./aizex-multi.sh status # 停止所有实例 ./aizex-multi.sh stop
10. 多 slot 批处理支持与附件丢失修复
问题:多 slot 并行处理时,上传的附件在发送消息前被不必要的导航冲掉
根因分析:
域名判断不完整:SessionStore 只识别
*.memofun.net,不识别*.aizex.net域名目录路径重复追加:
Settings.ensure_directories()非幂等,多次调用重复追加-instance_id后缀导航误判:进入
*.aizex.net域名时被误判为错误页面,触发不必要的重新导航
解决方案:
扩展域名支持:修改
SessionStore._is_supported_chat_host()同时支持*.memofun.net和*.aizex.net幂等目录创建:修改
Settings.ensure_directories()使用_ensure_instance_suffix()helper 确保路径只追加一次后缀优化 URL 更新:recovery 成功后同时更新内存中的 active base URL 和磁盘文件
添加导航诊断日志:在
ensure_ready_page()中添加详细日志,便于问题诊断
批处理框架:
SlotPool (
src/batch/engine.py):管理多个独立的 AizexService 实例JobRunner (
src/batch/runner.py):读取 job 配置,分发任务到多个 slot 并行执行任务历史 (
src/batch/history.py):JSON Lines 格式记录任务执行历史CLI 接口 (
src/batch/__main__.py):支持 run、status、resume、create 命令
使用示例:
# 创建批处理任务配置 python -m src.batch create --name my_job --files file1.txt file2.txt --slots 3 # 运行批处理任务 python -m src.batch run job_my_job.json # 查看任务状态 python -m src.batch status job_my_job.json
关键技术决策
非 headless 模式:headless 浏览器被 Cloudflare 拦截,必须用非 headless。
persistent context:号池 session 依赖 WebSocket 连接,关闭浏览器即失效。使用 persistent context 保持 cookie 和连接。
恢复时不关旧浏览器:recovery 完成后通过
adopt_context()直接替换主浏览器引用,避免 WebSocket 断开。短锁轮询:
wait_and_get不长期持有锁,用"短锁检查 → 释放 → 等待 → 再检查"的模式,避免阻塞其他操作。send_message 冷却:服务端强制 3 秒间隔,防止 AI 客户端连续发送导致页面混乱。
动态 URL:号池域名每次不同(如 a.memofun.net),恢复后通过
settings.update_base_url()更新。单一职责原则:Settings管配置,SessionStore管运行时状态,职责清晰分离。
统一错误处理:所有工具使用相同的结果工厂,错误响应格式一致。
部署架构
Mac 端:运行 MCP Server + Chrome 浏览器 + SSH 隧道
VPS 端:运行 nanobot(通过 SSH 隧道连接 Mac 的 MCP Server)
控制脚本:
单实例:
./aizex.sh start/stop/restart/status/test/log/tunnel多实例:
./aizex-multi.sh start/stop/status/log
快速开始
安装
git clone <repo-url> ~/aizex_mcp
cd ~/aizex_mcp
pip install -e .
playwright install chromium配置
cp .env.example .env
# 编辑 .env,填入 Aizex 账号密码和 URL关键配置项:
# Aizex URLs
AIZEX_BASE_URL=https://chat.aizex.com
AIZEX_CHAT_URL=/chat
AIZEX_LOGIN_URL=/login
# Authentication (required for login)
AIZEX_USERNAME=your_username_here
AIZEX_PASSWORD=your_password_here
# Browser settings (必须设置为 false)
AIZEX_BROWSER_HEADLESS=false
# 运行时状态存储
AIZEX_SESSION_STORE_DIR=./.session运行
chmod +x aizex.sh
./aizex.sh start # 启动 MCP 服务 + SSH 隧道
./aizex.sh test # 端到端测试
./aizex.sh status # 查看状态开发模式运行
make install # 安装依赖
make run # 启动 MCP 服务器(开发模式)nanobot 连接
在 nanobot 的 config.json 中添加:
{
"tools": {
"mcpServers": {
"aizex": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}
}IDE中mcp的配置
{ "mcpServers": { "aizex-mcp": { "command": "python3", "args": [ "run_stdio.py" ], "cwd": "/Users/csbot/aizex_mcp", "alwaysAllow": [ "aizex_health", "aizex_list_models", "aizex_list_conversations", "aizex_select_model", "aizex_new_chat", "aizex_send_message", "aizex_wait_and_get", "aizex_check_downloads", "aizex_upload_file", "aizex_get_last_response", "aizex_is_generating", "aizex_select_conversation", "aizex_download_file", "aizex_refresh_page", "aizex_recover_session" ], "timeout": 300 } } }
开发指南
项目结构
aizex_mcp/
├── src/
│ ├── browser/ # 浏览器自动化层
│ │ ├── actions.py # 原子操作(发送消息、切换模型等)
│ │ ├── service.py # 服务编排层
│ │ ├── engine.py # 浏览器引擎
│ │ ├── recovery.py # 会话恢复
│ │ ├── page_sentinel.py # 页面监控
│ │ └── ...
│ ├── mcp_server/ # MCP 服务层
│ │ ├── server.py # FastMCP 服务端
│ │ └── schemas.py # 数据模型
│ ├── core/ # 核心层
│ │ ├── settings.py # 配置管理
│ │ ├── session_store.py # 运行时状态管理
│ │ └── errors.py # 错误处理
│ └── batch/ # 批处理层(新增)
│ ├── __init__.py
│ ├── engine.py # SlotPool:管理多个 AizexService 实例
│ ├── runner.py # JobRunner:任务分发和执行
│ ├── history.py # 任务历史记录(JSON Lines 格式)
│ └── __main__.py # CLI 接口
├── textbook/ # 教材批量生成系统(新增)
│ ├── prepare.py # 配置解析和 job.json 生成
│ ├── run.sh # 一键运行脚本
│ ├── chapters/ # 参考教材内容
│ ├── runs/ # 运行配置
│ └── output/ # 生成结果
├── config/
│ └── selectors/
│ └── aizex.yaml # CSS 选择器配置
├── tests/ # 测试
├── .env.example # 环境变量示例
├── aizex.sh # 单实例控制脚本
├── aizex-multi.sh # 多实例控制脚本
├── job_example.json # 批处理任务配置示例
├── Makefile # 构建脚本
└── pyproject.toml # 项目配置测试
# 运行所有测试
make test
# 运行特定测试
pytest tests/test_mcp_tools.py -xvs
# 测试模型列表功能
pytest tests/test_mcp_tools.py::test_aizex_list_models_tool -xvs通过inspector直接测试
代码质量
# 代码格式化
make format
# 代码检查
make lint
# 类型检查
make type-check故障排除
常见问题
浏览器无法启动
检查 Chrome 是否已安装
确认
AIZEX_BROWSER_HEADLESS=false查看日志:
./aizex.sh log
登录失败
检查
.env中的用户名密码确认网络连接正常
查看浏览器控制台错误
会话被踢
自动恢复:
aizex_recover_session手动恢复:重启服务
./aizex.sh restart
文件上传失败
检查文件路径是否存在
确认文件大小不超过限制
查看页面是否支持文件上传
日志查看
./aizex.sh log # 查看服务日志
tail -f aizex.log # 实时查看日志AizexService 完整方法清单和调用顺序约束
方法清单
方法 | 参数 | 返回值 | 用途 |
| 无 | 无 | 启动服务:启动浏览器 → 注入cookies → 导航 → 登录检查 → 备用recovery |
| 无 | 无 | 关闭服务:停止浏览器引擎 |
| 无 |
| 确保页面就绪:检查URL → 检查登录 → 自动recovery |
| 无 |
| 健康检查:返回状态/URL/uptime |
| 无 |
| 新建对话 |
| 无 |
| 列出可用模型 |
|
|
| 选择模型 |
|
|
| 发送消息 |
|
|
| 检查是否正在生成 |
| 无 |
| 获取最后一条回复 |
|
|
| 等待生成完成并获取回复 |
| 无 |
| 列出对话列表 |
|
|
| 选择对话 |
|
|
| 上传文件 |
|
|
| 检查可下载文件 |
|
|
| 下载指定文件 |
| 无 |
| 下载所有文件 |
|
|
| 下载多个文件 |
| 无 |
| 刷新页面 |
|
|
| 恢复session |
|
|
| 查询积分余额 |
调用顺序约束
startup() # 必须首先调用
↓
new_chat() → select_model() # 建议顺序(Claude对话禁止中途切模型)
↓
send_message() # 发送消息
↓
wait_and_get() # 等待回复(内部自动轮询)
↓
[可选] upload_file() / check_downloads() / download_file()
↓
shutdown() # 最后调用关键约束:
startup()→new_chat()→send_message()是标准链路Claude 对话禁止在已有消息后切模型(会导致session失效)
wait_and_get()内部使用短锁轮询,不会阻塞其他操作的lock获取upload_file()必须在send_message()之前调用recover_session()成功后需重新new_chat()开始新对话
认证和会话生命周期
Cookies 来源
启动时注入:
startup()从.last_cookies.json读取并注入到浏览器contextRecovery 时获取:
recover_session()完成 pool re-entry 后,从新context提取全量cookies并保存到.last_cookies.json持久化文件:
.last_cookies或.last_cookies.{instance_id}.json(多实例隔离)
Cookies 过期场景
场景 | 原因 | 检测方式 |
其他用户登录同一号池 | Aizex号池session被踢 | PageSentinel检测"其他地方登录"等关键词 |
Authing session过期 | Authing SSO登录态过期 | 登录检查失败 |
浏览器被强杀 | Ctrl+C或kill -9 | 重启后inject的cookies可能失效 |
Cloudflare challenge | Cloudflare验证拦截 | 页面URL跳转到challenge页 |
Recovery 流程
recover_session() 的完整流程:
1. 启动临时非headless浏览器(独立profile: /tmp/aizex-recovery-profile-{instance_id})
2. 导航到 https://aizex.net/plusPool
3. 如果需要登录 → 点击"登录/注册" → Authing认证 → 验证pool可访问
4. 如果已有Authing session → 直接验证pool可访问
5. 切换到高级号池(如果有)
6. 采集积分信息(顺路)
7. 点击指定pool卡片(pool_index)
8. 等待新tab打开 → 提取新URL
9. 返回 RecoveryResult(包含 new_base_url, cookies, browser_context, credits)
10. 主服务调用 engine.adopt_context() 接管新浏览器
11. 更新 settings.base_url 和 session_store
12. 保存cookies到 .last_cookies.json注意:Recovery 使用独立的浏览器profile,不复用主浏览器的profile,避免SingletonLock冲突。
Session 失效的触发条件
响应中检测到关键词:
check_and_recover_response()检查回复文本是否包含"其他地方登录"、"号池重进"等PageSentinel pre_check 检测:每次
run_locked()操作前,PageSentinel 检查页面是否有session kicked弹窗手动触发:用户调用
aizex_recover_session工具
手动输入密码
系统不支持在运行时手动输入密码。认证凭据必须在 .env 中预先配置:
AIZEX_USERNAME=your_username
AIZEX_PASSWORD=your_password所有错误状态和对应的恢复路径
错误状态 | 触发条件 | 恢复方法 | 自动/手动 |
| 响应含"其他地方登录"等关键词;PageSentinel检测到踢出弹窗 | 调用 | 手动(需用户确认) |
| Authing登录态过期;启动时检测未登录 | 调用 | 手动 |
| PageSentinel检测到challenge页 | 调用 | 手动 |
| 页面URL离开Aizex域名;about:blank | 调用 | 自动(run_locked内) |
| 页面结构变化导致CSS选择器失效 | 调用 | 手动 |
| 发送间隔小于3秒 | 等待3秒后重试 | 自动(服务端强制) |
|
| 调用 | 手动 |
| 附件数量超过上限 | 减少附件数量 | 手动 |
| AI生成过程中出错 | 调用 | 手动 |
| 上传/下载文件路径不存在 | 检查文件路径 | 手动 |
| 多个浏览器实例共用同一profile | 使用不同的 | 配置层面 |
自动 Recovery 触发条件
在 run_locked() 内部,以下情况会自动触发 _auto_recover_in_place():
ensure_ready_page():导航后发现未登录,或URL不在Aizex域名
PageSentinel pre_check:检测到needs_recovery(SESSION_KICKED、CLOUDFLARE_BLOCKED)
简单导航失败:尝试导航后仍然不健康
冷却限制:自动recovery有5分钟冷却期,防止频繁触发。
SlotPool 和单实例 MCP 的关系
架构关系
┌─────────────────────────────────────────────────────────────┐
│ MCP Server (单实例) │
│ instance_id="0" │
│ pool_index=0 │
│ profile: /srv/aizex/profile │
└─────────────────────────────────────────────────────────────┘
↓ 完全独立
┌─────────────────────────────────────────────────────────────┐
│ SlotPool (批处理) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Slot 0 │ │ Slot 1 │ │ Slot 2 │ │
│ │ instance_id │ │ instance_id │ │ instance_id │ │
│ │ = "batch_0" │ │ = "1" │ │ = "2" │ │
│ │ pool_index= │ │ pool_index= │ │ pool_index= │ │
│ │ 0 │ │ 1 │ │ 2 │ │
│ │ profile: │ │ profile: │ │ profile: │ │
│ │ /srv/aizex/ │ │ /srv/aizex/ │ │ /srv/aizex/ │ │
│ │ profile- │ │ profile-1 │ │ profile-2 │ │
│ │ batch_0 │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘隔离机制
资源 | MCP Server | SlotPool Slot 0 | SlotPool Slot 1 |
instance_id | "0" | "batch_0" | "1" |
Browser profile |
|
|
|
Cookies |
|
|
|
Chat URL |
|
|
|
Downloads |
|
|
|
Artifacts |
|
|
|
是否会冲突
不会冲突,因为:
浏览器profile隔离:每个instance_id使用不同的Chromium profile目录,避免SingletonLock冲突
Cookies隔离:每个instance_id使用不同的cookies文件,不会互相覆盖
SessionStore隔离:每个instance_id维护独立的活跃URL
Pool选择:每个slot可以指定不同的pool_index,进入不同的号池
共享的资源
代码和配置:所有实例共享同一份代码和
.env配置(但通过环境变量可以覆盖)Aizex账号:所有实例使用同一个Aizex账号登录(通过Authing SSO)
号池:不同slot可以进入不同pool_index的号池,也可以进入同一个(但会被Aizex踢出)
注意事项
不要让多个实例进入同一个pool卡片:会被Aizex检测为并发登录,导致session被踢
MCP Server 运行时可以同时跑 SlotPool:因为使用不同的instance_id,完全隔离
Ctrl+C 强杀的影响:只会影响被强杀的实例,其他实例不受影响
贡献指南
Fork 项目
创建功能分支 (
git checkout -b feature/amazing-feature)提交更改 (
git commit -m 'Add amazing feature')推送到分支 (
git push origin feature/amazing-feature)创建 Pull Request
许可证
MIT License
联系方式
如有问题或建议,请通过项目 Issues 页面反馈。
This server cannot be deployed
Maintenance
Related MCP Connectors
A paid remote MCP for AI agent browser DevTools MCP, built to return verdicts, receipts, usage logs,
A paid remote MCP for AI agent browser approval MCP, built to return verdicts, receipts, usage logs,
Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Related MCP Servers
- FlicenseBqualityDmaintenancePlaywright wrapper for MCP that enables LLM-powered clients to control a browser for automation tasks.101-
- FlicenseNot gradedqualityDmaintenanceExposes Playwright browser automation as MCP tools, enabling AI assistants to control a real browser tab-by-tab for form filling, navigation, and more, while preserving the user's active session.-
- AlicenseAqualityDmaintenanceProvides browser automation, audio transcription, and LLM chat as MCP tools for any agent.7MIT
- AlicenseNot gradedqualityBmaintenanceEnables autonomous web QA by exposing Playwright browser control as MCP tools for navigation, accessibility snapshotting, interaction, and bug detection.1 npmMIT