[Stunt Double MCP server. Know where your users will get stuck, before they do. Beside it, Claude Code asks why the Parlour booking checklist failed on Monday and Stunt Double reports that nothing on the site changed: the earlier passes invented a phone number and card, and this time the agent followed its instructions and stopped at the Mobile field.]
Stunt Double MCP Server
Deploy AI user personas to validate user journeys at scale. Find UX friction before real users do.
Stunt Double deploys AI agents with realistic user personas to validate user journeys at scale. Create actors, run automated workflows and checklists against any web app, and surface friction points before real users encounter them. Integrates with Claude, Linear, GitHub, and Slack.
Contents
- This repository
- Quick Start: Claude Code, Claude Code plugin, Skills, Claude, ChatGPT and Codex, Codex CLI, Gemini CLI, VS Code, OpenCode, Windsurf, Other clients, Cursor
- Stunt Double Studio: Hooks, Local or cloud
- Authentication: What a connection can reach
- Available Tools: Account, Workspaces, Search, Projects, Guidelines, Actors, Knowledge, Conversations, Checklists, Workflows, Feedback, GitHub, Interviews, Prompts, Resources, Stunt Double Index
- Example prompts: Demo targets
- Privacy Policy
- Support
- Transport
- MCP Registry
- Links
- Verifying changes
- License
[stuntdouble on npm]
[A Claude Code session asking why the Parlour booking checklist failed on Monday. Claude calls Stunt Double, compares the failing run with the two passing runs before it and explains that the agent stopped at the required Mobile field, and that the earlier passes only got through by inventing a phone number and card.]
This repository
This repo holds plugin and MCP configuration (.claude-plugin/plugin.json and .mcp.json for Claude, .cursor-plugin/plugin.json, marketplace.json and root mcp.json for Cursor, server.json for the MCP registry), plus skills, agents, and Cursor rules. There is no package.json and no server code here: the MCP endpoint is hosted at https://app.stuntdouble.io/api/mcp from the main Stunt Double codebase, and the Claude plugin's local server is the published stuntdouble npm package from StuntKit. See CONTRIBUTING.md for how to validate edits and avoid confusing this folder with a Node package.
Quick Start
Claude Code
Claude Code plugin
The repository is also a Claude plugin: it bundles the hosted MCP server and the Stunt Double Studio server (.mcp.json) with the skills in skills/, the agents in agents/ and the Studio hooks in hooks/.
Type /stuntdouble: to list the plugin's skills. The Studio ones are /stuntdouble:setup, /stuntdouble:run, /stuntdouble:open, /stuntdouble:cloud and /stuntdouble:doctor.
Skills (any agent)
The skills in skills/ install into Claude Code, Cursor, Codex, OpenCode and other agents that read SKILL.md files, using the skills CLI. They drive the MCP server above, so connect that too.
Claude (web, Desktop, mobile)
Go to Settings → Connectors → Add custom connector and paste:
ChatGPT and Codex
The repository also carries an OpenAI plugin manifest (.openai-plugin/plugin.json, in the Agent Plugins format) with the directory listing, review test cases and release notes. node scripts/build-openai-plugin.mjs checks it against OpenAI's limits and writes dist/stuntdouble-openai-plugin.zip (in the Codex layout the portal accepts: the manifest as .codex-plugin/plugin.json, a .mcp.json for the hosted server, the skills and the logos), which is what goes into the plugin submission portal.
Until it is published in the directory, connect it in ChatGPT developer mode (Settings → Apps → Advanced) as a custom connector with:
The checklist run and Index report tools render as cards in ChatGPT (and in other MCP Apps hosts, Claude among them).
Codex CLI
Or add it to ~/.codex/config.toml by hand and then run codex mcp login stuntdouble:
Gemini CLI
Or add it to ~/.gemini/settings.json (or .gemini/settings.json in a project):
Run /mcp auth stuntdouble inside Gemini CLI to sign in.
VS Code (GitHub Copilot)
Or add it to .vscode/mcp.json in a workspace (or run MCP: Open User Configuration for every workspace):
The tools appear in Copilot Chat's agent mode.
OpenCode
Add it to opencode.json in a project (or ~/.config/opencode/opencode.json), then run opencode mcp auth stuntdouble:
Windsurf
Add it to ~/.codeium/windsurf/mcp_config.json (or Windsurf Settings → Cascade → MCP Servers → View raw config):
Other clients
Any client that speaks Streamable HTTP and OAuth can connect to https://app.stuntdouble.io/api/mcp directly. For a client that only runs local (stdio) servers, bridge it with mcp-remote, which handles the OAuth sign-in:
Cursor
This repository is a Cursor plugin: .cursor-plugin/plugin.json and .cursor-plugin/marketplace.json, root mcp.json (the hosted MCP server), plus the skills in skills/, rules in rules/, and agents in agents/. The plugin logo is assets/logo.png. Auth is OAuth 2.1 with PKCE; no API keys.
Install as a plugin (recommended): once published, install Stunt Double from the Cursor marketplace. For a team marketplace or local clone, add this repo as a marketplace and install the stuntdouble plugin; Cursor discovers the MCP server, skills, rules and agents from the default folders.
MCP only (no skills, rules or agents): add the block below to a Cursor MCP config:
- Project-local:
.cursor/mcp.json at the root of your project.
- Global (all projects):
~/.cursor/mcp.json on macOS/Linux (see Cursor MCP docs for your OS).
Use only url for remote servers (Streamable HTTP is negotiated automatically). Extra keys such as "type": "streamable-http" are not part of Cursor's documented mcp.json shape and can break plugin validation.
The server.json file is the separate MCP registry manifest for mcp-publisher and directory listings; Cursor's installer does not use it.
Stunt Double Studio
Run checklists against localhost, staging or production from Claude Code, free and with no account. Your own Claude Code session is the actor: the plugin's local server drives a local Chrome, keeps each run as files in your project and serves a viewer where you watch a run live or stop it. Local runs count against your Claude plan, or your API key when Claude Code uses one; Stunt Double makes no model calls.
Install the Claude Code plugin, then:
A run is carried out by the stuntdouble:stuntdouble-actor subagent, whose only tools are the local browser and run tools, so page text and screenshots stay out of your main conversation. Those tools are navigate, read_page, find, get_page_text, click, type, form_input, key, scroll, screenshot, start_run, evaluate_check and finish_run; the server's open_ui returns the viewer link. The local server is npx [email protected] mcp (source), pinned to an exact version in each plugin release. Claude Code starts it with each session (npx adds about 1.5 seconds), and the browser and viewer start only on the first run. It needs Node 22.18 or later and Google Chrome (or Playwright's Chromium). On native Windows the server does not start yet, since Claude Code needs cmd /c npx there: use WSL.
Everything lives in .stuntdouble/: stuntdouble.json, hooks.json, actors/, checklists/ and runs/, each run with its run.json, an activity.jsonl of every action and a screenshot per verdict. Actors and checklists are the hosted create_actor and create_checklist inputs, so /stuntdouble:cloud pushes them unchanged (except browser_config, which the cloud does not take yet, so cloud runs use the default desktop browser) and writes the cloud ids back. Commit the folder (its .gitignore leaves out .live/) and your team gets the same checklists and run history; npx stuntdouble view opens the viewer over it without Claude Code.
Hooks
/stuntdouble:setup also writes .stuntdouble/hooks.json, which switches on two Claude Code hooks that ship in the plugin (hooks/hooks.json). Without that file they do nothing, in well under 100 ms.
ui_globs decides which edits count as UI changes; checklists_for maps a checklist to the files it covers, and an edit no entry matches suggests the rest once per session. Edits made inside a subagent are skipped. Globs are relative to the project root and take **, *, ? and {a,b}. To switch a hook off for the project, set it to false; to switch both off, delete the file. The file is committed with the rest of .stuntdouble/, so to switch the hooks off for yourself only, set STUNTDOUBLE_HOOKS=off in your shell or under env in .claude/settings.local.json. The hooks are Claude Code only: the Cursor plugin and the ChatGPT and Codex package leave them out.
Local or cloud
See pricing for the cloud plans. The local server runs only in Claude Code for now: the Cursor mcp.json and the ChatGPT and Codex package carry the hosted server alone.
Authentication
Authentication is handled automatically via OAuth 2.1 with PKCE. The first time your AI client connects, a browser window will open for you to sign in and authorise access to your Stunt Double account. No API keys or tokens required.
For Cursor, the OAuth redirect URI is fixed to cursor://anysphere.cursor-mcp/oauth/callback (docs).
What a connection can reach
The server acts as you, never more. Every tool resolves the workspace it is
being asked about and checks your membership of it before doing anything, so a
connection reaches exactly the workspaces list_workspaces returns for you, and
an archived workspace reaches nothing. A workspace you are not a member of
answers the same way one that does not exist does: "not found".
That holds for ids too, not just the workspace_id you pass. A tool that takes
another object's id (a checklist for an automation step, an actor for an
interview participant) checks that object belongs to the same workspace before
storing or running it, and refuses with "not found in this workspace" otherwise.
Refusals never say which workspace an id does belong to.
Scopes narrow this further, never widen it. The consent screen names what the
connection asked for, and a token granted mcp:read is not shown the write or
run tools at all: they are absent from tools/list rather than present and
failing.
Available Tools
Account
Notification channel and timezone are account settings rather than workspace ones, so
they are the same answer in every workspace. Pass the timezone when creating a
scheduled workflow, or "every weekday at 9" becomes nine in UTC.
Workspaces
get_workspace reports the workspace security controls under settings: public
sharing, the feedback widget, self-hosted workers, and the network policy. They are
ceilings set by an admin, so a feature switched off there cannot be switched back on for
a single project.
Search
search takes a workspace_id plus an optional query, types filter, project_id
filter and limit (max 50). Terms are matched as prefixes, so a partial word is enough.
Omit query to browse the most recently updated items. Results carry the id you need
for the matching getter, so it is usually cheaper than listing an entity type and
filtering the list yourself. Reach for it before creating anything, to find the actor or
checklist that already covers the job.
Projects
A project is archived, never deleted, and an archived project reads as missing from
every tool here. Registering an MCP server and attaching it to a project are
workspace-admin actions in the dashboard; list_project_mcp_servers is how you check
what tools a run will actually have before writing a checklist that depends on one.
Guidelines
Standing rules the team holds the product to: design system, tone of voice, brand,
content, accessibility, compliance, security, performance, or shared knowledge. A
guideline is owned by the workspace and attached to the projects it applies to, so
one rule can hold for every project without being retyped. Whatever is in force is
rendered into every checklist run, design review, interview and triage for that project.
Two switches decide whether a rule is in force for a project: the library's enabled
and the attachment's. list_project_guidelines folds them into one enabled so you
never have to reason about both. A rule with apply_to_design_reviews set also holds for
design reviews raised from Slack or Linear, which carry no project to attach it through.
Codify a standard as a guideline rather than repeating it in each checklist, and search
the library before writing a new rule: attaching the one that already exists keeps the
team's standard in a single place to edit.
Actors
Knowledge
Conversations
Checklists
Workflows
A workflow is a graph, not a list: its steps run by following the connections between them. The step tools maintain those connections, so adding, removing and reordering steps is enough to build one. connect_workflow_steps is only needed to branch.
Feedback
GitHub
Interviews
Structured user interviews: actors or generated personas run through a discussion guide (sections + questions/tasks) against a target URL, then Stunt Double synthesises themes and recommendations.
Prompts
Most MCP clients (Claude, Claude Code, Cursor) surface these as slash commands. Each is a self-contained recipe: which tools to call, in what order, and how to report back.
Resources
Read-only context a client can attach without calling a tool. The guide and the connection are always listed; the workspace resources need mcp:read, the same as the tools that return that data.
resources/list includes one projects entry per workspace, so a client can browse them without expanding the template.
Stunt Double Index
The Stunt Double Index is a public ranking of how AI agents experience websites: each tracked domain is scored out of 100 from HTTP probes plus live agent sessions, one per AI provider and benchmark task. Index data is public rather than workspace data, so the read tools reach any tracked site.
get_index_report, list_index_sessions and request_index_rerun take a domain, or a project_id to use the Index domain linked to that project (which checks your membership like any project read). A full URL is fine as a domain: the protocol, path and a leading www. are dropped.
Only the domain's owner can re-run it: whoever claimed it or, while it is unclaimed, an account with a work email on that domain. A domain can be re-run once every 10 minutes. After a re-run, poll list_index_sessions with the returned run_id about every 60 seconds until the sessions finish, then read get_index_report.
request_index_score is open to any signed-in account. It scores public web domains only, respects robots.txt and X-Robots-Tag opt-outs, and never rescores a site the Index already tracks (it answers already_tracked; use request_index_rerun for that). The site becomes public on the leaderboard. The probes finish in under a minute; agent sessions asked for with include_agent_sessions draw on a shared daily budget, so they may be queued to run later that day (agent_sessions is then deferred or retrying). Read get_index_report for the probe score straight away, and poll list_index_sessions with the run_id if sessions started.
No account needed for the read tools: search_index_domains, get_index_report and list_index_sessions are also served, read-only and with no sign-in, at https://app.stuntdouble.io/api/mcp/index. Connect any MCP client to that URL and leave the OAuth fields empty. It carries only those three tools, and project_id does not resolve there, so pass a domain. request_index_rerun and request_index_score need the signed-in server.
Example prompts
Four prompts that exercise the core of the server once it is connected:
- Verify a flow: "Create a checklist that completes the checkout on https://checkout.demo.stuntdouble.io and reaches the confirmation page, then run it and tell me which checks failed."
- Run a user interview: "Set up an interview with three personas (a first-time diner, a regular and a screen reader user) about booking a table on https://parlour.demo.stuntdouble.dev, launch it, and summarise the report."
- Check agent readiness: "How well can AI agents use stripe.com according to the Stunt Double Index, and which categories are dragging its score down?"
- Triage feedback: "Summarise the open feedback on my main project, group it into themes, and mark anything already fixed as resolved."
Demo targets
Try the server without pointing it at your own product. These public demo apps have deliberate defects for actors to find, so runs never touch real customers:
Privacy Policy
The server is hosted by Stunt Double and acts as the signed-in user. It reads and writes only the workspaces that user belongs to, within the OAuth scopes they grant (mcp:read, mcp:write, mcp:run). It does not read your conversation with the AI client beyond the arguments passed to each tool call, and it does not access the client's memory, chat history or files.
Data created through the server (projects, actors, checklists, runs, interviews, feedback) is stored in your Stunt Double workspace and handled under the Stunt Double Privacy Policy, which covers collection, use, storage, sub-processors, retention and your rights. Revoke a connection at any time by disconnecting it in your AI client.
Support
Transport
This server uses Streamable HTTP transport. The endpoint is:
MCP Registry
The server is listed in the official MCP Registry as io.stuntdouble/mcp-server, so registry-backed clients and directories can find it by name:
Each version merged to main is published there automatically (see CONTRIBUTING.md).
Links
Verifying changes
From the repo root:
More context in CONTRIBUTING.md. GitHub Actions runs the same checks on push and pull requests.
License
MIT