@useswarm/mcp
Advanced tools
| /** | ||
| * 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; |
+95
-164
| /** | ||
| * 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">✓</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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); | ||
| } | ||
| 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":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAe,MAAM,MAAM,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAW,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAO7B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAQvD,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAA6B;IAC5D,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAGrC;IACC,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,OAAO,IAAI,OAAO,CAAc,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QAC5D,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,MAAc,CAAC;QAEnB,0BAA0B;QAC1B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM,EAAE,KAAK,EAAE,CAAC;gBAChB,WAAW,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAElB,mEAAmE;QACnE,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACjC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAExD,4CAA4C;YAC5C,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBAC7D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;oBACjB,6BAA6B,EAAE,GAAG;oBAClC,8BAA8B,EAAE,MAAM;oBACtC,8BAA8B,EAAE,cAAc;iBAC/C,CAAC,CAAC;gBACH,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC5E,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;oBACzD,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;oBACjB,IAAI,OAA6D,CAAC;oBAClE,IAAI,CAAC;wBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7B,CAAC;oBAAC,MAAM,CAAC;wBACP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;wBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;wBACxD,OAAO;oBACT,CAAC;oBAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;oBAEjE,IAAI,KAAK,EAAE,CAAC;wBACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;wBAC/F,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;wBACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;4BACd,QAAQ,GAAG,IAAI,CAAC;4BAChB,YAAY,CAAC,OAAO,CAAC,CAAC;4BACtB,MAAM,CAAC,KAAK,EAAE,CAAC;4BACf,WAAW,CAAC,IAAI,KAAK,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC,CAAC;wBACnD,CAAC;wBACD,OAAO;oBACT,CAAC;oBAED,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;wBAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;wBAC/F,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC,CAAC,CAAC;wBAC5E,OAAO;oBACT,CAAC;oBAED,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;wBAC/F,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC;wBAC1D,OAAO;oBACT,CAAC;oBAED,UAAU;oBACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;oBAC/F,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;oBAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACd,QAAQ,GAAG,IAAI,CAAC;wBAChB,YAAY,CAAC,OAAO,CAAC,CAAC;wBACtB,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,gBAAgB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;wBAClD,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;oBAChD,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,wBAAwB;QACxB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,WAAW,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;gBAC1D,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,oBAAoB,IAAI,CAAC,IAAI,WAAW,CAAC;YAC7D,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,sBAAsB,kBAAkB,CAAC,WAAW,CAAC,UAAU,KAAK,EAAE,CAAC;YAEtG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,0CAA0C,QAAQ,IAAI,CAAC,CAAC;YAEtE,sEAAsE;YACtE,IAAI,CAAC;gBACH,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;gBAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ;oBAC1C,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;wBAC5B,CAAC,CAAC,OAAO;wBACT,CAAC,CAAC,UAAU,CAAC;gBACjB,UAAU,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YAC9E,CAAC;YAAC,MAAM,CAAC;gBACP,wDAAwD;YAC1D,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;;QAiBD,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO;;;;;;;;;;;;SAYA,UAAU,CAAC,KAAK,CAAC;;;;QAIlB,CAAC;AACT,CAAC"} | ||
| {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"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"} |
+8
-4
@@ -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 {}; |
+130
-49
@@ -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
@@ -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":"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"} |
| 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"; |
+541
-167
| /** | ||
| * 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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"} |
+8
-8
| { | ||
| "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 | |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
260004
16.54%41
7.89%3360
18.64%449
12.25%31
24%13
8.33%