npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@choonkeat/agent-reverse-proxy

v0.2.9

Published

MCP server with reverse proxy and debug instrumentation for app preview

Readme

agent-reverse-proxy

A reverse proxy that sits in front of your web app, injecting debug instrumentation and exposing MCP tools so AI agents can inspect the running page — query DOM elements, capture console logs, errors, and network requests.

Install

npx @choonkeat/agent-reverse-proxy --help

Or install globally:

npm install -g @choonkeat/agent-reverse-proxy

Usage

# Proxy requests to your app on port 3000 (default)
agent-reverse-proxy

# Specify a different app port
agent-reverse-proxy --app-port 8080

# Specify the proxy port (default: 20000 + app-port)
agent-reverse-proxy --proxy-port 9000

# Plain reverse proxy, no debug script injection
agent-reverse-proxy --no-inject

# HTTP-only mode (no stdio MCP transport)
agent-reverse-proxy --no-stdio

# Custom tool prefix (default: "proxied")
agent-reverse-proxy --tool-prefix preview

The proxy starts on localhost:23000 (by default) and forwards to your app on localhost:3000. HTML responses get a small debug script injected that captures console output, errors, and network activity.

How it works

Browser ──► agent-reverse-proxy (:23000) ──► Your app (:3000)
                   │
                   ├── Injects debug script into HTML responses
                   ├── Captures console.log/warn/error/info/debug
                   ├── Captures fetch() and XMLHttpRequest
                   ├── Captures uncaught errors and promise rejections
                   ├── Tracks SPA navigation (pushState, popstate)
                   └── Exposes MCP tools for AI agents

MCP tools

The proxy registers two MCP tools (prefixed with --tool-prefix, default proxied):

proxied_browser_snapshot

Query DOM elements by CSS selector. Returns text content, inner HTML, visibility, and bounding rect.

{ "selector": "h1" }

proxied_browser_console_messages

Listen for console output, errors, and network requests for a specified duration (1–30 seconds).

{ "duration_seconds": 5 }

MCP resources

  • proxied-browser://reference — How the proxy works: tools, message types, port configuration
  • proxied-browser://help — Debugging workflow and tips

Port configuration

| Environment variable | Flag | Default | |---|---|---| | APP_PORT or PORT | --app-port | 3000 | | PROXY_PORT | --proxy-port | 20000 + app port |

Embedding as a Go library

The root package is agentproxy — import it to mount the proxy inside your own server.

Fixed target (proxy all requests to one backend)

package main

import (
	"log"
	"net/http"
	"net/url"

	agentproxy "agent-reverse-proxy"
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	target, _ := url.Parse("http://localhost:3000")

	// 1. Create the proxy
	proxy, err := agentproxy.New(agentproxy.Config{
		Target:      target,
		ToolPrefix:  "preview",
		ThemeCookie: "my-theme",
	})
	if err != nil {
		log.Fatal(err)
	}

	// 2. Create an MCP server and register tools + resources
	mcpServer := mcp.NewServer(&mcp.Implementation{
		Name:    "my-app",
		Version: "1.0.0",
	}, nil)
	proxy.RegisterTools(mcpServer)
	proxy.RegisterResources(mcpServer)

	// 3. Wire up all handlers
	mux := http.NewServeMux()
	mux.Handle("/mcp", proxy.MCPHandler(mcpServer)) // MCP-over-HTTP
	mux.Handle("/", proxy)                           // reverse proxy + debug endpoints

	log.Fatal(http.ListenAndServe(":8080", mux))
}

proxy (http.Handler) serves:

| Path | What | |------|------| | /__agent-reverse-proxy-debug__/inject.js | Debug instrumentation script | | /__agent-reverse-proxy-debug__/ws | WebSocket for iframe debug clients | | /__agent-reverse-proxy-debug__/agent | WebSocket for agent connections | | /__agent-reverse-proxy-debug__/ui | WebSocket for UI observers | | /__agent-reverse-proxy-debug__/open | Open a URL in the Preview pane | | /__agent-reverse-proxy-debug__/shell | Double-iframe shell page | | /* | Reverse proxy to target (with HTML injection) |

proxy.MCPHandler(mcpServer) (http.Handler) serves the StreamableHTTP MCP endpoint. Mount it wherever you want (e.g. /mcp, /api/mcp).

Dynamic target (target URL in the request path)

Set Target: nil — the proxy extracts the backend from the path as /{scheme}/{host:port}/{path...}:

proxy, _ := agentproxy.New(agentproxy.Config{
	Target:     nil, // dynamic mode
	ToolPrefix: "preview",
})

// GET /http/localhost:3000/hello → proxies to http://localhost:3000/hello
// GET /https/api.example.com:443/v1 → proxies to https://api.example.com:443/v1

Mounting at a base path

Set BasePath to mount the proxy under a prefix. All debug endpoints and proxy routes are served relative to this path:

proxy, _ := agentproxy.New(agentproxy.Config{
	BasePath:   "/preview",
	Target:     target,
	ToolPrefix: "preview",
})

mux := http.NewServeMux()
mux.Handle("/preview/", proxy) // note: trailing slash to match sub-paths
// Now:
//   /preview/              → proxied to target /
//   /preview/hello         → proxied to target /hello
//   /preview/__agent-reverse-proxy-debug__/inject.js → debug script
//   /preview/mcp           → NOT handled (mount MCPHandler separately if needed)

The injected <script src> tag and the WebSocket URL in inject.js automatically include the base path — no extra configuration needed.

API summary

// Create a proxy instance
proxy, err := agentproxy.New(cfg agentproxy.Config) (*agentproxy.Proxy, error)

// http.Handler — serves reverse proxy + all debug endpoints
proxy.ServeHTTP(w, r)

// Register MCP tools (browser_snapshot, browser_console_messages)
proxy.RegisterTools(mcpServer *mcp.Server)

// Register MCP resources (reference, help)
proxy.RegisterResources(mcpServer *mcp.Server)

// Returns an http.Handler for the MCP-over-HTTP endpoint
proxy.MCPHandler(mcpServer *mcp.Server) http.Handler

// Access the DebugHub for direct message routing
proxy.Hub() *agentproxy.DebugHub

Features

  • Reverse proxies HTTP and WebSocket connections
  • Injects debug script into HTML responses (handles gzip-encoded responses)
  • Modifies Content-Security-Policy headers to allow debug script and WebSocket
  • Strips Domain from Set-Cookie headers so cookies work through the proxy
  • Auto-upgrades ws:// to wss:// on HTTPS pages (with warning banner)
  • Shows a "waiting for app" page with auto-retry when the app isn't running
  • Supports both stdio and HTTP MCP transports

License

MIT