qaa-agent 1.8.0 → 1.8.1

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/.mcp.json CHANGED
@@ -3,6 +3,10 @@
3
3
  "playwright": {
4
4
  "command": "npx",
5
5
  "args": ["@playwright/mcp@latest"]
6
+ },
7
+ "context7": {
8
+ "command": "npx",
9
+ "args": ["-y", "@upstash/context7-mcp@latest"]
6
10
  }
7
11
  }
8
12
  }
package/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
 
4
4
  All notable changes to QAA (QA Automation Agent) are documented here.
5
5
 
6
+ ## [1.8.1] - 2026-04-16
7
+
8
+ ### Added
9
+
10
+ - **Context7 MCP integration** — `@upstash/context7-mcp` is now bundled alongside Playwright MCP. The installer registers both MCP servers in the user-scope config (`~/.claude.json`) so they're available in every project on the machine, not just in the QAA repo. Context7 gives every QAA agent on-demand access to up-to-date library documentation (Playwright, Cypress, Jest, Vitest, pytest, and any other framework), keeping generated tests aligned with current APIs instead of outdated training data.
11
+ - **`bin/install.cjs` installer script** — the file was referenced in `package.json` but didn't actually exist on npm, causing `npx qaa-agent` to fail silently (`No bin file found at bin/install.cjs`). The installer now performs three steps on every run: (1) copies agents, commands, skills, templates, workflows, docs, and config files into the chosen scope (`~/.claude/qaa` for global, `./.claude/qaa` for local), (2) registers both MCP servers in `~/.claude.json` with idempotency — existing entries are not duplicated, and (3) deep-merges the QAA permissions into the user's `settings.json` without overwriting their existing settings.
12
+
13
+ ### Changed
14
+
15
+ - **MCP registration is now user-scope by default** — previously MCPs were defined only in the project-level `.mcp.json`, which meant they only activated when the user opened the QAA repo itself. They now register in `~/.claude.json`, making them available in every Claude Code project on the user's machine. The project-level `.mcp.json` is kept for QAA development purposes but is no longer the source of truth for end users.
16
+
17
+ ### Fixed
18
+
19
+ - **Silent `npx qaa-agent` failure** — users who installed QAA via npm before this release did not get Playwright or Context7 MCPs registered because the installer script was missing from the published package. Publishing 1.8.1 restores the expected behavior: a single `npx qaa-agent` command copies all files and registers both MCPs globally.
20
+
6
21
  ## [1.8.0] - 2026-04-13
7
22
 
8
23
  ### Added
package/README.md CHANGED
@@ -43,7 +43,9 @@ npx qaa-agent
43
43
  The interactive installer:
44
44
 
45
45
  1. Copies agents, commands, skills, templates, and workflows into your runtime directory
