Feedthrough

io.github.feedthrough由 GitHub 帳號 feedthrough 發布v0.4.0更新於 Oct 24, 2026

Debug bridge inside your web app: an agent reads the DOM, console and network. Any browser.

已驗證STDIO僅桌面瀏覽器自動化開發者工具

概覽

AI 產生的概覽

在執行中的網頁裡嵌入除錯橋接,讓 AI 助理讀取 DOM、主控台與網路資料並操作頁面。

可以做什麼
Feedthrough 會把除錯橋接注入正在執行的網頁,並透過 stdio 以 MCP 工具的形式提供。檢查類工具包括 query_dom、inspect_element、get_html、get_console_logs、get_network_requests、get_page_info 與 connection_status;互動類工具包括 click、fill、hover、press_key、set_style、set_attribute、set_text 與 reset_overrides。它支援任何瀏覽器,並提供 Vite、Next.js、Nuxt、SvelteKit、Remix、Webpack、Cypress 與 Playwright 的轉接器。
適用情境
適合在開發階段除錯網頁時使用:讓助理查看即時 DOM 狀態、主控台錯誤與網路請求,或點擊、填寫表單並觀察結果。它面向本機開發流程,頁面執行在你自己的瀏覽器中,而不是另外啟動的受控瀏覽器。
執行需求
需要 Node.js 22 或更新版本以及 npx,以便在本機透過 stdio 執行 npm 套件 @feedthrough/mcp。還需要把橋接套件注入頁面,通常透過建置工具轉接器完成。WebSocket 伺服器預設綁定 127.0.0.1 的 8765 埠;FEEDTHROUGH_PORT 可覆寫埠號,FEEDTHROUGH_ALLOWED_HOST_SUFFIXES 控制允許連線的非回送來源。未宣告需要帳號或 API 金鑰。
安裝前請注意
擷取的網路請求包含請求與回應內容以及標頭,例如 Authorization 與 Cookie;這些資料會經由本機 WebSocket 離開頁面並送達所連接的 AI 助理,若助理由雲端提供,敏感值會到達該服務商。請僅在開發機器與開發資料上使用,不要把橋接套件注入正式環境建置。set_style、set_attribute 與 set_text 只作為預覽修改執行中的 DOM,不會寫入原始碼。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Feedthrough,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Feedthrough

Debug with AI — from inside your app.

Feedthrough injects a lightweight debug bridge into any running web page, then exposes everything — DOM state, console logs, network requests, and user interactions — as MCP tools. Any MCP-compatible AI agent can inspect and drive the page conversationally, in real time.

Browser (any) └── @feedthrough/core          ← injected into your page      ├── console interceptor      ├── fetch / XHR interceptor      └── DOM inspector      ↕  WebSocket@feedthrough/mcp               ← MCP server, exposes tools over stdio └── Tools: click, fill, inspect_element, query_dom,            get_console_logs, get_network_requests, …      ↕  MCP protocolClaude Code / Cursor / any MCP client

The name

Many physics and chemistry experiments run inside a sealed vacuum chamber, with all the air pumped out so nothing contaminates the experiment. The catch: you still need to control instruments inside the chamber and read their measurements, and the smallest air leak ruins the run. A feedthrough is the part that solves this — a specially engineered connector that carries electrical signals through the chamber wall while keeping the vacuum perfectly intact. You can't reach inside, but the feedthrough lets you observe and control what's happening in there anyway.

The parallel is exact: Feedthrough extracts runtime debug data from inside a running web app without disturbing it, and sends control signals back in — clicks, keystrokes, DOM queries — without breaking the execution environment.


Why Feedthrough?

Every other browser MCP tool is an external observer — it controls the browser from outside via Puppeteer or CDP and only works in Chrome. Feedthrough is an embedded agent. It runs inside the page, so it sees:

  • Framework internals (React component trees, Redux store, custom globals)
  • Any browser, not just Chrome
  • Your existing dev workflow — no separate controlled browser to launch
  • Cypress's own browser context during test runs

Packages

