Skip to main content
Glama
helmif

semantic-dom-mcp

by helmif

extract_semantic_dom_after

Runs declared fill/click/press/select/goto/wait actions, then captures the resulting DOM as Semantic JSON to expose post-interaction UI like toasts, validation messages, and dialogs.

Instructions

Like extract_semantic_dom, but first performs a short DECLARED list of actions (fill/click/press/select/goto/wait) in the main frame, then returns Semantic JSON of the RESULTING state. Use it for post-interaction UI a plain snapshot cannot see: success/error toasts, validation messages, opened dialogs. Derive action locators from a prior extract_semantic_dom call. The page must remain on allowlisted hosts after the actions, or nothing is extracted. Uniqueness reflects capture time — accumulating UI (chat threads, lists) can multiply matches later. The result's observed block lists navigations, xhr/fetch requests (method, path, status), console errors, dialogs and popups seen while the actions ran — use them for waitForURL/waitForResponse.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesThe page to extract. Must be http/https and on an allowlisted host.
rolesNoKeep only nodes with these roles or tags (e.g. ['button','textbox','row']).
scopeNoCSS selector to extract within — take it from an outline region's `selector` (e.g. 'main table', '[role="dialog"]'). Everything outside is skipped.
actionsYesDeclared actions (fill/click/press/select/goto/wait) executed in order in the MAIN frame after navigation.
viewportNoViewport preset — 'mobile' is 375x812 with touch, for responsive states.desktop
wait_forNoNavigation wait. 'auto' (default) waits for load, then until the DOM has been quiet for 500ms (max 6s) — works on SPAs that render after load and on pages whose analytics never let the network go idle. 'networkidle' times out on such pages.auto
max_nodesNoCap on extracted nodes; truncation is flagged, never silent.
settle_msNoWait after the last action before snapshotting (for toasts/animations).
visible_onlyNoSkip hidden nodes entirely.
wait_selectorNoOptional selector to await before extracting (for SPA content).
include_hiddenNoKeep hidden nodes flagged rather than dropping them.
include_tablesNoAttach structured `tables` (headers, row identity, cells) and `dialogs` (label/value fields) inside the scope, for value assertions.
max_output_charsNoBudget for the node list; nodes past it are dropped in document order and counted in `omitted` (never silent).
wait_selector_afterNoSelector to await (visible) AFTER the actions, before snapshotting — deterministic wait for late-rendering toasts/modals instead of guessing settle_ms.
include_click_targetsNoOpt-in heuristic: also include cursor:pointer elements with content that match no other rule (JS-click product cards without anchors/roles/test-ids). Heuristic nodes carry a context_note.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed10 schema fields changedv0.8.0
    • changedInput schema / properties / actions / description
      Previous value: -"Declared actions executed in order in the MAIN frame after navigation."New value: +"Declared actions (fill/click/press/select/goto/wait) executed in order in the MAIN frame after navigation."
    • changedInput schema / properties / actions / items / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "locator": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "nth": {
      -            "description": "Optional .nth(i) index from the extraction's disambiguation guidance.",
      -            "minimum": 0,
      -            "type": "integer"
      -          },
      -          "role": {
      -            "description": "ARIA role — required when strategy is 'role'.",
      -            "type": "string"
      -          },
      -          "strategy": {
      -            "description": "Locator strategy, matching the strategies in extraction output.",
      -            "enum": [
      -              "test-id",
      -              "role",
      -              "label",
      -              "placeholder",
      -              "text",
      -              "id",
      -              "css"
      -            ],
      -            "type": "string"
      -          },
      -          "value": {
      -            "description": "The locator value (test id, accessible name, label, selector...).",
      -            "minLength": 1,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "strategy",
      -          "value"
      -        ],
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "fill",
      -        "type": "string"
      -      },
      -      "value": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "locator",
      -      "value"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "locator": {
      -        "$ref": "#/properties/actions/items/anyOf/0/properties/locator"
      -      },
      -      "type": {
      -        "const": "click",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "locator"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "key": {
      -        "maxLength": 30,
      -        "type": "string"
      -      },
      -      "locator": {
      -        "$ref": "#/properties/actions/items/anyOf/0/properties/locator"
      -      },
      -      "type": {
      -        "const": "press",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "locator",
      -      "key"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "ms": {
      -        "exclusiveMinimum": 0,
      -        "maximum": 10000,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "wait",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "ms"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "locator": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "nth": {
      +            "description": "Optional .nth(i) index from the extraction's disambiguation guidance.",
      +            "minimum": 0,
      +            "type": "integer"
      +          },
      +          "playwright": {
      +            "description": "A `playwright` expression exactly as an extraction returned it (scoped forms and .nth included). When given, strategy/value are not needed.",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "role": {
      +            "description": "ARIA role — required when strategy is 'role'.",
      +            "type": "string"
      +          },
      +          "strategy": {
      +            "default": "css",
      +            "description": "Locator strategy, matching the strategies in extraction output (ignored when `playwright` is given).",
      +            "enum": [
      +              "test-id",
      +              "role",
      +              "label",
      +              "placeholder",
      +              "text",
      +              "id",
      +              "css"
      +            ],
      +            "type": "string"
      +          },
      +          "value": {
      +            "default": "",
      +            "description": "The locator value (test id, accessible name, label, selector...). Empty for a bare role inside `within`.",
      +            "type": "string"
      +          },
      +          "within": {
      +            "additionalProperties": false,
      +            "description": "Scope to a container first; copy the extraction's `within` verbatim.",
      +            "properties": {
      +              "kind": {
      +                "enum": [
      +                  "row",
      +                  "listitem",
      +                  "test-id",
      +                  "css"
      +                ],
      +                "type": "string"
      +              },
      +              "value": {
      +                "minLength": 1,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "kind",
      +              "value"
      +            ],
      +            "type": "object"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "secret": {
      +        "description": "Mark the value as a secret: it is scrubbed from every string the server returns. Password fields are detected automatically.",
      +        "type": "boolean"
      +      },
      +      "type": {
      +        "const": "fill",
      +        "type": "string"
      +      },
      +      "value": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "locator",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "locator": {
      +        "$ref": "#/properties/actions/items/anyOf/0/properties/locator"
      +      },
      +      "type": {
      +        "const": "click",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "locator"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "key": {
      +        "maxLength": 30,
      +        "type": "string"
      +      },
      +      "locator": {
      +        "$ref": "#/properties/actions/items/anyOf/0/properties/locator"
      +      },
      +      "type": {
      +        "const": "press",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "locator",
      +      "key"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Choose a <select> option by value or label.",
      +    "properties": {
      +      "locator": {
      +        "$ref": "#/properties/actions/items/anyOf/0/properties/locator"
      +      },
      +      "type": {
      +        "const": "select",
      +        "type": "string"
      +      },
      +      "value": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "locator",
      +      "value"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "description": "Navigate within the flow (must be http/https and allowlisted).",
      +    "properties": {
      +      "type": {
      +        "const": "goto",
      +        "type": "string"
      +      },
      +      "url": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "url"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "ms": {
      +        "exclusiveMinimum": 0,
      +        "maximum": 10000,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "wait",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "ms"
      +    ],
      +    "type": "object"
      +  }
      +]
    • addedInput schema / properties / include_tables
      Added value: +{
      +  "default": false,
      +  "description": "Attach structured `tables` (headers, row identity, cells) and `dialogs` (label/value fields) inside the scope, for value assertions.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / max_output_chars
      Added value: +{
      +  "description": "Budget for the node list; nodes past it are dropped in document order and counted in `omitted` (never silent).",
      +  "exclusiveMinimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / roles
      Added value: +{
      +  "description": "Keep only nodes with these roles or tags (e.g. ['button','textbox','row']).",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / scope
      Added value: +{
      +  "description": "CSS selector to extract within — take it from an outline region's `selector` (e.g. 'main table', '[role=\"dialog\"]'). Everything outside is skipped.",
      +  "type": "string"
      +}
    • addedInput schema / properties / visible_only
      Added value: +{
      +  "default": false,
      +  "description": "Skip hidden nodes entirely.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / wait_for / default
      Previous value: -"networkidle"New value: +"auto"
    • changedInput schema / properties / wait_for / description
      Previous value: -"Navigation wait condition."New value: +"Navigation wait. 'auto' (default) waits for load, then until the DOM has been quiet for 500ms (max 6s) — works on SPAs that render after load and on pages whose analytics never let the network go idle. 'networkidle' times out on such pages."
    • changedInput schema / properties / wait_for / enum
      Previous value: -[
      -  "load",
      -  "domcontentloaded",
      -  "networkidle"
      -]New value: +[
      +  "auto",
      +  "load",
      +  "domcontentloaded",
      +  "networkidle"
      +]
  2. First observedv0.4.0

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=false, so safety is partly covered. The description adds substantial behavior beyond them: allowlist enforcement causing silent non-extraction, the timing-dependent uniqueness caveat for accumulating UI, and the contents of the `observed` block (navigations, xhr/fetch method/path/status, console errors, dialogs, popups) with guidance to use them for waitForURL/waitForResponse.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the 'Like extract_semantic_dom, but...' framing, then usage, then caveats, then the observed-block payoff. Every sentence carries information, though the prose is dense and a couple of clauses (uniqueness note, observed block) are packed into long sentences that could be split for scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter mutation-adjacent extraction tool with no output schema, the description covers the action model, locator sourcing, allowlist constraints, timing caveats, and the shape of the returned observation metadata. Nothing an agent needs to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes beyond the schema by listing the declared action verbs (fill/click/press/select/goto/wait), naming the `observed` block fields for follow-up waits, and instructing where locators should come from (a prior extraction). That is meaningful semantic guidance layered on top of fully documented parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the base operation it extends (extract_semantic_dom), states the specific added behavior (executes a declared action list in the main frame first), and states what is returned (Semantic JSON of the resulting state). An agent can distinguish it from extract_semantic_dom and the session_* tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it ('post-interaction UI a plain snapshot cannot see: success/error toasts, validation messages, opened dialogs') and how to prepare ('Derive action locators from a prior extract_semantic_dom call'). It also states the failure condition (page must remain on allowlisted hosts or nothing is extracted), which is a clear 'when this won't work' qualifier.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.