The Scrollytelling MCP server connects the widget library to Claude Code, Cursor, VS Code, Claude and any other MCP client. Your agent searches the widgets and pulls finished, paste-ready HTML — carousels, sticky splits, interactive maps, charts — without you leaving the editor. It works on every plan, including Free, and never spends credits.
Pick your client. Every path ends the same way: a browser opens, you sign in with your normal Scrollytelling account (email or Google), approve the connection, and the client handles tokens and refresh from there. No keys to copy.
One command, then run /mcp, pick scrollytelling and choose Authenticate:
claude mcp add --transport http scrollytelling https://api.scrollytelling.ai/mcp
No API key needed. Your client opens a browser sign-in with your normal Scrollytelling account the first time it connects. Add --scope user to make it available in every project.
Add this to ~/.cursor/mcp.json (every project) or .cursor/mcp.json (one project), then open Cursor Settings → Tools & MCP and click Needs login next to scrollytelling:
{
"mcpServers": {
"scrollytelling": {
"url": "https://api.scrollytelling.ai/mcp"
}
}
}Cursor opens the browser sign-in and stores the tokens itself.
Run this in a terminal (VS Code 1.101 or newer, Copilot agent mode), then pick Allow when VS Code asks to sign in:
code --add-mcp '{"name": "scrollytelling", "type": "http", "url": "https://api.scrollytelling.ai/mcp"}'{
"servers": {
"scrollytelling": {
"type": "http",
"url": "https://api.scrollytelling.ai/mcp"
}
}
}VS Code supports the sign-in flow natively — no keys, no secrets file.
In Claude (web or desktop) open Settings → Connectors → Add custom connector. Name it Scrollytelling, paste the server URL, click Add, then Connect and sign in:
https://api.scrollytelling.ai/mcp
Custom connectors are available on Claude's paid plans (Pro, Max, Team and Enterprise) — that's Claude's rule, not ours. The connector then works in chat and in Claude's desktop app.
Any client that speaks MCP over Streamable HTTP with OAuth 2.1 (PKCE and dynamic client registration) needs the URL alone. A script or a client without OAuth can send a personal API key as the bearer token instead — create one under Settings → Integrations:
curl https://api.scrollytelling.ai/mcp \
-H "Authorization: Bearer stl_your_personal_api_key" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Discovery lives at /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server on the API origin. The server is stateless JSON-RPC: POST only, no server-sent streams.
The connection identifies you; what it can read is decided live, per request. Widget tools work on every plan and never spend credits. Story tools only ever see the stories of the account you signed in with. Disconnect an agent any time under Settings → Integrations — and the same connection works again the moment you approve it.
Three tools cover the whole loop; two more handle your published stories.
search_widgets“a map”, “sticky image”, “chart” — the agent gets slugs, summaries and what each widget is for.
get_widgetThe widget's docs, the JSON schema of its props and a complete example it can adapt.
render_widgetYour content in, a self-contained HTML document out — or an iframe snippet for an existing page.
Try asking:
Most scrollytelling, GSAP and animation MCP servers you find on registries are code generators: you describe an effect and the model writes fresh code from scratch. Useful for one-off snippets, but the output is whatever the model produces that day — untested, unstyled, and yours to debug. Ask twice and you get two different carousels.
The Scrollytelling server is the other kind: a component MCP, the same model shadcn/ui uses. Your agent searches a library of finished, production-tested widgets and gets the real thing — rendered by the exact engine that publishes every Scrollytelling story, with responsive layout, reduced-motion support, lazy-loaded media and documented props already handled. Generation gives you a starting point; a component MCP gives you the shipped thing.
| Code-generator MCP | Scrollytelling (component MCP) | |
|---|---|---|
| What you get | Fresh code the model wrote for this request | The real source of a finished widget, rendered by the engine that publishes every Scrollytelling story |
| Consistency | Different every time, even for the same prompt | Byte-identical output for the same props — today, next month, in CI |
| Responsive, accessible, reduced motion | If the model remembered | Built in and tested on every widget |
| Styling | Unstyled, or styled to whatever the model guessed | Design tokens (accent, background, text, fonts) applied the same way as in the editor |
| Debugging | Yours — nobody else has ever run that code | Ours — the widget is the one thousands of published stories already run |
| Updates | Never; the snippet is frozen the moment it is written | Render again and you get the current widget; published-story embeds update themselves |
| Cost | Model tokens for every line of code | No AI, no credits — a library lookup |
The two are not rivals: let a generator write the glue code around a page, and let the component server hand it the sections that have to work.
get_story_embed. (Preview it here.)videoUrl renders as an autoplay background, and a frame set you already have renders with real scrubbing.| Tool | What it does | Inputs |
|---|---|---|
search_widgets | Find widgets by name, purpose or keyword; an empty query lists all 13. | query (optional) |
get_widget | A widget's docs, the JSON schema of its props and a complete example call. | slug |
render_widget | Render one widget with your content to self-contained HTML, or to an <iframe srcdoc> snippet. | type, props, heading, subheading, design, format, iframeHeight |
list_stories | Your stories with publish status and public URL. | publishedOnly (optional) |
get_story_embed | A published story's URL, iframe embed, oEmbed endpoint and WordPress shortcode. | storyId, height |
Every tool is read-only and idempotent. render_widget accepts design tokens — accentColor, backgroundColor, textColor, headingFont, bodyFont — and format: "iframe" for an <iframe srcdoc> snippet.
| Resource | Contents |
|---|---|
scrollytelling://concepts/scroll-driven-storytelling | Patterns: what holds, what moves, which widget — plus pacing and asset rules. |
scrollytelling://concepts/embedding | Using the rendered HTML as a file, inside a page (iframe srcdoc), or in React/Vue/Svelte. |
scrollytelling://widgets/{slug} | Per-widget docs and props schema, one resource per widget. |
/mcp → scrollytelling → Authenticate), or check the API-key header if you use one. Tokens last 24 hours and refresh automatically; a disconnected agent (Settings → Integrations) gets a 401 until you approve it again.https://api.scrollytelling.ai/mcp over https.get_widget.Yes. It works on every plan, including Free, and never spends credits. It's the same widget library you can customise by hand on the widgets pages — just reachable from your coding agent.
No. Your client opens a browser sign-in with your normal Scrollytelling account (email or Google), you approve the connection, and the client keeps its own tokens. A personal API key is only for scripts or clients that don't support OAuth.
Claude Code, Cursor, VS Code (Copilot agent mode), Claude's custom connectors, and any client that speaks MCP over Streamable HTTP with OAuth 2.1. The setup block above covers each one.
No. It's a component library: the server searches the catalogue and renders a finished widget with the content your agent passes in. Your agent is the only AI in the loop, and it runs on your side.
No — it's read-only. It can list your stories and hand back embed codes for the published ones; creating and editing happens in the editor.
Yes. The rendered widget is a complete, self-contained HTML document with no runtime dependency on us (the map loads its tiles from public servers). Save it, host it, embed it — anywhere.
Yes. Every widget is the same one published stories ship: responsive layouts, real DOM text, lazy-loaded media, keyboard controls where there are controls, and reduced-motion support.
Treat the HTML as a static asset: render an iframe with srcdoc (ask for format "iframe"), or write the file to your public folder and point an iframe at it. Don't inject it with innerHTML — inline scripts won't run that way.
Settings → Integrations → Connected agents → Disconnect. The agent gets a 401 until you approve it again. Removing the server from the client also stops it using the connection.
On the widgets pages: search, open any widget, drop in your own text and images, and copy the embed code — no account needed.
120 calls a minute per connection, 24 items per list widget (40 pins on a map, 50 chart points), images under 1.5 MB as data: URIs, and a 4 MB request. Enough for any page; ask us if you need more.
Search, open and customise every widget in the browser — your own text and images, no account, no AI.