Skip to main content
Glama
README.md
# shinyprobe

An MCP server that gives coding agents hands and eyes on a running Shiny app, R or Python.

## Why

Coding agents write Shiny code blind. Once the app runs, they cannot set an input, see the
plot, or tell which output broke and why. shinyprobe gives them a real browser on the running
app, and it understands Shiny rather than just the page.

**It knows when Shiny has finished.** Every action waits for the app to settle, then reports
which outputs changed and what went wrong. No sleeping, polling or guessing from screenshots.
A generic browser tool cannot tell "still computing" from "nothing happened"; shinyprobe can,
including on slow hosted apps.

**Errors come with an address.** A failing output returns the R or Python traceback, with
file and line (`app.R#14`), attached to the output it broke. `validate()` is a warning,
`req()` is silent, and only real errors are errors. A crash says so, with the exit code and
the last console lines.

**It catches mistakes you would not see.** It warns when a widget rejects a value (a select
given a choice it doesn't have) and when an output never renders, usually a typo'd id. Both
otherwise look fine and are quietly wrong.

**It handles real app structure.** Tabs, accordions, sidebars, `renderUI` and modules all
work. Clicking something on another tab opens that tab first, as a user would. If a
`conditionalPanel` hides it, the error names the condition to meet.

**It shortens the fix-and-check loop.** `get_console` shows what the app printed.
`launch_app(replay=True)` restarts the app after a code change and replays the same inputs
and clicks, so "fix it, then get back to where it broke" is one call.

**It returns data, not just pictures.** Tables come back as columns and rows, plots with
their axis ranges and mapped variables, htmlwidgets with their data payload.

**It stays out of your app.** No R packages to install, no changes to your code. It works on
local apps and on public deployments.

The difference: an agent can *check* its work instead of assuming it. "I've written the
change" becomes "I've written the change, set `n` to 5, the table has five rows, and nothing
errored".

## Quickstart

    uvx shinyprobe install-browser
    claude mcp add shinyprobe -- uvx shinyprobe

Then ask your agent to launch your app, change inputs and read outputs.

You need R with `shiny` for R apps, or a Python with `shiny` for Python apps. shinyprobe finds
`Rscript` and `python` on your PATH (and R's default install folder on Windows); set
`SHINYPROBE_RSCRIPT` or `SHINYPROBE_PYTHON` to use others. Set `SHINYPROBE_HEADED=1` to
watch the browser.

## Tools

| Tool | What it does |
|---|---|
| `launch_app` | Start the app in a folder or file and open it. Relaunching the same path keeps the `app_id`; `replay=True` reruns the previous run's actions. |
| `attach` | Open an app that is already running, locally or deployed. |
| `stop_app` | Close the page and stop a launched app. |
| `list_controls` | Every input (id, type, label, value, choices) and output (id, type, status), with visibility. |
| `set_inputs` | Set inputs through their widgets and wait for the app to settle. |
| `click` | Click a button, opening any tab or panel around it first. |
| `show` | Open the tab, accordion panel, sidebar or `<details>` holding an element, by id or label. |
| `upload_file` | Upload a local file into a file input. |
| `read_outputs` | Text, tables as rows, plots and widgets as images plus their data. |
| `get_errors` | Every error so far: server traces, output errors, browser errors, crashes. |
| `get_console` | The app's own console output, for launched apps. |
| `screenshot` | The whole page or one element. |

Every action returns the same envelope: `status` (`settled`, `no_change`, `timeout` or
`disconnected`), `changed_outputs`, `errors` and `warnings`.

## Hosted apps

`attach` works on public deployments such as shinyapps.io. You lose what lives in the host's
process: no server tracebacks, no console, and hosts usually hide error messages ("An error
has occurred…"), though you still learn which output failed. Each attach is a real session
on that server and counts towards its usage. Apps behind a login are not supported yet.

TDQS

A4.1/5.0

Scored across 12 tools

Disambiguation5/5

Every tool targets a distinct action: lifecycle (attach, launch_app, stop_app), UI inspection (list_controls), interaction (set_inputs, click, show, upload_file), output reading (read_outputs), and diagnostics (get_errors, screenshot, get_console). No two tools overlap in purpose, making misselection highly unlikely.

Naming Consistency5/5

All names follow a consistent verb_noun pattern in snake_case (e.g., launch_app, set_inputs, read_outputs). Single verbs like attach and click are still clear and fit the pattern, with no mixed conventions or vague terms.

Tool Count5/5

12 tools is well-scoped for a Shiny app interaction server. Each tool covers a necessary capability for starting, controlling, inspecting, and debugging apps, without redundancy or bloat.

Completeness5/5

The surface covers the full lifecycle from launch to stop, all common input interactions, output reading, and error/console diagnostics. No obvious gaps exist for typical Shiny testing workflows, making the set self-sufficient.

Maintenance

ActivityMaintained
ResponsivenessNo issues