Skip to main content
Glama
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.