Agent setup
Snapvisor in OpenCode
Let OpenCode review your UI: list builds, read screenshot diffs, approve or reject changes and comment, all over the Snapvisor MCP server.
Let the agent do it
Paste this sentence into OpenCode. It fetches the setup instructions and runs every step below itself.
Add to ClaudeMCP requires a paid plan
Fetch and execute the appropriate instructions to set me up for Snapvisor from https://snapvisor.io/agent-setup/prompt.md
Connect OpenCode by hand
- Add the server to
~/.config/opencode/opencode.json(every project) oropencode.jsonat the project root (this project only). If the file already exists, merge thesnapvisorentry into itsmcpobject instead of replacing the file.{ "mcp": { "snapvisor": { "type": "remote", "url": "https://mcp.snapvisor.io", "enabled": true } } } - Start the OAuth sign-in. It opens the Snapvisor consent screen in the browser, which the user approves.
opencode mcp auth snapvisor
With a personal access token instead
- Same file, with OAuth switched off and the token read from
SNAPVISOR_ACCESS_TOKENthrough OpenCode's{env:NAME}substitution.{ "mcp": { "snapvisor": { "type": "remote", "url": "https://mcp.snapvisor.io", "enabled": true, "oauth": false, "headers": { "Authorization": "Bearer {env:SNAPVISOR_ACCESS_TOKEN}" } } } }
Create the token under Settings, Tokens in the app, keep it in your shell profile, and never commit it.
Add the SDK
- Only do this step inside a project that has a UI test suite; otherwise skip it and say so in the completion message. Use the package manager the project already uses (the lockfile tells you): the commands below are written for npm.
- Playwright (
@playwright/testinpackage.json): install the SDK, register its reporter inplaywright.config.ts, and capture screenshots withargosScreenshotin the tests that render UI.npm install --save-dev @snapvisor/playwright - The reporter uploads from CI only, so local runs stay offline:
// playwright.config.ts import { defineConfig } from "@playwright/test"; import { createArgosReporterOptions } from "@snapvisor/playwright/reporter"; export default defineConfig({ reporter: [ process.env.CI ? ["dot"] : ["list"], [ "@snapvisor/playwright/reporter", createArgosReporterOptions({ uploadToArgos: !!process.env.CI }), ], ], }); - Storybook: install
@snapvisor/storybook. Vitest browser mode: install@snapvisor/vitest. Then wire them as the SDK page describes.npm install --save-dev @snapvisor/storybook - Any other runner that writes screenshots to a folder: install the CLI and upload that folder after the tests run.
npm install --save-dev @snapvisor/cli npx @snapvisor/cli upload ./screenshots - Python projects: follow the Python SDK section of https://snapvisor.io/docs/sdks.
- Uploads authenticate with the project's
ARGOS_TOKEN, found in the project's settings at https://app.snapvisor.io. It belongs in CI secrets, never in the repository. On GitHub Actions no token is needed: https://snapvisor.io/docs/learn/integrations/github-tokenless-authentication. - Optional: the CLI can also inspect builds, submit reviews and post comments from the terminal.
loginopens the browser for the user to approve;whoamiconfirms it.npx @snapvisor/cli login npx @snapvisor/cli whoami
Verify the connection
- The
snapvisorMCP server normally shows only two tools,search_toolsandexecute_typescript, and every operation is reached through them. Callsearch_toolswith the querygetMe; it answers with the declaration ofexternal_getMe. Then callexecute_typescriptwith this program:return await external_getMe({}); - If the server instead lists
getMeas a tool of its own, call that tool directly. Either way, success is a response naming the signed-in user and the accounts the connection can reach; each accountslugis theownerargument of every other operation. - Most agents load MCP servers when a session starts. If no
snapvisortool is available to you yet, do not report failure: the completion message tells the user to restart the session and ask you to verify the connection. - A
401means the browser sign-in has not been completed yet. Insideexecute_typescripta refused call throws an error carrying the same message; wrap the call intry/catchto read it. An answer that asks for an upgrade means the connection works and the account is on the Free plan.