
Swipium
io.github.GeroPalomboPublished by GitHub account GeroPalombov2.4.0Updated Nov 3, 2026
Mobile QA on local Android Emulators and iOS Simulators: autopilot tests, evidence, reports.
Overview
Local MCP server that lets a coding agent QA mobile apps on Android emulators and iOS simulators, with evidence-backed reports.
- What you can do
- Start, poll, cancel and explain QA runs, and read their artifacts
- Check the environment, start sessions, prepare Android and iOS targets, and set up WebDriverAgent
- Resolve, build and install app artifacts, including bundletool for .aab files
- Inspect and control devices: info, orientation, geolocation, network, Metro, app control, screen recording
- Drive the app: snapshots, element actions, screenshots, health checks, visual text search, waits
- Run smoke and exploratory checks, build an app map, test features, run and repair flows, generate suites and log issues
- When to use it
- Useful for mobile developers who want an agent to smoke test, reproduce bugs, or gate a release on a local emulator or simulator before shipping a build. It fits hands-on UI testing of React Native, Expo, Flutter or native apps from a coding agent.
- Requirements
- Runs locally over stdio via the npm package swipium; Node.js 22.12 or newer. Android needs platform-tools, the Emulator and an AVD; iOS needs macOS with Xcode and a simulator, plus WebDriverAgent 6.0+ for structured interaction. Optional env vars: SWIPIUM_PROJECT_ROOT, SWIPIUM_TEST_EMAIL, SWIPIUM_TEST_PASSWORD. Emulators and simulators only; physical devices are refused.
Installation
In SourceWeft
- Open Swipium in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
Swipium
An MCP server that lets coding agents QA mobile apps on Android Emulators and iOS Simulators.
[npm version] [License: MIT] [Node >= 22.12] [MCP] [Platform]
Swipium gives an AI coding agent (Claude Code, Codex, Gemini CLI, Cursor, VS Code, and other MCP clients) the tools a QA engineer uses: find or build the app, boot a simulator, install and launch it, read the screen, tap and type through real user flows, and write a report backed by screenshots, logs, and UI dumps. A run can be turned into a repeatable flow, a test suite, or Appium code.
It is for mobile developers who want their agent to catch the broken login screen before a TestFlight or Play Console build. It runs locally (stdio; the server opens no network port, and the WebDriverAgent it manages for iOS takes commands on 127.0.0.1 only, though its screen stream port is reachable from the network; see Security), drives devices through adb, simctl, and WebDriverAgent rather than Appium, and asks your consent before anything with side effects. swipium.com
A session, abbreviated
Three calls: start the run, wait for it, and (only when the inlined head isn't enough) read report.md. The report behind that summary, rendered with npx swipium report --latest --format markdown, includes:
Contents
Requirements · Quickstart · Starter prompts · How it works · Tools · Where results go · Configuration · CLI · CI · Upgrading · Troubleshooting · Security
Requirements
Node.js 22.12 or newer. On an older Node.js the server prints a warning on stderr and swipium verify fails. Swipium works with emulators and simulators only; physical devices are refused with PHYSICAL_DEVICE_UNSUPPORTED (why). Structured iOS automation needs WebDriverAgent 6.0 or newer (qa_wda {action:"setup"} builds and starts one); without it an iOS Simulator is visual-only.
MCP: a stdio server that speaks protocol revisions 2025-06-18, 2025-11-25 and 2026-07-28; the client's first message picks one. Claude Code 2.1.285 and later connect on 2026-07-28, Codex 0.146 on 2025-06-18. Any stdio MCP client should work (protocol versions).
- Android: platform-tools, the Emulator, and at least one AVD (usually via Android Studio).
adbon yourPATHis used if present, else the SDK copy from$ANDROID_HOME,$ANDROID_SDK_ROOT, or the default SDK location (~/Library/Android/sdk,~/Android/Sdk,%LOCALAPPDATA%\Android\Sdk). Theemulatorbinary that boots AVDs andaapt2come from the SDK first..aabfiles need bundletool. - iOS (macOS only): Xcode and a simulator. Taps, typing, and UI-tree snapshots need WebDriverAgent (WDA, the on-simulator automation server Appium uses); without it iOS is visual-only (iOS modes).
Quickstart
1. Register Swipium with your client. From your app repository, for Claude Code:
For Claude Code, init also sets SWIPIUM_MAX_WAIT_MS=110000 (one call can wait up to 110 s, so most runs finish in one call) and installs the swipium-qa agent skill under .claude/skills/ (~/.claude/skills/ for --scope user; --no-skill skips it). --trust-local (local or user scope only) also pre-approves the consent actions that run no project code, so boots and installs stop prompting while builds, Metro and WebDriverAgent still ask. A Claude Code plugin with the same server and skill is in plugin/. Swipium is also listed in the MCP Registry as io.github.GeroPalombo/swipium, so registry-aware clients can find and install it.
The same command handles codex, gemini, cursor, and vscode (swipium init <client> --apply). Claude Desktop, Windsurf, manual configs, and per-client details are in docs/mcp-server.md.
Codex: swipium init codex --apply appends a [mcp_servers.swipium] block to ~/.codex/config.toml (or $CODEX_HOME/config.toml) with longer timeouts and an env_vars line, and installs the skill under .agents/skills/. Codex doesn't pass your shell environment to MCP servers, so without that line SWIPIUM_TEST_*, ANDROID_HOME and JAVA_HOME never reach Swipium. If you already have a block, init prints the line to add. Keep tool_timeout_sec = 600 (Codex setup).
Headless runs (codex exec, claude -p, CI): these clients answer consent prompts automatically, so nothing gated (boot, install, build) runs unless you pre-approve exact actions with SWIPIUM_CONSENT_PREAPPROVE in the server env; approving in the chat doesn't help. Pre-approval isn't tied to a device, so on a machine with several emulators or simulators also pin one with SWIPIUM_DEVICE (Headless runs).
2. Restart the client and check that it lists qa_test_this, qa_doctor, and qa_report.
3. Ask the agent to test the app:
qa_test_this runs by default (mode:"execute", since 2.3.0); pass mode:"plan" for a side-effect-free preview. goal:"smoke" is the fastest path. With no goal, qa_test_this runs the smoke check and then tries to generate a test suite. With the skill installed, "test this app with Swipium" is enough.
If a tool returns PROJECT_ROOT_UNRESOLVED, name the absolute project path in your prompt or set SWIPIUM_PROJECT_ROOT in the server config (Project root).
What you'll see
- One approval prompt listing the exact build, boot, and install commands. Clients with MCP elicitation show a real prompt; others return
requiresConsent, which the agent must relay to you. - The first build can take minutes. The run is a background job.
waitForCompletionwaits up to about 45 s by default (about 105 s with theSWIPIUM_MAX_WAIT_MS=110000thatinit claudesets). Aqa_job_statuspoll returns at once unless the agent passeswaitMs; Swipium tells it to pass 45000, and a poll is capped at 50 s (110 s with that setting). - Two states. The job
statusisrunning,done,failed, orcancelled. The run'sresult.stateiscompletedorneeds_input(jobdone), orblockedorunsafe(jobfailed).needs_inputmeans one question for you, such as login credentials. - A report with separate verdicts for the app, coverage, and Swipium itself. A completed run inlines a short head (verdict, failures with their failing step and screenshot URI) and saves
report.mdfor the agent; a blocked run names the fix. For you there isreport.html: one self-contained page with the verdict, each failure with its screenshot and log, and the step timeline, which opens offline in any browser (the agent gives you its path,reportHtmlPath; what's in it).
Starter prompts
Clients that support MCP prompts can use the built-in ones instead: swipium_setup_check, swipium_guardrail_validation, swipium_full_smoke, swipium_bug_repro, swipium_test_feature, swipium_generate_suite, and swipium_convert_run_to_flow.
How it works
qa_test_this finds or builds the app, boots a simulator, installs and launches the app, runs a smoke check (plus exploration or suite generation, per goal), and always writes a report. Failures carry a failureCode that qa_explain_blocker explains. For hands-on work the agent opens a session (qa_start_session), reads the screen with qa_snapshot, acts on element refs such as @e3 (stable while the element stays on screen), and batches 3 or more known steps in one qa_flow_run {flowYaml}.
Concepts, explained in docs/concepts.md:
- Project root: the repository under test, from the
projectRootargument, MCP roots,SWIPIUM_PROJECT_ROOT,CLAUDE_PROJECT_DIR, or the server's working directory. - Consent: builds, boots, installs, data wipes, network changes, and repo-supplied commands need your single-use approval.
- Sessions and jobs: a session holds one run's device, app, and evidence; long work is a job you poll.
- Secrets and redaction: credentials are redacted from text output; screenshots are not.
- iOS modes: visual-only through
simctl, or full interaction with WDA. - The app map is Swipium's durable memory of your app's screens; a flow is a replayable YAML script (docs/flows.md); a POM suite is a generated page-object test suite. See the glossary.
Tools
Grouped by capability (qa_status without arguments returns the same groups). Every tool's parameters and behavior are in docs/tools.md; swipium verify lists what your installed version exposes.
Every tool carries MCP annotations: read-only tools declare readOnlyHint:true and openWorldHint:false (so clients can auto-approve them); the rest also declare destructiveHint and idempotentHint.
Where results go
<your repo>/.swipium/: app map, flows, test suite, issue ledger, visual baselines, generated files, the WebDriverAgent build cache (cache/wda-derived-data, about 200 MB per project;ios.wda.derivedDataPathmoves it), and your configuration (config.json,fixtures.json,policy.json).swipium scanmerges its results intoconfig.jsonand keeps every key you set (WDA team, OCR and mask commands,appId); it never regenerates the file. AnappIdcounts as yours when it has noappIdSource, orappIdSource:"config.json", or when it differs fromscanAppId(the id the last scan detected, which scan stores next to it); then it is kept even with a scanappIdSourceleft in place, andappIdSourcebecomesconfig.json. One an earlier scan wrote and you didn't change is refreshed. A config from a scan older than 2.3.0 has noscanAppId: there a hand-editedappIdwith a scanappIdSourceis still replaced, and scan printsreplaced appId <old> in config.json (written by an earlier scan from <source>; ...), so removeappIdSourceto keep yours. The first time Swipium writes the app map, issue ledger, or WDA build cache in a Git repository, it adds.swipium/to.gitignore. Never pruned automatically.~/.swipium/runs/: per-session state and evidence (screenshots, logs, UI dumps, reports), returned asswipium://URIs. When a server process first loads its session registry, it prunes in the background (for at most 2 s per start) session directories older thanSWIPIUM_RETENTION_DAYS, keeping registered sessions and the newestSWIPIUM_RETENTION_KEEPper project whose root still exists.swipium gccleans up on demand. Session files are 0600 in 0700 directories, and so are~/.swipium'sregistry.json,projects.jsonandprocesses.json.
Configuration & environment variables
Set these in the MCP server's env block (or your shell, for CLI commands). This is the complete list of variables Swipium reads.
Codex forwards only the names listed in env_vars (plus a fixed whitelist such as HOME and PATH); swipium init codex writes that line for you. It deliberately leaves out CLAUDE_PROJECT_DIR, SWIPIUM_DISABLE_DEVICE_DISCOVERY and the approval grants (SWIPIUM_CONSENT_PREAPPROVE, SWIPIUM_CONSENT_PREAPPROVE_RUN_CODE, SWIPIUM_ALLOW_REMOTE_WDA): set those literally in env = { ... } so an inherited shell export or a direnv file in a cloned repo can't grant approvals. Add your own custom SWIPIUM_* flow variables (and SWIPIUM_DEVICE, if you pin a device) to the list. Details: docs/mcp-server.md.
An invalid SWIPIUM_MAX_WAIT_MS, SWIPIUM_TOOLS, or SWIPIUM_LOG_LEVEL falls back to its default with a warn line on stderr at startup.
Generated flows, suites, and code never contain credential values; they reference SWIPIUM_TEST_*, SWIPIUM_SECRET_N, or SWIPIUM_GEN_<FIELD>, which you set when replaying. Generated Appium projects read their own variables (SWIPIUM_PLATFORM, APPIUM_HOST, ANDROID_*, IOS_*, …), documented in their README.
CLI reference
With no subcommand, swipium runs the stdio MCP server (what clients launch). swipium --help prints this list.
CI
swipium report renders a finished run as a self-contained HTML report, JUnit, a GitHub job summary, Markdown, JSON, or (experimental) SARIF; --fail-on-gate fails the job when the .swipium/policy.json release gate blocks. The CLI does not drive devices: CI still needs an agent (such as claude -p) calling the MCP tools, including qa_flow_run to replay saved flows. Nobody answers consent prompts in CI, so either install the app in the workflow before the agent step (safest) or pre-approve the exact actions the agent needs. Recipe: docs/ci-reports.md.
Upgrading
Restart your MCP client after every upgrade; a client still running the old server gets STALE_CLIENT errors.
- From 2.3.x to 2.4.0: JUnit marks tool and environment failures and the not-tested case as
<error>and lists only high findings; the latest attempt per workflow wins in the release gate (two separateqa_flow_runcalls that fail, then pass, now pass as flaky, and scripts countingtestOutcomesinreport.jsonmust skipsupersededentries);report.mdis at most 2 KB, so parsereport.json; SARIF is experimental and only holds high app findings; the Playwright export is deprecated; the CI recipe uploadsswipium-report.htmlinstead of~/.swipium/runs. See the 2.4.0 upgrade checklist. - From 2.2.x to 2.3.0: Node.js 22.12 or newer;
qa_test_thisandqa_test_featurerun by default (mode:"plan"previews); element lines drop empty names and mark non-clickable elements with a trailing-;qa_reportreturns a lean view (format:"json"for the full report); a run that tested nothing (including one that launched the app but exercised no workflow, or only has aqa_notepass with no device evidence) is never SHIP and fails--fail-on-gate; budget stops areok:false(BUDGET_EXHAUSTED) and the default budget is 30 min / 60 actions / 40 screenshots;qa_act type(and flowinputTextwithinto) fails withTEXT_INPUT_MISMATCHwhen the field doesn't read back what was typed, coordinate targets included; an app that renders nothing, or stays on its loading screen, at launch isblockedwithBLANK_SCREEN; shared folders such as~/Library,~/Downloads,/tmpor/Applicationsare refused asprojectRoot; managed WebDriverAgents run on a per-simulator port (8101 to 8900) instead of 8100; an invalid.swipium/policy.jsonmakesswipium reportexit 2; Swipium-booted emulators quick-boot from their snapshot with-gpu auto. See the 2.3.0 upgrade checklist. - From 2.0.x to 2.2.0: element lists in
structuredContentare now@eNstrings (passresponseMode:"verbose"for objects), Codex needs theenv_varsline,qa_wda buildreturns a job, and waits end within about 50 s. See the 2.2.0 upgrade checklist. - From 1.5.x: 2.0 removed and renamed tools, reads only
SWIPIUM_*variables in flows and fixtures, and asks consent for every install. Work through the 2.0.0 upgrade checklist and the migration table first, then the 2.2.0 one.
Troubleshooting
Every error has a failureCode, nextSteps, and retrySafe. qa_explain_blocker explains any code, qa_doctor checks the toolchain, and the full catalog is in docs/tools.md.
If tool calls time out in the client, raise its tool timeout (Codex tool_timeout_sec = 600): waits and job polls end within about 50 s, but a few synchronous steps, such as a large qa_ios install, long saved flows in qa_smoke, or qa_mobile_audit, can take longer.
Security
Swipium is a local stdio process and the server opens no network port. A WebDriverAgent it manages for iOS takes commands on 127.0.0.1 only, but its MJPEG screen stream (port = WDA port + 1000, for example 9101) listens on every network interface, because WebDriverAgent can't restrict it; use a firewall on untrusted networks. Actions with side effects need your consent; each approval is single-use and bound to its session, and only the server's own environment can pre-approve actions (SWIPIUM_CONSENT_PREAPPROVE), never a repository file or the model. Known secret values are redacted from snapshots, artifacts, and reports, and generated output is checked for leaked secrets. A cloned repository's .swipium/ is treated as untrusted: repo-supplied commands are shown verbatim in the consent prompt, flows read only SWIPIUM_* variables, and Swipium never runs git. Screenshots are never redacted, so use qa_start_session { sensitive: true } to refuse all screen captures when that matters. Details: Threat Model. Report vulnerabilities privately per the Security Policy.
Contributing and license
See CONTRIBUTING.md, SUPPORT.md, the docs index, and the CHANGELOG. MIT licensed; see LICENSE.
Source: README.md at commit a6a544e
Tools
0Version history
3- v2.4.0LatestNov 3, 2026
- v2.3.5Oct 19, 2026
- v2.3.0Oct 12, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts