
Choose the right migration path
Source:vignettes/choose-the-right-migration-path.Rmd
choose-the-right-migration-path.Rmdshinymcp does two jobs. It is a runtime for interactive
cards and MCP Apps you write yourself, and it is an experimental
converter that gets existing Shiny apps part of the way there. The
runtime is the part to lean on today. Conversion still produces a
scaffold you finish by hand.
There are four ways to start, depending on what you already have.
1. Authored card from scratch
Reach for this when you already know the small interaction you want.
app <- mcp_app(
ui = htmltools::tagList(
mcp_select("dataset", "Dataset", c("mtcars", "iris")),
mcp_text("summary")
),
tools = list(
list(
name = "inspect_dataset",
description = "Inspect a built-in dataset",
inputSchema = list(
type = "object",
properties = list(dataset = list(type = "string"))
),
fun = function(dataset = "mtcars") {
list(summary = paste(capture.output(summary(get(dataset))), collapse = "\n"))
}
)
)
)You write the handler yourself, so the runtime behaves the same way in preview, shinychat, and MCP hosts.
2. Wrapped module with explicit handler
Reach for this when you already have a bounded module or server-side computation you trust. You keep the Shiny UI fragment, expose only the inputs and outputs you want in the card, and supply an explicit tool handler. Nothing runs your arbitrary server code automatically; the handler you write is what the card calls.
3. Selective migration into multiple cards
Use as_mcp_apps() or
convert_app(mode = "cards") when the original Shiny app
contains several connected reactive islands that should become separate
chat cards.
cards <- as_mcp_apps("path/to/shiny-app")
convert_app("path/to/shiny-app", mode = "cards")The output is still a scaffold. Tool bodies come out as placeholders, large reactive groups need review, and side effects and unsupported widgets need manual treatment.
4. Full scaffold conversion
Reach for convert_app(mode = "scaffold") when you want a
starting point to finish by hand.
convert_app("path/to/shiny-app", mode = "scaffold")Always review CONVERSION_NOTES.md. The generated code is
a draft, not a promise that the source app now has a bounded headless
runtime.
Runtime versus scaffold
The line between the two is who wrote the handlers. If you wrote them
yourself, you are on the runtime path and can trust the behavior. If
convert_app() generated them, treat the result as scaffold
output until you have replaced the placeholders.