ptc-web
ptc-web
A standalone browser-content MCP server for JavaScript-rendered pages.
Demo software. It gives compatible MCP clients bounded, inspectable access to web content. Its URL policy and resource limits are deliberate boundaries, but it is not a general-purpose browser automation service.
Read JavaScript-rendered pages as bounded Markdown or structured records. Keep site-specific interpretation in extraction recipes while the server owns browser access, HTML parsing, extraction, and resource limits.
Implemented foundation
TypeScript and Node.js 20.19 or newer, with exact dependency versions.
Official
@modelcontextprotocol/serverv2 and MCP2026-07-28only over stdio. Legacy initialization is rejected.Playwright Chromium in a server-owned persistent profile, temporary by default and never shared with the user's normal browser profile.
Immutable, expiring DOM snapshots; paginated Markdown/text reads; literal passage finding; and declarative CSS-selector record extraction.
Mozilla Readability for articles, Turndown with GFM for Markdown, and Cheerio for selectors.
Deterministic authored fixtures for article, listing, discussion, documentation, dynamic rendering, and a held-out article layout.
Install and run
Install the Chromium build matching this package once, then start the MCP server through npm:
npx -y playwright@1.63.0 install chromium
npx -y ptc-webFor a source checkout:
pnpm install --frozen-lockfile
pnpm exec playwright install chromium
pnpm run build
node dist/src/cli.jsThe process speaks MCP on stdout and writes only bounded diagnostics to stderr.
--help and --version do not start Chromium.
Tools
Tool | Contract |
| Open a permitted URL and wait for a bounded readiness condition. |
| Freeze the current DOM into an immutable snapshot and return a preview. |
| Read paginated Markdown or text using |
| Apply a declarative container/field CSS recipe to a snapshot. |
| Find paginated literal passages in a snapshot representation. |
| Close a browser page; its snapshots remain readable until expiry. |
Every cursor is process-local, integrity protected, and bound to the immutable snapshot, operation, representation, and recipe/query that issued it. A cursor cannot silently resume against changed parameters. Snapshot coverage reports DOM truncation, blocked subrequests, network request count, and the fact that unloaded site content remains unknown.
Access policy
Public HTTP(S) is allowed by default. URL credentials, other schemes, and IPs that are not globally routable are denied. Hostnames are resolved and every answer must be public. Each intercepted fetch disables automatic redirects; Chromium receives one redirect hop at a time, and every next hop is routed through policy before it is fetched. The same policy applies to every browser subrequest. Service workers are disabled.
Tests and deliberate local installations can allow exact origins (scheme, host, and port) with a comma-separated value:
PTC_WEB_ALLOW_LOCAL_ORIGINS=http://127.0.0.1:8123,http://[::1]:8123 node dist/src/cli.jsThis does not allow other ports or other local origins.
Configurable limits
Environment variable | Default | Meaning |
| 2 MiB | Retained UTF-8 DOM bytes per snapshot. |
| 8 MiB | Response-body bytes per browser network request. |
| 256 | Requests including explicit redirect hops per page. |
| 48,000 | Serialized application result target per tool call. |
| 32 | Live snapshots in one server process. |
| 8 | Concurrent page handles. |
| 500 | Containers considered by one extraction. |
| 200 | Matches considered by one find. |
| 15,000 | Maximum open/readiness time. |
| 300,000 | Snapshot lifetime. |
All limits must be positive integers; the result limit must be at least 8 KiB.
PTC_WEB_PROFILE_DIR opts into a host-owned dedicated profile directory.
PTC_WEB_HEADLESS=false displays Chromium. Temporary profiles, pages, and
snapshots are cleaned up on normal shutdown; cancellation closes an in-flight
page.
Validation
pnpm run verifyThe default suite covers the library, browser behavior, MCP stdio transport, security boundaries, fixtures, and extraction behavior. One optional compatibility lane exercises the server through PtcRunner; the server itself does not depend on PtcRunner.
Design
Search, arbitrary click/scroll operations, existing-Chrome integration, hosted extraction services, and a custom extension are intentionally outside this foundation.
Development and releases
CI tests Node.js 20.19, 22, and 24 on Linux and macOS, and smoke-tests the packed npm artifact. See RELEASING.md for the tag-driven npm release process. This project is available under the MIT License.
Dynamic screen-scraper example
The dynamic-parser example combines
ptc-web with a separately installed filesystem MCP server. A workflow opens
a JavaScript-rendered page, selects parser code from a writable file, executes
that parser against the captured page, and saves the result. Changing the
parser file changes the screen scraper on the next run without restarting the
runtime or modifying ptc-web.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/andreasronge/ptc-web'
If you have feedback or need assistance with the MCP directory API, please join our Discord server