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:

TokenMint it atReaches
AccountAccount settingsMCP Access TokensEvery project you own — one token per machine instead of one per repo. Your agent picks which project to write to; see Pick a project.
Projecta project's AI Agents page → Generate tokenThat 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

ClientAdd it viaFileFormat / key
Claude Codeclaude mcp add or edit file.mcp.json (project) / user scopeJSON · mcpServers
CursorSettings → Tools & MCP, or edit file.cursor/mcp.json / ~/.cursor/mcp.jsonJSON · mcpServers
Codex CLIcodex mcp add or edit file~/.codex/config.tomlTOML · [mcp_servers.stepskit]
Claude Desktopedit config fileclaude_desktop_config.jsonJSON · mcpServers
VS Code / Copilotedit file.vscode/mcp.jsonJSON · 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/mcp

The 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/mcp

That 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 liststepskit 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:

  1. A project argument on the tool call — a one-off override, available on get_integration_status, verify_integration, add_allowed_domain, get_project_theme, update_project_theme, create_tour, list_tours, list_tooltips, list_surveys, and list_announcements.
  2. The select_project tool — switches projects for the rest of the session.
  3. --project <slug> in the server's args.
  4. STEPSKIT_PROJECT in the server's env.
  5. 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.