Start

Your computer · Local MCP

Run ShotOps on your own machine with npx shotops-mcp: local screenshot paths, local rendering, and nothing but what you choose leaving the computer.

View as Markdown

The same server, the same tool contract and the same render engine as ShotOps Cloud — running as a process on your machine, over stdio. Your screenshots are read off your disk, the renders happen on your CPU, and an ordinary render or export uploads nothing.

#Connect Claude Code

The preferred path is one command. Claude Code saves the Local MCP entry, starts the server when it is needed, and lets npx fetch the package the first time:

claude mcp add shotops -- npx -y shotops-mcp

Then ask the agent for something and it connects on demand. To check the package is reachable before you wire a client to it:

npx -y shotops-mcp help

That prints the subcommands and exits. A bare npx shotops-mcp with no subcommand starts the MCP server and speaks JSON-RPC on stdout — useful to a client, unreadable to you.

Node 20.12 or newer is required.

#Connect Cursor or another client

Any client that can start a subprocess can run this server. The three things a client needs are the command, the arguments, and nothing else — no URL, no header, no token.

For Cursor or any client with a JSON config, use the standard stdio entry:

{
  "mcpServers": {
    "shotops": {
      "command": "npx",
      "args": ["-y", "shotops-mcp"]
    }
  }
}

ChatGPT cannot use this door. Its connectors speak HTTP to a URL and have no way to start a local process. Use ShotOps Cloud instead.

#Chromium

The renderer draws the device mockups in a real browser, so it needs Playwright's Chromium — about 150 MB, which is why it is not inside the npm package.

Whether it arrives on its own depends on your package manager: Playwright's install script fetches it, and some setups block install scripts by default. Install it explicitly and the question goes away:

npx playwright install chromium

Chromium boots lazily, on the first render_strip or emit_bundle call rather than at startup, so the server connects instantly and the first render is the slow one.

#Point at screenshots on disk

This is the reason to run locally. A screenshot entry can be a path, and the server reads the file directly:

{
  "screenshots": [
    { "path": "/Users/you/screens/01_today.png" },
    { "path": "/Users/you/screens/02_forecast.png" }
  ]
}

No upload, no ref, no round trip. { "path": … } works on render_strip, emit_bundle and import_screenshot, and emit_bundle takes already-rendered panels the same way, so you can render in one call and package in another with nothing leaving the machine.

The path form is local only. ShotOps Cloud refuses it outright and says so: reading a caller-supplied filesystem path on a shared host would be a local-file-inclusion hole. The mirror is also true — { "url": … } and ChatGPT attachments are refused here, because there is no account storage to import them into. Pass a URL straight to render_strip instead and it fetches at render time. Screenshots and assets covers each input form.

#Sign in (optional)

Previewing needs no account at all. Signing in connects this machine to a ShotOps account so the account-shaped tools work — saved looks, existing projects, project reads and re-renders — and so store-ready output has an entitlement to check. Rendering still runs here and still spends no cloud credits.

npx shotops-mcp login      # opens ShotOps in your browser, saves the token it gets back
npx shotops-mcp whoami     # which account is connected, and its plan
npx shotops-mcp logout     # revokes that token and removes it from this machine

The token lands in ~/.shotops/credentials.json, readable only by you, and every later npx shotops-mcp picks it up — there is nothing to paste into a client config. It is an ordinary ShotOps API token; revoke it any time from the account menu in Studio.

For CI, or to point one client at a different account, pass the token explicitly:

SHOTOPS_TOKEN=shotops_… claude mcp add shotops -- npx -y shotops-mcp

--token wins over SHOTOPS_TOKEN, which wins over a saved browser login — so a token in the environment is never quietly shadowed by whoever last signed in on this machine.

Without any token, save_project still has a route: a new project made from local paths uploads that project's record and its source PNGs as a private pending claim and returns an openUrl instead of a project id. One browser sign-in through that link and the project is yours, screenshots included. An unclaimed link expires after seven days. Updating an existing project needs the token that owns it.

#What leaves your machine

Ordinary renders and exports upload nothing. render_strip and emit_bundle read your PNGs, run Chromium here, and write the panels and the zip back — no screenshot bytes go anywhere.

Four things do reach the network, and each is something you asked for:

WhatWhen
The npm package and ChromiumInstall time, from the registry and from Playwright's CDN
Your account tokennpx shotops-mcp login, once, in your browser
A project record and its source PNGsOnly on save_project — a deliberate save, so the project can reopen in a browser on another device
The image at a URL you passedOnly when you hand a render an https:// screenshot instead of a path

refine_project is the one further exception: it runs the agent turn here and renders here, but asks ShotOps' servers to run each AI pass, so it spends AI cloud credits on your account.

Share links need the hosted connection. What ShotOps stores when it does store something, and for how long, is in Privacy and Terms.

Next: Your first strip runs the whole path end to end, or Plans and output explains what separates a preview from something you can ship.