chatgpt-pro-mcp
by JNSlayer2
README.md
# chatgpt-pro-mcp
`chatgpt-pro-mcp` is an **experimental guarded MCP bridge** for Codex/open-ultrawork `ProResearchJobV1` workflows.
It is intentionally **not** a ChatGPT API wrapper and does **not** expose ChatGPT Pro as a synchronous `/v1/responses` model. It exposes a narrow async job interface so Codex can submit bounded research work, poll status, fetch a report artifact, and then run Codex-side source verification / claim promotion gates.
Current state: **fake adapter + guarded host-side Web adapter**. The Web adapter can classify a logged-in ChatGPT page, submit a bounded `ProResearchJobV1` only when explicitly enabled, return early for async work, later reattach/fetch the result, and import it as `ProResearchResultV1`. It still does **not** expose ChatGPT as a synchronous `/v1/responses` model, and it does not claim Deep Research equivalence unless the UI/session actually provides that behavior and Codex verifies the returned sources/claims.
## Why this exists
Codex/open-ultrawork needs a high-strength research counselor lane:
```text
Codex/open-ultrawork
-> ProResearchJobV1
-> chatgpt-pro-mcp async job
-> guarded ChatGPT Pro Web/App UI lane
-> report + sources + claim ledger
-> Codex source verification / supported-unsupported classification / next tests
```
The user should not be dragged into mechanical copy/paste unless login, CAPTCHA, terms, billing, or another human-only event blocks automation.
## Tools
- `get_bridge_status`
- `get_web_preflight`
- `submit_deep_research`
- `get_deep_research_status`
- `fetch_deep_research_result`
- `cancel_deep_research`
This MCP server intentionally does **not** expose raw browser tools like `goto`, `click`, `type`, `read_dom`, or cookie/session export.
## Run locally
```bash
npm ci
npm test
node scripts/selftest.mjs
npm run doctor
node src/mcp-server.mjs
```
`npm run doctor` runs unit/contract/security tests, the fake selftest, redaction scan, and Web preflight. Web preflight is advisory: real submission still requires a manually logged-in dedicated browser profile and explicit submit opt-in.
CLI smoke:
```bash
node src/cli.mjs web-preflight
node src/cli.mjs submit '{"schema":"ProResearchJobV1","title":"MCP smoke","question":"Research MCP async bridge patterns with primary sources.","privacy_classification":"public","output_requirements":{"language":"zh-Hant","format":"markdown","citations_required":true,"include_uncertainty":true}}'
```
## Fake UI fixture tests
The sandbox includes local fake ChatGPT HTML fixtures for completed/running/login/terms/billing states. These tests validate the state-machine and fail-closed behavior without opening a real browser or touching a real ChatGPT account.
## Docker sandbox
Docker is optional. If you want containerized contract/security tests:
```bash
docker build -t chatgpt-pro-mcp:sandbox .
docker run --rm chatgpt-pro-mcp:sandbox npm test
```
For this project, Docker is suitable for schema/security/fake-UI tests. Real ChatGPT Web/App automation will likely need a host-side browser profile adapter because ChatGPT session state must not be baked into a container image or public repo.
## Safety rules
Permanent hard-deny actions:
- login / signup / OAuth authorization
- password / OTP / passkey entry
- upgrade / subscribe / purchase / checkout / payment / billing
- accept terms / privacy policy
- enable connector / install plugin
- change settings
- read/export/delete chat history
If encountered, the bridge returns `waiting_user` or `blocked` and fails closed.
V0 intentionally rejects file attachments. Put only public-safe, minimized context in the `question`; do not send local absolute paths, secrets, raw logs, or private thread URLs.
See `SECURITY.md` and `THREAT_MODEL.md`.
## Host-side Web adapter guard
The Web adapter is present but disabled by default. It only runs when all of these are true:
```bash
CHATGPT_PRO_MCP_ADAPTER=web
CHATGPT_PRO_MCP_ENABLE_REAL_UI=1
```
Even then, it first opens the ChatGPT entrypoint and classifies auth/terms/billing/ready states. It returns `waiting_user` unless `CHATGPT_PRO_MCP_ALLOW_SUBMIT=1` is also set. With submit enabled, it sends only the fixed research-job prompt, waits for the current assistant response, imports the result, and marks all claims as `needs_verification` by default.
Config values are fail-closed: invalid wait-time env vars or non-ChatGPT entrypoints abort before browser control.
## Manual session setup for future real smoke
Use a dedicated profile. The script opens ChatGPT in a normal browser window; you complete login/CAPTCHA/terms manually, then close the browser. The bridge never receives your password/OTP.
```bash
CHATGPT_PRO_MCP_PROFILE_DIR=$HOME/.chatgpt-pro-mcp/profiles/default npm run web:login-native
```
Then guarded smoke can run with:
```bash
CHATGPT_PRO_MCP_ADAPTER=web CHATGPT_PRO_MCP_ENABLE_REAL_UI=1 CHATGPT_PRO_MCP_WEB_LAUNCH_MODE=native-cdp CHATGPT_PRO_MCP_PROFILE_DIR=$HOME/.chatgpt-pro-mcp/profiles/default node src/cli.mjs submit '{...ProResearchJobV1...}'
```
Without `CHATGPT_PRO_MCP_ALLOW_SUBMIT=1`, the adapter classifies the UI and stops before prompt submission.
Note: `web:login-profile` uses Playwright and may be blocked by ChatGPT/Cloudflare. Prefer `web:login-native` for manual login because it launches a normal macOS browser with the same isolated profile.
## Real Web smoke
After manual login succeeds, a bounded real smoke can be run with explicit opt-in:
```bash
CHATGPT_PRO_MCP_ADAPTER=web \
CHATGPT_PRO_MCP_ENABLE_REAL_UI=1 \
CHATGPT_PRO_MCP_ALLOW_SUBMIT=1 \
CHATGPT_PRO_MCP_WEB_LAUNCH_MODE=native-cdp \
CHATGPT_PRO_MCP_PROFILE_DIR=$HOME/.chatgpt-pro-mcp/profiles/default \
node scripts/web-real-smoke.mjs
```
Expected result: `status=completed`, `marker_found=true`, and result metadata similar to:
```json
{
"deep_research_confirmed": false,
"author_model": "chatgpt-pro-web",
"executor_host": "chatgpt-pro-mcp-web-adapter",
"authority_mode": "research_ui_bridge",
"sync_responses_model": false
}
```
This proves Web UI collaboration and information return. It does not prove full ChatGPT Deep Research mode unless the report itself shows source-backed Deep Research behavior and Codex verifies the sources.
## Optional Codex MCP registration
To expose the bridge as a Codex MCP server on a local machine:
```bash
bash scripts/install-codex-mcp.sh --preflight # read-only checks
bash scripts/install-codex-mcp.sh # guarded, no submit
bash scripts/install-codex-mcp.sh --allow-submit # enables bounded Web UI submissions
```
The installer updates `$CODEX_HOME/config.toml`, creates a timestamped backup, and uses the current checkout path. It does not copy browser profiles, cookies, audit logs, or `.data/`.
Fresh clone path:
```bash
git clone https://github.com/JNSlayer2/chatgpt-pro-mcp.git
cd chatgpt-pro-mcp
npm ci
npm run doctor
npm run web:login-native # human login only, if needed
bash scripts/install-codex-mcp.sh --allow-submit
```
Every submitted job includes a public-safe `plan_id` and the prompt title is prefixed with `[Codex ProResearch]` so the ChatGPT sidebar remains searchable and you can inspect Codex/subagent communication directly.
## Async open-ultrawork behavior
For open-ultrawork-style long research jobs, prefer async mode:
```bash
CHATGPT_PRO_MCP_RETURN_AFTER_SUBMIT=1
```
In this mode `submit_deep_research` returns `running` as soon as the ChatGPT thread is created. `fetch_deep_research_result` can later reattach to the private local thread URL stored in `.data/`, wait with `wait_seconds`, extract the latest assistant response, and import a `ProResearchResultV1`. The private thread URL is not returned through MCP and `.data/` must remain uncommitted.
Deep Research selection is best-effort:
```bash
CHATGPT_PRO_MCP_RESEARCH_MODE=auto # try if a visible Deep Research control exists
CHATGPT_PRO_MCP_RESEARCH_MODE=standard # do not try
CHATGPT_PRO_MCP_REQUIRE_DEEP_RESEARCH=1 # fail closed if the control is unavailable
```
The bridge records whether a Deep Research control was found in `result.authority.research_mode`. If it is not enabled, the output is still useful as a ChatGPT Pro Web research memo, but it must not be described as verified Deep Research.
`deep_research_confirmed` is a separate promotion gate and defaults to `false`; a clicked UI control alone is not enough to promote a report to confirmed Deep Research.
## Source verification helper
After a completed job, you can check source reachability:
```bash
node scripts/verify-source-links.mjs --task-id dr_<uuid> --data-dir .data
```
This only verifies link reachability. It does **not** verify that a claim is supported by source content; Codex/open-ultrawork still owns claim-by-claim promotion.
## Local runtime cleanup
The bridge keeps private task records and artifacts under `.data/` so later fetch calls can reattach to the same ChatGPT thread. Clean old local job records with a dry run first:
```bash
npm run cleanup -- --older-than 30d
npm run cleanup -- --older-than 30d --confirm
```
Cleanup removes old `.data/jobs/*` records and matching `.data/artifacts/*` folders only. It does not touch browser profiles, cookies, audit logs, or ChatGPT history.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues