pbi-webview2
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PBI_POLL_MS | No | Interval between poll probes in milliseconds. Default: 1000 | |
| PBI_OUTPUT_DIR | No | Directory for screenshots and baselines. Default: <os tmpdir>/pbi-webview2-output | |
| PBI_DESKTOP_EXE | No | Explicit path to PBIDesktop.exe for direct-launch fallback. | |
| PBI_CDP_ENDPOINT | No | CDP endpoint to attach to. Always 127.0.0.1, never localhost. Default: http://127.0.0.1:9222 | |
| PBI_DESKTOP_BRIDGE | No | Explicit path to Microsoft's powerbi-desktop bridge CLI entry (.js, .cmd, .bat, or .exe). Used by pbi_launch. | |
| PBI_EVAL_BUDGET_MS | No | Per-page.evaluate time budget in milliseconds. Default: 30000 |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| pbi_launchA | Launch Power BI Desktop on a .pbip WITH the CDP debug port. Resolves a launcher in order: PBI_DESKTOP_BRIDGE env → powerbi-desktop on PATH → direct PBIDesktop.exe (reported as launcher: bridge-env|bridge-path|direct). Injects the WebView2 remote-debugging env var into Desktop's own process, spawns detached, waits until the CDP port answers. If the port is already up, reports the running instance instead of launching a second one. Pre-flight warns about orphaned PBIDesktop/msmdsrv. After it returns cdpUp:true, call pbi_wait_for {text:""} — the canvas is still rendering. |
| pbi_statusA | Connect to Power BI Desktop over CDP and report status: build, title bar, active page, page count, zoom, canvasReady. Returns {connected:false,...} if unreachable. |
| pbi_pagesA | List all report page tabs as [{name, active}]. |
| pbi_goto_pageA | Navigate to a page by EXACT name. Returns as soon as the tab switches (the canvas may still be rendering — use pbi_wait_for before reading values); waitReady:true blocks until visuals are painted. On not-found returns closest candidates. |
| pbi_deselectC | Clear visual/group selection via the neighbour-page-and-back trick (never blind-clicks the canvas). Returns {selectedBefore, selectedAfter, page}. |
| pbi_state_probeB | Batched scorecard: {activePage, toggles, cards, badges, selectedCount, slicerItemsVisible, visibleVisualCount}. |
| pbi_read_cardsA | Parsed card visuals as [{title, value}]. |
| pbi_clickA | Generic tag-then-act click by text | ariaLabel | selector (ctrl for action buttons; index disambiguates). Overlay-intercept coordinate fallback. Returns {clicked, method, matchedLabel, candidateCount}. |
| pbi_set_slicerA | Set a slicer: kind "button" (buttonSlicerVisual, returns aria-pressed before/after) or "item" (list slicer item, returns a fresh state probe). |
| pbi_fire_bookmarkA | Fire ANY bookmark by name via the View > Bookmarks pane (trusted coordinate click; optional group; expandable groups auto-expanded). Returns {fired, landedPage, warning?}. |
| pbi_read_matrixA | Read a matrix/grid fully as {columns, rows:[{header, cells}], ariaRowCount, ariaColCount, complete}. Scrolls virtualized grids and merges by row header. |
| pbi_matrix_expandB | Expand or collapse a matrix hierarchy row (by rowHeader). Grid re-renders; returns {rowsBefore, rowsAfter}. |
| pbi_cross_filter_testB | Click a data point and judge whether a cross-filter FIRED (highlights rose OR card fingerprint changed). Optional restore re-clicks and verifies baseline. Returns {fired, highlightsBefore, highlightsAfter, changedCards, restored}. |
| pbi_hover_tooltipA | Trusted mouse-move hover to a point (offsetX/offsetY to aim off-center, e.g. donut ring) and read the tooltip text. Returns {tooltipText} or {tooltipText:null}. |
| pbi_scan_errorsA | Scan visible visuals for broken/errored surfaces + recent non-benign console errors. Excludes the permanent favicon.ico error (reported as benignFaviconCount). |
| pbi_perf_analyzerA | Run the Performance Analyzer lane: per-visual render ms; optional captureQueryFor grabs one visual DAX via clipboard (clobbers clipboard). Restores pane + ribbon. |
| pbi_page_sweepA | HEAVY, deliberately renders every page: each page switch makes Desktop re-query all its visuals (blank/busy for that page’s real load time, often 10-30s+). Run as an intentional health sweep (≤2 pages per call; user warned/away), never casually. Iterates pages, waits canvas-ready (cap 30s/page), records loadMs + error scan + cards fingerprint; restores the original page. |
| pbi_baselineA | Capture / compare / list value baselines. capture: store {cards, badges, visibleVisualCount} per page (default current; pages:["*"]=all) to /baselines/.json. compare: re-capture + diff. list: available baseline names. |
| pbi_wait_forB | Poll body innerText until text appears (text) or disappears (textGone). Returns {satisfied, elapsedMs}. |
| pbi_evalA | Escape hatch: evaluate a function-body or arrow-fn string in the reportView page. Rejects any code referencing powerBIAccessToken. Returns the JSON-serialized result. NOTE: the powerBIAccessToken rejection is a best-effort textual guard (a regex on the code string), not a sandbox. |
| pbi_run_codeA | TRUSTED escape hatch (browser_run_code_unsafe equivalent). Runs an async JS function with the live Playwright reportView |
| pbi_snapshotA | Accessibility-tree snapshot of the reportView page (browser_snapshot equivalent) for structure discovery when a selector drifts. Returns the ARIA snapshot (roles + accessible names, indented) as lines. selector scopes to a sub-tree (default "body"); filter (regex string) keeps only matching lines (with their indent); maxLines caps output. Read-only. |
| pbi_typeA | Type text into an editable element (input/textarea/contenteditable/searchbox/textbox) via TRUSTED keyboard input. Target resolution: selector > element whose aria-label includes ariaLabel > first visible search/text input. Focuses the input IN-PAGE and ABORTS (typed:false) if focus does not land on it — never sends keystrokes to the canvas. clear empties the input via its own value (no global select-all); submit presses Enter. Returns {typed, matchedLabel, cleared, submitted}. WARNING: real typing mutates report state — restore/clear when testing. |
| pbi_search_slicerA | Type into a slicer's search box and (optionally) click the matching result. Focuses the box IN-PAGE and ABORTS (searched:false) if focus does not land on it — never sends keystrokes to the canvas (a mis-focused select-all+delete once removed all page visuals). Clears via the input's own value, types query, polls for filtered .slicerItemContainer items, returns them as matches. With pick, clicks the item equalling (then including) pick. Returns {searched, picked, pickedLabel?, matches} or {searched:false, reason}. Mutates a filter when pick clicks — restore after. |
| pbi_context_menuA | Right-click a data point / visual to open its context menu and read the items (drillthrough, Show as a table, Summarize, …). Right-clicks at the on-path point for SVG (else bbox center). With click, invokes the menu item matching (exact then contains) it and returns {opened, items, clicked, clickedItem}. Without click, reads items then presses Escape to CLOSE the menu (leaves no menu open). Returns {opened:false, reason} if no menu appeared. |
| pbi_screenshotA | Screenshot the reportView page to the output dir (never the repo). Optional filename + fullPage. With visualTitle, clips the shot to the matching visual (exact then case-insensitive contains on the same title logic as pbi_visuals) and returns {clippedTo}; on a miss returns {saved:false, reason, candidates}. Returns {path}. |
| pbi_visualsA | List every visible visual on the active page as [{title, type, x, y, width, height, hasError}]. type is a class-token heuristic (barChart, slicer, card, tableEx, pivotTable, donutChart, …; null when unknown); title from the container/descendant aria-label or .visualTitle; hasError reuses the broken-visual scan. Coordinates are getBoundingClientRect() rounded. Read-only. |
| pbi_read_dax_editorA | Read the DAX query view editor text (Monaco). Reaches the daxQueryView CDP target (a SEPARATE page from reportView); returns {ok:false, reason} if that view has never been opened in Desktop (open it via the DAX query view tab first — this tool will NOT open ribbon views). Read-only. |
| pbi_read_tmdlA | Read the TMDL view editor text (Monaco). Reaches the tmdlView CDP target (a SEPARATE page from reportView); returns {ok:false, reason} if that view has never been opened in Desktop (open the TMDL view tab first — this tool will NOT open ribbon views). Read-only. |
| pbi_dax_queryA | Write DAX into the DAX query view editor and RUN it, then read the results grid. Reaches the daxQueryView CDP target (SEPARATE from reportView); {ok:false, reason} if the view has never been opened in Desktop (open the DAX query view tab first — this tool will NOT open ribbon views). Runs via F5 on the focused editor, falling back to a visible "Run" button. Returns {ran, columns, rows, rowCount, error?}. CAVEAT: this OVERWRITES whatever DAX the user had in the query editor — prior text is NOT restored (unrecoverable). Use a throwaway query view. |
| pbi_dialogA | Automate a Desktop dialog (desktopDialogHost CDP target — exists ONLY while a dialog is showing). action:"read" returns {open, text, buttons}; action:"click" trusted-clicks the button matching |
| pbi_deep_snapshotA | Raw-CDP deep inspection of the reportView page. what:"axtree" (default) = a compact {role,name} projection of the full accessibility tree (capped to maxNodes, totalNodes reported); "dom" = a DOMSnapshot size probe ({documentCount, note}); "heap" = V8 heap usage ({usedMB, totalMB}). Read-only; safe. |
| pbi_emulate_themeA | Force the WebView media query prefers-color-scheme to light/dark/no-preference (via page.emulateMedia). Returns {emulated, scheme}. NOTE (verified 2026-07-15): the signal flips correctly (matchMedia reflects it) but Power BI Desktop reports do NOT restyle on prefers-color-scheme — report theming is driven by theme.json + app settings, not this CSS signal — so this is effectively INERT for PBI report canvases (it would matter only for a generic web app). Kept for completeness; do not expect a visual change. RESET to "no-preference" when done. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bibiibjorn/pbi-webview2'
If you have feedback or need assistance with the MCP directory API, please join our Discord server