h5-devtools-mcp
Enables debugging of H5 pages running inside Android WebViews on real devices over adb and the Chrome DevTools Protocol, without needing chrome://inspect. Provides tools to list debuggable WebView pages (with app package, title, URL, and visibility), attach to a page and buffer console output, read console messages and uncaught exceptions incrementally with level/keyword filtering, evaluate JavaScript expressions in the page, and detach from a page.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@h5-devtools-mcplist debuggable WebViews, then show me recent console errors on the order page"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
h5-devtools-mcp
English | 简体中文
An MCP server that lets coding agents (Claude Code, Codex, Cursor…) debug H5 pages running inside Android WebViews on real devices — read console output and uncaught exceptions, and run JavaScript in the page, without opening chrome://inspect.
Status: v0.1, early. Android only.
How it works
Coding agent ──MCP (stdio)──▶ h5-devtools-mcp ──adb forward──▶ webview_devtools_remote_<pid> ──CDP──▶ WebView pageEvery debuggable WebView exposes a Chrome DevTools Protocol endpoint on an abstract unix socket. The server discovers those sockets over adb (the same way chrome://inspect does), forwards them to local ports, and connects with CDP.
Related MCP server: Android DevTools MCP
Requirements
Node.js 18+
adbon yourPATH(or setADB_PATH)An Android device with USB debugging enabled
The app must enable WebView debugging (debug builds usually do):
WebView.setWebContentsDebuggingEnabled(true);Setup
# Claude Code
claude mcp add h5-devtools -- npx -y h5-devtools-mcpOther MCP clients (Cursor, Codex…) take the same command: npx -y h5-devtools-mcp.
From source
git clone https://github.com/xianguoGou/h5-devtools-mcp.git
cd h5-devtools-mcp
npm install && npm run build
claude mcp add h5-devtools -- node /absolute/path/to/h5-devtools-mcp/dist/index.jsTools
Tool | What it does |
| List debuggable pages: app package, title, URL, visibility |
| Connect to a page and start buffering console output |
| Read buffered entries, filtered by level / keyword / |
| Run a JavaScript expression in the page and return the result (promises are awaited) |
| Disconnect from a page |
Output is designed to be token-cheap: compact one-line entries, long messages truncated, and since_seq so an agent only reads what's new instead of re-reading the whole buffer on every turn.
Example
> list_targets
- id: R5CT1234/webview_devtools_remote_8812/3A1F…
app: com.example.app (pid 8812) on SM-S9180
title: "Order"
url: https://m.example.com/order
> get_console { "levels": ["error"] }
#41 10:32:01.123 [error exception] TypeError: Cannot read properties of undefined (reading 'price')
at https://m.example.com/assets/index-8f2a.js:1:48213
next since_seq: 57Troubleshooting
"no debuggable WebView found" — the app hasn't enabled WebView debugging, or no WebView is alive yet. Open the H5 page first.
"debugger in use" — only one debugger can attach to a page. Close the
chrome://inspectDevTools window."unauthorized" — accept the USB debugging prompt on the device.
Known limitations
Debugger-in-use detection is best-effort. It relies on
/json/listomittingwebSocketDebuggerUrl. Recent Chromium accepts several CDP clients per page, so attach may succeed alongside an open DevTools window; older WebViews may still refuse.list_targetscan take ~3s per unresponsive app. Sockets are queried one by one with a 3s timeout, and Android freezes background apps, so their WebView sockets stop answering.attachonly re-checks the target's own socket and stays fast.evaluate_jsruns with the page's full privileges — it can read cookies, storage and tokens, and change page state. Keep it behind your agent's tool-permission prompt.The e2e script expects port 9333 to be free. If a previous run left a headless Chromium behind, it attaches to that one; kill it first.
Development
The e2e test uses a fake adb and headless Chromium in place of a phone:
npm run build
CHROME=/path/to/chrome npm run test:e2eRoadmap
Discover devices and WebView pages
Console messages, uncaught exceptions, browser log entries
Network requests and responses
JSBridge call logging (configurable bridge shapes)
evaluate_jsscreenshotJSBridge mocking
iOS (WKWebView via WebKit Inspector Protocol)
License
MIT
Available Tools
5 toolsattachAttach to a pageA
Connect to a WebView page and start buffering its console output and uncaught exceptions. Recent messages the engine still holds are replayed on attach, but attach before reproducing an issue to be sure nothing is missed.
| Name | Required | Description | Default |
|---|---|---|---|
| target_id | Yes | Target id from list_targets |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are given, so the description carries the full behavioral burden. It discloses useful behavior—recent messages are replayed on attach, and attaching before reproduction avoids missing messages—but omits permissions, side effects, idempotency, and whether the operation is reversible. It provides some transparency but leaves key operational traits unstated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action and followed by the key timing caveat. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple one-parameter schema, no annotations, and no output schema, the description covers purpose, behavior, and a critical usage caveat well. It could mention the relationship with detach or get_console for a fuller workflow picture, but it is largely complete for the attach action itself.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%; the sole parameter target_id is fully documented as 'Target id from list_targets'. The description adds no further parameter semantics, so the baseline of 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Connect') and resource ('WebView page'), and describes the exact effect: starting to buffer console output and uncaught exceptions. This distinguishes it from siblings like get_console (read buffered output), detach (stop), and list_targets (discover targets), even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear condition for use: 'attach before reproducing an issue to be sure nothing is missed.' This tells the agent when to invoke it. However, it does not name alternatives (e.g., get_console for reading without buffering) or state when not to use it, so it falls short of the explicit when/when-not/alternatives bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
detachDetach from a pageA
Disconnect from a page and discard its buffered events.
| Name | Required | Description | Default |
|---|---|---|---|
| target_id | No | Defaults to the most recently attached page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It adds valuable non-obvious context that buffered events are discarded, but it does not disclose permissions, reversibility, whether the page is closed, or the effect on other attached clients.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One tight sentence with zero waste. The core action and its most important side effect are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, this covers the basic action and one key side effect. It remains incomplete about whether detaching closes the page, whether it can be reattached, and what a caller should expect afterward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single optional `target_id` is fully documented in the schema. The description adds no parameter-specific meaning beyond that baseline, which is appropriate here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: "Disconnect from a page." This is clearly the counterpart to the sibling `attach`, though it does not explicitly name that sibling or distinguish itself from `list_targets`/`get_console`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: call this when you want to disconnect from a page, and the note about discarding buffered events hints at a consequence. However, there is no explicit when-to-use vs. when-not guidance, no mention of `attach`, and no prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
evaluate_jsEvaluate JavaScript in a pageADestructive
Run a JavaScript expression in an attached page and return its result. Plain objects/arrays come back as JSON (so nested Map/Set/DOM values show as {}); other values (DOM nodes, Map, Set, Error, window) as a short description. Promises are awaited. For multiple statements or await, wrap them: (async () => { ... })(). Runs with the page's full privileges, so it can read cookies/storage and change page state.
| Name | Required | Description | Default |
|---|---|---|---|
| target_id | No | Defaults to the most recently attached page | |
| expression | Yes | JavaScript expression to evaluate |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond annotations: it discloses that execution runs with the page's full privileges, can read cookies/storage and mutate page state (consistent with destructiveHint=true), awaits promises, and explains how different return types are serialized. This is exactly the behavioral detail annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tightly packed sentences with zero filler, front-loaded with the core action and return contract, then privileges. Every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full return-value burden and does so thoroughly (JSON for plain objects/arrays, short description for DOM/Map/Set/Error/window). Privilege and mutation scope are also covered, so nothing needed to call or interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description goes further by implying the expression parameter must be a single expression and must be wrapped in an async IIFE for statements/await. It adds no extra detail for target_id beyond the schema's own default note.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Run a JavaScript expression in an attached page and return its result') and is clearly distinct from the siblings (list_targets, attach, get_console, detach). An agent can identify the tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete usage guidance ('For multiple statements or await, wrap them: (async () => { ... })()') and notes target_id defaults to the most recently attached page. It stops short of naming when-not-to-use or pointing to a sibling such as get_console for log inspection, so no explicit alternatives are offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_consoleRead console outputARead-only
Read buffered console messages, uncaught exceptions and browser log entries from an attached page. Returns the most recent matching entries. Pass since_seq from a previous call to get only new entries.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max entries to return (default 50) | |
| levels | No | Only these levels, e.g. ["warn", "error"] | |
| keyword | No | Case-insensitive substring match on message text and location | |
| since_seq | No | Only entries with seq greater than this | |
| target_id | No | Defaults to the most recently attached page | |
| exclude_keywords | No | Drop entries whose text or location contains any of these (case-insensitive), e.g. ["google-analytics", "doubleclick"] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already establishes the safety profile, so the description's job is additive context, which it delivers: it discloses that output is buffered, that the most recent matching entries are returned (ordering/truncation behavior), and that since_seq enables incremental retrieval. It omits buffer bounds or whether old entries are evicted, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with zero filler; the core purpose is front-loaded and the incremental-fetch hint follows naturally. Every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, six-parameter tool with a fully described schema and no output schema, the description covers purpose, return ordering, and the key incremental pattern. It leaves the attach prerequisite and buffer-eviction behavior unstated, which is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so levels, keyword, exclude_keywords, limit, and target_id are fully documented in the schema itself. The description only elaborates on since_seq, which is already explained in the schema, so it adds little beyond the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Read) and precise resource (buffered console messages, uncaught exceptions, browser log entries) scoped to 'an attached page'. The resource is naturally distinct from siblings like attach/detach/evaluate_js, but the description never explicitly contrasts itself with them, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives one concrete usage pattern: 'Pass since_seq from a previous call to get only new entries,' which is genuinely actionable for incremental polling. However, there is no when-not guidance, no prerequisites (e.g. must a page be attached first?), and no mention of alternatives, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_targetsList WebView pagesARead-only
List debuggable H5 pages running inside Android WebViews (and Chrome) on connected devices. Returns a target id for each page to pass to attach.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already declares this is a safe read. The description adds real behavioral value beyond that: it scopes the result set (WebView/Chrome pages on connected devices) and discloses the shape of what comes back (a target id per page for attach). It stops short of covering failure modes like no connected devices.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with what gets listed and followed by the one fact an agent needs next (the returned target id feeds attach). No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-arg listing tool with an annotation covering its safety profile, this covers purpose, scope, and the handoff to attach without an output schema. Minor omissions (empty-result behavior, whether filtering exists) do not block correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the schema imposes no burden; the baseline for a no-param tool is 4. The description appropriately says nothing about arguments rather than padding with irrelevant detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('List') and a precise resource ('debuggable H5 pages running inside Android WebViews (and Chrome) on connected devices'), and it names the follow-up sibling action ('pass to attach'). An agent can distinguish this from attach/detach/evaluate_js immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the usage context clear implicitly by tying the output to the 'attach' step, so an agent knows to call this before attaching. It does not state when-not to use it or mention alternatives, keeping it short of full explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.1- First observed
attach - First observed
detach - First observed
evaluate_js - First observed
get_console - First observed
list_targets
TDQS
Scored across 5 tools
Each tool maps to a distinct step in the debug session: list_targets discovers pages, attach connects, get_console reads buffered logs, evaluate_js executes code, and detach disconnects. There is no meaningful overlap between any pair; an agent can select unambiguously.
The dominant pattern is verb_noun (list_targets, get_console, evaluate_js), which is clean and readable. attach and detach are bare verbs, a minor but explainable deviation since their object is implied by the session model.
Five tools is exactly right for a focused WebView debugging workflow — one per lifecycle stage with no filler. Nothing feels padded or missing at the count level.
The full core loop (discover, attach, observe console, evaluate JS, detach) is covered, including sequence-based log polling, so agents won't hit dead ends. Secondary debugging surfaces like network inspection, screenshots, or device-level listing are absent but not essential to the stated purpose.
Maintenance
Related MCP Connectors
remote debug iOS/Android/Unity/Godot/Flutter/RN/Web on real-device.ui-tree/screenshots/taps,tests.
Drive real devices from your AI Coding tool. Embed a client SDK (Unity, Godot, Flutter, iOS/macOS, Android, React Native, Web) in your app, then capture screenshots, traverse the UI tree, inject taps and key events, and run automated test tasks on the physical device over a secure relay.
Live browser debugging for AI assistants — DOM, console, network via MCP.
On-demand cloud browser sessions; page actions need a compatible CDP client.
1
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables remote control of Android devices via ADB, including screen operations, input, app management, file transfer, and advanced tools like UI testing and performance analysis.25MIT
- AlicenseAqualityDmaintenanceEnables an agent to inspect and interact with Android emulators or physical devices via ADB, capturing UI snapshots, tapping nodes, typing text, and reading app logs.10MIT
- AlicenseAqualityCmaintenanceEnables MCP clients to read console logs and network requests from a connected mobile H5 page and, with explicit user authorization, execute JavaScript in that page.49MIT
- AlicenseAqualityBmaintenanceEnables debugging Flutter apps on Android by exposing the widget tree and source locations, supporting hot reload and pixel-level UI diffs, along with filtered Android logs, crash traces, and device interaction.2622 PyPIMIT