@marrowdev/browse-core
v0.16.0
Published
The browser-side reading kit behind marrow-browse: the map of what can be pressed, opening what can be opened, walking pages, and reading the DOM. Published so Marrow's deep read can share it instead of keeping a second copy.
Downloads
673
Readme
marrow-browse
人がログイン/2FA/CAPTCHA を通し、AI がその先を歩くローカル MCP サーバ。 ブラウザは本人のマシンの、昨日ログインしたままの Chrome。
売りは「解けること」ではなく「解かないと言い切れること」。 CAPTCHA を解かず、破壊的な control を押さず、人に手渡す。
[ browse-mcp ] browse_open / act / read / paginate / wait_for_human / list / close / shutdown
↓
[ 実 Chrome ] 永続プロファイル ~/.local/share/marrow/profiles/default
└ keeper タブ browse-mcp/keeper.ts ← 閉じると全部落ちる=この製品が持つ唯一の面使い方はリポのルートにある USAGE.md、道具の詳細は browse-mcp/README.md。
🚨 ここをリンクにしないこと(#19)。この README は @marrowdev/browse-core に同梱されて配られる
(リポのルート=あのパッケージのルート)。⚠️ npm は README を files に関わらず必ず同梱するので、
外すこともできない ⇒ tarball に入っていない物へのリンクは npmjs.com で 404 する(#12 と同じ穴)。
💭 @marrowdev/browse-mcp の方は browse-mcp/ に自分のルートを持つので、配るのはあちらの README。
browse-mcp/check-dist.mjs が prepublishOnly から両方のパッケージを見張っている。
この repo が出している 2 つのパッケージ
| | | |
|---|---|---|
| @marrowdev/browse-mcp | bin | これ —— 下に書いてあるローカル MCP サーバ。客が npx で入れる物 |
| @marrowdev/browse-core | library | src/ の読む道具 5 本(押せる物の地図・開く・歩く・読む)を TS のまま配る。Marrow の deep 読みがコピーを持たずに借りるためだけに在る |
💭 npm でこのページを読んでいて、探しているのが後者なら —— 下の説明は前者(MCP サーバ)の物。
library の中身は src/affordance.ts / reveal.ts / paginate.ts / dom.ts / wait.ts で、
⚠️ 出所は LAN の Gitea なので公開の置き場は無い(repository を載せていないのはそのため)。
🚨 library を使うなら、起動時に describeHost() を呼ぶ(0.15.0・#37)
affordance.ts の 2 つの文字列は呼び出し側のモデルに届く(破壊的 control の断り/地図の
cap 警告)。⭐ 0.14.0 まで、その 2 つは marrow-browse と名乗り、browse_wait_for_human と
browse_act を名指ししていた —— 出荷している客が 1 人だった間は真だった文。
import { describeHost } from '@marrowdev/browse-core/affordance';
describeHost({
product: 'your-tool', // 断りが名乗る名前
handoff: 'your_wait_for_human', // ⚠️ 無いなら書かない(後述)
snapshot: 'your_act {do:"snapshot"}', // 地図を取り直す呼び方
});⭐ 呼ばなくても壊れない —— 名前を 1 つも出さない、真だが少し漠然とした文になる。
🚨 handoff を「それらしい名前」で埋めないこと。 ⚠️ handoff.ts は tarball に入っていない
ので、library の客に人へ手渡す道具が在るとは限らない —— 🚨 無い道具を名指しされたモデルは、
断られた control を押す別の道を探しに行く(それを止めるのが断りの唯一の役目)。
📌 実例は marrow-hand: 動詞が無いので handoff を渡さず、文は「人に渡せ」で終わる。
この repo の成り立ち(2026-08-11)
Marrow から割って出た。理由は技術ではなく速度 —— SaaS(③)と同じ repo に居ると、
②の実装が回らなかった。⚠️ 屋号は共有したまま(@marrowdev/ / marrow-browse の名前は残る)。
分けたのは製品の線であって、屋号ではない。
**運転手は Playwright のまま。**Marrow 側は chromiumoxide(Rust)を持っているが、
②がそちらへ寄る予定は無い —— 🚨 客が買っているのは本人のプロファイルであって、
バイナリの数ではない。加えて connectOverCDP は bun でハングするので node が load-bearing。
src/ に 6 本しか居ないのはなぜか
Marrow の src/ は 20 本あったが、この面が実際に辿るのは 6 本だけだった(実測):
| | |
|---|---|
| affordance.ts / reveal.ts | 押せる物の地図と、開けられる物を開く仕事 —— ②の核 |
| paginate.ts / wait.ts / dom.ts | 歩く・待つ・読む |
| handoff.ts | 壁で人に手渡す |
残り 11 本(orchestrator / crawler / judge / store …)は Marrow に残った。
⚠️ Marrow 側の deep 読みはこの 6 本のうち 5 本を使うので、あちらは
@marrowdev/browse-core をパッケージとして引く(版を固定する側)。
🚨 ここは長く @marrowdev/browse-mcp と書いてあったが、2026-08-13 に Marrow の
package.json を見たら @marrowdev/browse-core: ^0.1.0 だった —— bin と library は別物で、
②の客が npx で入れるのが前者、③が引くのが後者。混ぜると「客に③の荷物を積まない」という
分け方の理由ごと消える。
⚠️ **履歴は持ってきていない。**②の経緯(Marrow #16 の手渡し / Marrow #51 の破壊的ガード / Marrow #69 の掃除 など)は
Marrow の git log と HANDOFF.md に残っている。消えてはいない、こちらに無いだけ。
検査
🚨 browse-mcp/probes/e2e-lifecycle.ts は回さない。あれだけは共有プロファイルを使い
browse_shutdown まで踏むので、走らせるとログインを失いうる(前科あり)。
bun run check # 型検査(src + browse-mcp を全部)
bun run browse-mcp/probes/probe-doc-paths.ts # 文書が指す物が実在するか(ブラウザを起こさない)
bun run browse-mcp/probes/probe-redact-notice.ts # ロック画面のフィルタ: 秘密は消え、名前は残るか(同上)
bun run browse-mcp/probes/probe-handoff.ts # 手渡し(偽の通知器)
bun run browse-mcp/probes/probe-paginate-wire.ts # MCP の面
bun run browse-mcp/probes/probe-changed-contract.ts # changed: の契約 + 語彙 + ref 表記
bun run browse-mcp/probes/probe-map-arrival.ts # まだ届いていない地図が完成した顔をしていないか
bun run browse-mcp/probes/probe-keeper.ts # keeper タブ(2 プロファイル・遅い)
bun run browse-mcp/probes/probe-chrome-missing.ts # Chrome 不在が名前で止まるか
bun run browse-mcp/probes/probe-act-latency.ts # 遅れて着いた効果を `no` と言わないか
# ── survey(判定を持たない台。⭐ 数を出すだけで、緑にも赤にもならない)────────────
bun run browse-mcp/probes/survey-page-adapter-acts.ts # act() は playwright でない Page でも同じことをするか(marrow-hand#1 Q1b)
bun run browse-mcp/probes/survey-page-adapter-hard.ts # 上の 2 つが測れなかった 3 点(marrow-hand#1 Q1c)
bun run browse-mcp/probes/survey-extension-transport.ts # 拡張は MCP の面を運べるか、どう運ぶか(marrow-hand#1 Q2)
# ⭐ この 3 本の答えが marrow-hand になった
bun run browse-mcp/probes/survey-what-the-wall-reads.ts # 壁は実際に何を読んでいるのか(#22 / #31・⚠️ esbuild で束ねてから走らせる)
bun run browse-mcp/probes/probe-hidden-controls.ts # 見えない control を「押せる」と言わないか
bun run browse-mcp/probes/probe-destructive-guard.ts # 破壊的な control を名前で断るか
bun run browse-mcp/probes/probe-two-servers.ts # 1 プロファイルに 2 サーバ同時(Marrow #6 の主題)
bun run browse-mcp/probes/probe-stdin-close.ts # 客が去ったらサーバも去るか(attach 済みが本番・#2)
bun run browse-mcp/probes/probe-node-floor.ts # 古い node を②の名前で断るか(無ければ exit 2)
bun run browse-mcp/probes/probe-server-version.ts # 握手で名乗る版が、実際に走っている build の版か(#21)
# 起動時の掃除。⚠️ 2 本在るのは強さが違うから(#3)
bun run browse-mcp/probes/probe-sweep-older-selves.ts # 本物のサーバ 4 本で測る(node が要る)
bun run browse-mcp/probes/probe-sweep-portable.ts # 囮で判定機構だけ測る(`ps` さえ在れば走る=macOS 可)⚠️ bun run では走らない 3 本(node が要る= connectOverCDP が bun でハングするので、
bun で回すと probe 自身がその罠にかかる)。各ファイルの冒頭に esbuild で焼く 1 行が書いてある:
browse-mcp/probes/probe-cdp-attach.ts # 誰の物でもないブラウザで②が成立するか
browse-mcp/probes/probe-emulation-fidelity.ts # 人が見ている画面を見ているか(playwright の再描画ではなく)
browse-mcp/probes/probe-keeper-offer.ts # keeper が窓を奪わず新しい build を差し出すか💭 この一覧が実物と揃っているかは probe-doc-paths.ts が測る(検査 3)——
HANDOFF が「README の probe 一覧は手で写した=腐る側」と言っていた所で、
実際 2026-08-13 の時点で 4 本が一覧から漏れていた。
⚠️ probe は実ブラウザを起こす(headless・使い捨てプロファイル)。
🚨 この一覧には「赤で正しい」probe が混ざりうる —— 直す前に検出器として書かれたもの。 赤の意味は probe 自身が最後の行で名乗る。逆に、そういう probe が理由なく緑になったら疑う。