PackageDescription
@feedthrough/coreIn-browser bridge — intercepts console, fetch, XHR; handles commands
@feedthrough/mcpMCP server — bridges any MCP client to the browser via WebSocket
@feedthrough/cypressCypress adapter — auto-injects the bridge before each test page load
@feedthrough/playwrightPlaywright adapter — injects the bridge via page.addInitScript()
@feedthrough/viteVite plugin for apps with a static index.html
@feedthrough/webpackWebpack plugin — adds bridge as a global entry point
@feedthrough/nextjsNext.js adapter — wraps next.config.ts with withFeedthrough()
@feedthrough/nuxtNuxt 3 module
@feedthrough/sveltekitSvelteKit adapter — injects via the handle hook
@feedthrough/remixRemix adapter — injects via a Vite dev server middleware

Framework support

FrameworkAdapterNotes
Vite + React / Vue / Solid / Preact@feedthrough/viteStatic index.html — plugin uses transformIndexHtml
Next.js@feedthrough/nextjsWraps the webpack config; dev only
Nuxt 3@feedthrough/nuxtRegisters as a Nuxt module; dev only
SvelteKit@feedthrough/sveltekithandle hook with transformPageChunk; dev only
Remix@feedthrough/remixVite dev server middleware; dev only
Webpack apps@feedthrough/webpackGlobal entry point; guards against production mode
Cypress@feedthrough/cypresswindow:before:load hook
Playwright@feedthrough/playwrightpage.addInitScript()

Quick start

1. Start the MCP server

bash
npx @feedthrough/mcp

The server listens for browser connections on ws://127.0.0.1:8765 and exposes MCP tools on stdio. Override the port with FEEDTHROUGH_PORT=9000. If the port is already taken, the server steps up to the next free one rather than refusing to start — see Running several sessions at once.

2. Add it to your MCP client config

json
{  "mcpServers": {    "feedthrough": {      "command": "npx",      "args": ["@feedthrough/mcp"]    }  }}

3. Inject the bridge into your page

Vite + React / Vue / Solid / Preact:

ts
// vite.config.tsimport { feedthrough } from "@feedthrough/vite";export default defineConfig({ plugins: [feedthrough()] });

Next.js:

ts
// next.config.tsimport { withFeedthrough } from "@feedthrough/nextjs";export default withFeedthrough()({ /* your next config */ });

Nuxt 3:

ts
// nuxt.config.tsexport default defineNuxtConfig({ modules: ["@feedthrough/nuxt"] });

SvelteKit:

ts
// src/hooks.server.tsimport { feedthroughHandle } from "@feedthrough/sveltekit";import { sequence } from "@sveltejs/kit/hooks";export const handle = sequence(feedthroughHandle);

Remix:

ts
// vite.config.tsimport { feedthrough } from "@feedthrough/remix";export default defineConfig({ plugins: [remix(), feedthrough()] });

Webpack:

ts
// webpack.config.mjsimport { FeedthroughPlugin } from "@feedthrough/webpack";export default { plugins: [new FeedthroughPlugin()] };

Cypress:

ts
// cypress/support/e2e.tsimport { setupFeedthrough } from "@feedthrough/cypress";setupFeedthrough();

Playwright:

ts
// import test from the adapter instead of @playwright/testimport { test, expect } from "@feedthrough/playwright";

Or manually (any bundler):

ts
// main.tsif (import.meta.env.DEV) {  import("@feedthrough/core").then(({ init }) => init());}

4. Open your page and start asking

Once the bridge connects you'll see [feedthrough] tab connected in the MCP server output. For the simplest experience, keep a single tab open. Multiple tabs can connect at the same time and commands are routed to the most recently active one, but a single tab avoids any ambiguity.

Then ask your AI agent:

> What's on the page right now?> Click the submit button and tell me what network requests fired> Why is the counter showing the wrong value?

MCP tools

