Aizex MCP
Click on "Install 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: agentify-desktop
核心组件
浏览器层 (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 installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/94series/aizex_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server