Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@useswarm/mcp

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@useswarm/mcp - npm Package Compare versions

Comparing version
2.1.2
to
2.3.0
+33
dist/auth/codex-setup.d.ts
/**
* Write a `[mcp_servers.useswarm]` block to the user's `~/.codex/config.toml`,
* which is how OpenAI's Codex CLI registers MCP servers (mirrors what
* `claude mcp add useswarm -- ...` does for Claude Code).
*
* We deliberately avoid pulling a TOML dependency — we only need to read the
* file, find any pre-existing `[mcp_servers.useswarm]` (and its sub-tables
* like `[mcp_servers.useswarm.env]`), strip them, and append our own block.
* Everything else in the file (other MCP servers, top-level keys, comments
* outside our blocks) is preserved.
*/
export interface CodexMcpSpec {
/** Executable to run, e.g. "node" or "npx". */
command: string;
/** Arguments passed to the command. */
args: string[];
/** Optional environment variables to inject when Codex spawns the MCP. */
env?: Record<string, string>;
}
export interface CodexWriteResult {
path: string;
/** True if config.toml didn't exist before this call. */
created: boolean;
/** True if a previous useswarm block was overwritten. */
replaced: boolean;
}
/** Path to the Codex CLI's MCP config file. */
export declare function codexConfigPath(): string;
/**
* Write `~/.codex/config.toml` with a fresh `[mcp_servers.useswarm]` block,
* preserving everything else. Creates the file (and `~/.codex/`) if needed.
*/
export declare function writeCodexMcpConfig(spec: CodexMcpSpec): CodexWriteResult;
/**
* Write a `[mcp_servers.useswarm]` block to the user's `~/.codex/config.toml`,
* which is how OpenAI's Codex CLI registers MCP servers (mirrors what
* `claude mcp add useswarm -- ...` does for Claude Code).
*
* We deliberately avoid pulling a TOML dependency — we only need to read the
* file, find any pre-existing `[mcp_servers.useswarm]` (and its sub-tables
* like `[mcp_servers.useswarm.env]`), strip them, and append our own block.
* Everything else in the file (other MCP servers, top-level keys, comments
* outside our blocks) is preserved.
*/
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
import { resolve } from "path";
import { homedir } from "os";
const SECTION = "useswarm";
/** Path to the Codex CLI's MCP config file. */
export function codexConfigPath() {
return resolve(homedir(), ".codex", "config.toml");
}
function renderSection(spec) {
const lines = [`[mcp_servers.${SECTION}]`];
lines.push(`command = ${JSON.stringify(spec.command)}`);
lines.push(`args = [${spec.args.map((a) => JSON.stringify(a)).join(", ")}]`);
if (spec.env && Object.keys(spec.env).length > 0) {
const inline = Object.entries(spec.env)
.map(([k, v]) => `${k} = ${JSON.stringify(v)}`)
.join(", ");
lines.push(`env = { ${inline} }`);
}
return lines.join("\n");
}
/**
* Strip any existing `[mcp_servers.useswarm]` block (and its sub-tables) from
* a TOML string. We treat a "block" as everything from the matching header
* line up to (but not including) the next single-bracket section header,
* double-bracket array-of-tables header, or end of file.
*/
function stripUseswarmBlocks(content) {
// not used; replaced by stripBlocks below
return false;
}
function stripBlocks(content) {
const lines = content.split("\n");
const out = [];
let inUseswarm = false;
let hadMatch = false;
for (const line of lines) {
const trimmed = line.trim();
const isArrayHeader = /^\[\[[^\]]+\]\]$/.test(trimmed);
const isSectionHeader = !isArrayHeader && /^\[(?!\[)[^\]]+\]$/.test(trimmed);
if (isSectionHeader) {
const name = trimmed.slice(1, -1).trim();
if (name === `mcp_servers.${SECTION}` || name.startsWith(`mcp_servers.${SECTION}.`)) {
inUseswarm = true;
hadMatch = true;
continue; // drop the header line itself
}
inUseswarm = false;
}
else if (isArrayHeader) {
// [[...]] always exits whatever section we were in.
inUseswarm = false;
}
if (!inUseswarm) {
out.push(line);
}
}
return { stripped: out.join("\n"), hadMatch };
}
/**
* Write `~/.codex/config.toml` with a fresh `[mcp_servers.useswarm]` block,
* preserving everything else. Creates the file (and `~/.codex/`) if needed.
*/
export function writeCodexMcpConfig(spec) {
const path = codexConfigPath();
const dir = resolve(homedir(), ".codex");
mkdirSync(dir, { recursive: true });
let existing = "";
let created = true;
if (existsSync(path)) {
existing = readFileSync(path, "utf-8");
created = false;
}
const { stripped, hadMatch } = stripBlocks(existing);
const newSection = renderSection(spec);
const trimmed = stripped.replace(/\s+$/, "");
const out = trimmed.length > 0 ? `${trimmed}\n\n${newSection}\n` : `${newSection}\n`;
writeFileSync(path, out, { mode: 0o600 });
return { path, created, replaced: hadMatch };
}
//# sourceMappingURL=codex-setup.js.map
{"version":3,"file":"codex-setup.js","sourceRoot":"","sources":["../../src/auth/codex-setup.ts"],"names":[],"mappings":"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"}
+31
-15
/**
* Browser-based login flow for the MCP CLI.
* Device-code login for the MCP CLI.
*
* Flow:
* 1. CLI starts a temporary local HTTP server on a random port
* 2. Opens browser to the Useswarm web app's MCP auth page
* with a callback URL pointing to the local server
* 3. User logs in on the web app (or is already logged in)
* 4. Web app creates an API key and POSTs it to the callback URL
* as a JSON body — the key never appears in a URL
* 5. CLI captures the API key, stores it, and shuts down the local server
*
* Similar to: `gh auth login`, `stripe login`, `vercel login`
* Reuses the same `/api/cli/auth/initiate` + `/api/cli/auth/poll` endpoints
* the Swarm CLI uses, so the MCP and CLI share one auth surface. Device-code
* works in any host that can spawn the MCP and surface its stderr — Claude
* Desktop, Cursor, Codex CLI, future ones — without needing a browser-callback
* server reachable from inside the spawned process. We print a short URL +
* code; the user opens the URL on any device, enters the code, authorizes;
* we poll until the API hands back an API key.
*/

@@ -18,2 +15,10 @@ export interface LoginResult {

apiUrl: string;
user?: {
name: string;
email: string;
};
organization?: {
name: string;
planType: string;
};
}