ToolDescription
get_instructions()Usage guide — recommended workflow, tool ordering, and selector tips
query_dom(selector)All elements matching a CSS selector
inspect_element(selector, properties?)Tag, attributes, full bounding rect + inViewport, ancestor path, curated computed styles, overflow info (clipped/overflowing content), clipped-by-ancestor info, effective visibility (visible + hiddenReason, accounting for ancestors), occlusion (hittable + occludedBy), accessibility (a11y: role, name, states), pseudo ::before/::after content, live form state; properties reads extra CSS props by name
get_html(selector)Raw outerHTML of a region (capped at 50 KB)
get_console_logs(limit?, levels?, match?, since?)Console output (all methods) plus uncaught errors & promise rejections; filter by levels, match, or since timestamp
get_network_requests(filter?, since?)Captured fetch + XHR — URL, method, status, duration, headers, request/response bodies (10 KB cap); narrow by filter or since
get_page_info()URL, title, readyState, viewport size, scroll position, user agent, and which bridge this page is connected to
connection_status()Connected tabs and which one is active, plus this server's name, version, and bound port
click(selector)Click an element via native click() (fires click + default activation, not the pointer sequence)
fill(selector, value)Set an input/textarea/select value (fires input + change, not keystrokes)
hover(selector)Fire mouseover/mouseenter to mount hover UI (JS handlers, not CSS :hover)
press_key(selector, key)Dispatch a key press — Enter, Escape, Tab, arrow keys, or a character
set_style(selector, properties)Preview a visual fix — set inline CSS live (not saved to source)
set_attribute(selector, name, value)Preview an attribute change — toggle disabled, swap a class, set aria-* (null removes)
set_text(selector, text)Preview wording/label changes — replace an element's text
reset_overrides()Undo every live set_style / set_attribute / set_text change

Live edit is a preview, not a save. set_style / set_attribute / set_text mutate the running DOM so the agent can show you a fix without a rebuild. They are not written to your source and reset on reload/HMR. The loop: the agent previews live, you confirm, then it edits the actual source to make it stick. Changes a framework owns (text, controlled attributes) may be overwritten on the next render — the tool result flags this so the agent can tell you.


Example app

examples/react-app is a small React app with three deliberate bugs — a good sandbox for trying out the diagnostic workflow:

bash
# Terminal 1 — appcd examples/react-app && pnpm dev    # http://localhost:5173
# Terminal 2 — MCP servercd packages/mcp && node dist/index.js

Connect an AI agent and ask it to find what's wrong. The three bugs are all invisible from the UI but findable in under a minute via get_console_logs, get_network_requests, and query_dom.


Running several sessions at once

Two AI agent sessions on one machine each start their own Feedthrough MCP server, and only one of them can have port 8765. That is handled, but it is worth knowing how.

The server moves, and tells you where it went. On a busy port it steps up (8766, 8767, …) instead of failing. connection_status() reports the port it actually bound, and the agent passes that to the dev server it starts:

bash
FEEDTHROUGH_PORT=8766 npm run dev

