Skip to contents

Lets coding agents run a shiny module of an R package, set its inputs, read its arguments, return values and outputs, and screenshot it, through the Model Context Protocol. The module runs in module2app_bare(), the testbed without displays for humans.

Usage

crow_tools()

crow_mcp_server(plugin_root = NULL)

Arguments

plugin_root

The root of the agent plugin which starts the server, to check that it belongs to the installed crow version.

Value

  • crow_tools(): A named list of ellmer::tool()s.

  • crow_mcp_server(): Does not return; serves the tools until the MCP client disconnects.

Details

The tools offer two tiers of cost:

  • module_test_server runs shiny::testServer() on module2app_bare_server() in a new R process, without a browser. It takes a few seconds and keeps no state.

  • module_app_start runs module2app_bare() in a new R process and drives it with shinytest2::AppDriver in Chrome. It takes about ten seconds to start, and runs until module_app_stop. module_app_set, module_app_get and module_app_screenshot use the running app.

All tools report the server arguments and return values as unevaluated and evaluated trees (see mixed_react_tree()), the raw events of shiny::reactlog() on request, and the logs of their R and shiny processes, errors first.

Every tool starts its R processes in path, the package root with the DESCRIPTION, and loads the package from there with pkgload::load_all(), so it runs the working tree, not an installed version. Running apps load the package when they start; restart them after changing the package. Each app runs in its own processes, which end when the app or the MCP server stops.

Security

The tools evaluate the R code that the agent passes, such as server_args, with the rights of the user running the MCP server. Only a sandbox around the agent and the MCP server isolates your system from that code. Changes to running apps (module_app_set) accept only JSON, because the apps listen on local websockets that any web page in the same browser could reach.

See also

Other agentic coding: module2app_bare_ui()

Examples

if (FALSE) { # \dontrun{
# combine with btw's tools for documentation and package development
mcptools::mcp_server(
  c(btw::btw_tools(c("docs", "pkg")), crow::crow_tools()),
  session_tools = FALSE
)
} # }