@@ -28,8 +33,19 @@ export interface StoredConfig {

/**
* Opens the browser to the Useswarm login page and waits for the callback
* with an API key.
* Run the device-code login flow against the given API URL. Prints the
* verification URL + user code to stderr (the universal MCP-host channel)
* and polls until the API key is issued.
*
* `appUrl` is accepted for backward compatibility with the previous
* browser-callback signature; it's no longer used because the API now
* embeds the frontend URL into `verificationUrl`.
*/
export declare function loginViaBrowser(opts: {
appUrl: string;
export declare function loginViaDeviceCode(opts: {
apiUrl: string;
appUrl?: string;
}): Promise<LoginResult>;
/**
* Backward-compat alias. The old browser-callback flow has been replaced by
* the device-code flow above; both names point at the same implementation
* so external imports keep working.
*/
export declare const loginViaBrowser: typeof loginViaDeviceCode;
/**
* Browser-based login flow for the MCP CLI.
* Device-code login for the MCP CLI.
*
* Flow:
* 1. CLI starts a temporary local HTTP server on a random port
* 2. Opens browser to the Useswarm web app's MCP auth page
* with a callback URL pointing to the local server
* 3. User logs in on the web app (or is already logged in)
* 4. Web app creates an API key and POSTs it to the callback URL
* as a JSON body — the key never appears in a URL
* 5. CLI captures the API key, stores it, and shuts down the local server
*
* Similar to: `gh auth login`, `stripe login`, `vercel login`
* Reuses the same `/api/cli/auth/initiate` + `/api/cli/auth/poll` endpoints
* the Swarm CLI uses, so the MCP and CLI share one auth surface. Device-code
* works in any host that can spawn the MCP and surface its stderr — Claude
* Desktop, Cursor, Codex CLI, future ones — without needing a browser-callback
* server reachable from inside the spawned process. We print a short URL +
* code; the user opens the URL on any device, enters the code, authorizes;
* we poll until the API hands back an API key.
*/
import { createServer } from "http";
import { randomBytes } from "crypto";
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";

@@ -39,157 +34,93 @@ import { resolve } from "path";

/**
* Opens the browser to the Useswarm login page and waits for the callback
* with an API key.
* Run the device-code login flow against the given API URL. Prints the
* verification URL + user code to stderr (the universal MCP-host channel)
* and polls until the API key is issued.
*
* `appUrl` is accepted for backward compatibility with the previous
* browser-callback signature; it's no longer used because the API now
* embeds the frontend URL into `verificationUrl`.
*/
export async function loginViaBrowser(opts) {
const state = randomBytes(16).toString("hex");
return new Promise((resolveLogin, rejectLogin) => {
let resolved = false;
let server;
// Timeout after 5 minutes
const timeout = setTimeout(() => {
if (!resolved) {
resolved = true;
server?.close();
rejectLogin(new Error("Login timed out after 5 minutes"));
export async function loginViaDeviceCode(opts) {
const apiUrl = opts.apiUrl.replace(/\/$/, "");
const initRes = await fetch(`${apiUrl}/api/cli/auth/initiate`, { method: "POST" });
if (!initRes.ok) {
throw new Error(`Failed to start authentication: HTTP ${initRes.status}`);
}
const init = (await initRes.json());
if (!init.deviceCode || !init.userCode || !init.verificationUrl) {
throw new Error("Auth API returned an incomplete initiate response.");
}
// Print info to stderr — works in any MCP host that surfaces stderr to the
// user, and is harmless when the host doesn't (the user can still tail the
// MCP log file). We try to spawn the system browser opener as a convenience,
// but the URL is always printed in plain text so the user can copy-paste.
console.error("");
console.error(" Useswarm — sign in to continue");
console.error("");
console.error(` Code: ${init.userCode}`);
console.error(` URL: ${init.verificationUrl}`);
console.error("");
console.error(" Open the URL, confirm the code matches, and authorize.");
console.error("");
try {
const { spawn } = await import("child_process");
const opener = process.platform === "darwin"
? "open"
: process.platform === "win32"
? "start"
: "xdg-open";
spawn(opener, [init.verificationUrl], { stdio: "ignore", detached: true }).unref();
}
catch {
// No system opener — user has the URL above.
}
const deadline = Date.now() + init.expiresIn * 1000;
console.error("Waiting for authorization...");
while (Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 2500));
let poll;
try {
const pollRes = await fetch(`${apiUrl}/api/cli/auth/poll?device_code=${encodeURIComponent(init.deviceCode)}`);
if (pollRes.status === 404) {
// Server lost the code — bail rather than spinning forever.
throw new Error("Authentication code is no longer valid.");
}
}, 5 * 60 * 1000);
// C-2: Accept POST with JSON body instead of GET with query params
server = createServer((req, res) => {
const url = new URL(req.url ?? "/", `http://localhost`);
// CORS preflight for the browser-side fetch
if (req.method === "OPTIONS" && url.pathname === "/callback") {
res.writeHead(204, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type",
});
res.end();
return;
if (!pollRes.ok) {
// Transient HTTP error — keep polling.
continue;
}
if (url.pathname === "/callback") {
if (req.method !== "POST") {
res.writeHead(405, { "Content-Type": "application/json", "Allow": "POST" });
res.end(JSON.stringify({ error: "Method not allowed" }));
return;
}
let body = "";
req.on("data", (chunk) => { body += chunk; });
req.on("end", () => {
let payload;
try {
payload = JSON.parse(body);
}
catch {
res.writeHead(400, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Invalid JSON body" }));
return;
}
const { api_key: apiKey, state: receivedState, error } = payload;
if (error) {
res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" });
res.end(JSON.stringify({ success: false, error }));
if (!resolved) {
resolved = true;
clearTimeout(timeout);
server.close();
rejectLogin(new Error(`Login failed: ${error}`));
}
return;
}
if (receivedState !== state) {
res.writeHead(400, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" });
res.end(JSON.stringify({ error: "State mismatch — possible CSRF attack" }));
return;
}
if (!apiKey) {
res.writeHead(400, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" });
res.end(JSON.stringify({ error: "No API key received" }));
return;
}
// Success
res.writeHead(200, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" });
res.end(JSON.stringify({ success: true }));
if (!resolved) {
resolved = true;
clearTimeout(timeout);
server.close();
saveStoredConfig({ apiKey, apiUrl: opts.apiUrl });
resolveLogin({ apiKey, apiUrl: opts.apiUrl });
}
});
return;
}
res.writeHead(404);
res.end("Not found");
});
// Listen on random port
server.listen(0, "127.0.0.1", async () => {
const addr = server.address();
if (!addr || typeof addr === "string") {
rejectLogin(new Error("Failed to start callback server"));
return;
}
const callbackUrl = `http://127.0.0.1:${addr.port}/callback`;
const loginUrl = `${opts.appUrl}/mcp/auth?callback=${encodeURIComponent(callbackUrl)}&state=${state}`;
console.error(`\nOpening browser to log in...`);
console.error(`If the browser doesn't open, visit:\n ${loginUrl}\n`);
// Open browser — use spawn with array args to prevent shell injection
try {
const { spawn: spawnChild } = await import("child_process");
const opener = process.platform === "darwin"
? "open"
: process.platform === "win32"
? "start"
: "xdg-open";
spawnChild(opener, [loginUrl], { stdio: "ignore", detached: true }).unref();
}
catch {
// Browser open failed — user can manually visit the URL
}
console.error("Waiting for login...");
});
});
poll = (await pollRes.json());
}
catch (err) {
const msg = err.message ?? "";
if (msg.startsWith("Authentication code is no longer"))
throw err;
// Network blip — keep polling.
continue;
}
if (poll.status === "complete" && poll.apiKey) {
saveStoredConfig({ apiKey: poll.apiKey, apiUrl });
return {
apiKey: poll.apiKey,
apiUrl,
...(poll.user ? { user: poll.user } : {}),
...(poll.organization ? { organization: poll.organization } : {}),
};
}
if (poll.status === "expired") {
throw new Error("Authentication code expired — please try again.");
}
if (poll.status === "consumed") {
throw new Error("This code was already used. Re-run login to start over.");
}
// status === "pending" — keep polling
}
throw new Error("Authentication timed out after 10 minutes.");
}
function successPage() {
return `<!DOCTYPE html>
<html>
<head><title>Useswarm MCP — Logged In</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #0a0a0a; color: #fafafa; }
.card { text-align: center; padding: 3rem; max-width: 400px; }
h1 { font-size: 1.5rem; margin-bottom: 0.5rem; }
p { color: #888; }
.check { font-size: 3rem; margin-bottom: 1rem; }
</style></head>
<body>
<div class="card">
<div class="check">&#10003;</div>
<h1>Logged in to Useswarm MCP</h1>
<p>You can close this tab and return to your terminal.</p>
</div>
</body>
</html>`;
}
function escapeHtml(s) {
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}
function errorPage(error) {
return `<!DOCTYPE html>
<html>
<head><title>Useswarm MCP — Error</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #0a0a0a; color: #fafafa; }
.card { text-align: center; padding: 3rem; max-width: 400px; }
h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #ff4444; }
p { color: #888; }
</style></head>
<body>
<div class="card">
<h1>Login Failed</h1>
<p>${escapeHtml(error)}</p>
<p>Close this tab and try again.</p>
</div>
</body>
</html>`;
}
/**
* Backward-compat alias. The old browser-callback flow has been replaced by
* the device-code flow above; both names point at the same implementation
* so external imports keep working.
*/
export const loginViaBrowser = loginViaDeviceCode;
//# sourceMappingURL=login.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"}

@@ -6,3 +6,4 @@ #!/usr/bin/env node

* Tunnels your localhost via cloudflared, runs AI agent swarms against
* your app, and returns structured issues so Claude can fix and re-test.
* your app, and returns structured issues so the host (Claude / Codex /
* Cursor / etc.) can fix and re-test.
*

@@ -16,11 +17,14 @@ * Tools:

* New user? Just run:
* useswarm-mcp setup # Adds to Claude Code, auto-logins on first use
* useswarm-mcp setup # Registers hosts AND signs in (one-shot)
* useswarm-mcp setup --client claude # Claude Code only
* useswarm-mcp setup --client codex # Codex CLI only
* useswarm-mcp setup --skip-login # Register without signing in (for CI/env-key flows)
*
* Other commands:
* useswarm-mcp login # Browser-based login
* useswarm-mcp login # Device-code login (works in any host)
* useswarm-mcp logout # Clear credentials
* useswarm-mcp whoami # Check auth status
* useswarm-mcp serve # Start MCP server (stdio, auto-logins if needed)
* useswarm-mcp serve # Start MCP server (stdio). Exits if no key — never auto-logins.
* useswarm-mcp serve --http # HTTP+SSE on port 3100
*/
export {};

@@ -6,3 +6,4 @@ #!/usr/bin/env node

* Tunnels your localhost via cloudflared, runs AI agent swarms against
* your app, and returns structured issues so Claude can fix and re-test.
* your app, and returns structured issues so the host (Claude / Codex /
* Cursor / etc.) can fix and re-test.
*

@@ -16,9 +17,12 @@ * Tools:

* New user? Just run:
* useswarm-mcp setup # Adds to Claude Code, auto-logins on first use
* useswarm-mcp setup # Registers hosts AND signs in (one-shot)
* useswarm-mcp setup --client claude # Claude Code only
* useswarm-mcp setup --client codex # Codex CLI only
* useswarm-mcp setup --skip-login # Register without signing in (for CI/env-key flows)
*
* Other commands:
* useswarm-mcp login # Browser-based login
* useswarm-mcp login # Device-code login (works in any host)
* useswarm-mcp logout # Clear credentials
* useswarm-mcp whoami # Check auth status
* useswarm-mcp serve # Start MCP server (stdio, auto-logins if needed)
* useswarm-mcp serve # Start MCP server (stdio). Exits if no key — never auto-logins.
* useswarm-mcp serve --http # HTTP+SSE on port 3100

@@ -39,7 +43,17 @@ */

import { TunnelTransport } from "./tunnel/transport.js";
import { loginViaBrowser, loadStoredConfig } from "./auth/login.js";
import { loginViaDeviceCode, loadStoredConfig } from "./auth/login.js";
import { writeCodexMcpConfig } from "./auth/codex-setup.js";
import { closeTunnel } from "./lib/target-tunnel.js";
import { existsSync, unlinkSync } from "fs";
import { existsSync, readFileSync, unlinkSync } from "fs";
import { homedir } from "os";
import { randomBytes } from "crypto";
const PKG_VERSION = (() => {
try {
const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
}
catch {
return "0.0.0";
}
})();
// Clean up tunnels on exit

@@ -53,12 +67,12 @@ for (const sig of ["SIGINT", "SIGTERM", "exit"]) {

.description("Useswarm Dev MCP — automated UX testing loop for local development. Tunnel, test, fix, repeat.")
.version("2.0.0");
.version(PKG_VERSION);
// ─── login ────────────────────────────────────────────────
program
.command("login")
.description("Log in to Useswarm via the browser (creates an API key)")
.option("--app-url <url>", "Useswarm web app URL", process.env.USESWARM_APP_URL ?? "https://useswarm.co")
.description("Log in to Useswarm (device-code flow — works in any host)")
.option("--app-url <url>", "Useswarm web app URL", process.env.USESWARM_APP_URL ?? "https://www.useswarm.co")
.option("--api-url <url>", "Useswarm API URL", process.env.USESWARM_API_URL ?? "https://api.useswarm.co")
.action(async (opts) => {
try {
const result = await loginViaBrowser({
const result = await loginViaDeviceCode({
appUrl: opts.appUrl,

@@ -70,3 +84,3 @@ apiUrl: opts.apiUrl,

console.log(`Stored in: ~/.useswarm/config.json`);
console.log(`\nNext: run 'useswarm-mcp setup' to add to Claude Code.`);
console.log(`\nNext: run 'useswarm-mcp setup' to register with your MCP host.`);
}

@@ -127,29 +141,103 @@ catch (err) {

.command("setup")
.description("One-command setup: adds Useswarm MCP to Claude Code. Opens browser to log in on first use.")
.action(async () => {
.description("Register Useswarm MCP with your host (Claude Code, Codex CLI, or both) and sign in if needed.")
.option("--client <client>", "Which MCP host(s) to configure: claude, codex, or all", "all")
.option("--app-url <url>", "Useswarm web app URL", process.env.USESWARM_APP_URL ?? "https://www.useswarm.co")
.option("--api-url <url>", "Useswarm API URL", process.env.USESWARM_API_URL ?? "https://api.useswarm.co")
.option("--skip-login", "Don't run device-code login even if no key is stored", false)
.action(async (opts) => {
const choice = String(opts.client ?? "all").toLowerCase();
if (!["claude", "codex", "all"].includes(choice)) {
console.error(`Unknown --client value: "${opts.client}". Expected: claude, codex, or all.`);
process.exit(1);
}
const wantsClaude = choice === "claude" || choice === "all";
const wantsCodex = choice === "codex" || choice === "all";
const cliPath = resolve(__dirname, "../dist/cli.js");
console.log("\nConfiguring Claude Code...\n");
try {
const { execFileSync } = await import("child_process");
// Remove existing config if present
const successes = [];
const failures = [];
if (wantsClaude) {
try {
execFileSync("claude", ["mcp", "remove", "useswarm"], { stdio: "pipe" });
const { execFileSync } = await import("child_process");
try {
execFileSync("claude", ["mcp", "remove", "useswarm"], { stdio: "pipe" });
}
catch {
// Wasn't installed — fine.
}
execFileSync("claude", ["mcp", "add", "useswarm", "--", "node", cliPath], { stdio: "pipe" });
successes.push("Claude Code (registered via `claude mcp add`)");
}
catch {
// Didn't exist
catch (err) {
failures.push({
client: "Claude Code",
error: `${err.message}\n Manual setup: claude mcp add useswarm -- node ${cliPath}`,
});
}
// Add as stdio MCP — serve auto-logins via browser if no creds
execFileSync("claude", ["mcp", "add", "useswarm", "--", "node", cliPath], { stdio: "inherit" });
console.log("\nDone! Useswarm MCP added to Claude Code.");
console.log("On first use, your browser will open to log in automatically.\n");
console.log("Try it — open Claude Code and say:");
console.log(' "Use dev_test to test http://localhost:3000 with goal \'complete signup\'"');
console.log("");
}
catch (err) {
console.error(`Failed to configure: ${err.message}`);
console.error(`\nManual setup:`);
console.error(` claude mcp add useswarm -- node ${cliPath}`);
if (wantsCodex) {
try {
const result = writeCodexMcpConfig({ command: "node", args: [cliPath] });
const verb = result.created ? "created" : result.replaced ? "updated" : "appended to";
successes.push(`Codex CLI (${verb} ${result.path})`);
}
catch (err) {
failures.push({
client: "Codex CLI",
error: `${err.message}\n Manual setup: add the following to ~/.codex/config.toml\n [mcp_servers.useswarm]\n command = "node"\n args = [${JSON.stringify(cliPath)}]`,
});
}
}
console.log();
for (const s of successes)
console.log(` ${s}`);
if (failures.length > 0) {
console.log();
for (const f of failures) {
console.error(` ${f.client} — failed:`);
console.error(` ${f.error}`);
}
}
if (successes.length === 0) {
console.error("\nNo clients configured.");
process.exit(1);
}
// Run login here — at setup time, in the user's terminal, where the
// device-code URL + code can be read and clicked without competing
// with an MCP host's UI. We deliberately do NOT auto-login at serve
// time (when the AI tool spawns the MCP) because the host typically
// can't surface an interactive flow well.
const stored = loadStoredConfig();
const hasKey = !!stored.apiKey || !!process.env.USESWARM_API_KEY;
if (opts.skipLogin) {
console.log();
console.log("Skipped login (--skip-login). Run `useswarm-mcp login` later if needed.");
}
else if (hasKey) {
console.log();
console.log(`Already signed in (key ...${(stored.apiKey ?? process.env.USESWARM_API_KEY ?? "").slice(-4)}). Skipping login.`);
console.log("Run `useswarm-mcp logout && useswarm-mcp login` to switch accounts.");
}
else {
console.log();
console.log("Signing in to Useswarm — opening device-code flow in your browser...");
try {
const result = await loginViaDeviceCode({
appUrl: opts.appUrl,
apiUrl: opts.apiUrl,
});
console.log();
console.log(`Signed in. API key: ...${result.apiKey.slice(-4)}`);
console.log(`Stored in: ~/.useswarm/config.json`);
}
catch (err) {
console.error();
console.error(`Login failed: ${err.message}`);
console.error("Re-run `useswarm-mcp login` from a terminal to retry. The MCP is registered with your host but won't work until a key is stored.");
process.exit(1);
}
}
console.log();
console.log("Setup complete. Open your host and try:");
console.log(' "Use dev_test to test http://localhost:3000 with goal \'complete signup\'"');
console.log();
});

@@ -166,3 +254,3 @@ // ─── serve (default command) ──────────────────────────────

.option("--api-key <key>", "Useswarm API key")
.option("--app-url <url>", "Useswarm web app URL", process.env.USESWARM_APP_URL ?? "https://useswarm.co")
.option("--app-url <url>", "Useswarm web app URL", process.env.USESWARM_APP_URL ?? "https://www.useswarm.co")
.action(async (opts) => {

@@ -180,20 +268,13 @@ // M-9: Warn when secrets are passed via CLI arguments (visible in process list)

// Load stored credentials as fallback
let apiKey = opts.apiKey ?? stored.apiKey;
// Auto-login if no credentials found
const apiKey = opts.apiKey ?? stored.apiKey;
// No auto-login at serve time: when the AI host spawns the MCP it can't
// reliably surface an interactive device-code flow, and a half-finished
// login mid-session is worse than a clean error. Login happens in `setup`
// (or `login`) — anywhere the user has a real terminal.
if (!apiKey && !process.env.USESWARM_API_KEY && !process.env.USESWARM_SESSION_TOKEN) {
console.error("[useswarm-mcp] No API key found. Opening browser to log in...\n");
try {
const result = await loginViaBrowser({
appUrl: opts.appUrl ?? "https://useswarm.co",
apiUrl: opts.apiUrl ?? "https://api.useswarm.co",
});
apiKey = result.apiKey;
stored = loadStoredConfig(); // Reload after login saved it
console.error(`[useswarm-mcp] Logged in! Key: ...${apiKey.slice(-4)}\n`);
}
catch (err) {
console.error(`[useswarm-mcp] Login failed: ${err.message}`);
console.error("[useswarm-mcp] Pass --api-key or set USESWARM_API_KEY env var.");
process.exit(1);
}
console.error("[useswarm-mcp] No API key found in ~/.useswarm/config.json or USESWARM_API_KEY env.");
console.error("[useswarm-mcp] Run one of these from a terminal, then restart your host:");
console.error("[useswarm-mcp] npx @useswarm/mcp setup # registers + signs in");
console.error("[useswarm-mcp] npx @useswarm/mcp login # signs in only (already registered)");
process.exit(1);
}

@@ -200,0 +281,0 @@ const cfg = loadConfig({

@@ -1,1 +0,1 @@

{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAoB,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACrF,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,2BAA2B;AAC3B,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAU,EAAE,CAAC;IACzD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,cAAc,CAAC;KACpB,WAAW,CAAC,gGAAgG,CAAC;KAC7G,OAAO,CAAC,WAAW,CAAC,CAAC;AAExB,6DAA6D;AAE7D,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,2DAA2D,CAAC;KACxE,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;KAC5G,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;KACxG,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;YACtC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAClF,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,6DAA6D;AAE7D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAClE,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,UAAU,CAAC,UAAU,CAAC,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,6DAA6D;AAE7D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,yBAAyB,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,eAAe,EAAE;YAChD,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,sCAAsC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,gCAAgC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,4DAA4D;AAE5D,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,+FAA+F,CAAC;KAC5G,MAAM,CACL,mBAAmB,EACnB,uDAAuD,EACvD,KAAK,CACN;KACA,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;KAC5G,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;KACxG,MAAM,CAAC,cAAc,EAAE,sDAAsD,EAAE,KAAK,CAAC;KACrF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1D,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,MAAM,qCAAqC,CAAC,CAAC;QAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,KAAK,CAAC;IAC5D,MAAM,UAAU,GAAG,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC;IAE1D,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACrD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAwC,EAAE,CAAC;IAEzD,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YACvD,IAAI,CAAC;gBACH,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3E,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;YACD,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7F,SAAS,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,GAAG,GAAG,CAAC,OAAO,qDAAqD,OAAO,EAAE;aACpF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACzE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;YACtF,SAAS,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,GAAG,GAAG,CAAC,OAAO,8HAA8H,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG;aAC9K,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oEAAoE;IACpE,mEAAmE;IACnE,oEAAoE;IACpE,oEAAoE;IACpE,0CAA0C;IAC1C,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAEjE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;QAC9H,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;IACrF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;QACpF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;gBACtC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,kIAAkI,CAAC,CAAC;YAClJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEL,6DAA6D;AAE7D,MAAM,QAAQ,GAAG,OAAO;KACrB,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;KACrC,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,QAAQ,EAAE,yCAAyC,CAAC;KAC3D,MAAM,CAAC,eAAe,EAAE,WAAW,EAAE,MAAM,CAAC;KAC5C,MAAM,CAAC,UAAU,EAAE,kCAAkC,CAAC;KACtD,MAAM,CAAC,wBAAwB,EAAE,6BAA6B,CAAC;KAC/D,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;KAClD,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;KAC7C,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;KAC5G,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,gFAAgF;IAChF,IAAI,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAChC,MAAM,gBAAgB,GACpB,oFAAoF;QACpF,iEAAiE,CAAC;IACpE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACjG,OAAO,CAAC,KAAK,CAAC,kBAAkB,gBAAgB,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,KAAK,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACrH,OAAO,CAAC,KAAK,CAAC,kBAAkB,gBAAgB,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,sCAAsC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC;IAE5C,wEAAwE;IACxE,wEAAwE;IACxE,0EAA0E;IAC1E,wDAAwD;IACxD,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACpF,OAAO,CAAC,KAAK,CAAC,qFAAqF,CAAC,CAAC;QACrG,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC1F,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACxF,OAAO,CAAC,KAAK,CAAC,sFAAsF,CAAC,CAAC;QACtG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC;QACrB,UAAU,EAAE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QACxC,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,MAAM;QAC/B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QACrD,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;QAC5B,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW;KACpD,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,8EAA8E,CAAC,CAAC;QAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEpC,wDAAwD;IAExD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,sEAAsE;QACtE,MAAM,eAAe,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,qCAAqC,eAAe,EAAE,CAAC,CAAC;QAEtE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACjD,+CAA+C;YAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,aAAa,GACjB,MAAM,KAAK,SAAS;gBACpB,8CAA8C,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAE9D,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;gBAC5B,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;gBACrD,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAChC,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;gBACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,6BAA6B,CAAC,CAAC;YAC/E,CAAC;YAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC7B,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACzC,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,GAAG,KAAK,UAAU,IAAI,GAAG,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;gBACjD,iDAAiD;gBACjD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;gBACtD,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;oBACjC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;oBACnD,OAAO;gBACT,CAAC;gBAED,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACxC,OAAO;YACT,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,8DAA8D;QAC9D,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;YAC5C,OAAO,CAAC,KAAK,CAAC,2CAA2C,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,iDAAiD,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC1D,CAAC;IAED,wDAAwD;IAExD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACjG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,wDAAwD;QACxD,oDAAoD;QACpD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC/D,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,YAAY,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAE5C,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;YAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,KAAK,EAAE,GAAG,CAAC,WAAW;YACtB,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;gBAClC,OAAO,eAAe,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;YACvD,CAAC;YACD,WAAW,EAAE,CAAC,SAAS,EAAE,EAAE;gBACzB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,OAAO,CAAC,KAAK,CAAC,uCAAuC,SAAS,UAAU,CAAC,CAAC;gBAC1E,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;gBACpD,OAAO,CAAC,KAAK,CAAC,yDAAyD,SAAS,UAAU,CAAC,CAAC;YAC9F,CAAC;YACD,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE;gBACzB,OAAO,CAAC,KAAK,CAAC,uCAAuC,MAAM,mBAAmB,CAAC,CAAC;YAClF,CAAC;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/D,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;IAED,wDAAwD;IAExD,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,kFAAkF,CAAC,CAAC;QAClG,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
export interface ServerConfig {
/** API base URL (default: http://localhost:8080) */
/** API base URL (default: https://api.useswarm.co) */
apiBaseUrl: string;

@@ -4,0 +4,0 @@ /** API key for authenticating with the Useswarm API */

/**
* Dev Loop Tools — the core developer experience tools for the MCP server.
* Dev Loop Tools — the four MCP tools a coding agent uses to drive
* Useswarm's UX testing platform from inside its host (Claude Code, Codex,
* Cursor, etc.).
*
* These tools enable a self-iterating development loop:
* 1. `dev_test` — Tunnel localhost via cloudflared, run a swarm UX test, return batch ID
* 2. `dev_watch` — Poll a batch test until done, return structured results with issues
* 3. `dev_status` — Check tunnel + test status at a glance
* Loop shape:
* code change → dev_test (tunnel + start) → dev_watch (poll for results)
* → agent fixes code from `issues[]` → dev_test again → repeat.
*
* The developer workflow:
* Claude makes a code change → calls dev_test (tunnels + runs swarm) →
* calls dev_watch (waits for results) → reads issues → fixes code →
* calls dev_test again → repeat until clean.
*
* This eliminates manual browser testing — the swarm tests user flows
* automatically and reports back structured findings.
* Descriptions are deliberately structured "WHEN / WHAT IT DOES / RETURNS"
* because coding agents (especially Codex) pick the right tool based on
* front-loaded intent signals, not buried prose.
*/

@@ -17,0 +14,0 @@ import type { ApiClient } from "../lib/api-client.js";

/**
* Dev Loop Tools — the core developer experience tools for the MCP server.
* Dev Loop Tools — the four MCP tools a coding agent uses to drive
* Useswarm's UX testing platform from inside its host (Claude Code, Codex,
* Cursor, etc.).
*
* These tools enable a self-iterating development loop:
* 1. `dev_test` — Tunnel localhost via cloudflared, run a swarm UX test, return batch ID
* 2. `dev_watch` — Poll a batch test until done, return structured results with issues
* 3. `dev_status` — Check tunnel + test status at a glance
* Loop shape:
* code change → dev_test (tunnel + start) → dev_watch (poll for results)
* → agent fixes code from `issues[]` → dev_test again → repeat.
*
* The developer workflow:
* Claude makes a code change → calls dev_test (tunnels + runs swarm) →
* calls dev_watch (waits for results) → reads issues → fixes code →
* calls dev_test again → repeat until clean.
*
* This eliminates manual browser testing — the swarm tests user flows
* automatically and reports back structured findings.
* Descriptions are deliberately structured "WHEN / WHAT IT DOES / RETURNS"
* because coding agents (especially Codex) pick the right tool based on
* front-loaded intent signals, not buried prose.
*/
import { z } from "zod";
import { tunnelTargetUrl, isLocalhostUrl, closeTunnel, } from "../lib/target-tunnel.js";
import { loadStoredConfig } from "../auth/login.js";
// Track active state so dev_status can report on it

@@ -25,38 +23,197 @@ let activeTunnelUrl = null;

let lastTestStartedAt = null;
/**
* Translate raw API errors into messages the calling agent can act on.
* The api-client already sanitizes; this layer adds recovery hints.
*/
function explainApiError(err) {
const raw = err instanceof Error ? err.message : String(err);
if (/API 401/i.test(raw) || /Unauthorized/i.test(raw)) {
return (`${raw}\n\n` +
`Your Useswarm API key is missing, expired, or revoked. Recovery:\n` +
` 1. From a terminal, run: npx @useswarm/mcp login\n` +
` 2. Or set USESWARM_API_KEY in the MCP host's env config.\n` +
` 3. Then retry the tool call.\n` +
`Run 'useswarm-mcp whoami' to verify the key.`);
}
if (/API 403/i.test(raw)) {
return (`${raw}\n\n` +
`Your plan does not include this feature, or quota is exhausted. ` +
`Visit https://www.useswarm.co/billing to upgrade, then retry.`);
}
if (/API 404/i.test(raw)) {
return `${raw}\n\nThe resource was not found. If this was dev_watch, the batchId may be wrong or expired.`;
}
if (/API 429/i.test(raw)) {
return `${raw}\n\nYou're rate-limited or out of monthly test quota. Wait a moment, or upgrade at https://www.useswarm.co/billing.`;
}
if (/cloudflared not found/i.test(raw) || /ENOENT/i.test(raw)) {
return (`${raw}\n\n` +
`Cloudflare tunnel binary missing. Install with:\n` +
` macOS: brew install cloudflared\n` +
` Linux: npm install -g cloudflared\n` +
`Alternative: use a public URL (skip the tunnel) or set NGROK_AUTHTOKEN.`);
}
return raw;
}
export function registerDevLoopTools(server, api) {
// ─── dev_test: tunnel + run swarm test in one call ─────────────
server.tool("dev_test", `Start a UX test loop iteration on your local dev server. This tool:
1. Detects if the URL is localhost and automatically opens a cloudflared tunnel
2. If backendUrl is provided, spins up a reverse proxy that merges frontend + backend onto one tunnel (routes /api/*, /auth/*, /graphql, /trpc/* to the backend, everything else to the frontend)
3. Kicks off a swarm of AI agents to test the user flow
4. Returns a batch ID for tracking with dev_watch
IMPORTANT: If the app has a separate backend server (common with Next.js + Express, React + Rails, etc.), pass backendUrl so API calls work through the tunnel. Without it, the frontend will load but API calls will fail.
Examples:
- Frontend only: targetUrl="http://localhost:3000"
- Frontend + Backend: targetUrl="http://localhost:3000", backendUrl="http://localhost:8080"
- With WebSocket paths: targetUrl="http://localhost:3000", backendUrl="http://localhost:8080", backendPaths=["/ws", "/socket.io"]
Use this as the "test" step in a code→test→fix loop. After making changes,
call dev_test to have real AI agents try the user flow and report issues.`, {
targetUrl: z.string().describe("Frontend URL to test (e.g. 'http://localhost:3000'). Localhost URLs are auto-tunneled via cloudflared."),
goal: z.string().min(1).describe("What the agents should try to accomplish (e.g. 'complete the signup flow and reach the dashboard')"),
userDescription: z.string().min(1).describe("Target audience description (e.g. 'first-time SaaS users aged 25-40')"),
agentCount: z.number().min(1).max(20).optional().describe("Number of test agents (default 3). More agents = more diverse feedback but longer wait."),
backendUrl: z.string().optional().describe("Separate backend/API server URL if running on a different port (e.g. 'http://localhost:8080'). When provided, a reverse proxy merges both servers onto one tunnel — routing /api/*, /auth/*, /graphql, /trpc/* to the backend and everything else to the frontend. Required for apps with separate frontend and backend servers."),
backendPaths: z.array(z.string()).optional().describe("Extra path prefixes to route to the backend server, in addition to the defaults (/api, /auth, /graphql, /trpc). Use for WebSocket endpoints or custom API paths (e.g. ['/ws', '/socket.io', '/v1'])."),
maxSteps: z.number().min(1).max(200).optional().describe("Max steps per agent (default from server)"),
provider: z.enum(["openai", "anthropic"]).optional().describe("AI provider for the agents"),
model: z.string().optional().describe("Model override for the agents"),
// WARNING: Auth credentials/cookies pass through the relay server in plaintext when tunnel
// transport is active. Use test-only accounts, not production credentials.
auth: z.object({
mode: z.enum(["agent_login", "cookie_injection", "signup"]).optional().describe("Auth mode. 'agent_login' (default) uses username+password against an existing account; 'cookie_injection' uses session cookies + a startUrl (skips login — agent starts already authenticated); 'signup' takes one base email and gives each persona a unique `local+<hash>@domain` sub-alias to register with, so synthetic users land in isolated inboxes."),
// Login mode
loginUrl: z.string().url().optional().describe("Login page URL (login mode only; defaults to targetUrl)"),
username: z.string().min(1).max(256).optional().describe("Login username/email (login mode)"),
password: z.string().min(1).max(256).optional().describe("Login password (login mode)"),
// Cookie injection mode
cookies: z.array(z.object({
// ─── dev_list_swarms ─────────────────────────────────────────────
server.tool("dev_list_swarms", [
"List the saved persona swarms tied to the user's Useswarm account (personal + active org).",
"",
"WHEN TO CALL:",
" - The user mentions a swarm by name ('use my B2B Buyers swarm', 'test with the SMB swarm').",
" - You want to offer the user a choice of saved swarms before generating new personas.",
" - Before passing `swarmId` to dev_test — fetch fresh IDs here.",
"",
"RETURNS: { swarms: Array<{ id, name, description, agentCount, createdAt }> }",
" - id → UUID to pass as dev_test's `swarmId`",
" - name → human label (e.g. 'B2B SaaS Buyers')",
" - description → free-text purpose, optional",
" - agentCount → number of personas the swarm contains",
"",
"If the list is empty, the user hasn't saved any swarms — fall back to passing userDescription to dev_test.",
].join("\n"), {}, async () => {
try {
const data = await api.get("/api/cli/swarms");
const swarms = (data.swarms ?? []).map((s) => ({
id: s.id,
name: s.name,
description: s.description ?? null,
agentCount: s.agentCount ?? null,
personaCount: Array.isArray(s.personas) ? s.personas.length : null,
createdAt: s.createdAt ?? null,
}));
const response = {
swarms,
count: swarms.length,
_devLoop: {
hint: swarms.length === 0
? "No saved swarms found. Pass userDescription to dev_test to generate personas on the fly."
: `Found ${swarms.length} swarm(s). Pass one of these IDs as dev_test's swarmId to reuse its personas.`,
},
};
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
}
catch (err) {
return {
content: [{ type: "text", text: `Error listing swarms: ${explainApiError(err)}` }],
isError: true,
};
}
});
// ─── dev_test ────────────────────────────────────────────────────
server.tool("dev_test", [
"Run an AI-agent UX test against a frontend URL (typically your local dev server).",
"",
"WHEN TO CALL:",
" After you make a code change and want real agents to walk through a user flow",
" (signup, checkout, onboarding, etc.) and tell you what's broken or confusing.",
" This is the 'test' step of the code → test → fix loop.",
"",
"WHAT IT DOES:",
" 1. If targetUrl is localhost, opens a Cloudflare tunnel so cloud agents can reach it.",
" 2. If backendUrl is set, also stands up a reverse proxy that merges frontend + backend",
" onto one tunnel (routes /api/*, /auth/*, /graphql, /trpc/* to backend).",
" 3. Generates AI personas matching userDescription and runs them against the URL.",
" 4. Returns a batchId immediately. Tests take ~1-3 minutes — call dev_watch next.",
"",
"RETURNS: { batchId, dashboardUrl, _devLoop: { nextStep, ... } }.",
"",
"AUTH (optional): pass `auth` if the test needs a signed-in user. See `auth` param.",
"",
"PERSONAS — two modes (mutually exclusive):",
" - Provide `swarmId` to use a saved swarm tied to the user's account",
" (call dev_list_swarms first if you don't know the IDs).",
" - Otherwise the runtime auto-generates personas from `userDescription`.",
"",
"TYPICAL PROMPTS THAT MAP HERE:",
" - 'test localhost:3000 with goal X'",
" - 'run a swarm test on my app'",
" - 'have agents try the signup flow'",
" - 'use my B2B Buyers swarm to test the pricing page'",
].join("\n"), {
targetUrl: z
.string()
.describe("Frontend URL. Localhost (e.g. 'http://localhost:3000') is auto-tunneled via cloudflared. " +
"Public URLs are hit directly. Schemeless input ('localhost:3000') is normalized to http://."),
goal: z
.string()
.min(1)
.describe("Concrete user goal in plain English. Be specific — 'complete checkout' beats 'test the app'. " +
"Example: 'sign up with email + password, then reach the dashboard'."),
swarmId: z
.string()
.uuid()
.optional()
.describe("UUID of a saved swarm tied to the user's account. When set, that swarm's stored personas run instead of generating new ones. " +
"Mutually exclusive with userDescription/agentCount — if you pass swarmId, omit the other two. " +
"Call dev_list_swarms first to discover available IDs."),
userDescription: z
.string()
.min(1)
.optional()
.describe("Who the agents should pretend to be — drives persona generation. " +
"Required when swarmId is not provided. " +
"Example: 'first-time SaaS users, mostly non-technical, ages 25-45'."),
agentCount: z
.number()
.min(1)
.max(20)
.optional()
.describe("How many parallel personas to generate. Default 3. Ignored when swarmId is set (the saved swarm's count is used). " +
"Higher = broader signal but longer wait and more credits used."),
backendUrl: z
.string()
.optional()
.describe("REQUIRED when your frontend and backend run on different ports (Next+Express, React+Rails, etc.). " +
"Without it, the frontend loads in the cloud browser but API calls 404 because the cloud can't see :8080. " +
"Example: 'http://localhost:8080'. With this set, /api/*, /auth/*, /graphql, /trpc/* route to backendUrl through one tunnel."),
backendPaths: z
.array(z.string())
.optional()
.describe("Extra path prefixes routed to backendUrl in addition to the defaults (/api, /auth, /graphql, /trpc). " +
"Use for WebSockets, gRPC-Web, or non-standard API paths. Example: ['/ws', '/socket.io', '/v1']. " +
"Each entry must start with '/' and be longer than just '/'."),
maxSteps: z
.number()
.min(1)
.max(200)
.optional()
.describe("Cap on actions per agent. Default depends on plan. Increase for complex multi-step flows."),
provider: z
.enum(["openai", "anthropic"])
.optional()
.describe("Which model family runs the agents. Default is the server-side default; only override if you have a specific reason."),
model: z.string().optional().describe("Exact model override (advanced). Example: 'gpt-5.4-cua' or 'claude-sonnet-4-6'."),
auth: z
.object({
mode: z
.enum(["agent_login", "cookie_injection", "signup"])
.optional()
.describe("Auth strategy. Omit to auto-infer from which fields you pass:\n" +
" - 'cookie_injection': you have a logged-in session — paste cookies, agent skips login.\n" +
" BEST when login requires CAPTCHA, SSO, or MFA. Pair with `startUrl` (e.g. the dashboard URL).\n" +
" - 'agent_login': you have a username + password for an EXISTING test account.\n" +
" Agent navigates to loginUrl (or targetUrl), fills the form, submits.\n" +
" - 'signup': you're testing the sign-up flow. Pass one base email; each persona gets\n" +
" a unique 'local+<hash>@domain' sub-alias so confirmations route back to your single inbox."),
loginUrl: z
.string()
.url()
.optional()
.describe("agent_login: URL of the login form. Defaults to targetUrl if omitted. Localhost gets tunneled automatically."),
username: z
.string()
.min(1)
.max(256)
.optional()
.describe("agent_login: existing-account username/email. Use a test-only account — credentials transit the relay."),
password: z
.string()
.min(1)
.max(256)
.optional()
.describe("agent_login: existing-account password. Use a test-only account."),
cookies: z
.array(z.object({
name: z.string(),

@@ -69,18 +226,46 @@ value: z.string(),

sameSite: z.string().nullish(),
})).optional().describe("Session cookies for cookie_injection mode. Each cookie needs name/value/domain at minimum. Other fields (path, secure, httpOnly, sameSite) are optional and accept null."),
// Signup mode
signupEmail: z.string().email().optional().describe("Base email for signup mode, e.g. 'you@yourdomain.com'. Each persona gets a unique `local+<hash>@domain` alias derived from this. Use a provider that supports plus-addressing (Gmail, Fastmail, custom domains) so all aliases route back to one inbox."),
signupPassword: z.string().min(1).max(256).optional().describe("Optional shared password the agent uses when filling sign-up forms. If omitted, the runtime mints a strong random password per persona-run (not persisted — accounts are throwaway)."),
// Shared
startUrl: z.string().url().optional().describe("URL to land on after auth. Recommended for cookie_injection — the post-auth dashboard URL. For login mode, overrides the default post-login redirect. For signup, can pre-navigate to the sign-up form."),
}).optional().describe("Auth setup if the site requires it. WARNING: Use test-only accounts — credentials/cookies may pass through the relay server."),
}))
.optional()
.describe("cookie_injection: session cookies for an already-logged-in user. " +
"Need name+value+domain at minimum; other fields optional/nullable. " +
"TIP: capture with the 'Cookie-Editor' Chrome extension → Export → JSON, then paste here. " +
"Cookies captured from prod ('.example.com') are auto-rewritten to match the tunnel host."),
signupEmail: z
.string()
.email()
.optional()
.describe("signup: base email (e.g. 'you@yourdomain.com'). Each persona registers with a unique " +
"'you+<base36ts><rand>@yourdomain.com' alias derived from this. Use Gmail, Fastmail, or any " +
"domain that supports plus-addressing."),
signupPassword: z
.string()
.min(1)
.max(256)
.optional()
.describe("signup: shared password for every persona's form. Omit to have the runtime mint random per-persona passwords."),
startUrl: z
.string()
.url()
.optional()
.describe("Where to land AFTER auth. Strongly recommended for cookie_injection (point at the dashboard URL). " +
"For agent_login it overrides the default post-login redirect; for signup it can pre-navigate to the form."),
})
.optional()
.describe("Auth setup if the test needs a signed-in user. Three modes — cookie_injection (paste cookies, skip login), " +
"agent_login (existing account), signup (test the sign-up flow). " +
"WARNING: credentials/cookies transit the Useswarm relay over HTTPS. Use test-only accounts, never production secrets."),
}, async (params) => {
try {
let targetUrl = params.targetUrl;
// Normalize URLs without protocol
if (!targetUrl.startsWith("http")) {
targetUrl = `http://${targetUrl}`;
}
// Warn (don't block) if another test is already in flight; the API
// is happy to run multiple but the agent often forgets.
if (activeBatchId) {
console.error(`[useswarm-mcp] Note: previous batch ${activeBatchId} is still tracked locally. ` +
`Starting a new one — call dev_watch on the new batchId, not the old one.`);
}
let tunnelNote = "";
// Validate backendPaths — must start with /, no bare "/" to prevent routing all traffic
// Validate backendPaths — must start with /, no bare "/"
if (params.backendPaths) {

@@ -90,3 +275,9 @@ for (const p of params.backendPaths) {

return {
content: [{ type: "text", text: `Error: Invalid backendPath "${p}". Each path must start with "/" and be at least 2 characters (e.g. "/ws", "/v1"). Bare "/" is not allowed.` }],
content: [
{
type: "text",
text: `Error: Invalid backendPath "${p}". Each path must start with "/" and be at least 2 chars ` +
`(e.g. "/ws", "/v1"). Bare "/" is rejected because it would route ALL traffic to the backend.`,
},
],
isError: true,

@@ -105,3 +296,3 @@ };

catch {
// Will try cloudflare without ngrok fallback
// Fall back to Cloudflare only — same behaviour as before.
}

@@ -121,3 +312,5 @@ const tunnelOpts = {

const defaultPaths = ["/api", "/auth", "/graphql", "/trpc"];
const allPaths = params.backendPaths ? [...params.backendPaths, ...defaultPaths] : defaultPaths;
const allPaths = params.backendPaths
? [...params.backendPaths, ...defaultPaths]
: defaultPaths;
tunnelNote += ` with reverse proxy (frontend: ${targetUrl}, backend: ${params.backendUrl}, routes: ${allPaths.join(", ")})`;

@@ -133,12 +326,47 @@ }

}
// Build the test request
// Persona source: saved swarm or generate-on-the-fly. The API requires
// exactly one of swarmId vs generatePersonas; enforce that here so the
// calling agent gets an actionable error instead of an opaque 400.
if (params.swarmId && (params.userDescription || params.agentCount)) {
return {
content: [
{
type: "text",
text: "Error: pass either `swarmId` (use a saved swarm) OR `userDescription`+`agentCount` (generate new personas), not both. " +
"If you want to test against your saved swarm, omit userDescription and agentCount — the swarm's personas and count are used.",
},
],
isError: true,
};
}
if (!params.swarmId && !params.userDescription) {
return {
content: [
{
type: "text",
text: "Error: either `swarmId` or `userDescription` is required. " +
"Provide a swarmId to reuse a saved persona set (call dev_list_swarms to discover IDs), or a userDescription to generate fresh personas.",
},
],
isError: true,
};
}
const body = {
targetUrl,
goal: params.goal,
userDescription: params.userDescription,
generatePersonas: {
};
if (params.swarmId) {
body.swarmId = params.swarmId;
// userDescription is required by the API even with swarmId — pass a
// placeholder derived from the goal so the audit log has something
// human-readable. The API doesn't use it for persona generation.
body.userDescription = `Saved swarm ${params.swarmId}`;
}
else {
body.userDescription = params.userDescription;
body.generatePersonas = {
agentCount: params.agentCount ?? 3,
audienceDescription: params.userDescription,
},
};
};
}
if (params.maxSteps)

@@ -150,10 +378,6 @@ body.maxSteps = params.maxSteps;

body.model = params.model;
// H-7: Warn about credential exposure through relay
if (params.auth) {
console.error("[useswarm-mcp] Warning: Auth credentials/cookies will pass through the relay server. Use test-only accounts.");
}
// Forward auth, infer mode if not provided, and tunnel any localhost URLs inside it.
if (params.auth) {
const auth = { ...params.auth };
// Infer mode from which fields are provided when caller didn't set it explicitly.
// Infer mode from fields if not explicit.
if (!auth.mode) {

@@ -167,10 +391,35 @@ if (auth.cookies && auth.cookies.length > 0)

}
// Validate mode-specific requirements early so the caller gets a clear error.
if (auth.mode === "cookie_injection") {
if (!auth.cookies || auth.cookies.length === 0) {
return {
content: [{ type: "text", text: "Error: cookie_injection mode requires a non-empty `auth.cookies` array." }],
content: [
{
type: "text",
text: "Error: cookie_injection mode requires a non-empty `auth.cookies` array. " +
"Tip: capture cookies with the Cookie-Editor browser extension (Export → JSON) and paste them here.",
},
],
isError: true,
};
}
// Sanity-check each cookie: minimum fields must be non-empty strings.
for (const [i, c] of auth.cookies.entries()) {
if (!c.name || !c.value || !c.domain) {
return {
content: [
{
type: "text",
text: `Error: cookie #${i} is missing one of name/value/domain. ` +
`Got: ${JSON.stringify({ name: c.name, hasValue: !!c.value, domain: c.domain })}.`,
},
],
isError: true,
};
}
}
if (!auth.startUrl) {
console.error("[useswarm-mcp] Warning: cookie_injection without `auth.startUrl`. The agent will land on " +
"targetUrl (often the login page) and may not know it's already authenticated. " +
"Recommended: set startUrl to the post-login destination (e.g. '/dashboard').");
}
}

@@ -180,3 +429,8 @@ else if (auth.mode === "signup") {

return {
content: [{ type: "text", text: "Error: signup mode requires `auth.signupEmail` (a base email — each persona gets a unique +<hash> alias)." }],
content: [
{
type: "text",
text: "Error: signup mode requires `auth.signupEmail` (a base email — each persona gets a unique +<hash> sub-alias).",
},
],
isError: true,

@@ -188,3 +442,9 @@ };

return {
content: [{ type: "text", text: "Error: agent_login mode requires `auth.username` and `auth.password`." }],
content: [
{
type: "text",
text: "Error: agent_login mode requires `auth.username` and `auth.password`. " +
"Use a test-only account. If you have an active session instead, switch to cookie_injection mode.",
},
],
isError: true,

@@ -205,5 +465,6 @@ };

const data = await api.post("/api/cli/tests", body);
activeBatchId = data.batchId ?? data.id ?? null;
activeBatchId =
data.batchId ?? data.id ?? null;
lastTestStartedAt = new Date();
const appUrl = process.env.USESWARM_APP_URL ?? "https://useswarm.co";
const appUrl = process.env.USESWARM_APP_URL ?? "https://www.useswarm.co";
const resultsUrl = `${appUrl}/dashboard/home/results/${activeBatchId}`;

@@ -219,3 +480,4 @@ const response = {

startedAt: lastTestStartedAt.toISOString(),
nextStep: `Call dev_watch with batchId "${activeBatchId}" to poll for results. The test typically takes 1-3 minutes. View live: ${resultsUrl}`,
nextStep: `Call dev_watch with batchId "${activeBatchId}" to poll for results. ` +
`Tests typically take 1-3 minutes. View live: ${resultsUrl}`,
},

@@ -226,23 +488,39 @@ };

catch (err) {
const message = err instanceof Error ? err.message : String(err);
return { content: [{ type: "text", text: `Error starting dev test: ${message}` }], isError: true };
return {
content: [{ type: "text", text: `Error starting dev test: ${explainApiError(err)}` }],
isError: true,
};
}
});
// ─── dev_watch: poll until test completes, return structured results ────
server.tool("dev_watch", `Poll a batch test until it completes, then return structured results.
Returns the test status, per-agent results, synthesis report, and a list
of actionable issues found. Use this after dev_test to get the results.
The response includes:
- status: "running" | "completed" | "failed"
- issues: array of { severity, category, description, persona } objects
- synthesis: overall report text
- agentResults: per-agent pass/fail and thoughts
If still running, returns partial progress. Call again to check.`, {
batchId: z.string().describe("Batch test ID from dev_test"),
wait: z.boolean().optional().describe("If true, poll up to 3 minutes waiting for completion (default true)"),
// ─── dev_watch ───────────────────────────────────────────────────
server.tool("dev_watch", [
"Wait for a UX test to finish, then return structured findings the agent can act on.",
"",
"WHEN TO CALL:",
" Right after dev_test (with the returned batchId). This is the 'wait for results' step.",
" Also use to re-check a test that was still running on the last call.",
"",
"WHAT IT DOES:",
" Polls the Useswarm API every 5s (up to 3 minutes by default), then closes the tunnel and returns",
" the synthesized findings. Each finding has severity, title, description, persona attribution,",
" and a recommendation — so the agent can decide what to fix.",
"",
"RETURNS: { status, issues: Ticket[], recommendedActions, judgeVerdict, agentResults, synthesis, _devLoop: { nextStep } }",
" - issues[] is the prioritized ticket list with concrete UX problems found.",
" - recommendedActions[] is the LLM judge's concrete fix suggestions.",
" - Empty issues + status 'completed' = the flow worked, no problems found.",
"",
"If the test is still running after the wait window, returns { status: 'still_running' } so you can call again.",
].join("\n"), {
batchId: z
.string()
.describe("Batch ID returned by dev_test. If you've lost it, look at the dashboardUrl from the previous dev_test response."),
wait: z
.boolean()
.optional()
.describe("true (default): poll up to 3 minutes for completion. " +
"false: return immediately with current status — useful for quick checks."),
}, async (params) => {
try {
const maxWaitMs = (params.wait ?? true) ? 180_000 : 0; // 3 minutes max
const maxWaitMs = (params.wait ?? true) ? 180_000 : 0;
const pollIntervalMs = 5_000;

@@ -260,5 +538,5 @@ const startTime = Date.now();

if (elapsed >= maxWaitMs) {
// Return partial results
return {
content: [{
content: [
{
type: "text",

@@ -269,14 +547,20 @@ text: JSON.stringify({

batchId: params.batchId,
progress: {
completedRuns: data.completedRuns,
totalRuns: data.totalRuns,
failedRuns: data.failedRuns,
},
partialData: data,
hint: "Call dev_watch again to continue polling, or call get_test_status for a quick check.",
hint: "Test is still running. Call dev_watch again with the same batchId to keep waiting, " +
"or open dashboardUrl in a browser for live progress.",
}, null, 2),
}],
},
],
};
}
// Wait before next poll
await new Promise((r) => setTimeout(r, pollIntervalMs));
}
// Extract structured issues from the results
const issues = extractIssues(data);
// Tear down the tunnel — agents are done, no longer needed
const recommendedActions = extractRecommendedActions(data);
// Tear down the tunnel — agents are done.
const tunnelWasClosed = !!activeTunnelUrl;

@@ -290,8 +574,30 @@ const previousTunnelUrl = activeTunnelUrl;

lastTestStartedAt = null;
const judge = data.judge;
const synthesis = data.synthesis;
const nextStep = issues.length > 0
? `Found ${issues.length} issue(s). Read 'issues' and 'recommendedActions' below, fix the code, ` +
`then call dev_test again to verify the fixes.`
: (data.status === "completed"
? "All agents completed successfully — no UX issues surfaced. The flow is working as expected."
: `Run finished with status "${data.status}". Inspect 'agentResults' for per-persona failure reasons.`);
const response = {
status: data.status,
batchId: params.batchId,
overallUxScore: data.overallUxScore ?? null,
issueCount: issues.length,
issues,
issueCount: issues.length,
synthesis: data.synthesis ?? data.report ?? null,
recommendedActions,
judgeVerdict: judge
? {
verdict: judge.verdict ?? null,
confidence: judge.confidence ?? null,
evidenceBlocks: judge.evidenceBlocks ?? null,
}
: null,
synthesis: synthesis
? {
executiveSummary: synthesis.executiveSummary ?? null,
positives: synthesis.positives ?? null,
}
: null,
agentResults: summarizeAgentResults(data),

@@ -301,6 +607,3 @@ _devLoop: {

previousTunnelUrl,
localUrl: activeTargetUrl,
nextStep: issues.length > 0
? `Found ${issues.length} issue(s). Fix the code and call dev_test again to verify the fixes.`
: "All agents completed successfully! No issues found. The user flow is working as expected.",
nextStep,
},

@@ -311,12 +614,52 @@ };

catch (err) {
const message = err instanceof Error ? err.message : String(err);
return { content: [{ type: "text", text: `Error watching test: ${message}` }], isError: true };
return {
content: [{ type: "text", text: `Error watching test: ${explainApiError(err)}` }],
isError: true,
};
}
});
// ─── dev_status: quick health check ────────────────────────────
server.tool("dev_status", `Check the current dev loop status — tunnel health, active test, and connection info.
Use this to verify everything is set up before running dev_test, or to
troubleshoot if a test isn't working.`, {}, async () => {
// ─── dev_status ──────────────────────────────────────────────────
server.tool("dev_status", [
"Diagnose the local MCP setup: auth state, active tunnel, and any running test.",
"",
"WHEN TO CALL:",
" - Before dev_test if you're unsure whether auth is configured.",
" - After any tool error, to see whether the API is reachable and the key is valid.",
" - As a first 'is this thing on?' check.",
"",
"RETURNS: { auth: { configured, valid, apiUrl }, tunnel: { active, url, reachable }, activeTest }",
" Use this to decide whether to ask the user to run `useswarm-mcp login`, install cloudflared, etc.",
].join("\n"), {}, async () => {
try {
const stored = loadStoredConfig();
const apiKeyConfigured = !!stored.apiKey || !!process.env.USESWARM_API_KEY;
const apiUrl = stored.apiUrl ?? process.env.USESWARM_API_URL ?? "https://api.useswarm.co";
// Probe the API to see whether the key is actually valid.
let apiKeyValid = null;
let apiKeyError;
if (apiKeyConfigured) {
try {
// /api/cli/swarms is auth-gated and returns 200 with an empty list
// even for a brand-new account, so it's a safe liveness probe.
await api.get("/api/cli/swarms");
apiKeyValid = true;
}
catch (err) {
apiKeyValid = false;
apiKeyError = err instanceof Error ? err.message : String(err);
}
}
const status = {
auth: {
configured: apiKeyConfigured,
valid: apiKeyValid,
apiUrl,
keyHint: stored.apiKey ? `...${stored.apiKey.slice(-4)}` : null,
error: apiKeyError ?? null,
recovery: !apiKeyConfigured
? "Run `npx @useswarm/mcp login` to authenticate."
: apiKeyValid === false
? "Stored API key was rejected. Run `npx @useswarm/mcp login` to refresh."
: null,
},
tunnel: {

@@ -333,3 +676,2 @@ active: !!activeTunnelUrl,

};
// Check if tunnel URL is actually reachable
if (activeTunnelUrl) {

@@ -355,3 +697,2 @@ try {

}
// Check latest test status if we have one
if (activeBatchId) {

@@ -366,3 +707,3 @@ try {

catch {
// Test might not exist anymore
// Test might not exist anymore — leave the field as-is.
}

@@ -373,8 +714,17 @@ }

catch (err) {
const message = err instanceof Error ? err.message : String(err);
return { content: [{ type: "text", text: `Error checking status: ${message}` }], isError: true };
return {
content: [{ type: "text", text: `Error checking status: ${explainApiError(err)}` }],
isError: true,
};
}
});
// ─── dev_close: tear down tunnel ───────────────────────────────
server.tool("dev_close", "Close the active cloudflared tunnel and clean up. Use when done testing.", {}, async () => {
// ─── dev_close ───────────────────────────────────────────────────
server.tool("dev_close", [
"Tear down the active tunnel and reverse proxy.",
"",
"WHEN TO CALL:",
" - You're done testing and want to free local resources.",
" - A previous test got stuck and you want a clean slate before dev_test again.",
" - dev_watch already auto-closes on completion — only call dev_close if you skipped dev_watch.",
].join("\n"), {}, async () => {
try {

@@ -389,19 +739,46 @@ await closeTunnel();

return {
content: [{
content: [
{
type: "text",
text: JSON.stringify({ closed: true, previousTunnel: prev }, null, 2),
}],
},
],
};
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
return { content: [{ type: "text", text: `Error closing tunnel: ${message}` }], isError: true };
return {
content: [{ type: "text", text: `Error closing tunnel: ${explainApiError(err)}` }],
isError: true,
};
}
});
}
/**
* Walk the API response and pull out the structured ticket list the synthesis
* pipeline produces. Falls back to per-run failure reasons so we still surface
* something even when synthesis isn't ready yet.
*/
function extractIssues(data) {
const issues = [];
// Extract from synthesis/report if present
const synthesis = data.synthesis;
if (synthesis) {
// PRIMARY SOURCE: synthesis.tickets[] — what the API actually returns.
const tickets = synthesis?.tickets;
if (Array.isArray(tickets)) {
for (const t of tickets) {
issues.push({
severity: normalizeSeverity(t.severity),
title: t.title ?? "Untitled issue",
description: t.description ?? "",
recommendation: t.recommendation,
effortSize: t.effortSize,
agentCount: t.agentCount,
totalAgents: t.totalAgents,
userImpact: t.userImpact,
dropOffRisk: t.dropOffRisk,
flaggedBy: t.flaggedBy,
});
}
}
// FALLBACK: legacy synthesis shapes from older API versions.
if (synthesis && issues.length === 0) {
const findings = (synthesis.findings ?? synthesis.issues ?? synthesis.problems);

@@ -412,5 +789,8 @@ if (Array.isArray(findings)) {

severity: normalizeSeverity(f.severity),
category: f.category ?? "ux",
description: f.description ?? f.message ?? f.text ?? JSON.stringify(f),
persona: f.persona,
title: f.title ?? "",
description: f.description ??
f.message ??
f.text ??
JSON.stringify(f),
recommendation: f.recommendation,
});

@@ -420,39 +800,24 @@ }

}
// Extract from individual runs
const runs = (data.runs ?? data.testRuns ?? data.agentRuns);
if (Array.isArray(runs)) {
for (const run of runs) {
const status = run.status;
const verdict = run.verdict;
// If an agent failed or gave a negative verdict, that's an issue
if (status === "failed" || verdict === "fail" || verdict === "negative") {
const persona = run.persona;
const personaName = persona?.name ?? run.personaName ?? "Unknown agent";
const reason = run.failureReason ?? run.verdictReason ?? run.error;
if (reason && !issues.some((i) => i.description === reason)) {
issues.push({
severity: status === "failed" ? "critical" : "high",
category: "user-flow",
description: reason,
persona: personaName,
});
}
}
// Check thoughts for friction/issues
const thoughts = (run.thoughts ?? run.agentThoughts);
if (Array.isArray(thoughts)) {
for (const thought of thoughts) {
const friction = thought.friction;
const issue = thought.issue;
if (friction || issue) {
const desc = friction ?? issue;
if (!issues.some((i) => i.description === desc)) {
issues.push({
severity: "medium",
category: "friction",
description: desc,
persona: run.persona?.name,
step: thought.step,
});
}
// FALLBACK: per-run failure reasons, when no synthesis exists at all
// (e.g. test failed before synthesis ran).
if (issues.length === 0) {
const runs = (data.runs ?? data.testRuns ?? data.agentRuns);
if (Array.isArray(runs)) {
for (const run of runs) {
const status = run.status;
const verdict = run.verdict;
if (status === "failed" || verdict === "fail" || verdict === "negative") {
const persona = run.persona;
const personaName = persona?.name ?? run.personaName ?? "Unknown agent";
const reason = run.failureReason ??
run.verdictReason ??
run.error;
if (reason && !issues.some((i) => i.description === reason)) {
issues.push({
severity: status === "failed" ? "critical" : "high",
title: `${personaName} could not complete the goal`,
description: reason,
category: "user-flow",
flaggedBy: [{ personaName, personaIndex: -1 }],
});
}

@@ -463,3 +828,2 @@ }

}
// Sort by severity
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };

@@ -469,2 +833,11 @@ issues.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));

}
/**
* Pull the judge's recommendedActions[] up to the top level so the host agent
* gets concrete "do X" fix suggestions, not just symptom descriptions.
*/
function extractRecommendedActions(data) {
const judge = data.judge;
const actions = judge?.recommendedActions;
return Array.isArray(actions) ? actions : [];
}
function normalizeSeverity(s) {

@@ -491,5 +864,6 @@ if (!s)

status: run.status,
uxScore: run.uxScore ?? null,
verdict: run.verdict ?? null,
verdictReason: run.verdictReason ?? run.failureReason ?? null,
stepsCompleted: run.stepsCompleted ?? run.stepCount ?? null,
stepsCompleted: run.stepsCompleted ?? run.stepsTaken ?? run.stepCount ?? null,
};

@@ -496,0 +870,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"file":"dev-loop.js","sourceRoot":"","sources":["../../src/tools/dev-loop.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"dev-loop.js","sourceRoot":"","sources":["../../src/tools/dev-loop.ts"],"names":[],"mappings":"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"}
{
"name": "@useswarm/mcp",
"version": "2.1.2",
"version": "2.3.0",
"description": "Automated UX testing loop for local dev. Tunnel via cloudflared, run AI agent swarms, get structured issues, fix and repeat.",

@@ -13,8 +13,2 @@ "type": "module",

],
"scripts": {
"dev": "tsx watch src/cli.ts",
"start": "node dist/cli.js",
"build": "tsc",
"start:relay": "tsx src/relay/index.ts"
},
"dependencies": {

@@ -36,3 +30,9 @@ "@modelcontextprotocol/sdk": "^1.12.1",

"typescript": "^5.7.0"
},
"scripts": {
"dev": "tsx watch src/cli.ts",
"start": "node dist/cli.js",
"build": "tsc",
"start:relay": "tsx src/relay/index.ts"
}
}
}
+73
-24

@@ -19,12 +19,23 @@ # @useswarm/mcp

One command adds Useswarm MCP to Claude Code and auto-logs you in on first use:
One command registers the MCP with Claude Code + Codex CLI **and** signs you in:
```bash
npx @useswarm/mcp setup
npx @useswarm/mcp@latest setup
```
After that, ask Claude to test your app:
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 run `setup` or `login` again.
## Updating
```bash
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.
## Installation

@@ -34,19 +45,34 @@

No installation needed:
```bash
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)
```
### Option B: Global install (stable path, easy upgrades)
```bash
npx @useswarm/mcp setup
npm install -g @useswarm/mcp
useswarm-mcp setup
# upgrade later:
npm update -g @useswarm/mcp
# no re-setup needed — the global path is stable
```
### Option B: Manual setup
### Option C: Manual setup
```bash
# 1. Log in (creates an MCP API key, stores at ~/.useswarm/config.json)
# 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
# 2. Add to Claude Code
claude mcp add useswarm -- npx @useswarm/mcp serve
```
### Option C: From source (contributors)
### Option D: From source (contributors)

@@ -56,7 +82,8 @@ ```bash

pnpm install
cp .env.example .env
# Edit .env with USESWARM_API_KEY
pnpm dev
pnpm build
node dist/cli.js setup --client codex # or --client claude
```
See [CODEX_TESTING.md](./CODEX_TESTING.md) for the local-build iteration loop.
## CLI commands

@@ -66,10 +93,11 @@

|---------|-------------|
| `useswarm-mcp setup` | Add to Claude Code and auto-login on first use |
| `useswarm-mcp login` | Open browser to log in, store API key in `~/.useswarm/config.json` |
| `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 API key |
| `useswarm-mcp serve` | Start MCP server (stdio transport, default) |
| `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 |
| `useswarm-mcp serve --api-key KEY` | Override stored API key for this process |
| `useswarm-mcp serve --api-url URL` | Override API base URL |

@@ -79,4 +107,12 @@

The server exposes four tools that form a test-fix-retest loop:
The server exposes five tools that form a test-fix-retest loop:
### `dev_list_swarms`
List 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_test`

@@ -90,4 +126,5 @@

| `goal` | Yes | What agents should accomplish (e.g. "complete the signup flow") |
| `userDescription` | Yes | Target audience (e.g. "first-time SaaS users") |
| `agentCount` | No | Number of AI personas (1–20, default 3) |
| `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 |

@@ -102,2 +139,4 @@ | `backendPaths` | No | Extra path prefixes for backend routing (e.g. `["/ws", "/v1"]`) |

> Use dev_list_swarms, then dev_test on http://localhost:3000 with goal "complete checkout" using my "B2B Buyers" swarm.
### `dev_watch`

@@ -230,2 +269,12 @@

### Codex CLI
```bash
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](./CODEX_TESTING.md).
### Cursor

@@ -318,3 +367,3 @@

| `USESWARM_SESSION_TOKEN` | — | Session token (alternative to API key) |
| `USESWARM_APP_URL` | `https://useswarm.co` | Web app URL (login flow) |
| `USESWARM_APP_URL` | `https://www.useswarm.co` | Web app URL (login flow + dashboard links) |
| `MCP_PORT` | `3100` | HTTP transport port |

@@ -405,5 +454,5 @@ | `MCP_TUNNEL` | `false` | Enable tunnel to relay |

|---|---|
| Web app | https://useswarm.co |
| Web app | https://www.useswarm.co |
| API | https://api.useswarm.co |
| MCP relay | https://mcp.useswarm.co |
| Docs | https://docs.useswarm.co |