genat-mcp 1.2.3 → 1.2.5
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 +16 -2
- package/index.js +2 -2
- package/package.json +2 -2
- package/run-genat.mjs +114 -0
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ npm install /path/to/n8n_playwright_tests/mcp-genat
|
|
|
32
32
|
|
|
33
33
|
| Variable | Required | Default | Description |
|
|
34
34
|
|--------------------|----------|---------|-------------|
|
|
35
|
-
| **N8N_WEBHOOK_URL** | No | `http://localhost:5678/webhook-test/webhook-genat` | n8n GenAT webhook URL. Set this if your n8n instance is elsewhere (e.g. `https://your-n8n-host/webhook-test/webhook-genat`). |
|
|
35
|
+
| **N8N_WEBHOOK_URL** | No | `http://localhost:5678/webhook-test/webhook-genat-login` | n8n GenAT webhook URL. Set this if your n8n instance is elsewhere (e.g. `https://your-n8n-host/webhook-test/webhook-genat-login`). |
|
|
36
36
|
| **N8N_INSECURE_TLS** | No | (off) | Set to `1`, `true`, or `yes` to skip TLS certificate verification for HTTPS webhooks. Use only for dev/internal n8n with self-signed or internal CA certs (e.g. K8s). Not recommended for production. |
|
|
37
37
|
| **SERVICE_BASE_URL** | No | (none) | Base URL for DOM Analyzer and Accessibility Analyzer (e.g. `http://host.docker.internal` or `http://your-tunnel.ngrok.io`). Required when n8n runs on a remote host (K8s) so the workflow can reach the services. The workflow appends `:3456/analyze-dom` and `:3458/analyze-accessibility`. |
|
|
38
38
|
|
|
@@ -68,9 +68,23 @@ If the global binary is not on PATH, use the full path, e.g. `node $(npm root -g
|
|
|
68
68
|
## Requirements
|
|
69
69
|
|
|
70
70
|
- **Node.js** 20+
|
|
71
|
-
- **n8n** with the [GenAT workflow](../workflows/genat-accessibility-tests.json) imported and activated (webhook path `webhook-test/webhook-genat`)
|
|
71
|
+
- **n8n** with the [GenAT workflow](../workflows/genat-accessibility-tests-with-login.json) imported and activated (webhook path `webhook-test/webhook-genat-login`)
|
|
72
72
|
- **DOM Analyzer** and **Accessibility Analyzer** services running (see main README: `npm run services` from repo root)
|
|
73
73
|
|
|
74
|
+
## Standalone script: run-genat.mjs
|
|
75
|
+
|
|
76
|
+
When the MCP fails (e.g. TLS/connection issues), use the standalone script:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# From a project that has genat-mcp installed
|
|
80
|
+
N8N_WEBHOOK_URL='https://your-n8n/webhook-test/webhook-genat-login' N8N_INSECURE_TLS=1 node node_modules/genat-mcp/run-genat.mjs https://example.com .
|
|
81
|
+
|
|
82
|
+
# Or from mcp-genat directory
|
|
83
|
+
N8N_WEBHOOK_URL='https://your-n8n/webhook-test/webhook-genat-login' N8N_INSECURE_TLS=1 node run-genat.mjs https://example.com /path/to/project
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Important:** Use `webhook-genat-login` (not `webhook-genat`). Import and activate [genat-accessibility-tests-with-login.json](../workflows/genat-accessibility-tests-with-login.json) in n8n.
|
|
87
|
+
|
|
74
88
|
## Tool: GenAT
|
|
75
89
|
|
|
76
90
|
- **url** (string): Page URL to analyze for accessibility.
|
package/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { detectFramework } from './detect-framework.js';
|
|
|
12
12
|
import { detectLogin } from './detect-login.js';
|
|
13
13
|
import { writeGeneratedFiles } from './write-files.js';
|
|
14
14
|
|
|
15
|
-
const N8N_WEBHOOK_URL = process.env.N8N_WEBHOOK_URL || 'http://localhost:5678/webhook-test/webhook-genat';
|
|
15
|
+
const N8N_WEBHOOK_URL = process.env.N8N_WEBHOOK_URL || 'http://localhost:5678/webhook-test/webhook-genat-login';
|
|
16
16
|
const SERVICE_BASE_URL = process.env.SERVICE_BASE_URL || null;
|
|
17
17
|
const N8N_INSECURE_TLS = /^1|true|yes$/i.test(process.env.N8N_INSECURE_TLS || '');
|
|
18
18
|
|
|
@@ -51,7 +51,7 @@ function insecureHttpsFetch(url, { method = 'GET', headers = {}, body }) {
|
|
|
51
51
|
const server = new McpServer(
|
|
52
52
|
{
|
|
53
53
|
name: 'GenAT',
|
|
54
|
-
version: '1.2.
|
|
54
|
+
version: '1.2.5',
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
capabilities: {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genat-mcp",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"mcpName": "io.github.asokans@oclc.org/genat",
|
|
5
5
|
"description": "MCP server GenAT: generate accessibility tests via n8n workflow (url + project folder)",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"bin": { "genat-mcp": "index.js" },
|
|
9
9
|
"engines": { "node": ">=20" },
|
|
10
|
-
"files": ["index.js", "detect-framework.js", "detect-login.js", "write-files.js"],
|
|
10
|
+
"files": ["index.js", "detect-framework.js", "detect-login.js", "write-files.js", "run-genat.mjs"],
|
|
11
11
|
"keywords": ["mcp", "accessibility", "playwright", "n8n", "model-context-protocol", "a11y", "testing"],
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
package/run-genat.mjs
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Standalone GenAT script: calls the n8n webhook directly and writes generated files.
|
|
4
|
+
* Use when the MCP fails (e.g. TLS/connection issues). Defaults to webhook-genat-login.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node run-genat.mjs <url> [parentProjectFolder]
|
|
8
|
+
* N8N_WEBHOOK_URL='https://your-n8n/webhook-test/webhook-genat-login' node run-genat.mjs <url> .
|
|
9
|
+
*
|
|
10
|
+
* Env:
|
|
11
|
+
* N8N_WEBHOOK_URL - webhook URL (default: http://localhost:5678/webhook-test/webhook-genat-login)
|
|
12
|
+
* N8N_INSECURE_TLS - set to 1 for self-signed/internal certs
|
|
13
|
+
*/
|
|
14
|
+
import https from 'node:https';
|
|
15
|
+
import { resolve } from 'node:path';
|
|
16
|
+
import { detectFramework } from './detect-framework.js';
|
|
17
|
+
import { detectLogin } from './detect-login.js';
|
|
18
|
+
import { writeGeneratedFiles } from './write-files.js';
|
|
19
|
+
|
|
20
|
+
const DEFAULT_WEBHOOK = 'http://localhost:5678/webhook-test/webhook-genat-login';
|
|
21
|
+
const N8N_WEBHOOK_URL = process.env.N8N_WEBHOOK_URL || DEFAULT_WEBHOOK;
|
|
22
|
+
const N8N_INSECURE_TLS = /^1|true|yes$/i.test(process.env.N8N_INSECURE_TLS || '');
|
|
23
|
+
|
|
24
|
+
function insecureHttpsFetch(url, { method = 'GET', headers = {}, body }) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const req = https.request(
|
|
27
|
+
url,
|
|
28
|
+
{
|
|
29
|
+
method,
|
|
30
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
31
|
+
agent: new https.Agent({ rejectUnauthorized: false }),
|
|
32
|
+
},
|
|
33
|
+
(res) => {
|
|
34
|
+
let data = '';
|
|
35
|
+
res.on('data', (chunk) => (data += chunk));
|
|
36
|
+
res.on('end', () => {
|
|
37
|
+
resolve({
|
|
38
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
39
|
+
status: res.statusCode ?? 0,
|
|
40
|
+
text: () => Promise.resolve(data),
|
|
41
|
+
json: () => Promise.resolve(JSON.parse(data || 'null')),
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
req.on('error', reject);
|
|
47
|
+
if (body) req.write(typeof body === 'string' ? body : JSON.stringify(body));
|
|
48
|
+
req.end();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function main() {
|
|
53
|
+
const url = process.argv[2];
|
|
54
|
+
const parentProjectFolder = resolve(process.argv[3] || '.');
|
|
55
|
+
|
|
56
|
+
if (!url) {
|
|
57
|
+
console.error('Usage: node run-genat.mjs <url> [parentProjectFolder]');
|
|
58
|
+
console.error('Example: N8N_WEBHOOK_URL=https://your-n8n/webhook-test/webhook-genat-login node run-genat.mjs https://example.com .');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let framework;
|
|
63
|
+
try {
|
|
64
|
+
framework = detectFramework(parentProjectFolder);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
framework = { scriptType: 'typescript', bddFramework: 'none', pageObject: false, projectSummary: '' };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let login = {};
|
|
70
|
+
try {
|
|
71
|
+
login = detectLogin(parentProjectFolder) || {};
|
|
72
|
+
} catch (_) {}
|
|
73
|
+
|
|
74
|
+
const body = {
|
|
75
|
+
url,
|
|
76
|
+
scriptType: framework.scriptType,
|
|
77
|
+
bddFramework: framework.bddFramework,
|
|
78
|
+
pageObject: framework.pageObject,
|
|
79
|
+
projectSummary: framework.projectSummary,
|
|
80
|
+
...(login.username && { loginUsername: login.username }),
|
|
81
|
+
...(login.password && { loginPassword: login.password }),
|
|
82
|
+
...(login.loginUrl && { loginUrl: login.loginUrl }),
|
|
83
|
+
...(login.usernameSelector && { loginUsernameSelector: login.usernameSelector }),
|
|
84
|
+
...(login.passwordSelector && { loginPasswordSelector: login.passwordSelector }),
|
|
85
|
+
...(login.submitSelector && { loginSubmitSelector: login.submitSelector }),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const fetchOpts = {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { 'Content-Type': 'application/json' },
|
|
91
|
+
body: JSON.stringify(body),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const useInsecureTls = N8N_INSECURE_TLS && N8N_WEBHOOK_URL.startsWith('https://');
|
|
95
|
+
const response = useInsecureTls
|
|
96
|
+
? await insecureHttpsFetch(N8N_WEBHOOK_URL, fetchOpts)
|
|
97
|
+
: await fetch(N8N_WEBHOOK_URL, fetchOpts);
|
|
98
|
+
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const text = await response.text();
|
|
101
|
+
console.error(`GenAT reached the n8n webhook, but n8n responded with ${response.status}:`);
|
|
102
|
+
console.error(text);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const data = await response.json();
|
|
107
|
+
const written = await writeGeneratedFiles(parentProjectFolder, data);
|
|
108
|
+
console.log('GenAT wrote:', written.join(', '));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
main().catch((err) => {
|
|
112
|
+
console.error(err);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|