Skip to content

UI TestEngine: add listAllEntries for one-shot flat tree dump#5967

Merged
Grantim merged 3 commits into
masterfrom
mcp-ui-listAllEntries
Apr 23, 2026
Merged

UI TestEngine: add listAllEntries for one-shot flat tree dump#5967
Grantim merged 3 commits into
masterfrom
mcp-ui-listAllEntries

Conversation

@Grantim
Copy link
Copy Markdown
Contributor

@Grantim Grantim commented Apr 23, 2026

Summary

  • Walking the UI tree via ui.listEntries costs 4–5 sequential round-trips to reach a known widget. This PR adds ui.listAllEntries (MCP) + uiListAllEntries (Python) returning every entry in the subtree at path (default empty → whole tree) as a flat depth-first list of (path, TypedEntry) pairs. Groups appear in the list and their descendants follow on subsequent rows, so the tree structure is recoverable from the flat output.
  • TypedEntry and ui.listEntries are unchanged — purely additive.
  • Follow-up to UI TestEngine: expose disabled/blocked state on entries #5961 (prior-session plan step 2).

Design notes

  • PathedEntry = std::pair<std::vector<std::string>, TypedEntry> alias in MRUITestEngineControl.h keeps the signature readable.
  • Factored typeOf(Entry) in MRUITestEngineControl.cpp so the flat listEntries and the new recursive walker share the variant switch.
  • Factored mcpTypeStr(EntryType) in MRViewerMcp.cpp so the old and new MCP handlers share the enum→string.
  • pybind11 auto-converts pair → tuple and vector<pair<…>> → list of tuples; no new binding class needed.
  • Output schema is Array(Object{path, name, type, status}). Mcp::Schema has no $ref for recursive children, but the flat-with-path shape sidesteps that and is trivially serializable.

Test plan

Live-verified end-to-end against a freshly-built MeshInspector via the MCP SSE endpoint:

  • ui.listAllEntries({path:[]}) returns 84 entries, 9857 bytes serialized (under the ~10 KB budget from the plan).
  • Flat output is the same set of (path, type) tuples as a recursive walk via ui.listEntries0 missing, 0 extra, 0 status drift.
  • Subtree rooting at ["QuickAccess"] returns 9 entries all with the correct path prefix; first-level set matches ui.listEntries at the same path.
  • Bogus path returns the same "No such entry: \…`. Known entries are: …"error shape aslistEntries(sharedfindGroup` helper).
  • Omitting path defaults to empty (whole tree).
  • tools/list shows ui.listAllEntries registered alongside the other 10 ui.* tools.

🤖 Generated with Claude Code

Walking the UI tree via `ui.listEntries` costs 4-5 sequential round-
trips to reach a known widget. The new `ui.listAllEntries` MCP tool
(plus Python mirror `uiListAllEntries`) returns every entry in the
subtree at `path` (default empty = whole tree) as a flat depth-first
list of `(path, TypedEntry)` pairs — groups appear in the list with
their descendants on subsequent rows, so the tree structure is
recoverable from the flat output. `TypedEntry` and `ui.listEntries`
are untouched — purely additive.

- `PathedEntry = pair<vector<string>, TypedEntry>` alias in
  MRUITestEngineControl.h keeps the signature readable.
- `typeOf(Entry)` factored out so `listEntries` and the new walker
  share the variant switch; `mcpTypeStr(EntryType)` factored out so
  the old and new MCP handlers share the enum-to-string.
- pybind11 auto-converts `pair` to tuple and `vector<pair<…>>` to
  list of tuples — no new binding class needed.

Output schema: `Array(Object{path, name, type, status})`. Declared
recursive `children`-tree schemas in `Mcp::Schema` aren't supported
(no `\$ref`), and the flat-with-path form sidesteps that entirely
while remaining trivially serializable.

Live-verified via MCP on a default-state viewer:
* 84 entries returned, 9857 bytes serialized (under the 10 KB budget).
* Identical set of `(path, type)` tuples to a recursive
  `ui.listEntries` walk (0 missing, 0 extra, 0 status drift).
* Subtree rooting at `["QuickAccess"]` returns 9 entries all with the
  correct prefix; first-level matches `ui.listEntries` at that path.
* Bogus path returns the same "No such entry" error as `listEntries`.
* Omitting `path` defaults to empty (whole tree).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Grantim and others added 2 commits April 23, 2026 19:14
Signed-off-by: Grant Karapetyan <grant.karapetyan@meshinspector.com>
Master's #5968 landed while this PR was in review and refactored
`composeStatus` to a single-argument form (blocking-modal formatting
moved into `effectiveDisabledReason` upstream, and `rootLevelBlocked`/
`topBlockingModalName` were removed from this TU).

Update `walkAll` and `listAllEntries` accordingly:
- drop the `rootBlockingModal` and `isRootLevel` parameters from
  `walkAll` — every entry just calls `composeStatus(entryDisabledReason)`
  with the new 1-arg form;
- drop the `blockingModal` local in `listAllEntries`.

Side benefit: descendants now also surface `"disabled: blocked by
modal '<name>'"` when applicable (previously the old 2-arg path
special-cased only root-level entries; with the upstream refactor
that special case is obsolete).

Fixes the emscripten + macOS arm64 Release CI failures on this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Grantim Grantim merged commit 2187f9a into master Apr 23, 2026
35 checks passed
@Grantim Grantim deleted the mcp-ui-listAllEntries branch May 5, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants