e2e-ai 1.4.2 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -598,6 +598,16 @@ If e2e-ai is installed globally or as a project dependency, you can use the bina
598
598
 
599
599
  ### Available Tools
600
600
 
601
+ #### Orchestration (workflow automation)
602
+
603
+ | Tool | Description | Input |
604
+ |------|-------------|-------|
605
+ | `e2e_ai_plan_workflow` | Plan an automation workflow — returns an ordered todo list of steps | `goal`, `key?`, `from?`, `skip?`, `voice?`, `trace?`, `scanDir?` |
606
+ | `e2e_ai_execute_step` | Execute a single pipeline step | `step`, `key?`, `voice?`, `trace?`, `scanDir?`, `output?`, `extraArgs?` |
607
+ | `e2e_ai_get_workflow_guide` | Get the full workflow guide explaining how the pipeline works | (none) |
608
+
609
+ #### Project setup
610
+
601
611
  | Tool | Description | Input |
602
612
  |------|-------------|-------|
603
613
  | `e2e_ai_scan_codebase` | Scan project for test files, configs, fixtures, path aliases, and sample test content | `projectRoot?` (defaults to cwd) |
@@ -605,16 +615,35 @@ If e2e-ai is installed globally or as a project dependency, you can use the bina
605
615
  | `e2e_ai_read_agent` | Load an agent prompt by name — returns system prompt + config | `agentName` (e.g. `scenario-agent`) |
606
616
  | `e2e_ai_get_example` | Get the example context markdown template | (none) |
607
617
 
608
- ### Usage with AI Assistants
609
-
610
- Once configured, an AI assistant can:
611
-
612
- 1. **Scan your project** to understand its test structure, fixtures, and conventions
613
- 2. **Read agent prompts** to understand how each pipeline step works
614
- 3. **Validate context files** to ensure they have the right format before running commands
615
- 4. **Get the example template** as a starting point for writing `e2e-ai.context.md`
616
-
617
- This enables AI assistants to help you set up e2e-ai, debug pipeline issues, and generate better project context files.
618
+ ### How AI Orchestration Works
619
+
620
+ The MCP server includes built-in orchestration instructions that teach AI assistants (Claude Code, Cursor, etc.) how to run e2e-ai workflows autonomously. The protocol is:
621
+
622
+ 1. **Plan** The AI calls `e2e_ai_plan_workflow` with your goal. It returns an ordered step list.
623
+ 2. **Approve** The AI presents the plan to you for review. You can adjust steps before proceeding.
624
+ 3. **Execute** The AI runs each step one at a time via `e2e_ai_execute_step`, reporting results between steps. If a step fails, it stops and asks you how to proceed.
625
+
626
+ Each step is executed as a separate job (ideally a subagent) to keep context clean. The AI never runs multiple pipeline steps at once.
627
+
628
+ **Example interaction:**
629
+
630
+ > **You:** "Run the full test pipeline for PROJ-101"
631
+ >
632
+ > **AI:** *Calls `e2e_ai_plan_workflow`*, then presents:
633
+ > 1. `record` — Launch browser codegen + voice recording
634
+ > 2. `transcribe` — Transcribe voice via Whisper
635
+ > 3. `scenario` — Generate YAML test scenario
636
+ > 4. `generate` — Generate Playwright test
637
+ > 5. `refine` — Refactor test with AI
638
+ > 6. `test` — Run Playwright test
639
+ > 7. `heal` — Self-heal if failing (can skip if test passes)
640
+ > 8. `qa` — Generate QA documentation
641
+ >
642
+ > "Does this look right? Ready to start?"
643
+ >
644
+ > **You:** "Skip voice, go ahead"
645
+ >
646
+ > **AI:** *Removes transcribe, executes each step sequentially*
618
647
 
619
648
  ## Library API
620
649
 
package/dist/mcp.js CHANGED
@@ -14856,8 +14856,9 @@ class StdioServerTransport {
14856
14856
  }
14857
14857
 
14858
14858
  // src/mcp.ts
14859
- import { readFileSync as readFileSync2 } from "node:fs";
14859
+ import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
14860
14860
  import { join as join2 } from "node:path";