46
- 2. Configures the [Playwright MCP](https://www.npmjs.com/package/@playwright/mcp) server in your user-scope config (`~/.claude.json`) so it's available in **all projects**
46
+ 2. Registers **two MCP servers** in your user-scope config (`~/.claude.json`) so they're available in **all projects**:
47
+ - [Playwright MCP](https://www.npmjs.com/package/@playwright/mcp) — live browser control for E2E tests and locator extraction
48
+ - [Context7 MCP](https://www.npmjs.com/package/@upstash/context7-mcp) — up-to-date library documentation on demand
47
49
  3. Merges required permissions into `settings.json`
48
50
 
49
51
  **Supported runtimes:** Claude Code, OpenCode
@@ -55,48 +57,34 @@ The interactive installer:
55
57
  - [Node.js](https://nodejs.org/) 18+
56
58
  - [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed
57
59
 
58
- ### Playwright MCP (required for E2E)
60
+ ### Bundled MCP servers
59
61
 
60
- QAA uses [`@playwright/mcp`](https://www.npmjs.com/package/@playwright/mcp) to open a real browser, extract locators from live pages, run E2E tests, and auto-fix locator mismatches.
62
+ Both MCP servers are **registered automatically** in `~/.claude.json` when you run `npx qaa-agent`. No manual setup required — once installed, they're available in every Claude Code project on your machine.
61
63
 
62
- **You need to install the Playwright MCP server manually in your environment:**
64
+ #### Playwright MCP live browser control
63
65
 
64
- <details>
65
- <summary><strong>VS Code (Claude Code extension)</strong></summary>
66
+ Uses [`@playwright/mcp`](https://www.npmjs.com/package/@playwright/mcp) to:
66
67
 
67
- 1. Open VS Code Settings (`Ctrl+Shift+P` > `Preferences: Open User Settings (JSON)`)
68
- 2. Add the MCP server config:
68
+ - Open a real browser and navigate your running app
69
+ - Extract actual locators (`data-testid`, ARIA roles, labels) from live pages
70
+ - Run E2E tests, capture failures, and auto-fix locator mismatches
71
+ - Build a persistent **Locator Registry** (`.qa-output/locators/`) that caches real locators across features
69
72
 
70
- ```json
71
- {
72
- "claude-code.mcpServers": {
73
- "playwright": {
74
- "command": "npx",
75
- "args": ["@playwright/mcp@latest"]
76
- }
77
- }
78
- }
79
- ```
73
+ #### Context7 MCP — up-to-date library docs
80
74
 
81
- Or add it to your project's `.vscode/mcp.json`:
75
+ Uses [`@upstash/context7-mcp`](https://www.npmjs.com/package/@upstash/context7-mcp) to:
82
76
 
83
- ```json
84
- {
85
- "servers": {
86
- "playwright": {
87
- "command": "npx",
88
- "args": ["@playwright/mcp@latest"]
89
- }
90
- }
91
- }
92
- ```
77
+ - Fetch the latest documentation for Playwright, Cypress, Jest, Vitest, pytest, and any other library the agent is working with
78
+ - Keep generated tests aligned with current framework APIs instead of outdated training data
79
+ - Free tier: ~60 requests/hour, ~3,300 tokens/query
93
80
 
94
- </details>
81
+ #### Verifying the MCPs are connected
95
82
 
96
- <details>
97
- <summary><strong>Claude Code CLI</strong></summary>
83
+ Open Claude Code in any project and type `/mcp`. You should see both `playwright` and `context7` listed as connected.
98
84
 
99
- Add to `~/.claude.json` (user-scope, all projects):
85
+ #### Manual config (fallback)
86
+
87
+ If for any reason the automatic registration fails, you can add the servers manually to `~/.claude.json`:
100
88
 
101
89
  ```json
102
90
  {
@@ -104,21 +92,15 @@ Add to `~/.claude.json` (user-scope, all projects):
104
92
  "playwright": {
105
93
  "command": "npx",
106
94
  "args": ["@playwright/mcp@latest"]
95
+ },
96
+ "context7": {
97
+ "command": "npx",
98
+ "args": ["-y", "@upstash/context7-mcp@latest"]
107
99
  }
108
100
  }
109
101
  }
110
102
  ```
111
103
 
112
- Or add a `.mcp.json` file in your project root for project-scope only.
113
-
114
- </details>
115
-
116
- Once configured, Playwright MCP enables QAA to:
117
- - Open a real browser and navigate your running app
118
- - Extract actual locators (`data-testid`, ARIA roles, labels) from live pages
119
- - Run E2E tests, capture failures, and auto-fix locator mismatches
120
- - Build a persistent **Locator Registry** (`.qa-output/locators/`) that caches real locators across features
121
-
122
104
  ---
123
105
 
124
106
  ## Quick Start
@@ -328,7 +310,7 @@ qaa-agent/
328
310
  bin/ # Installer and CLI tools
329
311
  docs/ # User documentation
330
312
  CLAUDE.md # QA standards (read by every agent)
331
- .mcp.json # Playwright MCP server config
313
+ .mcp.json # Playwright + Context7 MCP server config
332
314
  settings.json # Claude Code permissions
333
315
  ```
334
316
 
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * QAA Agent Installer
5
+ *
6
+ * Installs QAA (QA Automation Agent) into the user's Claude Code environment.
7
+ *
8
+ * What it does:
9
+ * 1. Copies agents, commands, skills, templates, workflows, docs, bin, and config files
10
+ * to the chosen install directory (global ~/.claude/qaa or local ./.claude/qaa)
11
+ * 2. Registers Playwright MCP and Context7 MCP as global MCP servers
12
+ * 3. Merges required permissions into Claude Code settings.json
13
+ *
14
+ * Usage:
15
+ * npx qaa-agent
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const readline = require('readline');
21
+ const { execSync } = require('child_process');
22
+
23
+ // ── Helpers ──────────────────────────────────────────────────────────────────
24
+
25
+ function log(msg) { console.log(` ${msg}`); }
26
+ function success(msg) { console.log(` ✓ ${msg}`); }
27
+ function warn(msg) { console.log(` ⚠ ${msg}`); }
28
+ function fail(msg) { console.error(` ✗ ${msg}`); }
29
+
30
+ function ask(question) {
31
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
32
+ return new Promise(resolve => {
33
+ rl.question(` ${question} `, answer => {
34
+ rl.close();
35
+ resolve(answer.trim());
36
+ });
37
+ });
38
+ }
39
+
40
+ function copyDirRecursive(src, dest) {
41
+ if (!fs.existsSync(src)) return 0;
42
+ fs.mkdirSync(dest, { recursive: true });
43
+ let count = 0;
44
+ const entries = fs.readdirSync(src, { withFileTypes: true });
45
+ for (const entry of entries) {
46
+ const srcPath = path.join(src, entry.name);
47
+ const destPath = path.join(dest, entry.name);
48
+ if (entry.isDirectory()) {
49
+ count += copyDirRecursive(srcPath, destPath);
50
+ } else {
51
+ fs.copyFileSync(srcPath, destPath);
52
+ count++;
53
+ }
54
+ }
55
+ return count;
56
+ }
57
+
58
+ function deepMerge(target, source) {
59
+ for (const key of Object.keys(source)) {
60
+ if (
61
+ source[key] && typeof source[key] === 'object' && !Array.isArray(source[key]) &&
62
+ target[key] && typeof target[key] === 'object' && !Array.isArray(target[key])
63
+ ) {
64
+ deepMerge(target[key], source[key]);
65
+ } else if (Array.isArray(source[key]) && Array.isArray(target[key])) {
66
+ // Merge arrays without duplicates
67
+ const merged = [...new Set([...target[key], ...source[key]])];
68
+ target[key] = merged;
69
+ } else {
70
+ target[key] = source[key];
71
+ }
72
+ }
73
+ return target;
74
+ }
75
+
76
+ // ── MCP Registration ─────────────────────────────────────────────────────────
77
+
78
+ function registerMcpServers(claudeJsonPath) {
79
+ const mcpServers = {
80
+ playwright: {
81
+ command: 'npx',
82
+ args: ['@playwright/mcp@latest']
83
+ },
84
+ context7: {
85
+ command: 'npx',
86
+ args: ['-y', '@upstash/context7-mcp@latest']
87
+ }
88
+ };
89
+
90
+ let config = {};
91
+ if (fs.existsSync(claudeJsonPath)) {
92
+ try {
93
+ config = JSON.parse(fs.readFileSync(claudeJsonPath, 'utf-8'));
94
+ } catch {
95
+ config = {};
96
+ }
97
+ }
98
+
99
+ if (!config.mcpServers) config.mcpServers = {};
100
+
101
+ let added = [];
102
+ for (const [name, serverConfig] of Object.entries(mcpServers)) {
103
+ if (!config.mcpServers[name]) {
104
+ config.mcpServers[name] = serverConfig;
105
+ added.push(name);
106
+ }
107
+ }
108
+
109
+ fs.writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2) + '\n');
110
+ return added;
111
+ }
112
+
113
+ // ── Settings Merge ───────────────────────────────────────────────────────────
114
+
115
+ function mergeSettings(installDir, packageDir) {
116
+ const srcSettings = path.join(packageDir, 'settings.json');
117
+ if (!fs.existsSync(srcSettings)) return false;
118
+
119
+ const claudeDir = path.dirname(installDir);
120
+ const destSettings = path.join(claudeDir, 'settings.json');
121
+
122
+ const source = JSON.parse(fs.readFileSync(srcSettings, 'utf-8'));
123
+
124
+ let target = {};
125
+ if (fs.existsSync(destSettings)) {
126
+ try {
127
+ target = JSON.parse(fs.readFileSync(destSettings, 'utf-8'));
128
+ } catch {
129
+ target = {};
130
+ }
131
+ }
132
+
133
+ deepMerge(target, source);
134
+ fs.writeFileSync(destSettings, JSON.stringify(target, null, 2) + '\n');
135
+ return true;
136
+ }
137
+
138
+ // ── Main ─────────────────────────────────────────────────────────────────────
139
+
140
+ async function main() {
141
+ console.log('');
142
+ console.log(' ╔═══════════════════════════════════════╗');
143
+ console.log(' ║ QAA — QA Automation Agent Installer ║');
144
+ console.log(' ╚═══════════════════════════════════════╝');
145
+ console.log('');
146
+
147
+ // Determine package root (where the npm package files are)
148
+ const packageDir = path.resolve(__dirname, '..');
149
+
150
+ // Check that package files exist
151
+ const requiredDirs = ['agents', 'commands', 'skills'];
152
+ const missing = requiredDirs.filter(d => !fs.existsSync(path.join(packageDir, d)));
153
+ if (missing.length > 0) {
154
+ fail(`Package incomplete — missing: ${missing.join(', ')}`);
155
+ process.exit(1);
156
+ }
157
+
158
+ // Ask install scope
159
+ console.log(' Install scope:');
160
+ console.log(' 1) Global — ~/.claude/qaa (available in all projects)');
161
+ console.log(' 2) Local — ./.claude/qaa (this project only)');
162
+ console.log('');
163
+ const scopeChoice = await ask('Choose [1/2] (default: 1):');
164
+ const isGlobal = scopeChoice !== '2';
165
+
166
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
167
+ const claudeDir = isGlobal
168
+ ? path.join(homeDir, '.claude')
169
+ : path.join(process.cwd(), '.claude');
170
+ const installDir = path.join(claudeDir, 'qaa');
171
+
172
+ // Check for existing installation
173
+ if (fs.existsSync(installDir)) {
174
+ const overwrite = await ask('QAA already installed at this location. Overwrite? [y/N]:');
175
+ if (overwrite.toLowerCase() !== 'y') {
176
+ log('Installation cancelled.');
177
+ process.exit(0);
178
+ }
179
+ }
180
+
181
+ console.log('');
182
+ log(`Installing to: ${installDir}`);
183
+ console.log('');
184
+
185
+ // ── Step 1: Copy files ──────────────────────────────────────────────────
186
+
187
+ const dirsToCopy = ['agents', 'commands', 'skills', 'templates', 'workflows', 'docs', 'bin'];
188
+ const filesToCopy = ['CLAUDE.md', 'CHANGELOG.md', '.mcp.json', 'package.json'];
189
+
190
+ let totalFiles = 0;
191
+
192
+ for (const dir of dirsToCopy) {
193
+ const src = path.join(packageDir, dir);
194
+ const dest = path.join(installDir, dir);
195
+ if (fs.existsSync(src)) {
196
+ const count = copyDirRecursive(src, dest);
197
+ success(`${dir}/ — ${count} files`);
198
+ totalFiles += count;
199
+ }
200
+ }
201
+
202
+ for (const file of filesToCopy) {
203
+ const src = path.join(packageDir, file);
204
+ const dest = path.join(installDir, file);
205
+ if (fs.existsSync(src)) {
206
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
207
+ fs.copyFileSync(src, dest);
208
+ success(file);
209
+ totalFiles++;
210
+ }
211
+ }
212
+
213
+ console.log('');
214
+
215
+ // ── Step 2: Register MCP servers ────────────────────────────────────────
216
+
217
+ const claudeJsonPath = path.join(homeDir, '.claude.json');
218
+ const addedMcps = registerMcpServers(claudeJsonPath);
219
+
220
+ if (addedMcps.length > 0) {
221
+ success(`MCP servers registered: ${addedMcps.join(', ')} → ${claudeJsonPath}`);
222
+ } else {
223
+ success('MCP servers already configured (playwright, context7)');
224
+ }
225
+
226
+ // ── Step 3: Merge settings ──────────────────────────────────────────────
227
+
228
+ const settingsMerged = mergeSettings(installDir, packageDir);
229
+ if (settingsMerged) {
230
+ success('Permissions merged into settings.json');
231
+ }
232
+
233
+ // ── Done ────────────────────────────────────────────────────────────────
234
+
235
+ console.log('');
236
+ console.log(' ╔═══════════════════════════════════════╗');
237
+ console.log(' ║ Installation complete! ║');
238
+ console.log(' ╚═══════════════════════════════════════╝');
239
+ console.log('');
240
+ log(`${totalFiles} files installed to ${installDir}`);
241
+ log('MCP servers: playwright, context7');
242
+ log('');
243
+ log('Restart Claude Code, then run any QAA command:');
244
+ log(' /qa-start --dev-repo ./your-project');
245
+ log(' /qa-create-test login');
246
+ log(' /qa-map');
247
+ console.log('');
248
+ }
249
+
250
+ main().catch(err => {
251
+ fail(err.message);
252
+ process.exit(1);
253
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qaa-agent",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "QA Automation Agent for Claude Code — multi-agent pipeline that analyzes repos, generates tests, validates, and creates PRs",
5
5
  "bin": {
6
6
  "qaa-agent": "./bin/install.cjs"
@@ -22,7 +22,8 @@
22
22
  "author": "Backhaus7997",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@playwright/mcp": "latest"
25
+ "@playwright/mcp": "latest",
26
+ "@upstash/context7-mcp": "latest"
26
27
  },
27
28
  "files": [
28
29
  "bin/",