GoldenLoaf24h/browserpaw--plugins-browserpaw-dsh ↗★ 39
dsh-browserpaw
DeepSeek Harness bundle for BrowserPaw browser automation through the local MCP bridge.
Install
npx -p @deepseek-ai/dsh dsh plugin --profile web add 'github:GoldenLoaf24h/browserpaw#d8b48343d173031b0f2d92cb9993cd2457956062&path:plugins/browserpaw-dsh'README
Read the full README ↗dsh-browserpaw
DeepSeek Harness bundle for BrowserPaw. It registers the browserpaw skill and browserpaw_session tool, then connects that session to the local BrowserPaw MCP bridge.
Install
The package is not currently published to npm. DeepSeek Harness installs pnpm-compatible package paths, so build an installable tarball from this repository:
cd plugins/browserpaw-dsh
npm pack
dsh plugin --profile
add ./dsh-browserpaw-4.1.0.tgz
For local development, install the package directory directly:
dsh plugin --profile
add "/plugins/browserpaw-dsh"
Do not install github:GoldenLoaf24h/browserpaw directly: that repository root is not the DSH package, and DSH Git installs do not select a monorepo subdirectory.
Official packaging guidance: .
--profile is mandatory, and the command initializes the profile when it does not exist yet. The desktop profile is owned by the Electron host: a standalone npm dsh refuses it with profile "desktop" is managed exclusively by the Electron application, so use the Desktop CLI shim (/resources/runtime/cli/bin/dsh.cmd on Windows) or the Plugins panel for that profile. dsh plugin installs through pnpm and therefore needs registry and codeload.github.com access.
The installer reads this package's dsh.bundle.patch, so it registers itself as a profile
bundle layer on the way in — no manifest editing, no separate mount line. Restart the host
afterwards; both the browserpaw skill and the browserpaw_session tool appear once
apply() has run.
Verify the layer registered before restarting: dsh --profile --dump-config shows a
# == dsh-browserpaw layer header followed by its inserted browserpaw-skill entry.
BrowserPaw itself must be running: the native server listens on 127.0.0.1:12306 and writes
~/.chrome-mcp/bridge-token, and the plugin needs both before open can connect. Install
BrowserPaw first if browserpaw_session { action: "open" } reports a missing bridge token.
Verification & Official Upstream
- Audit Date: 2026-10-31
- Current Package Validation: DSH
0.2.1-rc.3successfully passesnpm pack, isolated package installation, Cordis skill/tool registration, parameter projection, output rendering, anddsh --profile --dump-config. The dump contains the# == dsh-browserpawlayer and the insertedbrowserpaw-skillentry. - Host Validation Date: 2026-10-18 (DSH
0.2.1-rc.1, isolated profile) - Official Pinned Upstream:
deepseek-ai/deepseek-harnessat commit571902028a75c64c1d767f4ae5fd099485f0ddf0(master branch, verified 2026-10-15). - Declared Peer Dependency: This plugin declares
@deepseek-ai/dsh-mcp-client >=0.2.0-rc.1as its peer dependency, marked optional. The range documents the client the plugin was built against; the client itself always comes from the harness image. Marking the peer optional is what keeps an installer from resolving a second copy — npm auto-installs a required peer, and a duplicate in-box@deepseek-ai/*package registers the same Cordis symbols twice (see Discussion #8287). - Discussion #8287 Reference: Discussion #8287 ("Duplicate in-box @deepseek-ai/* package in a profile silently breaks every tool call") establishes that in-box
@deepseek-ai/*packages must be excluded from plugin dependencies to avoid duplicate Cordis symbol registration. - Scope Boundary: This package is a lightweight transport session bridge (
browserpaw_session) and skill provider. Host-level validation has been completed in an isolated profile; see Host-Level Validation for the method and its remaining boundary.
Host-Level Validation
On 2026-10-18 the plugin was exercised end to end against a real DeepSeek Harness 0.2.1-rc.1 runtime launched in an isolated DSH profile whose bundle list contains dsh-browserpaw as a linked dependency. That run established:
- The package loads as a profile layer rather than as a plain dependency, so its
cordis.patch.ymlapplies andapply()executes. - The
browserpawskill registers through the runtime provider. - The
browserpaw_sessiontool registers. action: "open"connects to the live bridge athttp://127.0.0.1:12306/mcpand injects the MCP tools;action: "close"unloads them.
The native host and ~/.chrome-mcp/bridge-token were both in place for that run.
Boundary: the desktop profile is owned exclusively by the Electron host and was not exercised. The 0.2.1-rc.1 bridge result above is historical; a fresh live headless model session against the current package was not completed. Current validation establishes packaging, installation, configuration, and component contracts, not live current-runtime tool execution.
Tool-profile boundary: the native host announces its core profile by default, while the bundled skill body references the wider canonical set. chrome_tool_docs with activateForSession: true widens the server-side list, and BrowserPaw advertises tools.listChanged and forwards the notification through its bridge. Clients that implement the standard refresh can observe the new list; clients that cannot should run with CHROME_MCP_TOOL_PROFILE=full.
Bundle Manifest Declarations
DeepSeek Harness treats a package as a profile bundle layer only when its package.json declares a top-level dsh.bundle manifest:
dsh.bundle.patch— required for a bundle layer. It points at this package's./cordis.patch.yml, the loader patch that inserts thebrowserpaw-skillentry. A package withoutdsh.bundleis reconciled as an ordinary dependency: the loader printsdsh: warning: declares no dsh.bundle — installed as a plain dependency, not a profile layer, the patch never applies,apply()never runs, and neither the skill nor thebrowserpaw_sessiontool exists.dsh.manifestVersion— optional, and currently advisory: the loader does not reject a package that omits it. The field records the manifest schema the package was authored against (1here).engines.dsh— optional top-level declaration, enforced when present. A declaredengines.dshalone decides compatibility; when it is absent, the loader validates every@deepseek-ai/dsh*peer range instead. Prerelease versions participate in range matching, so the declared>=0.2.0-rc.1 <0.3.0-0admits the tested0.2.1-rc.1runtime. The upper bound excludes0.3.0: host-level validation covers only up to0.2.1-rc.1, so an unbounded range would claim compatibility with a future minor release that was never verified.- In-box packages —
@deepseek-ai/*packages must not be installed as profile dependencies; see the Discussion #8287 reference above.
Architecture & Lifecycle
- MCP Client: Bridges to local BrowserPaw Native Server (
http://127.0.0.1:12306/mcp) via@deepseek-ai/dsh-mcp-client. The client is resolved atopen()time throughctx.loader.import('@deepseek-ai/dsh-mcp-client'), and the module namespace it returns — which carriesapply— is whatctx.plugin()receives. Cordis rejects a bare specifier string (invalid plugin, expect function or object with an "apply" method, received string), and a static import cannot resolve from a linked plugin outside the harness image; bare-specifier-to-module resolution happens in the loader entry tree, not inctx.plugin(). In DeepSeek Harness vendored Cordis (vendor/cordis/src/registry.ts:331-334),ctx.plugin()returns a thenable wrapped Fork awaitingfiber.await(). - Skill Injection: Registers canonical
browserpawskill withsource: 'runtime'into DeepSeek Harness Cordis runtime, satisfying deferred definition validation (packages/skill/skill/src/index.ts:763). - Tool Registration & Schema: Exposes
browserpaw_sessiontool satisfying 3 verified official boundaries:- S-02: Declares required text projection callback
output.render(packages/core/tools/src/index.ts:1071-1078). - S-03: Declares
source: 'runtime'inctx.skills.register()for deferred definition validation (packages/skill/skill/src/index.ts:763). - S-04: Parameters schema uses standard JSON Schema object root (
type: 'object',properties.action), preserving status default on{}.
- S-02: Declares required text projection callback
- Tool Naming & Prefix: Canonical tool names stay
chrome_*(chrome_navigate,chrome_read_dom, and the rest). DeepSeek Harness exposes the injected MCP tools under themcp__browserpaw__namespace, so the callable names aremcp__browserpaw__chrome_*: the mcp-client has no rename capability and passes each tool's raw name through unchanged. The bundled skill mirror therefore documents the canonicalchrome_*names. - Fail-Loud Startup:
open()passesfailOnStartupError: true. The client defaults it tofalse, which lets a failed first connection retry in the background whileapply()still resolves;browserpaw_session { action: 'open' }would then report success with no tool registered, and the next call would target a name that does not exist. With the flag set, a bridge that cannot answer makesopen()reject withmcp-client(browserpaw): initial connection or tool synchronization failed, andstatuskeeps reportingactive: false. - Cleanup: Bound to Cordis fiber lifecycle via
ctx.effect(), ensuring disposal without dangling timers or orphaned connections.
Host Credential Boundaries
Different agent hosts enforce distinct authentication boundaries:
- DeepSeek Harness (DSH): Operates against a local HTTP MCP bridge. The plugin dynamically resolves the local bridge token from
process.env.CHROME_MCP_TOKENor~/.chrome-mcp/bridge-tokenand passesheaders: { 'x-mcp-token': token }to authenticate with the local server. - Hermes Agent (PR #136034): Operates credential-free via
ctx.call_mcp('browserpaw', ...). The plugin does not read environment tokens or local secret files; access control is enforced host-side viaplugins.entries.browserpaw.mcp_allowlistinconfig.yaml.