Connect your agent
The MCP server is identical for every client — it's always
npx -y @stepskit/mcp with your STEPSKIT_TOKEN. What differs is only where
the config lives and its format. The cleanest path is each tool's own
mcp add command or UI, which writes the right file for you.
Get a token
There are two kinds of token, and which you want depends on how many projects you work across:
| Token | Mint it at | Reaches |
|---|---|---|
| Account | Account settings → MCP Access Tokens | Every project you own — one token per machine instead of one per repo. Your agent picks which project to write to; see Pick a project. |
| Project | a project's AI Agents page → Generate token | That one project, forever. The smallest blast radius if it leaks. |
Either way, copy the token when you mint it — it's stored hashed and can't be
shown again. Everywhere below, sk_live_... stands for the token you copied.
At a glance
| Client | Add it via | File | Format / key |
|---|---|---|---|
| Claude Code | claude mcp add or edit file | .mcp.json (project) / user scope | JSON · mcpServers |
| Cursor | Settings → Tools & MCP, or edit file | .cursor/mcp.json / ~/.cursor/mcp.json | JSON · mcpServers |
| Codex CLI | codex mcp add or edit file | ~/.codex/config.toml | TOML · [mcp_servers.stepskit] |
| Claude Desktop | edit config file | claude_desktop_config.json | JSON · mcpServers |
| VS Code / Copilot | edit file | .vscode/mcp.json | JSON · servers |
After adding the server, restart your agent so it loads, then ask it to set up StepsKit and build a tour.
Keep the token out of the config file
MCP config files get committed. The snippets below reference the token
instead of containing it, so the file is safe in git — export the real value
once, in your shell profile or a local .env:
export STEPSKIT_TOKEN=sk_live_...How the reference works differs per client, and using the wrong mechanism fails
silently — so each snippet below uses the form its client actually documents:
Claude Code and Claude Desktop expand ${STEPSKIT_TOKEN} from the environment,
VS Code prompts you once and stores the value itself, and Codex forwards the
variable from your shell. Cursor is the exception — it isn't documented to
expand ${VAR}, so its config keeps the literal token and belongs in
.gitignore.
Claude Code
Run this in your project — it writes the config for you:
claude mcp add stepskit --env 'STEPSKIT_TOKEN=${STEPSKIT_TOKEN}' -- npx -y @stepskit/mcpThe single quotes matter — they stop your shell from expanding ${...} as
you run the command, so the placeholder lands in the config file and Claude Code
expands it at launch instead.
Or add it by hand to .mcp.json in your project root:
{
"mcpServers": {
"stepskit": {
"command": "npx",
"args": ["-y", "@stepskit/mcp"],
"env": { "STEPSKIT_TOKEN": "${STEPSKIT_TOKEN}" }
}
}
}Pass --scope user to the CLI (or edit your user config) to write the entry
once for every repo instead of per project — pair that with an account token so
the one entry can reach all your projects.
Verify: run /mcp in Claude Code — stepskit should be listed and connected.
Cursor
Add it from Settings → Tools & MCP → New MCP Server, or create
.cursor/mcp.json (project) / ~/.cursor/mcp.json (global):
{
"mcpServers": {
"stepskit": {
"command": "npx",
"args": ["-y", "@stepskit/mcp"],
"env": { "STEPSKIT_TOKEN": "sk_live_..." }
}
}
}Verify: open Settings → Tools & MCP — stepskit should show a green/active
indicator and its tools listed.
Codex CLI
Run this — it writes Codex's config for you:
codex mcp add stepskit --env STEPSKIT_TOKEN=sk_live_... -- npx -y @stepskit/mcpThat writes the literal token into config.toml. To keep it out of the file,
add the server by hand to ~/.codex/config.toml and use env_vars, which
forwards the variable from your shell:
[mcp_servers.stepskit]
command = "npx"
args = ["-y", "@stepskit/mcp"]
env_vars = ["STEPSKIT_TOKEN"]Verify: run codex mcp list — stepskit should appear.
Claude Desktop
Edit claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
{
"mcpServers": {
"stepskit": {
"command": "npx",
"args": ["-y", "@stepskit/mcp"],
"env": { "STEPSKIT_TOKEN": "${STEPSKIT_TOKEN}" }
}
}
}Restart Claude Desktop — stepskit appears under the tools (🔌) menu.
VS Code / GitHub Copilot
Create .vscode/mcp.json:
{
"inputs": [
{
"type": "promptString",
"id": "stepskit-token",
"description": "StepsKit MCP token",
"password": true
}
],
"servers": {
"stepskit": {
"command": "npx",
"args": ["-y", "@stepskit/mcp"],
"env": { "STEPSKIT_TOKEN": "${input:stepskit-token}" }
}
}
}VS Code prompts for the token the first time it starts the server and stores it securely, so nothing secret lives in the file.
Any other MCP client
Anything that speaks the Model Context Protocol works. Most clients (Windsurf,
Zed, etc.) use the same mcpServers JSON shown above — just point them at
npx -y @stepskit/mcp with STEPSKIT_TOKEN in the env. If the client doesn't
document ${VAR} expansion, put the literal token in and keep the file out of
git.
Pick a project
A project-scoped token carries its project in the credential, so there's nothing to choose — skip this section.
An account token reaches every project you own, so something has to say which one a tool call acts on. In order, highest priority first:
- A
projectargument on the tool call — a one-off override, available onget_integration_status,verify_integration,add_allowed_domain,get_project_theme,update_project_theme,create_tour,list_tours,list_tooltips,list_surveys, andlist_announcements. - The
select_projecttool — switches projects for the rest of the session. --project <slug>in the server'sargs.STEPSKIT_PROJECTin the server'senv.- Automatic, when the account has exactly one project.
The first two are your agent's to use: list_projects lists every project the
token can reach, marks the selected one, and says whether the token is pinned or
account-wide; select_project moves to another one (on a pinned token it
refuses, and tells you to mint an account token instead).
The next two are yours, and they set the default so nobody has to choose at all.
Prefer --project if you export environment variables globally — an exported
STEPSKIT_PROJECT follows you into every repo, which is the very footgun
account tokens remove, while an arg belongs to a single server entry:
{
"mcpServers": {
"stepskit": {
"command": "npx",
"args": ["-y", "@stepskit/mcp", "--project", "acme-web"],
"env": { "STEPSKIT_TOKEN": "${STEPSKIT_TOKEN}" }
}
}
}Both accept a project slug or id. The slug is readable but changes if the
project is renamed; the id is stable. list_projects prints both.
If nothing resolves and you own more than one project, tools don't guess — they return an error naming your projects and how to pick one. A project reference that matches nothing is an error too, never a quiet fallback to another project.
Optional: add StepsKit rules to your agent
Drop this into your project's CLAUDE.md, .cursorrules, or AGENTS.md so your
agent follows StepsKit conventions (stable selectors, unpublished-by-default,
the current capability boundary) even outside an MCP call:
# StepsKit (product onboarding tours)
When this project involves StepsKit:
- Author tours through the StepsKit MCP server (`@stepskit/mcp`) — use its
tools, don't hand-write API calls.
- Know which StepsKit project you're writing to. A token is either pinned to one
project or scoped to the whole account. If a tool says no project is selected,
call `list_projects` and then `select_project` — don't guess, and don't stop
to ask when the account has only one project or `STEPSKIT_PROJECT` is set.
- Call `get_integration_status` before creating a tour. If the embed isn't
installed, install it and run `verify_integration` (after the user loads a
page) before creating tours.
- Pick the install form from what this project is. If it has a `package.json`
and a bundler, install the package with whichever manager the repo uses —
check for `pnpm-lock.yaml`, `yarn.lock` or `bun.lock` before defaulting to
`npm install stepskit` (React/Next.js/Remix render
`<StepsKit apiKey="..." />` from `stepskit/react`; everything else calls
`stepskit.init()` once at the entrypoint). If it has no build step —
WordPress, a CMS theme, Google Tag Manager, plain HTML — use the CDN
`<script>` snippet instead, and don't add the dependency. Never leave both
in place: two loaders mean two embed instances.
- Installing the loader is only half the install. Wire visitor identity too:
find where this codebase resolves the authenticated user and call
`identify({ id, email, plan, ... })` ONCE, when auth state resolves (not per
route change) — off the `stepskit` import on the package, or
`window.stepskit` on the snippet. Without `id`, show-once frequency capping
falls back to a per-tab check that dies with the tab, and no targeting rule
that tests a value can match — while `verify_integration` still reports
green. Pass whatever attributes the codebase already has, under their real
field names.
- The npm package ships its own TypeScript types. Don't also hand-write a
`window.stepskit` global declaration — that's only for snippet installs.
- Never wire `track()`. It ships in the snippet's method list and on the typed
package but is a no-op today (it warns once and discards) — any
event-tracking calls you add would be dead code.
- For callout steps, prefer stable selectors: `data-testid`, `id`, or a unique
semantic class. Avoid brittle nth-child chains. Set
`selector_confidence: "low"` when you infer a selector from source and aren't
sure it matches the live DOM — low-confidence steps get flagged for review.
- Tours are created UNPUBLISHED. Never claim a tour is live; the user reviews and
publishes it from the StepsKit dashboard.
- Before promising a capability, call `get_capabilities`. StepsKit MCP can
CREATE and EDIT tours (callout/modal steps; name, behavior settings, visibility
targeting/frequency/trigger, and theme), tooltips, NPS surveys, and
announcements; set the FOUR project-wide default themes (one each for tours,
tooltips, announcements, and surveys — `update_project_theme` with
`surface`) plus per-item overrides; install/verify the embed; whitelist a
domain; and list or switch between the account's projects. It CANNOT yet do
per-step visual styling, add per-step or per-tooltip media/images, publish, or
read analytics — nor create a new project (that's a dashboard action). Say so
plainly instead of inventing a workaround.