AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Websense Mcp

mcp-spliffspliff70-wq-websense-mcp · by spliffspliff70-wq

WebSense MCP — non-vision, AI-native browser automation via the Semantic Action Graph. No screenshots, no CDP, no bot detection.

— No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add mcp-spliffspliff70-wq-websense-mcp

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ● Network access Used
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-spliffspliff70-wq-websense-mcp)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● yesterday

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Websense Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

WebSense MCP

[](https://github.com/spliffspliff70-wq/websense-mcp/releases/latest) [](LICENSE) [](extension/manifest.json)

> Non-vision, AI-native web automation via the Semantic Action Graph. No screenshots, no CDP, no bot detection.

Quick Start

  1. git clone https://github.com/spliffspliff70-wq/websense-mcp && cd websense-mcp && npm install
  2. Load the extension: chrome://extensions → Developer mode → Load unpacked → select

extension/. It auto-connects to the WebSocket hub on port 38401 (no launcher page).

  1. Register the MCP server in your client (stdio, or --http for the streamable-HTTP transport):
{ "mcpServers": { "websense": { "command": "node", "args": ["src/server.js"] } } }
  1. Call any tool (e.g. explore_page). Flow: MCP → WS → Extension → Content Script → DOM.

Bridge port: default 38401. Override with --port (server) and the matching PORT constant in extension/offscreen.js (extension). If the port is already taken, the hub logs a warning and the server keeps running (MCP still works) — the bridge just isn't claimed. Run multiple isolated servers with different --port values.

> Chrome-only. WebSense is built, tested and supported on Chrome / Chromium (MV3, offscreen > WS bridge). It has never been developed or tested on Firefox, and there is no Firefox code in > this repo. Do not expect it to work there.

Architecture

MCP Client (Claude / Cline / Cursor / Hermes)
    ↔ stdio
WebSense MCP Server (src/server.js)
    ↔ WebSocket localhost:38401
Chrome Extension (extension/)
    ├── background.js    service worker, tab management
    ├── offscreen.js     WebSocket client, auto-reconnect
    └── websense-cs.js   SAG extraction + native DOM interaction (CSP-safe)
    ↔ chrome.runtime.sendMessage
Live DOM

Tools (31) — call websense_guide first

> Count verified 2026-09-21 by tools/list against the RUNNING server > (POST http://127.0.0.1:9222/mcp, streamable HTTP JSON-RPC): 31 tools. > The same 31 reg(server, …) names are in src/server.js. Anything in these > docs that says 20/21/29/43/61 tools is stale.

Guide & Status

websense_guide · status (kind:page|bridge|doctor|downloads)

Exploration

explore_page (compact:list, intent:find, goal:goal-filter, preload:lazy, incremental:delta-since-last-scan)

Page Map (lossless, addressable)

page_snapshot (LOSSLESS inventory of the page held server-side; returns only the small INDEX — counts + sliceable dimensions. Nothing is cut: not interactive-only, not in-viewport-only, and it is scroll-stable) · page_slice (fetch ONE slice at full fidelity: tag|role|region|vp|interactive|query — every record carries a usable locator)

Read

read (format:text|content|markdown|diff|scrollextract|preload)

Interact

click (ref|xy, mode:click|hover|rightclick|drag) · type_text (ref+text|fields:[]) · form (state|select|toggle|upload) · scroll (direction|y|intoView) · press_key

Element Intel

reveal (kind:dropdown|tabs|accordion) · inspect (kind:element|geometry|relation)

Tabs & Navigation

navigate · tabs (list|switch|close|bind|frames|windows|focus|move|transfer|switchread)

Wait

wait (conditions ANDed | event mode)

Page Control

evaluate (script|query) · main_world (compiled fn in the page MAIN world — F12-insider path for reads/writes the isolated world can't do) · screenshot · dialog (accept|dismiss|keystroke)

Session & Network

session (reset|map|mermaid) · network_log · console_log (captured console + JS errors) · cookies (list/get/set/clear metadata — never values) · clipboard (copy|read)

AX Bridge

ax (state|read|click|type) — for canvas SPAs & chrome:// pages

REAL Input (genuine OS-level, for synthetic-ignoring widgets)

real_activate_tab (UIA tab-pill click) · real_click (SendInput at viewport x,y) · real_paste (OS click + clipboard + Ctrl+V)

Extension maintenance

respawn_offscreen (recreate the offscreen doc so current on-disk code loads) · extension_reload (chrome.runtime.reload + reconnect wait)

> Each tool absorbed 2-10 old one-verb tools. Full absorption table in websense_guide. All 65 original capabilities are callable — just through the consolidated tool with a mode/format/action/kind parameter instead of a separate tool name.

Dialog handling

  • JS dialogs (alert / confirm / prompt) are captured, including the ones the page itself

raises — a MAIN-world hook shadows the three functions (the content script's isolated-world copy was never called by page code, so dialogs used to go unseen and Chrome auto-dismissed them in a background tab). status lists them in pendingDialogs (waiting) and recentDialogs (already fired, with the outcome). Resolve with dialog action:"accept"|"dismiss" (+ value for prompt); the answer really reaches the page's promise. Confirm/prompt auto-answer after 30s so a page can never wedge.

  • DOM modals ([role=dialog], most in-app modals) are closed by ref; status.hasModal /

dialogCount come from a visibility-blind scan (a hidden modal still counts).

  • OS-level dialogs (HTTP basic-auth, proxy-auth, print): can't be intercepted by JS. dialog keystroke:true key:"enter"|"escape" injects a global keystroke through Windows control (PowerShell SendKeys). This is the windows-control bridge.
  • File picker: handled by form action:"upload" (DataTransfer API) — no OS dialog.

Iframes / frames (the other gap vs. a human — now closed)

  • tabs action:"frames" returns every frame in the target tab (pass tabId; omit it and you

get your bound tab) with its frameId and URL.

  • Pass frameId to any element tool (explore_page({frameId}), click({ref, frameId}), type_text({ref, frameId}), …) to target a specific iframe. This unlocks Gmail compose, Notion, Figma, and any site that renders key UI inside child frames.
  • read (format:"text") and element labels now include CSS ::before/::after content (icon-font glyphs, counters) that innerText misses.

Cross-browser

  • Chrome / Edge / Opera: load extension/manifest.json (MV3, offscreen WS bridge).

Key Features

  • CSP-Safe (30/31 tools): native DOM functions in the content script's isolated world. No eval, no string-to-code. Works on LinkedIn, GitHub, Google — any strict-CSP site. (evaluate is the only eval-based tool — and its script mode is blocked by the extension's own MV3 CSP on every page, so use its query mode or main_world; dialog keystroke:true is a Windows-control keystroke, and main_world uses Chrome's userScripts MAIN-world path which is CSP-proof by design.)
  • React-Compatible: native prototype value setters bypass React's value tracker, then input/change events are dispatched.
  • No Bot Detection: real Chrome profile, cookies, fingerprint. No CDP, no navigator.webdriver, no headless.
  • No Vision: all structured JSON; no screenshots, no vision model.
  • Action-Typed Elements: every element classified by action type with predicted effects.
  • Exploration Graph: persistent navigation map with Mermaid export.
  • Frame-Aware: targets iframes via frameId; no DOM region is unreachable.

Token cost — measured, not estimated

Real payloads from the three sites this tool is used on most (2026-09-25):

| call | x.com | Reddit | GitHub | |---|---|---|---| | explore_page{full:true} | 183 KB / 726 ms | 147 KB / 132 ms | 79 KB / 34 ms | | page_snapshot (lossless index) | 1.8 KB / 147 ms | 1.8 KB / 81 ms | 1.5 KB / 33 ms | | page_slice (25 records) | 8.4 KB | 8.1 KB | 7.8 KB | | explore_page{intent:"…"} | ~4 KB / 29 ms | ~4 KB / 30 ms | ~4 KB / 4 ms |

So the index is 53-102x smaller than a full explore, and intent is cheaper still. Start with intent when you know what you want, page_snapshot + page_slice when you need to map the page, and reserve full:true for small pages (forms, settings) where you genuinely want every action. A single full:true on a large SPA is the most expensive call in the toolset.

Background by default

Page ops never take the foreground. The complete list of things that do:

  1. real_activate_tab, real_click, real_paste — OS-input by design.
  2. tabs action:"focus" and action:"move".
  3. One automatic case: if the target tab's Chrome window is minimized or collapsed,

its viewport is 0×0 and every read comes back empty, so WebSense restores that window to read the page and then reports windowRestored: true with a note saying why. It never raises a window that is merely in the background or occluded.

  1. Things with no background path at all: native file dialogs (OS open/save), OS-level

print dialogs, and attaching a real file to a composer via a custom dropzone — that attaches a realm-local File that never uploads, so use real_paste.

Known limitations

  • dialog cannot answer a native dialog raised while the tab is hidden — Chrome auto-dismisses

those before the page can be reached. A MAIN-world hook records them either way (status.recentDialogs), so you can see that one fired, but the answer comes from the hook's auto-resolution rather than from you. Activate the tab first if the answer matters.

  • evaluate script mode runs your JS and returns its value. The isolated-world path

(new Function) is blocked by the extension's own MV3 CSP, so it transparently re-routes through the MAIN world (chrome.userScripts, no eval) and reports via:"main_world". This works on every page — it is not a strict-site limitation. evaluate{query:{…}} is still the lighter path for plain DOM reads.

  • Refs are stable: E# refs are assigned in viewport order on the first scan and then held by

element identity (per-element cache + a data-websense-ref attribute), so they survive re-explores, scrolls, and framework re-renders. Measured: 41/41 unchanged across a full re-explore, 0 changed after a scroll, 0 after a re-render, and a stale ref healed onto a replacement node with the same label and no id/class. A ref only dies when its element leaves the DOM with nothing to heal from. CSS-selector refs (#id) are still the safest choice for anything long-lived or across navigations.

  • One profile, per-tab isolation: concurrent jobs share one Chrome profile — there is no

cookie/storage isolation between them, so scope work with tabs action:"bind" + explicit tabId. Session state (map/history) is per-session: session action:"reset" clears only your own history, and one job's steps never appear in another's map.

  • Logged-in sites (LinkedIn etc.): must already be authenticated in that Chrome profile; navigate opens a fresh tab that needs an existing session cookie.
  • Canvas/WebGL content (Telegram web, TradingView, chrome:// pages): use ax action:"read" to see the native accessibility tree, then ax action:"click"|"type" to interact. Fallback: screenshot + vision.
  • ax tool uses chrome.debugger — stable Chrome compatible, shows a warning banner while attached. Requires explicit tabId.

v1.4.5 (2026-09-25) — twelve defects, three of them false promises

  • Truth fixes: the action effect verdict was unverifiable for every relayed action (it never

unwrapped the relay envelope); it no longer recommends a real OS click for a merely unmeasurable action; and the DELTA block no longer claims mutated:false means the action failed (it only means no interactive-element fingerprint changed).

  • Now working (previously never did): network_log captures real page traffic (MAIN-world

hook), wait{selector} succeeds, reveal kind:"dropdown" resolves, status kind:"doctor" reports a live service worker, navigate/tabs frames honor tabId, batch type_text counts are honest, extension_reload really reloads, and respawn_offscreen stops reporting false failures.

  • Privacy: password/OTP values are masked on every surface that can echo them.
  • Docs: the in-tool guide, MODEL_PROMPT.md (now generated from the guide, with a test that

fails on drift) and this README all state the measured behavior. See CHANGELOG.md for the full list.

v2.1-latchproof (2026-08-15)

  • Multi-slot concurrency (hub.js): request correlator is now Map — concurrent sessions no longer clobber each other.
  • Latch-proof routing (background.js): chrome.tabs.onActivated/onRemoved events keep the tab registry live; 0×0 viewport self-heal.
  • Honest interaction (websense-cs.js): type_text verify-persist — reports confirmed/reverted instead of phantom success.
  • AX bridge (offscreen.js): ax tool (state/read/click/type) via chrome.debugger (CDP Accessibility domain). Stable Chrome compatible, no dev-channel flags.
  • windows-control DPI-aware (uia_common.py): physical→logical coordinate scaling fixes clicks on scaled displays.

Testing

# Regression suite (127 tests: hub, delta, guide-truth guards — no Chrome needed)
npm test

# Full end-to-end live test (needs Chrome + extension loaded)
node test/mcp-client-test.js

# Keep MODEL_PROMPT.md in sync with the in-tool guide (runs inside npm test)
node tools/export-guide.mjs --check

File Structure

websense/
├── package.json
├── src/
│   ├── server.js       # MCP server with 31 consolidated tools
│   ├── hub.js          # WebSocket hub
│   ├── session.js      # Exploration map + diff engine
│   └── mermaid.js      # Mermaid export
├── extension/
│   ├── manifest.json   # Chrome MV3
│   ├── background.js    # Service worker (tab mgmt, offscreen lifecycle)
│   ├── offscreen.js     # WebSocket client (auto-reconnect)
│   ├── offscreen.html
│   └── websense-cs.js   # SAG extraction + native DOM interaction
└── test/
    └── mcp-client-test.js   # End-to-end MCP client test

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.