
Security News
npm Tooling Bug Incorrectly Marks One-Character Packages as Security Holders
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.
@useswarm/mcp
Advanced tools
Automated UX testing loop for local dev. Tunnel via cloudflared, run AI agent swarms, get structured issues, fix and repeat.
Automated UX testing loop for local development. Connects your AI coding editor (Claude Code, Cursor, VS Code, etc.) to the Useswarm UX testing platform via the Model Context Protocol.
You (in Claude Code) → "test my signup flow"
↓
Claude calls dev_test → tunnels localhost → runs AI agent swarm
↓
Claude calls dev_watch → gets structured UX issues
↓
Claude fixes the code → calls dev_test again
The MCP server runs locally via stdio. No remote server needed. It tunnels your localhost via Cloudflare so Useswarm's cloud agents can reach your dev server.
One command registers the MCP with Claude Code + Codex CLI and signs you in:
npx @useswarm/mcp@latest setup
After it finishes, open your editor and ask it to test your app:
Test localhost:3000 with goal "complete the signup flow". The audience is first-time SaaS users.
[!NOTE] Login happens in your terminal as part of
setup— not on first use inside the editor. If the MCP starts without a key, it exits with a clear message telling you to runsetuporloginagain.
npx @useswarm/mcp@latest setup
Same command — @latest pulls the newest npm release and rewrites the path in your editor's config so the next launch picks it up. Restart the editor afterwards.
npx @useswarm/mcp@latest setup # registers all hosts + signs in
npx @useswarm/mcp@latest setup --client claude # Claude Code only
npx @useswarm/mcp@latest setup --client codex # Codex CLI only
npx @useswarm/mcp@latest setup --skip-login # register only (use env-based keys)
npm install -g @useswarm/mcp
useswarm-mcp setup
# upgrade later:
npm update -g @useswarm/mcp
# no re-setup needed — the global path is stable
# Claude Code
claude mcp add useswarm -- npx @useswarm/mcp
npx @useswarm/mcp login # one-time, in a terminal
# Codex CLI — add to ~/.codex/config.toml
# [mcp_servers.useswarm]
# command = "npx"
# args = ["@useswarm/mcp"]
npx @useswarm/mcp login
cd apps/mcp-server
pnpm install
pnpm build
node dist/cli.js setup --client codex # or --client claude
See CODEX_TESTING.md for the local-build iteration loop.
| Command | Description |
|---|---|
useswarm-mcp setup | Register MCP with Claude Code + Codex CLI, then sign in (one-shot setup) |
useswarm-mcp setup --skip-login | Register only — for CI / env-key workflows |
useswarm-mcp login | Open browser to sign in; stores API key at ~/.useswarm/config.json |
useswarm-mcp logout | Clear stored credentials |
useswarm-mcp whoami | Show auth status and verify the stored key still works |
useswarm-mcp serve | Start MCP server (stdio, default). Refuses to start if no key — won't auto-login. |
useswarm-mcp serve --http | Start with streamable HTTP transport on port 3100 |
useswarm-mcp serve --tunnel | Start with WebSocket tunnel to mcp.useswarm.co |
useswarm-mcp serve --api-key KEY | Override stored API key for this process |
useswarm-mcp serve --api-url URL | Override API base URL |
The server exposes five tools that form a test-fix-retest loop:
dev_list_swarmsList the saved persona swarms tied to the user's account (personal + active org). Use this to discover swarm IDs before passing one to dev_test.
Returns { swarms: Array<{ id, name, description, agentCount, personaCount, createdAt }>, count }.
Use dev_list_swarms to show me which Useswarm persona sets are saved on my account.
dev_testTunnel your localhost (or hit a public URL directly) and start an AI agent swarm test.
| Parameter | Required | Description |
|---|---|---|
targetUrl | Yes | Frontend URL (e.g. http://localhost:3000) |
goal | Yes | What agents should accomplish (e.g. "complete the signup flow") |
swarmId | Conditional | UUID of a saved swarm (from dev_list_swarms). When set, runs that swarm's stored personas instead of generating new ones. Mutually exclusive with userDescription/agentCount. |
userDescription | Conditional | Target audience (e.g. "first-time SaaS users"). Required when swarmId is not set. |
agentCount | No | Number of AI personas to generate (1–20, default 3). Ignored when swarmId is set. |
backendUrl | No | Separate backend URL — when set, a reverse proxy routes /api/*, /auth/*, /graphql, /trpc/* to the backend through one tunnel |
backendPaths | No | Extra path prefixes for backend routing (e.g. ["/ws", "/v1"]) |
maxSteps | No | Max steps per agent |
provider | No | openai or anthropic |
model | No | Model override |
auth | No | Login credentials, sub-aliased sign-up, or session cookies — see Authenticated testing |
Use dev_test to test http://localhost:3000 with goal "sign up and reach the dashboard". The audience is first-time users.
Use dev_list_swarms, then dev_test on http://localhost:3000 with goal "complete checkout" using my "B2B Buyers" swarm.
dev_watchPoll a running test until it completes, then return structured results.
| Parameter | Required | Description |
|---|---|---|
batchId | Yes | Batch ID returned by dev_test |
wait | No | Poll up to 3 minutes for completion (default true) |
Returns issues sorted by severity with persona attribution, plus a synthesis report. Automatically tears down the tunnel when done.
dev_statusCheck the current state of the active tunnel and any running test.
dev_closeManually tear down the active tunnel and clean up.
If your app runs the frontend and backend on separate ports, pass backendUrl and the MCP server starts a reverse proxy automatically:
Use dev_test on http://localhost:3000 with backend at http://localhost:8080. Goal: "create a new project".
The proxy routes by path prefix:
| Path | Destination |
|---|---|
/api/* | Backend |
/auth/* | Backend |
/graphql | Backend |
/trpc/* | Backend |
| Everything else | Frontend |
For non-standard backend paths, pass backendPaths:
Test http://localhost:3000 with backend http://localhost:8080 and extra backend paths /ws and /socket.io. Goal: "send a message in the chat".
The auth parameter on dev_test supports three modes. All accept an optional startUrl to land the agent on a specific page after authentication.
agent_login (existing account)Agent navigates to loginUrl (or the target URL if omitted), fills credentials, submits.
{
"auth": {
"mode": "agent_login",
"loginUrl": "http://localhost:3000/login",
"username": "test@example.com",
"password": "testpass123",
"startUrl": "http://localhost:3000/dashboard"
}
}
signup (sub-aliased emails per persona)For testing sign-up flows where no account exists yet. You supply one base email; each persona registers with a unique local+<hash>@domain sub-alias derived from it. All confirmation emails route to your single inbox, but each persona has its own isolated address.
{
"auth": {
"mode": "signup",
"signupEmail": "you@yourdomain.com",
"signupPassword": "optional-shared-password",
"startUrl": "http://localhost:3000/signup"
}
}
| Field | Required | Description |
|---|---|---|
signupEmail | Yes | Base email. Each persona-run gets a unique local+<base36(timestamp)+random>@domain alias derived from this. |
signupPassword | No | Shared password used on every persona's sign-up form. If omitted, the runtime mints a strong random password per persona-run (not persisted). |
startUrl | No | URL where the sign-up form lives. |
The base email you@yourdomain.com becomes you+lwk3a8x7@yourdomain.com, you+lwk3a902@yourdomain.com, etc. — one per persona. The timestamp half guarantees the alias can never repeat in the future; the random half disambiguates personas spawned in the same millisecond. Generated aliases are persisted to the run record (cua_runs.generated_email) so confirmation emails can be correlated back to a persona later.
Use any provider that supports plus-addressing — Gmail, Fastmail, custom domains all work.
cookie_injection (skip login)Inject session cookies and have the agent start already authenticated.
{
"auth": {
"mode": "cookie_injection",
"cookies": [
{
"name": "session_token",
"value": "abc123...",
"domain": ".example.com",
"path": "/",
"secure": true,
"httpOnly": true
}
],
"startUrl": "http://localhost:3000/dashboard"
}
}
Each cookie needs name, value, domain at minimum; everything else is optional and accepts null. The easiest way to capture cookies is the Cookie-Editor browser extension — Export → JSON.
If mode is omitted, the MCP server infers it:
cookies array → cookie_injectionsignupEmail → signupagent_loginWhen testing localhost, cookie domains captured from a different host are auto-rewritten to match the tunnel; loginUrl and startUrl are also tunneled if they point at localhost.
Use test-only accounts. Credentials and cookies are sent to the Useswarm API over HTTPS but should not be production credentials.
claude mcp add useswarm -- npx @useswarm/mcp serve
npx @useswarm/mcp setup --client codex
This writes a [mcp_servers.useswarm] block to ~/.codex/config.toml. Restart Codex and the four tools (dev_test, dev_watch, dev_status, dev_close) will appear. The first dev_test triggers a device-code login if you haven't authenticated yet — the URL + code prints to Codex's stderr.
For testing the local build, iterating on tool definitions, or running Codex cloud, see CODEX_TESTING.md.
Add to .cursor/mcp.json:
{
"mcpServers": {
"useswarm": {
"command": "npx",
"args": ["@useswarm/mcp", "serve"],
"env": {
"USESWARM_API_KEY": "ux_..."
}
}
}
}
Add to .vscode/settings.json:
{
"mcp": {
"servers": {
"useswarm": {
"command": "npx",
"args": ["@useswarm/mcp", "serve"],
"env": {
"USESWARM_API_KEY": "ux_..."
}
}
}
}
}
If you're running with --tunnel, configure the editor with the streamable HTTP transport:
{
"mcpServers": {
"useswarm": {
"transport": "streamable-http",
"url": "https://mcp.useswarm.co/s/YOUR_SLUG/message"
}
}
}
The MCP server uses X-API-Key header authentication. Keys are SHA-256 hashed before storage server-side.
useswarm-mcp login
Opens your browser to useswarm.co/mcp/auth. After logging in, an MCP-scoped API key is created and stored in ~/.useswarm/config.json (file permissions: 0600).
Create a key in the Useswarm dashboard or pass one directly:
useswarm-mcp serve --api-key ux_your_key_here
Or via env:
export USESWARM_API_KEY=ux_your_key_here
useswarm-mcp serve
| Variable | Default | Description |
|---|---|---|
USESWARM_API_URL | https://api.useswarm.co | API base URL |
USESWARM_API_KEY | — | API key for authentication |
USESWARM_SESSION_TOKEN | — | Session token (alternative to API key) |
USESWARM_APP_URL | https://www.useswarm.co | Web app URL (login flow + dashboard links) |
MCP_PORT | 3100 | HTTP transport port |
MCP_TUNNEL | false | Enable tunnel to relay |
MCP_TUNNEL_TOKEN | — | Tunnel authentication token |
MCP_RELAY_URL | wss://mcp.useswarm.co | Tunnel relay WebSocket URL |
The server is designed for an iterative test-fix-retest workflow:
dev_testdev_watch for resultsA typical prompt:
Test my app at localhost:3000. The goal is "complete the checkout flow". If there are issues, fix them and re-test until it passes.
--http) — streamable HTTP on port 3100. For clients that prefer HTTP transport.--tunnel) — connects via WebSocket to the relay at mcp.useswarm.co. The relay assigns a public slug and proxies JSON-RPC through the tunnel.The relay at mcp.useswarm.co handles:
/tunnel)/s/:slug/message)The relay is deployed on AWS ECS Fargate. See infra/ for the Terraform configuration:
cd apps/mcp-server/infra
cp terraform.tfvars.example terraform.tfvars
terraform init
terraform plan
terraform apply
The MCP server uses Cloudflare Quick Tunnels by default (free, no account needed) and falls back to ngrok if Cloudflare is unavailable.
Install Cloudflare for the best experience:
# macOS
brew install cloudflared
# Linux
curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
-o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared
| Framework | Notes |
|---|---|
| Next.js / Nuxt / Remix | Single port — no backendUrl needed |
| React + Express | Use backendUrl for the Express server |
| Django / Rails | Add the tunnel URL to ALLOWED_HOSTS / config.hosts |
| Vite with proxy | If Vite proxies API calls, no backendUrl needed |
pnpm dev # MCP server in dev mode (auto-reload)
pnpm start:relay # Relay server locally
npx tsc --noEmit # Type-check
pnpm build # Build
| Service | URL |
|---|---|
| Web app | https://www.useswarm.co |
| API | https://api.useswarm.co |
| MCP relay | https://mcp.useswarm.co |
| Docs | https://docs.useswarm.co |
FAQs
Automated UX testing loop for local dev. Tunnel via cloudflared, run AI agent swarms, get structured issues, fix and repeat.
We found that @useswarm/mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.