Network Access Tools for ChatGPT Web UI
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., "@Network Access Tools for ChatGPT Web UIscrape https://news.ycombinator.com and list the top 5 story titles"
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.
Network access tools for ChatGPT web UI
A self-hosted MCP backend giving a ChatGPT conversation unrestricted owner-directed network access: arbitrary HTTP fetch (any method, caller headers, bodies), raw TCP sockets, outbound WebSockets, and browser-grade scraping with challenge solving — plus a full guarded public-read stack with DNS admission.
Deploy your own instance and connect it to your ChatGPT account. This repository contains the application source — not a hosted public service.
Build and archive gates
npm run build executes the actual compiled Worker in isolated workerd before
writing dist/.openai/artifact-manifest.json. It checks the 16-tool inventory,
software version, source/build fingerprint, and invalid-URI rejection without
contacting external targets. Generated hosting JSON is finalized using the
Sites packager's serialization before recording hashes; source settings and
JSON semantics are unchanged. The build fingerprint now includes release scripts,
and dirty script changes cannot be advertised as a clean baked Git commit.
npm run check:artifact verifies the existing output without rebuilding: runtime
checks, exact packaged bytes, source inputs and the WASM payload must still match.
Run it against the unchanged output being archived/uploaded. Source-only tests
or SOURCE-MANIFEST.json do not prove that a packaged Worker runs the new code.
These isolated checks also do not prove active hosted routing; independently
read back software_version and build_id through the actual installed app.
Regenerate the public source inventory with npm run update:manifest after
intentional source/version changes. No environment values or Git history are
included in that inventory.
Related MCP server: local-web-mcp
What runs where
┌─────────────────────────────────────────────────────────────────────┐
│ 1. ChatGPT web UI — the MCP CLIENT (the "plugin"/connector) │
│ │
│ • Discovers tools via MCP tools/list; invokes them via tools/call │
│ • Renders results into the model's context │
│ • Runs user-selected models (GPT-6.1 Sol etc.) — NOT your code │
│ • Caches the tool list per conversation session │
└──────────────────────────────┬──────────────────────────────────────┘
│ managed OAuth via the Sites gateway
│ HTTPS POST https://your-site/mcp
┌──────────────────────────────▼──────────────────────────────────────┐
│ 2. ChatGPT Sites worker — the MCP SERVER (this repository's source) │
│ │
│ • Implements the MCP protocol endpoint at /mcp (JSON-RPC) │
│ • Owner identity comes from the Sites dispatch gateway headers — │
│ caller-supplied identity headers are stripped before they arrive │
│ • Runs 16 tools inside Cloudflare Workers isolates: │
│ – QuickJS WASM + LinkeDOM for page script execution │
│ – guarded public reads (DNS admission, quality gates) │
│ – browser_open_fetch: unrestricted HTTP(S) via platform fetch │
│ – edge tools: raw TCP via cloudflare:sockets, WebSockets │
│ • D1 persists upstream recovery state across Worker instances │
│ • NO browser/Chromium here; no filesystem; no persistent cookies │
└──────────────────────────────┬──────────────────────────────────────┘
│ one HTTPS POST → /v1 or /scrape (Basic auth)
│ only when browser_scrape is invoked
┌──────────────────────────────▼──────────────────────────────────────┐
│ 3. Your VPS — browser-grade scraping endpoint (optional) │
│ │
│ • TRAWL may serve HTTP or escalate through browser tiers │
│ /v1 does not identify the tier; native /scrape does │
│ • Sessions persist in Redis on the VPS — never in the Sites worker │
│ • Hardened: read-only containers, dropped capabilities, non-root │
│ • Stateless from the worker's perspective: one POST per scrape │
│ • If down → browser_scrape returns route:"fallback" and the │
│ caller may explicitly choose the guarded worker path instead │
└─────────────────────────────────────────────────────────────────────┘What does NOT run where: no Chromium/browser in the Sites worker (page execution is QuickJS approximation); no arbitrary code execution on the VPS beyond TRAWL's own scraping engine. Open-fetch credentials come only from explicit caller arguments; Sites identity/OAuth is never forwarded. The optional scraper uses its separate private operator binding, not caller or Sites identity.
Failover is explicit, never silent. When the browser-grade endpoint is unavailable,
browser_scrapereturnsroute:"fallback"with a reason so the model can retry viabrowser_read_page/browser_open_fetch.Two hardening layers: the guarded stack keeps DNS admission and quality gates for public reads;
browser_open_fetchtrades those for unrestricted reach. Both disclose which path served the result.
Tools (16)
Tool | Purpose |
| Measured runtime contract: engines, limits, tool inventory |
| Fixed in-process DOM/JS demo proving script execution |
| Guarded public page → clean Markdown, title, links |
| Opt-in: run page scripts in QuickJS WASM/LinkeDOM |
| Structural DOM roles/targets, caller-held plans |
| Deterministic bounded rows/fields from selectors |
| Static article/catalog/media acquisition with presets |
| Guarded public GET/HEAD with admission + quality gate |
| Up to 32 ordered acquisitions, 8 concurrent |
| Unrestricted HTTP(S): any host, method, headers, body; 60s/32MB |
| Measured runtime capability probe (raw TCP, WebSocket, Caches) |
| Raw TCP to any host:port (starttls/TLS), bounded reads |
| Outbound WebSocket, send + receive messages |
| Validated DNS A reply from fixed 8.8.8.8:53; clear TCP, no DNSSEC/reachability claim |
| Operator retrieval; optional native render-only mode, readiness check and explicit provenance/failover |
| Parallel 2–10 URL scrape, 4-way concurrency, per-item isolation |
Highlights
Explicit rendering: legacy
/v1can serve a plain-HTTP tier. A route label, Chrome-like user agent or HTTP 200 does not prove JavaScript execution. Usebrowser_scrapewithrender: trueand a CSSready_selectorgrounded in the page, for example.quoteon a known quote listing. This requires the native TRAWL/scrapecontract (skipHttp,contentWaitForSelector). The adapter checks a reported browser tier and selector matches in the complete returned HTML, disclosesrender_evidence, and fails explicitly if unsupported or missing. This is not independent engine, screenshot or layout verification. Existing FlareSolverr-compatible deployments keep their legacy default.Readability extraction:
browser_scrapereturns cleaned text/title/links server-side (22KB cap) — the model sees content, not truncated HTML.SPA/login-shell detection: results flag
app_shell_suspectedwith reasons (SPA mount nodes, low visible text, login screens). Detection does not reroute automatically: callers must explicitly request nativerender: truewhen rendered content is needed, and still inspect readiness/content evidence.Circuit breaker: consecutive probe timeouts widen cooldown exponentially (60s→240s, capped); healthy responses reset it. Recognized target solve errors and caller aborts do not poison health. Opaque upstream 500/proxy/service errors still trigger a persisted cooldown while their cause is unknown.
Durable recovery state: configured MCP scraping requires its own private D1 binding,
UPSTREAM_STATE, declared in.openai/hosting.json. The supplied schema-onlydrizzle/migration is packaged intodist/.openai/drizzle/and applied through the normal Sites publication workflow. Do not connect another app's caption/financial database or copy a private native hosting identity. Cooldowns, fixed-class incident aggregates and auth stop latches survive new Worker instances. An expiring lease admits one health probe after cooldown; sequence fences stop older responses from overwriting newer outcomes. Recovery is on demand, not a background target-retry loop. Operator auth denials stay latched; remediation requires an authorized owner workflow. State-storage failures are explicit.browser_capabilities.upstream_recoveryexposes current durable counters and the most recent eight redacted aggregate records, not raw URLs/errors/secrets. Unknown 500s are not yet a diagnosed root cause merely because their tracking is durable. FirefoxNS_ERROR_UNKNOWN_HOSTis recognized as a target DNS failure only with an exact legacy request-URL/status binding; proxy-specific and unbound errors remain distinct. The failing target still reports a failure, while unrelated valid targets need not inherit a falsely opened global circuit.Anti-herd jitter: probe retries stagger across isolates.
4xx/5xx classification: TRAWL request-level errors don't block subsequent unrelated URLs; only endpoint-health failures do.
Install
1. Prerequisites
Node.js 22.13+, a ChatGPT account with Sites access, and (optional, for
browser_scrape) a Docker/Dokploy VPS for the TRAWL browser-grade endpoint.
git clone https://github.com/YOUR_USERNAME/chatgpt-web-ui-network-access.git
cd chatgpt-web-ui-network-access
npm ci
npm test # build, workerd, adapter, regression and privacy checks
npm run build # dist/server/index.js + quickjs.wasm2. Deploy the Sites worker
Deployment happens through ChatGPT's Sites workflow — not git push.
Open Work in ChatGPT web (or ask a Sites-capable agent) and reference this repository. Give it the source and ask it to create a private Site with the
mcpcapability (.openai/hosting.jsonis included).Set environment bindings in Site settings (names only enter source; values stay private):
Binding
Purpose
OWNER_EMAILYour authorized owner identity
ORIGINThe existing Site HTTPS origin, without a path
PROJECT_ID(optional) Native Site project identity for provenance
TRAWL_URL(optional) Your TRAWL endpoint base URL for
browser_scrapeTRAWL_TOKEN(optional) Basic-auth password for that endpoint
Without
TRAWL_URL,browser_scrapereturnsroute:"fallback"withtrawl_not_configured— the other 15 tools work regardless.Owner and origin bindings are required and read at runtime. Missing values fail closed. Do not replace private values with public-template placeholders in an existing deployment, or embed those values in committed source.
Publish the approved version and capture the HTTPS origin. Append
/mcpfor the MCP endpoint.
3. (Optional) Browser-grade endpoint on your VPS
Run a FlareSolverr-compatible scraper (e.g. TRAWL)
behind an HTTPS reverse proxy with Basic auth. See TECHNICAL_NOTES.md for the
hardened Compose pattern: read-only containers, dropped capabilities, non-root
services, and a Traefik basic-auth middleware.
4. Connect ChatGPT web UI
Install the Site-generated plugin from its card (Plugins → Personal → Created by
you), complete the managed authorization, and mention the app in a new chat.
Verify with browser_capabilities — it reports the measured tool inventory.
Security notes
Owner identity headers are trusted only behind the Sites dispatch gateway.
The adapter never fakes a TRAWL result and never silently downgrades: failover is a typed routing decision disclosed in every response.
Caller-supplied credentials (headers, bodies) are explicit per-call arguments; the worker has no cookie jar and never forwards Sites identity.
Probe/failure state is shared through the separate private D1 binding; persisted cooldown expiry permits an owned health probe on demand. A dead endpoint returns explicit fallback within the bounded probe budget (4s).
Known limitations
Raw TCP on port 53 is intercepted by the Cloudflare edge (DNS-over-TCP tool is demonstrative; DNS resolution uses DoH).
Worker
fetchcannot shape the TLS handshake (no JA3 control) — that is what the TRAWL browser tier provides.Plain-HTTP targets route directly to fallback (the browser tier is HTTPS-only in practice).
The connector caches the tool list per ChatGPT session; use a fresh chat after deploying new tools.
A listed tool or successful build is not live Internet acceptance. Platform restrictions and target denials remain possible; verify returned content, source URL, complete-body hash and explicit truncation fields.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Browse and inspect sites in your own Kitsuvo browser through an opt-in authenticated relay.
Call third-party APIs from agents without leaking secrets. SSRF blocked, per-key quotas.
Route HTTP requests through the Tor network. Rotating exit IPs, .onion support, no body logging.
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables reverse engineering of web applications and chat interfaces through browser automation, network traffic capture, and streaming API discovery. Provides comprehensive tools for analyzing network patterns, capturing streaming responses, and automating complex web interactions.1410 npm1ISC
- AlicenseAqualityCmaintenanceEnables Claude to fetch web pages from the user's own local network connection instead of AI datacenter IPs, including optional authenticated sessions, with verdicts for bot challenges, login walls, and other failures.1AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables web chats and other agents that cannot make HTTP requests to interact with parlor.sh rooms through remote MCP tools, such as fetching pages, creating/joining rooms, reading messages, posting, closing, and aliasing.MIT
- AlicenseNot gradedqualityBmaintenanceEnables fetching web URLs through authenticated residential egress with provider, country, and session controls. It also exposes tools for checking the exit IP, account status, and masked connection URL.24 npmMIT