Every build-tool adapter — vite, webpack, nextjs, nuxt, sveltekit, remix — reads FEEDTHROUGH_PORT (or FEEDTHROUGH_URL for a full ws:// URL) in Node at config-load time and bakes the result into the injected bridge. So a committed, argument-free feedthrough() pairs correctly in any session, with no file edits. An explicit serverUrl option always wins over the environment.

If you start the dev server yourself, the environment is unset and the page falls back to 8765, which may be another session's server. Either export the port before starting it, or pin one per project (below).

Pinning a port per project. For a project you always work on in its own session, pin the port on both ends and neither has to think about it. In .mcp.json:

json
{  "mcpServers": {    "feedthrough": {      "command": "npx",      "args": ["@feedthrough/mcp"],      "env": { "FEEDTHROUGH_PORT": "8770" }    }  }}

and in the app's config, feedthrough({ serverUrl: "ws://localhost:8770" }).

Telling bridges apart. Each server picks a readable name at startup (quiet-olive-heron) and sends it to every page that connects. The page logs one line to the browser console, stores it on window.__feedthrough.server, and returns it from get_page_info(). The agent's own name comes from connection_status(). Two different names mean the tab is paired with another session's server — so "am I driving the right app?" is one call, not something you notice by watching the wrong window change.


Using with an AI agent

Recommended workflow

  1. connection_status() — confirm the bridge is connected before anything else
  2. get_console_logs() — errors and app output often identify the root cause immediately
  3. get_network_requests() — look for failed fetches, wrong URLs, or missing calls
  4. query_dom(selector) — find elements and check what's rendered
  5. inspect_element(selector) — deep-dive on a specific element
  6. click() / fill() — interact, then re-check logs and network

Project-memory snippet

Add this to whatever project-memory file your AI agent reads — CLAUDE.md for Claude Code, .cursor/rules/*.md for Cursor, and so on — to prime it with the right workflow:

markdown
## Debugging with Feedthrough
A Feedthrough MCP server is configured. When investigating UI bugs:
1. Call `connection_status()` first — fail fast if no browser is connected.2. Check `get_console_logs()` before touching the DOM.3. Check `get_network_requests()` for failed or missing API calls.4. Use `query_dom` to orient yourself, `inspect_element` to dig into a specific element.5. Interact with `click` / `fill`, then re-check logs.
Prefer element IDs as selectors — they're stable. Avoid long attribute selectors.

Sample system prompt

For one-off sessions with any MCP client:

You have access to the Feedthrough MCP server. It gives you live access to a running web appfrom inside the browser — console logs, network requests, DOM state, and the ability to clickand fill inputs. Start by calling get_instructions() for the recommended workflow.

Security

v1 is local-only. Two guards enforce this:

  • Localhost binding — the WebSocket server binds to 127.0.0.1, so it is not reachable from other machines on the network.
  • Origin validation — each incoming WebSocket connection is checked against its Origin header. Loopback origins (localhost, 127.0.0.1, ::1) are always accepted, as is any host ending with an allowed suffix (default .test, so local dev domains like Laravel Valet's myapp.test connect out of the box). Override the suffix list with FEEDTHROUGH_ALLOWED_HOST_SUFFIXES (comma-separated; replaces the default — set it empty for loopback-only). Any other origin is rejected. A .test origin can only be presented by a page actually served from a .test host, which resolves locally, so this widens which local origins connect, not network reach.

What gets captured

Captured network requests include request and response bodies and headers, including Authorization, Cookie, and any other headers your app sends. That's intentional — debugging auth and session flows needs them. But the data does leave the page over the local WebSocket, flows through the MCP server, and reaches whichever AI agent you've connected. If that agent is cloud-backed, sensitive values reach the provider. Run Feedthrough only on dev machines and dev data. Do not inject @feedthrough/core into production builds.


Development

bash
pnpm install       # install all workspace depspnpm build         # build all packagespnpm typecheck     # typecheck all packages

Requires Node.js ≥ 22 and pnpm.

Releasing

Packages are versioned independently — bump only the package(s) you actually changed and leave the rest alone. Publishing to npm is handled by CI: the Publish to npm workflow runs on every published GitHub Release and publishes only the packages whose name@version isn't on npm yet, skipping the ones already published (via OIDC trusted publishing, no tokens).

To cut a release:

bash
# 1. Bump the changed package(s) onlypnpm --filter @feedthrough/mcp exec npm version 0.1.1 --no-git-tag-version# When bumping @feedthrough/mcp, also bump the version (and packages[].version) in# packages/mcp/server.json to match — the MCP registry validates them against npm.git add packages/mcp/package.json packages/mcp/server.jsongit commit -m "Release @feedthrough/mcp 0.1.1"git push
# 2. Create a GitHub Release (this triggers the publish workflow)gh release create v0.1.1 --title "v0.1.1" --notes "..."

The workflow builds all packages and publishes only the newly bumped ones. It also publishes @feedthrough/mcp to the official MCP registry (io.github.feedthrough/feedthrough) via GitHub OIDC whenever the registry is missing the current version, so a failed registry publish can be retried by re-running the workflow (Actions tab, "Run workflow") with no version bump. Mark a release as a pre-release to skip publishing.


License

MIT — see LICENSE.

來源:README.md,提交 2fbf986

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.4.0最新Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分