--- title: "Using autoslider.core via MCP" date: "`r Sys.Date()`" output: rmarkdown::html_document: theme: "spacelab" highlight: "kate" toc: true toc_float: true author: - Joe Zhu ([`shajoezhu`](https://github.com/shajoezhu)) vignette: > %\VignetteIndexEntry{MCP server} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} editor_options: markdown: wrap: 72 --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ## Overview `autoslider.core` ships an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that exposes the entire slide-generation pipeline as a set of tools any MCP-compatible AI client can call. This means you can drive slide creation conversationally — no manual R scripting required. The server lives at `inst/mcp/autoslider_mcp_server.R` and registers these tools: | Tool | What it does | |---|---| | `list_programs` | Discover available TLG programs | | `load_spec` | Load a `spec.yml` and `filters.yml` | | `show_spec` | Inspect the loaded spec | | `run_pipeline` | Run the full TLG pipeline against your datasets | | `add_ai_notes` | Generate speaker notes with an LLM | | `generate_slides` | Assemble outputs into a `.pptx` file | | `reset` | Clear session state | ## Prerequisites Install the required R packages: ```{r} install.packages("mcptools") # MCP server runtime # ellmer and autoslider.core are already in your renv/library ``` Locate the server script. In a package checkout it is at: ``` inst/mcp/autoslider_mcp_server.R ``` After installation you can find it with: ```{r} system.file("mcp/autoslider_mcp_server.R", package = "autoslider.core") ``` --- ## Example 1: Claude Code as the MCP client [Claude Code](https://claude.ai/code) is a terminal-based AI agent from Anthropic. Once the autoslider MCP server is registered, Claude Code can call all the tools above in a natural language conversation. ### Step 1 — Find the server script path Run this in R to get the absolute path to the server script: ```{r} system.file("mcp/autoslider_mcp_server.R", package = "autoslider.core") ``` Copy the result — you will paste it into the configuration below. ### Step 2 — Register the server > **Important:** Claude Code does **not** read MCP servers from > `.claude/settings.json`. That file is only for permissions, hooks, and > environment variables. MCP servers are registered with the > `claude mcp add` command (which writes to `~/.claude.json`) or via a > `.mcp.json` file. Do not put an `mcpServers` block in `settings.json` — > it will be silently ignored. The **recommended approach** is to register the server at *user* scope so it is available in every session, regardless of which directory you open Claude Code in. Run this in your terminal: ```bash claude mcp add autoslider --scope user -- Rscript /absolute/path/to/autoslider_mcp_server.R ``` Replace the path with the one you found in Step 1. The `--` separates Claude Code's own flags from the command it should run. The three scopes: | Scope | Flag | Where it is stored | Availability | |---|---|---|---| | User | `--scope user` | `~/.claude.json` (top level) | Every directory (recommended) | | Local | `--scope local` (default) | `~/.claude.json` (per project) | Only the directory you ran it in | | Project | `--scope project` | `.mcp.json` in the repo | Anyone who checks out the repo | For a team-shareable setup checked into the package repo, use `--scope project`, which creates a `.mcp.json`: ```json { "mcpServers": { "autoslider": { "command": "Rscript", "args": ["/absolute/path/to/autoslider_mcp_server.R"] } } } ``` > **API keys:** No `ANTHROPIC_API_KEY` is required to register or use the > server. It is only needed if you call `add_ai_notes` with > `provider = "anthropic"`. Add it later with > `--env ANTHROPIC_API_KEY=sk-...` on the `claude mcp add` command, or omit > it entirely if you use a local model (Ollama) or another provider. > **WSL users:** Use a single leading slash in paths — `/mnt/c/...`, not > `//mnt/c/...`. ### Step 3 — Verify the server is registered Restart Claude Code, then type `/mcp` in the session — you should see `autoslider` listed with a connected status. You can also list servers from the terminal: ```bash claude mcp list ``` If it shows an error or does not appear, run `claude doctor` (it flags config files that failed validation) and check: - The path is the exact output of `system.file(...)` from Step 1. - `Rscript` is on your `PATH` (test with `which Rscript`). - The `mcptools` R package is installed (`install.packages("mcptools")`). ### Step 4 — Drive the pipeline conversationally Open a Claude Code session and ask it to generate slides. Claude Code will invoke the MCP tools automatically. **Example conversation:** ``` User: Generate demographic slides using the example data and save them to /tmp/study_slides.pptx. Add AI speaker notes using Claude Haiku. Claude Code: I'll use the autoslider MCP tools to do this step by step. [calls list_programs] → t_dm_slide, t_ae_slide, g_km_slide, ... [calls load_spec with spec_path="default", filters_path="default", program_filter="t_dm_slide", suffix_filter=""] → Spec loaded: 2 output(s). [calls run_pipeline with dataset_paths="example"] → Pipeline complete: 2 succeeded, 0 failed. [calls add_ai_notes with provider="anthropic", model="claude-haiku-4-5", api_key="", prompt_path="default", base_url=""] → AI notes added to 2 output(s): t_dm_slide_FAS, t_dm_slide_SE [calls generate_slides with outfile="/tmp/study_slides.pptx", template="default"] → Slides written to: /tmp/study_slides.pptx Done! The file is at /tmp/study_slides.pptx. It contains 2 demographic slides with AI-generated speaker notes. ``` Claude Code decides the tool call sequence, reads your intent, and handles errors automatically. You can iterate in plain English: ``` User: Also add the adverse event slides for the FAS population. Claude Code: [calls reset] [calls load_spec with program_filter="t_dm_slide,t_ae_slide", suffix_filter="FAS"] [calls run_pipeline ...] [calls add_ai_notes ...] [calls generate_slides ...] ``` ### Step 5 — Use your own data Replace `"example"` with your actual datasets in the `run_pipeline` call: ``` User: Use adsl=/data/trial/adsl.rds and adae=/data/trial/adae.rds ``` Claude Code will pass `dataset_paths="adsl=/data/trial/adsl.rds,adae=/data/trial/adae.rds"` to `run_pipeline`. --- ## Example 2: Ollama local model (DeepSeek) for AI notes If you prefer to keep data on-premise or want to avoid cloud API costs, you can use a local model running in [Ollama](https://ollama.com) for the `add_ai_notes` step. The MCP server itself still runs locally as an `Rscript` process; only the note-generation step changes. ### Step 1 — Install Ollama and pull a model Download Ollama from and install it. Then pull DeepSeek: ```bash ollama pull deepseek-r1:1.5b # ~1 GB, fast on CPU # or a larger variant: ollama pull deepseek-r1:7b ``` Verify it is running: ```bash ollama list # NAME ID SIZE MODIFIED # deepseek-r1:1.5b ... 1.1 GB ... ``` Ollama listens on `http://localhost:11434` by default. No API key is needed. ### Step 2 — Register the server (no API key required) Register it exactly as in Example 1 — the server is the same; only the note-generation provider changes at call time: ```bash claude mcp add autoslider --scope user -- \ Rscript /absolute/path/to/autoslider_mcp_server.R ``` No API key is needed because Ollama is local and unauthenticated. ### Step 3 — Ask for Ollama-backed notes In a Claude Code session (or any MCP client), tell it to use Ollama: ``` User: Generate demographic slides with the example data, write speaker notes using the local DeepSeek model in Ollama, and save to /tmp/slides_local.pptx. Claude Code: [calls load_spec with spec_path="default", filters_path="default", program_filter="t_dm_slide", suffix_filter=""] [calls run_pipeline with dataset_paths="example"] [calls add_ai_notes with provider="ollama", model="deepseek-r1:1.5b", api_key="", prompt_path="default", base_url=""] → AI notes added to 2 output(s). [calls generate_slides with outfile="/tmp/slides_local.pptx", template="default"] → Slides written to: /tmp/slides_local.pptx ``` ### Running R in a Docker container? If your R session is inside a container, Ollama runs on the host, so `localhost` resolves to the container itself. Use the Docker host address instead: ``` base_url = "http://host.docker.internal:11434" ``` Pass this in your conversation: ``` User: Use the local DeepSeek model. My R is running in Docker so point Ollama at http://host.docker.internal:11434. ``` Claude Code will pass `base_url="http://host.docker.internal:11434"` to `add_ai_notes`. ### Calling the R functions directly If you prefer to skip the MCP layer and call the functions directly from R, the underlying workflow is the same — only the `get_ai_notes()` call changes: ```{r} library(autoslider.core) library(dplyr) library(filters) filters::load_filters( system.file("filters.yml", package = "autoslider.core"), overwrite = TRUE ) outputs <- read_spec(system.file("spec.yml", package = "autoslider.core")) |> filter_spec(program %in% "t_dm_slide", verbose = FALSE) |> generate_outputs( datasets = list( adsl = eg_adsl |> mutate(FASFL = SAFFL), adae = eg_adae ), verbose_level = 0 ) |> decorate_outputs() prompt_list <- get_prompt_list( system.file("prompt.yml", package = "autoslider.core") ) # Ollama / DeepSeek — no API key, runs fully offline outputs_ai <- get_ai_notes( outputs = outputs, prompt_list = prompt_list, platform = "ollama", model = "deepseek-r1:1.5b", base_url = "http://localhost:11434" ) generate_slides(outputs_ai, outfile = "slides_local.pptx") ``` --- ## Choosing a provider | Scenario | `provider` | `model` example | Notes | |---|---|---|---| | Cloud, best quality | `"anthropic"` | `"claude-haiku-4-5"` | Requires `ANTHROPIC_API_KEY` | | Fully local, offline | `"ollama"` | `"deepseek-r1:1.5b"` | No key; install Ollama first | | OpenAI-compatible API | `"openai"` | `"gpt-4o-mini"` | Requires `OPENAI_API_KEY` | | DeepSeek cloud API | `"deepseek"` | `"deepseek-chat"` | Requires `DEEPSEEK_API_KEY` | The `base_url` parameter lets you point any provider at a custom endpoint — useful for local proxies, enterprise gateways, or self-hosted models.