14861
+ import { execSync } from "node:child_process";
14861
14862
 
14862
14863
  // src/utils/scan.ts
14863
14864
  import { readdirSync, existsSync, readFileSync } from "node:fs";
@@ -14957,13 +14958,281 @@ function validateContext(content) {
14957
14958
  }
14958
14959
 
14959
14960
  // src/mcp.ts
14960
- var server = new McpServer({
14961
- name: "e2e-ai",
14962
- version: "1.1.2"
14963
- });
14961
+ var SERVER_INSTRUCTIONS = `
14962
+ # e2e-ai — Orchestration Guide
14963
+
14964
+ You have access to e2e-ai, an AI-powered E2E test automation tool. Follow this protocol when the user asks you to perform any e2e-ai automation.
14965
+
14966
+ ## Core Principle: Plan → Approve → Execute Step-by-Step
14967
+
14968
+ NEVER run multiple pipeline steps at once. Each step is a separate job with its own context.
14969
+
14970
+ ## Protocol
14971
+
14972
+ 1. **Plan first.** Call \`e2e_ai_plan_workflow\` with the user's goal. This returns a structured todo list of steps.
14973
+ 2. **Present the plan.** Show the user the ordered step list with descriptions. Ask for confirmation or adjustments before proceeding.
14974
+ 3. **Execute one step at a time.** For each step in the approved plan:
14975
+ a. Tell the user which step you're about to run and why.
14976
+ b. Call \`e2e_ai_execute_step\` with the step name and parameters.
14977
+ c. Report the result to the user (success, key output, any warnings).
14978
+ d. If the step fails, stop and discuss with the user before continuing.
14979
+ e. Move to the next step only after the current one succeeds.
14980
+ 4. **Use subagents when available.** If your AI platform supports subagents (e.g., Claude Code Agent tool), dispatch each step as a dedicated subagent to preserve context. Each subagent should:
14981
+ - Receive only the context it needs (step name, key, relevant file paths)
14982
+ - Call \`e2e_ai_execute_step\` to do its work
14983
+ - Return the result to the orchestrator
14984
+
14985
+ ## Step Dependencies
14986
+
14987
+ Steps produce artifacts that feed into later steps. The pipeline handles this automatically — each step picks up where the previous one left off. Do not skip steps unless the plan says a step can be skipped.
14988
+
14989
+ ## Interactive Steps
14990
+
14991
+ The \`record\` step opens a browser and requires user interaction. When the plan includes \`record\`:
14992
+ - Tell the user they need to interact with the browser window
14993
+ - The step will block until they close the codegen window
14994
+ - After recording completes, proceed with the next step
14995
+
14996
+ ## When Things Fail
14997
+
14998
+ - If \`test\` fails and \`heal\` is in the plan, that's expected — heal will attempt to fix it
14999
+ - If \`heal\` exhausts all retries, stop and show the user the last error output
15000
+ - For any other failure, stop and ask the user how to proceed
15001
+
15002
+ ## Available Workflows
15003
+
15004
+ - **Full test pipeline**: record → transcribe → scenario → generate → refine → test → heal → qa
15005
+ - **From existing recording**: transcribe → scenario → generate → refine → test → heal → qa
15006
+ - **AI-only (no recording)**: scenario → generate → refine → test → heal → qa
15007
+ - **Generate from scenario**: generate → refine → test → heal → qa
15008
+ - **Test + heal loop**: test → heal
15009
+ - **Scanner pipeline**: scan → analyze → push
15010
+ - **Single step**: any individual command
15011
+
15012
+ Always use \`e2e_ai_plan_workflow\` to determine the right steps — don't guess.
15013
+ `.trim();
15014
+ var TEST_PIPELINE_STEPS = [
15015
+ {
15016
+ name: "record",
15017
+ description: "Launch Playwright codegen in the browser. Optionally records voice narration for richer test scenarios.",
15018
+ produces: "codegen .ts file + optional .wav voice recording",
15019
+ requires: "none",
15020
+ interactive: true
15021
+ },
15022
+ {
15023
+ name: "transcribe",
15024
+ description: "Transcribe the voice recording via OpenAI Whisper. Merges timestamped voice comments into the codegen file.",
15025
+ produces: "transcript JSON + annotated codegen file",
15026
+ requires: "voice recording from record step",
15027
+ interactive: false,
15028
+ canSkip: "No voice recording exists or voice is disabled"
15029
+ },
15030
+ {
15031
+ name: "scenario",
15032
+ description: "AI analyzes the codegen + transcript and generates a structured YAML test scenario with semantic steps and expected results.",
15033
+ produces: "YAML test scenario file",
15034
+ requires: "codegen file (+ optional transcript)",
15035
+ interactive: false
15036
+ },
15037
+ {
15038
+ name: "generate",
15039
+ description: "AI converts the YAML scenario into a complete Playwright .test.ts file using project conventions from context.md.",
15040
+ produces: "Playwright .test.ts file",
15041
+ requires: "YAML scenario file",
15042
+ interactive: false
15043
+ },
15044
+ {
15045
+ name: "refine",
15046
+ description: "AI refactors the test: replaces raw selectors with semantic alternatives, adds proper timeouts, uses project helpers.",
15047
+ produces: "improved .test.ts file (in-place)",
15048
+ requires: "Playwright .test.ts file",
15049
+ interactive: false
15050
+ },
15051
+ {
15052
+ name: "test",
15053
+ description: "Run the Playwright test with trace/video/screenshot capture. Reports pass/fail status.",
15054
+ produces: "test results + trace files",
15055
+ requires: "Playwright .test.ts file",
15056
+ interactive: false
15057
+ },
15058
+ {
15059
+ name: "heal",
15060
+ description: "If the test failed, AI diagnoses the failure and patches the test. Retries up to 3 times with different strategies.",
15061
+ produces: "patched .test.ts file (if test was failing)",
15062
+ requires: "failing test + error output",
15063
+ interactive: false,
15064
+ canSkip: "Test already passes"
15065
+ },
15066
+ {
15067
+ name: "qa",
15068
+ description: "Generate formal QA documentation: markdown test case with preconditions, steps table, and optional Zephyr XML export.",
15069
+ produces: "QA markdown + optional Zephyr XML",
15070
+ requires: "Playwright .test.ts file + scenario",
15071
+ interactive: false
15072
+ }
15073
+ ];
15074
+ var SCANNER_PIPELINE_STEPS = [
15075
+ {
15076
+ name: "scan",
15077
+ description: "Scan the codebase AST: extract routes, components, hooks, imports, and dependency graph.",
15078
+ produces: "ast-scan.json with full codebase structure",
15079
+ requires: "none",
15080
+ interactive: false
15081
+ },
15082
+ {
15083
+ name: "analyze",
15084
+ description: "AI analyzes the AST scan to identify features, workflows, components, and generate test scenarios.",
15085
+ produces: "qa-map.json with features, workflows, scenarios",
15086
+ requires: "ast-scan.json from scan step",
15087
+ interactive: false
15088
+ },
15089
+ {
15090
+ name: "push",
15091
+ description: "Push the QA map to a remote API endpoint for integration with external tools.",
15092
+ produces: "push confirmation with version info",
15093
+ requires: "qa-map.json from analyze step + API config",
15094
+ interactive: false
15095
+ }
15096
+ ];
15097
+ var ALL_STEPS = [...TEST_PIPELINE_STEPS, ...SCANNER_PIPELINE_STEPS];
15098
+ function planWorkflow(goal, options) {
15099
+ const goalLower = goal.toLowerCase();
15100
+ const notes = [];
15101
+ const isScannerGoal = /\b(scan|analyze|qa.?map|feature.?analy|push.?qa|codebase.?scan)\b/.test(goalLower);
15102
+ const isSingleStep = ALL_STEPS.some((s) => goalLower === s.name || goalLower === `run ${s.name}`);
15103
+ let stepDefs;
15104
+ if (isScannerGoal && !isSingleStep) {
15105
+ stepDefs = [...SCANNER_PIPELINE_STEPS];
15106
+ if (!/\bpush\b/.test(goalLower)) {
15107
+ stepDefs = stepDefs.filter((s) => s.name !== "push");
15108
+ notes.push("Push step excluded — add it if you want to upload the QA map to a remote API.");
15109
+ }
15110
+ } else if (isSingleStep) {
15111
+ const stepName = ALL_STEPS.find((s) => goalLower.includes(s.name)).name;
15112
+ stepDefs = ALL_STEPS.filter((s) => s.name === stepName);
15113
+ } else {
15114
+ stepDefs = [...TEST_PIPELINE_STEPS];
15115
+ if (options.from) {
15116
+ const fromIdx = stepDefs.findIndex((s) => s.name === options.from);
15117
+ if (fromIdx > 0) {
15118
+ const skipped = stepDefs.slice(0, fromIdx).map((s) => s.name);
15119
+ stepDefs = stepDefs.slice(fromIdx);
15120
+ notes.push(`Starting from "${options.from}" — skipping: ${skipped.join(", ")}`);
15121
+ }
15122
+ } else {
15123
+ if (/\b(from recording|existing recording|already recorded)\b/.test(goalLower)) {
15124
+ stepDefs = stepDefs.filter((s) => s.name !== "record");
15125
+ notes.push("Skipping record — using existing recording files.");
15126
+ }
15127
+ if (/\b(from scenario|existing scenario|manual scenario|yaml)\b/.test(goalLower)) {
15128
+ stepDefs = stepDefs.filter((s) => !["record", "transcribe", "scenario"].includes(s.name));
15129
+ notes.push("Starting from generate — using existing scenario YAML.");
15130
+ }
15131
+ if (/\b(generate.?only|just.?generate|no.?record)\b/.test(goalLower)) {
15132
+ stepDefs = stepDefs.filter((s) => !["record", "transcribe"].includes(s.name));
15133
+ }
15134
+ if (/\b(test.?and.?heal|test.?heal|heal.?loop|fix.?test|self.?heal)\b/.test(goalLower)) {
15135
+ stepDefs = stepDefs.filter((s) => ["test", "heal"].includes(s.name));
15136
+ }
15137
+ if (/\b(refine|refactor)\b/.test(goalLower) && !/\brun\b/.test(goalLower)) {
15138
+ stepDefs = stepDefs.filter((s) => s.name === "refine");
15139
+ }
15140
+ if (/\bqa\b/.test(goalLower) && /\b(doc|only|generate)\b/.test(goalLower)) {
15141
+ stepDefs = stepDefs.filter((s) => s.name === "qa");
15142
+ }
15143
+ }
15144
+ }
15145
+ if (options.skip?.length) {
15146
+ stepDefs = stepDefs.filter((s) => !options.skip.includes(s.name));
15147
+ notes.push(`Skipping: ${options.skip.join(", ")}`);
15148
+ }
15149
+ if (options.voice === false) {
15150
+ stepDefs = stepDefs.filter((s) => s.name !== "transcribe");
15151
+ notes.push("Voice disabled — transcribe step removed.");
15152
+ }
15153
+ const cliBase = "e2e-ai";
15154
+ const steps = stepDefs.map((s, i) => {
15155
+ const args = [s.name];
15156
+ if (options.key && !["scan", "analyze", "push"].includes(s.name)) {
15157
+ args.push("--key", options.key);
15158
+ }
15159
+ if (s.name === "record") {
15160
+ if (options.voice === false)
15161
+ args.push("--no-voice");
15162
+ if (options.trace === false)
15163
+ args.push("--no-trace");
15164
+ }
15165
+ if (s.name === "scan" && options.scanDir) {
15166
+ args.push("--scan-dir", options.scanDir);
15167
+ }
15168
+ return {
15169
+ order: i + 1,
15170
+ name: s.name,
15171
+ description: s.description,
15172
+ command: `${cliBase} ${args.join(" ")}`,
15173
+ produces: s.produces,
15174
+ interactive: s.interactive,
15175
+ canSkip: s.canSkip
15176
+ };
15177
+ });
15178
+ const pipeline2 = isScannerGoal ? "scanner" : isSingleStep ? "single" : "test";
15179
+ if (!options.key && pipeline2 === "test" && steps.length > 1) {
15180
+ notes.push("No --key provided. Use --key <ISSUE-KEY> to organize files by issue.");
15181
+ }
15182
+ return { goal, pipeline: pipeline2, steps, notes };
15183
+ }
15184
+ function executeStep(stepName, options) {
15185
+ const args = [stepName];
15186
+ if (options.key && !["scan", "analyze", "push"].includes(stepName)) {
15187
+ args.push("--key", options.key);
15188
+ }
15189
+ if (stepName === "record") {
15190
+ if (options.voice === false)
15191
+ args.push("--no-voice");
15192
+ if (options.trace === false)
15193
+ args.push("--no-trace");
15194
+ }
15195
+ if (stepName === "scan" && options.scanDir) {
15196
+ args.push("--scan-dir", options.scanDir);
15197
+ }
15198
+ if (options.output) {
15199
+ args.push("--output", options.output);
15200
+ }
15201
+ if (options.extraArgs?.length) {
15202
+ args.push(...options.extraArgs);
15203
+ }
15204
+ const pkgRoot = getPackageRoot();
15205
+ const cliBin = join2(pkgRoot, "dist", "cli.js");
15206
+ const command = `node ${cliBin} ${args.join(" ")}`;
15207
+ try {
15208
+ const stdout = execSync(command, {
15209
+ cwd: process.cwd(),
15210
+ encoding: "utf-8",
15211
+ timeout: 300000,
15212
+ env: { ...process.env },
15213
+ stdio: ["pipe", "pipe", "pipe"]
15214
+ });
15215
+ return { success: true, output: stdout, command };
15216
+ } catch (err) {
15217
+ const stderr = err.stderr?.toString() ?? "";
15218
+ const stdout = err.stdout?.toString() ?? "";
15219
+ return {
15220
+ success: false,
15221
+ output: `EXIT CODE: ${err.status ?? "unknown"}
15222
+
15223
+ STDOUT:
15224
+ ${stdout}
15225
+
15226
+ STDERR:
15227
+ ${stderr}`,
15228
+ command
15229
+ };
15230
+ }
15231
+ }
15232
+ var server = new McpServer({ name: "e2e-ai", version: "1.2.0" }, { instructions: SERVER_INSTRUCTIONS });
14964
15233
  server.registerTool("e2e_ai_scan_codebase", {
14965
15234
  title: "Scan Codebase",
14966
- description: "Scan a project directory for test files, configs, fixtures, path aliases, and sample test content",
15235
+ description: "Scan a project directory for test files, configs, fixtures, path aliases, and sample test content. Use this during project setup or to understand test infrastructure.",
14967
15236
  inputSchema: exports_external.object({
14968
15237
  projectRoot: exports_external.string().optional().describe("Project root directory (defaults to cwd)")
14969
15238
  })
@@ -14976,7 +15245,7 @@ server.registerTool("e2e_ai_scan_codebase", {
14976
15245
  });
14977
15246
  server.registerTool("e2e_ai_validate_context", {
14978
15247
  title: "Validate Context",
14979
- description: "Validate that a context markdown file contains all required sections",
15248
+ description: "Validate that a context markdown file contains all required sections (Application, Test Infrastructure, Feature Methods, Import Conventions, Selector Conventions, Test Structure Template, Utility Patterns).",
14980
15249
  inputSchema: exports_external.object({
14981
15250
  content: exports_external.string().describe("The markdown content of the context file to validate")
14982
15251
  })
@@ -14988,7 +15257,7 @@ server.registerTool("e2e_ai_validate_context", {
14988
15257
  });
14989
15258
  server.registerTool("e2e_ai_read_agent", {
14990
15259
  title: "Read Agent",
14991
- description: "Read an agent prompt definition by name. Returns the agent name, system prompt, and config (model, max_tokens, temperature).",
15260
+ description: "Read an agent prompt definition by name. Returns the agent system prompt and config. Agents: transcript-agent, scenario-agent, playwright-generator-agent, refactor-agent, self-healing-agent, qa-testcase-agent, feature-analyzer-agent, scenario-planner-agent, init-agent.",
14992
15261
  inputSchema: exports_external.object({
14993
15262
  agentName: exports_external.string().describe("Agent name (e.g. scenario-agent, playwright-generator-agent)")
14994
15263
  })
@@ -15014,7 +15283,7 @@ server.registerTool("e2e_ai_read_agent", {
15014
15283
  });
15015
15284
  server.registerTool("e2e_ai_get_example", {
15016
15285
  title: "Get Example Context",
15017
- description: "Returns the full example context markdown file that shows the expected format for .e2e-ai/context.md",
15286
+ description: "Returns the full example context markdown file that shows the expected format for .e2e-ai/context.md.",
15018
15287
  inputSchema: exports_external.object({})
15019
15288
  }, async () => {
15020
15289
  try {
@@ -15030,6 +15299,87 @@ server.registerTool("e2e_ai_get_example", {
15030
15299
  };
15031
15300
  }
15032
15301
  });
15302
+ server.registerTool("e2e_ai_plan_workflow", {
15303
+ title: "Plan Workflow",
15304
+ description: "Plan an e2e-ai automation workflow. Call this FIRST when the user asks to run any automation. " + "Returns an ordered list of steps (todo list) that should be executed one at a time. " + "Present the plan to the user for approval before executing any step.",
15305
+ inputSchema: exports_external.object({
15306
+ goal: exports_external.string().describe('What the user wants to achieve. Examples: "run full pipeline for PROJ-101", ' + '"generate test from existing recording", "scan codebase and analyze features", ' + '"heal failing test PROJ-101", "refactor test PROJ-101"'),
15307
+ key: exports_external.string().optional().describe("Issue key (e.g. PROJ-101, LIN-42)"),
15308
+ from: exports_external.string().optional().describe("Start from a specific step (skip all prior steps)"),
15309
+ skip: exports_external.array(exports_external.string()).optional().describe('Steps to skip (e.g. ["transcribe", "heal"])'),
15310
+ voice: exports_external.boolean().optional().describe("Enable voice recording (default: true)"),
15311
+ trace: exports_external.boolean().optional().describe("Enable trace capture (default: true)"),
15312
+ scanDir: exports_external.string().optional().describe("Directory to scan (for scanner pipeline)")
15313
+ })
15314
+ }, async ({ goal, key, from, skip, voice, trace, scanDir }) => {
15315
+ const plan = planWorkflow(goal, { key, from, skip, voice, trace, scanDir });
15316
+ return {
15317
+ content: [{
15318
+ type: "text",
15319
+ text: JSON.stringify(plan, null, 2)
15320
+ }]
15321
+ };
15322
+ });
15323
+ server.registerTool("e2e_ai_execute_step", {
15324
+ title: "Execute Pipeline Step",
15325
+ description: "Execute a single e2e-ai pipeline step. Call this ONE STEP AT A TIME from an approved plan. " + "Each step produces artifacts consumed by later steps. " + "If your AI platform supports subagents, run each step in a dedicated subagent to preserve context. " + 'The "record" step is interactive and will open a browser window — the user must interact with it.',
15326
+ inputSchema: exports_external.object({
15327
+ step: exports_external.string().describe("Step name: record, transcribe, scenario, generate, refine, test, heal, qa, scan, analyze, push"),
15328
+ key: exports_external.string().optional().describe("Issue key (e.g. PROJ-101)"),
15329
+ voice: exports_external.boolean().optional().describe("Enable voice recording (record step only)"),
15330
+ trace: exports_external.boolean().optional().describe("Enable trace capture (record step only)"),
15331
+ scanDir: exports_external.string().optional().describe("Directory to scan (scan step only)"),
15332
+ output: exports_external.string().optional().describe("Custom output path (scan/analyze steps)"),
15333
+ extraArgs: exports_external.array(exports_external.string()).optional().describe("Additional CLI arguments")
15334
+ })
15335
+ }, async ({ step, key, voice, trace, scanDir, output, extraArgs }) => {
15336
+ const validSteps = ALL_STEPS.map((s) => s.name);
15337
+ if (!validSteps.includes(step)) {
15338
+ return {
15339
+ content: [{
15340
+ type: "text",
15341
+ text: `Error: Unknown step "${step}". Valid steps: ${validSteps.join(", ")}`
15342
+ }],
15343
+ isError: true
15344
+ };
15345
+ }
15346
+ const result = executeStep(step, { key, voice, trace, scanDir, output, extraArgs });
15347
+ return {
15348
+ content: [{
15349
+ type: "text",
15350
+ text: JSON.stringify({
15351
+ step,
15352
+ success: result.success,
15353
+ command: result.command,
15354
+ output: result.output
15355
+ }, null, 2)
15356
+ }]
15357
+ };
15358
+ });
15359
+ server.registerTool("e2e_ai_get_workflow_guide", {
15360
+ title: "Get Workflow Guide",
15361
+ description: "Returns the e2e-ai workflow guide explaining how the pipeline works, step by step. Useful for understanding what each step does and how they connect.",
15362
+ inputSchema: exports_external.object({})
15363
+ }, async () => {
15364
+ try {
15365
+ const guidePath = join2(getPackageRoot(), "templates", "workflow.md");
15366
+ if (!existsSync2(guidePath)) {
15367
+ return {
15368
+ content: [{ type: "text", text: "Error: workflow.md not found in templates" }],
15369
+ isError: true
15370
+ };
15371
+ }
15372
+ const content = readFileSync2(guidePath, "utf-8");
15373
+ return {
15374
+ content: [{ type: "text", text: content }]
15375
+ };
15376
+ } catch (err) {
15377
+ return {
15378
+ content: [{ type: "text", text: `Error: ${err.message}` }],
15379
+ isError: true
15380
+ };
15381
+ }
15382
+ });
15033
15383
  async function main() {
15034
15384
  const transport = new StdioServerTransport;
15035
15385
  await server.connect(transport);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "e2e-ai",
3
3
  "description": "AI-powered test automation pipeline — record, transcribe, generate, heal and ship Playwright tests from a single CLI",
4
- "version": "1.4.2",
4
+ "version": "1.4.3",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "bin": {
@@ -14,6 +14,10 @@ record → transcribe → scenario → generate → refine → test → heal →
14
14
 
15
15
  **In short:** You record yourself testing in the browser (optionally narrating what you're doing), and e2e-ai turns that into a production-ready Playwright test with QA documentation.
16
16
 
17
+ **Two ways to run it:**
18
+ - **CLI**: Run commands directly (`e2e-ai run --key PROJ-101`)
19
+ - **AI assistant**: Ask your AI tool (Claude Code, Cursor, etc.) — the MCP server guides it through the pipeline step by step, asking for your approval before starting
20
+
17
21
  ---
18
22
 
19
23
  ## Setup
@@ -198,6 +202,27 @@ This is independent from the test pipeline — use it to get an overview of your
198
202
 
199
203
  ---
200
204
 
205
+ ## AI-Assisted Workflow (MCP)
206
+
207
+ If you have the e2e-ai MCP server configured, you can ask your AI assistant to run the pipeline for you. The MCP server teaches the AI how to orchestrate the workflow:
208
+
209
+ 1. **You say:** "Run the full test pipeline for PROJ-101" (or any variation)
210
+ 2. **AI plans:** Calls `e2e_ai_plan_workflow` → gets an ordered step list
211
+ 3. **AI shows plan:** Presents the steps and asks for your approval
212
+ 4. **You adjust:** "Skip voice" / "Start from generate" / "Looks good, go"
213
+ 5. **AI executes:** Runs each step one at a time via `e2e_ai_execute_step`, reporting results between steps
214
+
215
+ Each step runs as a separate subagent (when supported by the AI platform) to keep context clean and focused. If a step fails, the AI stops and asks you what to do.
216
+
217
+ **Example prompts you can give your AI assistant:**
218
+ - "Run the full pipeline for PROJ-101"
219
+ - "Generate a test from the existing recording for PROJ-101, skip voice"
220
+ - "Just run test and heal for PROJ-101"
221
+ - "Scan the codebase and analyze features"
222
+ - "Refactor the test for PROJ-101"
223
+
224
+ ---
225
+
201
226
  ## File Structure
202
227
 
203
228
  After running the pipeline for `PROJ-101`: