Skip to main content
Glama
compnew2006

Browser Controller

by compnew2006

这个项目解决了什么问题

你提交了一个修复。你的智能体说"完成了,请验证。" 你切换到 Chrome,导航到页面,登录,点击各处,找到 bug。

你的智能体刚刚写了代码。它也可以验证。 你的浏览器已经为它打开着。它只是看不到。

现在它可以了。 Browser Controller 让任何兼容 MCP 的 AI 智能体(Cursor、Claude Desktop、Windsurf……)直接控制你已经打开的浏览器——你真实的会话、你的登录状态、你的 cookie。无需无头浏览器,无需全新配置文件,无需重新认证。

Related MCP server: Tabryn

核心能力

  • 同时支持多个智能体。 Cursor 可以驱动标签页 10,而 Claude 驱动标签页 11——两者通过同一个共享守护进程,互不阻塞。

  • 按标签页定位,而非"当前活动标签页"。 每个操作都指定一个 tabId。移动鼠标、切换标签页、看 YouTube——智能体始终在你指定的标签页上工作。它永远不会劫持你正在阅读的页面。

  • 按标签页隔离。 元素引用、控制台日志和网络缓冲区都按标签页隔离。来自标签页 10 的引用永远无法点击标签页 20 中的内容。

  • 按标签页并发。同一个标签页的两个操作会串行化(无竞争);对不同标签页的操作并行执行。

  • 标签页锁定。 智能体可以认领一个标签页,让其他智能体排队等待而不是竞争(browser_tabs { action: "lock" })。锁在 Chrome 的 service-worker 回收后依然有效(chrome.storage.session)。

  • 智能体控制防护罩。 当智能体在某个标签页上工作时,你会看到一个半透明的蓝色内框,并且你在该标签页上的输入会被阻止(鼠标、键盘、滚轮)——徽章显示 agent <name> controlling the tab,操作完成后消失。锁定标签页会在锁的存续期间保持一个普通边框。

  • 同源 iframe 穿透。 位于 iframe 内的旧式/企业界面(例如 iframe#mainFrame 中的 ONT 控制台)可以访问:所有定位工具都会搜索 iframe 文档,find/click_text 会遍历每个框架。

  • 原生对话框救援。 原生的 alert/confirm/prompt 会冻结页面的 JS 线程——browser_handle_dialog 通过 CDP 带外解除它,无需页面 JS,这也会解除该标签页上所有其他工具的阻塞。browser_tabs close/focus 始终有效,即使在冻结的标签页上也是如此。

  • 经过认证的本地连接。 令牌 + 一次性注册密钥,因此没有其他本地进程可以静默驱动你的浏览器。一切都在 localhost 上——无云端,无遥测。

  • 无调试器横幅。 browser_evaluate 通过 chrome.scripting 在页面的 MAIN 世界中运行——没有黄色的"此标签页正在被调试"横幅,真实值可以跨 MV3 世界边界返回。

  • 诚实的错误。 每个工具失败都会以真实的 isError 结果连同完整负载到达你的智能体——不会用"成功"响应来掩盖工作流中途的失败。


工作原理

三个部分,全部在你的机器上。没有任何内容离开 localhost。

  Agent (Cursor / Claude / Windsurf)        ── other agents connect too ──┐
                  │ stdio (MCP protocol)                                   │
                  ▼                                                        ▼
  ┌─────────────────────────────┐   ┌─────────────────────────────────────────┐
  │  thin MCP client            │   │  thin MCP client                        │
  │  (node mcp-server/dist/     │   │  (node mcp-server/dist/                 │
  │   index.js)                 │   │   index.js)                             │
  │  - speaks MCP over stdio    │   │  - spawns daemon if not running         │
  │  - forwards calls to daemon │   │  - gets its own sessionId               │
  └──────────────┬──────────────┘   └────────────────────┬───────────────────┘
                 │ local IPC socket (AF_UNIX / named pipe, token-auth)     │
                 ▼                                                          ▼
  ┌──────────────────────────────────────────────────────────────────────────┐
  │  DAEMON (single long-running process, owns port 7225)                     │
  │  - multiplexes N clients → 1 extension                                    │
  │  - tags every call with the client's sessionId                            │
  │  - heartbeat eviction, per-session rate limiting                          │
  └──────────────────────────────┬───────────────────────────────────────────┘
                                 │ WebSocket ws://127.0.0.1:7225 (token-auth)
                                 ▼
  ┌──────────────────────────────────────────────────────────────────────────┐
  │  Chrome Extension (Manifest V3 service worker)                            │
  │  - resolves the target tabId (never "the active tab" implicitly)          │
  │  - serializes same-tab actions, parallelizes cross-tab actions            │
  │  - executes click/type/snapshot/evaluate against the named tab            │
  └──────────────────────────────────────────────────────────────────────────┘

关键思路: 任何智能体首次运行时,瘦客户端会启动一个后台守护进程,它拥有端口 7225 和扩展连接。之后每个智能体(即使来自不同的 MCP 客户端)都通过本地 IPC 套接字连接到同一个守护进程,并获得自己的 sessionId。扩展看到的是一个稳定的连接,并将每个调用路由到调用者指定的确切标签页。


快速开始

该项目不在 Chrome 网上应用店或 npm 上——你需要从这个仓库安装。两个部分:MCP 服务器(在你的机器上运行,与你的 AI 智能体通信)和 Chrome 扩展(位于你的浏览器中,执行命令)。

前置条件: Node.js ≥ 20 和 Chrome/Chromium/Edge。

1. 克隆并构建

git clone https://github.com/compnew2006/browser-controller.git
cd browser-controller
npm install
npm run build        # compiles TypeScript → mcp-server/dist/

2. 加载 Chrome 扩展

  1. 打开 chrome://extensions 并启用开发者模式(右上角的开关)

  2. 点击加载已解压的扩展程序,选择克隆仓库中的 extension/ 文件夹

  3. 将 Browser Controller 图标固定到工具栏

灰点 = 等待守护进程。绿色 = 已连接。

3. 将 MCP 服务器添加到你的客户端

Cursor:设置 → MCP → "添加新的 MCP 服务器"。Claude Desktop:编辑 claude_desktop_config.json。Windsurf:设置 → MCP。任何兼容 MCP 的客户端都可以。

/path/to/browser-controller 替换为你克隆的绝对路径(Windows:使用 C:\\path\\to\\browser-controller\\mcp-server\\dist\\index.js):

{
  "mcpServers": {
    "browser-controller": {
      "command": "node",
      "args": ["/path/to/browser-controller/mcp-server/dist/index.js"]
    }
  }
}

默认情况下,守护进程会根据其父级 IDE("Cursor"、"Claude"……)为每个连接命名。要覆盖此设置——例如当多个智能体共享一个 IDE 时,或按项目标记它们——在参数中传入 --agent <name>。它优先于所有自动检测:

{
  "mcpServers": {
    "browser-controller": {
      "command": "node",
      "args": ["/path/to/browser-controller/mcp-server/dist/index.js", "--agent", "My Project Agent"]
    }
  }
}

该名称会出现在弹窗的已连接智能体列表中。(你也可以设置 MCP_AGENT_NAME 环境变量——效果相同。)使用相同名称重新连接会替换旧条目,因此 IDE 重启不会堆积重复项。

4. 将扩展与守护进程配对

守护进程使用两个密钥,均在首次运行时生成到 ~/.browser-controller/(Windows:%USERPROFILE%\.browser-controller\)。先让智能体"列出我的浏览器标签页"来启动它一次,然后:

  1. 读取密钥:

    cat ~/.browser-controller/enrollment.json   # one-time pairing secret
    cat ~/.browser-controller/token.json        # WebSocket auth token

    (注册密钥在首次运行时也会打印到 MCP 客户端的日志中。)

  2. 点击扩展图标 → 设置标签页 → 粘贴注册密钥认证令牌(除非你更改了 WS_PORT,否则端口保持 7225)。

绿点 = 你已连接。你的智能体现在可以看到你的浏览器了。

这些密钥可防止任何其他本地进程打开 WebSocket 并驱动你经过认证的浏览器会话。要轮换它们,请停止你的 MCP 客户端,删除该文件夹,下次运行时会重新创建两个密钥。完整的威胁模型请参阅 SECURITY.md


使用方法

模型是标签页优先的:智能体总是说明要对哪个标签页执行操作。它从不假设是"当前活动标签页"。

基本工作流

  1. 列出标签页以获取 tabId

    browser_tabs { action: "list" }
    → [{ id: 15, url: "...", title: "...", active: true, lockedBy: null }, ...]
  2. 快照该标签页以查看其结构并获取元素引用:

    browser_snapshot { tabId: 15 }
    → { tree: [ { ref: "e3", role: "button", name: "Sign in" }, ... ] }

    引用仅对此 tabId 有效。如果你导航或 DOM 发生变化,请重新快照。自上次快照以来的新元素会被标记为 isNew: true——在操作打开覆盖层/下拉菜单后,智能体可以只关注这些元素,而无需重新读取整个树。

  3. 交互,使用引用和相同的 tabId:

    browser_click { tabId: 15, ref: "e3" }
    browser_type  { tabId: 15, ref: "e5", text: "hello@example.com" }
    browser_press_key { tabId: 15, key: "Enter" }

    如果引用已过期但元素仍然存在,会通过稳健的选择器 + 文本/角色扫描自动找到它(响应携带 via: "fallback")。如果元素被完全滚动出视野(虚拟化信息流),响应会携带 freshRefs: [...] 及内联的新快照——在同一个步骤中用这些新引用之一重试,无需单独快照。

  4. 验证——操作后再次快照或读取文本。

多智能体协调(两个智能体,两个标签页)

  1. 智能体 A 列出标签页,选择标签页 10,可选地锁定它:browser_tabs { action: "lock", tabId: 10 }

  2. 智能体 B 列出标签页,选择标签页 11,锁定它:browser_tabs { action: "lock", tabId: 11 }

  3. 两者并行工作。每个智能体的调用针对自己的标签页串行化;两个标签页互不干扰。

  4. 完成后:browser_tabs { action: "unlock", tabId: 10 }

弹窗就是你的控制面板

一个固定高度的标签式外壳(主体从不滚动,只有列表滚动):

  • 标签页 — 每个打开的标签页及其锁所有者,工具栏中还有全部解锁,用于在智能体锁定中途崩溃时一键释放。

  • 智能体 — 每个已连接的智能体及其名称、会话 ID、运行时间,以及一个 ✕ 可立即断开连接(清除心跳尚未回收的僵尸进程)。

  • 设置 — WebSocket 端口、认证令牌、注册密钥。

  • 活动栏 — 底部一个可折叠的条带,显示最新的工具活动;展开可查看滚动日志。

需要了解的事项

  • 忘记 tabId 了? 你会收到明确的错误:tabId is required. Call browser_tabs list first.

  • 受保护的页面chrome://、网上应用店、devtools)无法被脚本化——你会收到 Cannot access protected page (chrome://...),而不是静默挂起。

  • browser_navigate 是唯一一个 tabId 可选的工具(默认为活动标签页)——但为了多智能体安全,请显式传入。仅哈希变化(例如 /page/page#section)在 URL 设置后立即解析,无需等待 complete 事件(SPA 在哈希变化时不会重新加载,因此该事件永远不会触发)。

  • browser_evaluate 在页面的 MAIN 世界中运行(无调试器横幅,CSP 安全)并返回真实值(跨世界边界进行 JSON 序列化)。它很强大但非幂等——超时后不会自动重试。

  • 滚动虚拟化信息流(Facebook/Instagram/Twitter):browser_scroll 返回 refsMayBeStale: true,因为这些站点会回收 DOM 节点。下次交互前请重新快照。

  • 重复元素:当多个元素共享文本+角色时(例如 3 个"点赞"按钮),回退解析器按序号(nth)选择正确的那个,而不仅仅是第一个匹配项。

  • 冻结的标签页(原生对话框阻塞)不会让你死锁:browser_handle_dialog 通过 CDP 解除它,browser_tabs { action: "close" } 始终有效,是保证退出的方式。


🧠 教你的智能体

智能体开箱即可使用全部 22 个工具,但当它了解标签页优先的工作流时会表现更好。从仓库根目录:

npm run setup:cursor   # or: node mcp-server/dist/index.js --setup cursor

这会安装:

  • ~/.cursor/rules/browser-controller.mdc — 标签页定位工作流、下拉菜单处理、何时锁定标签页

  • ~/.cursor/commands/check-browser.md — 为你的 Cursor 聊天添加 /check-browser

之后,在任何聊天中输入 /check-browser。或者直接说"在我的浏览器中检查结果",智能体就知道该做什么。

npm run setup:claude

在你的项目根目录添加一个 AGENTS.md。Claude Code 会自动发现它。

手动安装或自定义规则请参阅 agent-config/


它能做什么

22 个工具。每个页面交互工具都接受一个 tabId(唯一的例外是 browser_navigate,其中它是可选的)。

查看

工具

功能

browser_snapshot

带元素引用的无障碍树。紧凑模式(默认)仅返回可交互元素。遍历 shadow DOM 和 iframe。

browser_screenshot

将标签页捕获为图像(先激活标签页再捕获)

browser_text

从页面或元素提取原始文本

browser_find

通过自然语言查询元素——也会遍历同源 iframe

交互

工具

功能

browser_click

通过引用或 CSS 选择器点击——穿透同源 iframe

browser_click_text

按可见文本点击。可穿透 React portals 和覆盖层

browser_type

在输入框和 contenteditable 字段中键入

browser_press_key

按键组合(Enter、Escape、Ctrl+A)

browser_scroll

滚动页面和虚拟容器

browser_hover

触发工具提示和下拉菜单

browser_select

从原生 <select> 下拉菜单中选择

browser_wait

等待元素出现或消失

browser_fill_form

一次调用填充多个表单字段(React/Vue 安全的 setter)

browser_drag

元素到元素的拖拽(使用 CDP 保证可靠性)

browser_upload_file

通过 <input type="file"> 上传文件(使用 CDP,严格 CSP 安全)

browser_upload_file 将本地文件注入 <input type="file">,就像用户选择了它们一样:原生对话框永远不会打开,之后会触发 input/change 事件,因此 React/Vue 表单会做出响应。

browser_upload_file { tabId: 15, selector: "#resume", filePath: "/Users/me/resume.pdf" }
browser_upload_file { tabId: 15, ref: "e12", files: ["/tmp/a.png", "/tmp/b.png"] }

路径是绝对的,并且位于运行浏览器的机器本地。省略 ref/selector 会自动定位页面上的第一个文件输入;一次上传多个文件需要带有 multiple 的输入。

导航

工具

功能

browser_navigate

在标签页中转到 URL(tabId 可选,默认为活动标签页)

browser_tabs

列出 / 创建 / 关闭 / 聚焦 / 锁定 / 解锁 标签页

调试与高级

工具

功能

browser_console

控制台输出(log、warn、error)——按标签页,上限 200 条

browser_network

带状态码的 XHR/fetch 请求——按标签页,可选 limit

browser_evaluate

在页面的 MAIN world 中运行 JavaScript(无横幅,CSP 安全)

browser_handle_dialog

通过 CDP 关闭/接受打开的 alert/confirm/prompt(在冻结页面上也可用)

browser_run_action

通过 CDP 运行自包含的 JS action 对象


与其他方案对比

Browser Controller

Playwright MCP

Chrome DevTools MCP

使用你现有的浏览器

否,会启动新的

部分,需要调试端口

会话和 Cookie

已经存在

全新配置文件

手动设置

支持企业 SSO 登录

视情况而定

多代理、多标签页

标签页定位(不会劫持活动标签页)

不适用

经过身份验证的本地连接

不适用

设置

从源码构建 + 扩展

无头浏览器

--remote-debugging-port 的 Chrome


配置

环境变量

默认值

功能

WS_PORT

7225

守护进程用于扩展连接的 WebSocket 端口

BROWSER_CONTROLLER_PROGRESSIVE

(未设置)

设置为 1 以启用渐进式工具披露:启动时仅显示 browser_tools 元工具(约 150 个 token,而不是全部 22 个定义的约 4200 个)。代理通过 browser_tools {action:"list"/"search"} 发现工具,并通过 {action:"details", tool:"…"} 激活它们。默认(未设置)会预先显示所有工具——对于指令直接调用工具的代理来说是安全的。

MCP_AGENT_NAME

(自动:IDE 名称)

覆盖弹出窗口中显示的代理名称(与 --agent 相同)

守护进程状态文件

守护进程将所有内容保存在 ~/.browser-controller/(Windows:%USERPROFILE%\.browser-controller\):

文件

用途

enrollment.json

扩展的一次性配对密钥(模式 0600

token.json

扩展在每次 WebSocket 连接时必须提供的认证令牌(模式 0600

daemon.sock

瘦客户端连接的 IPC 套接字(mac/linux 上为 AF_UNIX;Windows 上为命名管道)

daemon.json

守护进程元数据(pid、端口、启动时间)——用于检测正在运行的守护进程

daemon.log

客户端启动守护进程时的 stdout/stderr

要完全重置:停止你的 MCP 客户端,删除该文件夹,下次运行时会用新的密钥重新创建。

可靠性

  • 守护进程在任何客户端首次运行时自动启动,并保持分离运行。

  • 连接断开时使用指数退避(1 秒 → 30 秒),每 10 秒进行 ping/pong 健康检查;错过 3 次 pong 的客户端将被驱逐。

  • 每会话 120 次/分钟的速率限制保护守护进程免受失控的代理循环影响。

  • 每个工具都有超时(大多数操作 5–15 秒,导航 60 秒),与每个工具的定义放在一起,因此不会与注册表脱节。

  • 幂等读取工具(snapshot、screenshot、text、find)在超时时会重试;有副作用的工具(click、type、navigate、evaluate)——以及 console/network(在 clear:true 时会修改状态)——绝不重试,因此点击不会触发两次。

  • 如果另一个进程已经占用了端口 7225,守护进程会拒绝启动,而不是杀死它没有启动的进程——它会报告冲突,以便你有意识地解决它。

通过为每个客户端设置 WS_PORT,在不同的端口上运行两个守护进程:

{
  "mcpServers": {
    "browser-work": {
      "command": "node",
      "args": ["/path/to/browser-controller/mcp-server/dist/index.js"]
    },
    "browser-personal": {
      "command": "node",
      "args": ["/path/to/browser-controller/mcp-server/dist/index.js"],
      "env": { "WS_PORT": "9333" }
    }
  }
}

更新每个扩展弹出窗口中的端口以匹配。


架构

一切都在你的机器上。扩展通过 localhost 上的经过身份验证的 WebSocket 连接到守护进程;MCP 客户端通过本地 IPC 套接字连接到守护进程。没有云、没有代理,没有任何东西离开你的浏览器。

browser-controller/
├── mcp-server/          MCP server (TypeScript)
│   └── src/
│       ├── daemon.ts        Single multi-client daemon (owns WS :7225)
│       ├── daemon-config.ts IPC protocol, paths, auth/enrollment tokens
│       ├── index.ts         Thin stdio MCP client (spawns daemon, multiplexes)
│       ├── bridge.ts        Extension WS server + cross-platform port probe
│       ├── register-tools.ts Progressive-disclosure wiring
│       └── tools/           One file per tool (22), registry pattern
├── extension/           Chrome extension (Manifest V3, plain JS, ES modules)
│   ├── background.js        Wiring only (~30 lines): inject router, register events, connect
│   ├── lib/                 state (buffers/locks/persistence), connection (WS lifecycle),
│   │                        router (dispatch + mutex/locks + control shield), page-exec,
│   │                        overlay, lock-ops, tab-concurrency (pure, unit-tested)
│   ├── handlers/            Tool implementations: navigation, interaction, inspection, tabs, cdp
│   ├── utils/               navigation + smart-selector fallback resolution
│   ├── events.js            chrome.* listeners (console capture, popup, webRequest, lifecycle)
│   ├── content.js           Console capture
│   └── popup/               Fixed tabbed shell (Tabs · Agents · Settings) + collapsible activity bar
├── agent-config/        Pre-built configs for Cursor + Claude Code
│   ├── cursor/              Rules and commands
│   ├── skills/              Browser automation skill
│   └── setup.mjs            One-command installer
└── tests/               15 suites / 215 tests

技术栈: TypeScript(严格模式)· MCP SDK · WebSocket · Chrome 扩展 Manifest V3 · Vitest

开发

git clone https://github.com/compnew2006/browser-controller.git
cd browser-controller
npm install
npm run build
npm test

命令

功能

npm run build

将 TypeScript 编译到 mcp-server/dist/

npm run dev

监视模式

npm test

运行完整测试套件(215 个测试)

npm run typecheck

仅进行类型检查,不输出

npm run setup:cursor

安装 Cursor 规则 + 命令

npm run setup:claude

安装 Claude Code AGENTS.md

该套件涵盖 WebSocket 桥接(包括令牌认证拒绝和统一错误通道)、工具注册表、守护进程生命周期(心跳驱逐、速率限制、IPC 认证)、每标签页并发(同标签页串行化 + 跨标签页并行),以及通过模拟的 chrome API 测试扩展行为(路由分发、shield 语义、evaluate 往返、iframe 穿透、对话框救援)。CI 在 Node 20 和 22 上运行该套件,外加 CodeQL 和 Scorecard 扫描。

更新现有安装

git pull
npm install
npm run build

然后有两个手动步骤:在 chrome://extensions重新加载扩展(运行中的 service worker 不会自行拾取文件更改),以及重启守护进程——它是长期运行的,也不会重新加载 dist/(杀掉它,或者直接重启你的 MCP 客户端,下次运行会在新构建上重新启动它)。


常见问题

这正是它的意义所在。扩展运行在你实际的 Chrome 中——相同的 Cookie、相同的会话、相同的本地存储。无需重新认证。

不会。MCP 客户端、守护进程和扩展都通过 localhost(IPC 套接字 + WebSocket)通信。没有任何东西离开你的机器。没有分析、没有遥测、没有云组件。有关威胁模型、认证设计和首次接触 TOFU 窗口,请参阅 SECURITY.md

任何兼容 MCP 的客户端。Cursor、Claude Desktop、Claude Code、Windsurf、Cline,以及任何其他支持 MCP 协议的客户端。多个客户端可以同时连接同一个守护进程运行。

可以。每个代理连接到共享守护进程,获取自己的 sessionId,并针对特定的 tabId。同一标签页上的操作通过每标签页互斥锁串行化;不同标签页上的操作并行运行。代理可以选择 lock 一个标签页以声明独占访问权;其他代理会在锁后面排队,而不是失败。

它不会——不会静默发生。每个页面交互工具都需要 tabId,如果缺少,你会收到明确的 tabId is required 错误。代理永远不会意外操作你正在查看的标签页。(唯一的例外是不带 tabIdbrowser_navigate,它使用活动标签页——但在多代理场景下,你应该始终传递 tabId。)

没有它们,你机器上的任何本地进程都可以打开到端口 7225 的 WebSocket,并驱动你已认证的浏览器会话(你的银行、你的邮箱、你公司的 SSO)。enrollment 密钥将扩展与守护进程恰好配对一次(带外,在任何 WebSocket 存在之前);然后 auth token 对每个连接进行认证。两者都存放在 ~/.browser-controller/ 中,权限为 0600

它们会从零启动一个新的浏览器实例——没有状态、没有 cookie、没有会话。你每次都必须重放完整的登录流程。而这个是连接到你已经打开的浏览器,所有内容都已加载完毕。


贡献

欢迎在问题跟踪器提交错误报告、功能请求和 PR。较大的更改请先打开一个 issue。

安全

参见 SECURITY.md——仅限 localhost 的架构、token + enrollment 设计、威胁模型和报告指南。

许可证

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityActive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables CLI coding agents to interact with your live browser tabs via MCP, using your real sessions and cookies without a sandbox.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Connects AI agents to your Chrome browser via MCP, enabling real-time control of existing tabs, sessions, and application state for development workflows.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI to control a real browser through MCP tools for clicking, typing, navigation, screenshots, and more. It supports a follow mode that tracks the active tab, plus fixed mode for controlling specific tabs.
    18
    MIT

Latest Blog Posts

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/compnew2006/browser-controller'

If you have feedback or need assistance with the MCP directory API, please join our Discord server