@jrpool/kilotest 38.1.0 → 39.0.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/.markdownlint-cli2.jsonc +12 -0
- package/.vscode/settings.json +3 -0
- package/CLAUDE.md +5 -0
- package/README.md +6 -4
- package/ai0BalanceForm/index.html +1 -1
- package/alerts.js +3 -1
- package/api/getReport.js +66 -0
- package/api/listDiagnoses.js +157 -0
- package/api/listIssues.js +225 -0
- package/api/listReports.js +87 -0
- package/api/listViolators.js +164 -0
- package/api/requestFeature.js +56 -0
- package/api/requestRetest.js +102 -0
- package/api/requestTest.js +106 -0
- package/api/routes.js +97 -0
- package/api/schemas.js +297 -0
- package/api/testSuite.js +294 -0
- package/api/util.js +149 -0
- package/diagnoses/index.js +2 -2
- package/docs/{AI-TOOL.md → AI-TOOLS.md} +54 -26
- package/docs/SERVICE.md +4 -1
- package/docs/decisions/001-api-design.md +59 -49
- package/eslint.config.mjs +13 -3
- package/index.html +1 -1
- package/index.js +202 -188
- package/issues/index.js +13 -21
- package/jsconfig.json +8 -0
- package/llms-full.txt +2 -2
- package/llms.txt +16 -11
- package/mcp.js +129 -65
- package/openapi.yaml +1234 -572
- package/package.json +18 -11
- package/reannotate/index.js +26 -15
- package/reannotateForm/index.js +15 -13
- package/redocly.yaml +4 -0
- package/reportHideForm/index.html +1 -1
- package/reportHideForm/index.js +24 -38
- package/reportIssue/index.js +3 -3
- package/reportIssues/index.js +128 -1
- package/reportUnhideForm/index.js +36 -44
- package/reportsExpungeForm/index.js +22 -16
- package/reportsPruneForm/index.js +22 -12
- package/reportsRewindForm/index.js +17 -9
- package/retestRec/index.js +8 -4
- package/retestRecForm/index.js +18 -6
- package/scripts/generate-openapi.js +83 -0
- package/targets/index.js +18 -13
- package/testOrder/index.js +11 -8
- package/tutorial/index.html +12 -12
- package/util.js +581 -539
- package/api/reportList.js +0 -83
- package/api/reportSummary.js +0 -181
- package/reportIssue/api.js +0 -183
- package/reportIssues/util.js +0 -138
- package/researchAgent.js +0 -206
- package/target/api.js +0 -126
- package/testRecForm/api.js +0 -55
package/llms.txt
CHANGED
|
@@ -8,20 +8,25 @@ There is a [detailed explanation of Kilotest and its capabilities for LLMs](http
|
|
|
8
8
|
|
|
9
9
|
## API
|
|
10
10
|
|
|
11
|
-
- [
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
11
|
+
- [List all available reports](/api/listReports)
|
|
12
|
+
- List all issues in one report: `/api/listIssues/{timeStamp}/{jobID}`
|
|
13
|
+
- List all elements exhibiting one issue in one report: `/api/listViolators/{issueID}/{timeStamp}/{jobID}`
|
|
14
|
+
- List all diagnoses of one element exhibiting one issue in one report: `/api/listDiagnoses/{catalogIndex}/{issueID}/{timeStamp}/{jobID}`
|
|
15
|
+
- Get one full report in JSON: `/api/getReport/{timeStamp}/{jobID}`
|
|
16
|
+
- Request testing of a web page: `/api/requestTest` (requires `POST` request)
|
|
17
|
+
- Request retesting of a web page: `/api/requestRetest/{timeStamp}/{jobID}` (requires `POST` request)
|
|
18
|
+
- Request adding or improving a feature: `/api/requestFeature` (requires `POST` request)
|
|
16
19
|
- [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml)
|
|
17
20
|
|
|
18
21
|
## Web UI
|
|
19
22
|
|
|
20
|
-
- [
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- [
|
|
23
|
+
- [List all available reports](https://kilotest.com/targets.html)
|
|
24
|
+
- List all issues in one report: `https://kilotest.com/reportIssues.html/{timeStamp}/{jobID}`
|
|
25
|
+
- List all elements exhibiting one issue in one report: `https://kilotest.com/reportIssue.html/{issueID}/{timeStamp}/{jobID}`
|
|
26
|
+
- List all diagnoses of one element exhibiting one issue in one report: `https://kilotest.com/diagnoses.html/{issueID}/{timeStamp}/{jobID}/{catalogIndex}`
|
|
27
|
+
- Get one full report in JSON: `https://kilotest.com/fullReport.json/{timeStamp}/{jobID}`
|
|
28
|
+
- [Request testing of a web page](https://kilotest.com/testRecForm.html)
|
|
29
|
+
- Request retesting of a web page: `https://kilotest.com/retestRecForm.html/{timeStamp}/{jobID}`
|
|
26
30
|
- [List the operations that Kilotest managers are authorized to request](https://kilotest.com/manage.html)
|
|
31
|
+
- [Provide statistics about frequently reported issues across all pages](https://kilotest.com/issues.html)
|
|
27
32
|
- [Tutorial, “Accessibility testing strategies”](https://kilotest.com/tutorial.html)
|
package/mcp.js
CHANGED
|
@@ -9,13 +9,32 @@ const {McpServer} = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
|
9
9
|
const {StreamableHTTPServerTransport} = require(
|
|
10
10
|
'@modelcontextprotocol/sdk/server/streamableHttp.js'
|
|
11
11
|
);
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
12
|
+
const getReportAPI = require('./api/getReport');
|
|
13
|
+
const listReportsAPI = require('./api/listReports');
|
|
14
|
+
const listIssuesAPI = require('./api/listIssues');
|
|
15
|
+
const listViolatorsAPI = require('./api/listViolators');
|
|
16
|
+
const listDiagnosesAPI = require('./api/listDiagnoses');
|
|
17
|
+
const requestTestAPI = require('./api/requestTest');
|
|
18
|
+
const requestRetestAPI = require('./api/requestRetest');
|
|
19
|
+
const requestFeatureAPI = require('./api/requestFeature');
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
getReportSchema,
|
|
23
|
+
listIssuesSchema,
|
|
24
|
+
listViolatorsSchema,
|
|
25
|
+
listDiagnosesSchema,
|
|
26
|
+
requestTestSchema,
|
|
27
|
+
requestRetestSchema,
|
|
28
|
+
requestFeatureSchema,
|
|
29
|
+
listReportsResponseSchema,
|
|
30
|
+
listIssuesResponseSchema,
|
|
31
|
+
listViolatorsResponseSchema,
|
|
32
|
+
listDiagnosesResponseSchema,
|
|
33
|
+
getReportResponseSchema,
|
|
34
|
+
requestTestResponseSchema,
|
|
35
|
+
requestRetestResponseSchema,
|
|
36
|
+
requestFeatureResponseSchema
|
|
37
|
+
} = require('./api/schemas');
|
|
19
38
|
|
|
20
39
|
// CONSTANTS
|
|
21
40
|
|
|
@@ -25,119 +44,164 @@ exports.mcpPath = '/mcp';
|
|
|
25
44
|
|
|
26
45
|
// Creates and returns an McpServer with Kilotest tools registered.
|
|
27
46
|
const createMCPServer = () => {
|
|
28
|
-
const server = new McpServer({
|
|
47
|
+
const server = new McpServer({
|
|
48
|
+
name: 'Kilotest',
|
|
49
|
+
version: '2.0.0',
|
|
50
|
+
description: 'Tools that test web pages for front-end quality (accessibility, usability, and standards conformity) and make test results available'
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
instructions: 'Use the listReports tool to start. If it shows that there is a report available about the page you want facts about, drill down with the listIssues, listViolators, and listDiagnoses tools. If not, use the requestTest tool to request that the page be tested. If the latest report about the page is obsolete, use the requestRetest tool to request that the page be retested.'
|
|
54
|
+
});
|
|
29
55
|
server.registerTool(
|
|
30
|
-
'
|
|
56
|
+
'listReports',
|
|
31
57
|
{
|
|
32
|
-
description: '
|
|
33
|
-
inputSchema: {
|
|
34
|
-
|
|
35
|
-
hostname: z.string().describe('All or part of the hostname of the URL of the web page.')
|
|
36
|
-
},
|
|
58
|
+
description: 'Provide basics about all available reports.',
|
|
59
|
+
inputSchema: {},
|
|
60
|
+
outputSchema: listReportsResponseSchema,
|
|
37
61
|
annotations: {
|
|
38
|
-
title: '
|
|
62
|
+
title: 'Provide basics about all available reports.',
|
|
39
63
|
readOnlyHint: true,
|
|
40
64
|
idempotentHint: true,
|
|
41
65
|
destructiveHint: false,
|
|
42
66
|
openWorldHint: false
|
|
43
67
|
}
|
|
44
68
|
},
|
|
45
|
-
async (
|
|
46
|
-
const result = await
|
|
47
|
-
return {content: [{type: 'text', text: JSON.stringify(result)}]};
|
|
69
|
+
async () => {
|
|
70
|
+
const result = await listReportsAPI.response();
|
|
71
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
48
72
|
}
|
|
49
73
|
);
|
|
50
74
|
server.registerTool(
|
|
51
|
-
'
|
|
75
|
+
'listIssues',
|
|
52
76
|
{
|
|
53
|
-
description: '
|
|
54
|
-
inputSchema:
|
|
77
|
+
description: 'Provide details about one report, including basics about the issues reported in it.',
|
|
78
|
+
inputSchema: listIssuesSchema,
|
|
79
|
+
outputSchema: listIssuesResponseSchema,
|
|
55
80
|
annotations: {
|
|
56
|
-
title: '
|
|
81
|
+
title: 'Provide details about one report, including basics about the issues reported in it.',
|
|
57
82
|
readOnlyHint: true,
|
|
58
83
|
idempotentHint: true,
|
|
59
84
|
destructiveHint: false,
|
|
60
85
|
openWorldHint: false
|
|
61
86
|
}
|
|
62
87
|
},
|
|
63
|
-
async () => {
|
|
64
|
-
const result = await
|
|
65
|
-
return {content: [{type: 'text', text: JSON.stringify(result)}]};
|
|
88
|
+
async ({timeStamp, jobID}) => {
|
|
89
|
+
const result = await listIssuesAPI.response([timeStamp, jobID]);
|
|
90
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
66
91
|
}
|
|
67
92
|
);
|
|
68
93
|
server.registerTool(
|
|
69
|
-
'
|
|
94
|
+
'listViolators',
|
|
70
95
|
{
|
|
71
|
-
description: '
|
|
72
|
-
inputSchema:
|
|
73
|
-
|
|
74
|
-
jobID: z.string().describe('Job identifier, e.g. x9z')
|
|
75
|
-
},
|
|
96
|
+
description: 'Provide details about one issue in one report, including basics about the elements of the tested page that were reported as exhibiting the issue.',
|
|
97
|
+
inputSchema: listViolatorsSchema,
|
|
98
|
+
outputSchema: listViolatorsResponseSchema,
|
|
76
99
|
annotations: {
|
|
77
|
-
title: '
|
|
100
|
+
title: 'Provide details about one issue in one report, including basics about the elements of the tested page that were reported as exhibiting the issue.',
|
|
78
101
|
readOnlyHint: true,
|
|
79
102
|
idempotentHint: true,
|
|
80
103
|
destructiveHint: false,
|
|
81
104
|
openWorldHint: false
|
|
82
105
|
}
|
|
83
106
|
},
|
|
84
|
-
async ({timeStamp, jobID}) => {
|
|
85
|
-
const result = await
|
|
86
|
-
return {content: [{type: 'text', text: JSON.stringify(result)}]};
|
|
107
|
+
async ({issueID, timeStamp, jobID}) => {
|
|
108
|
+
const result = await listViolatorsAPI.response([issueID, timeStamp, jobID]);
|
|
109
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
87
110
|
}
|
|
88
111
|
);
|
|
89
112
|
server.registerTool(
|
|
90
|
-
'
|
|
113
|
+
'listDiagnoses',
|
|
91
114
|
{
|
|
92
|
-
description: '
|
|
93
|
-
inputSchema:
|
|
94
|
-
|
|
95
|
-
timeStamp: z.string().describe('Report timestamp in YYMMDDTHHMM format, e.g. 260503T0432'),
|
|
96
|
-
jobID: z.string().describe('Job identifier, e.g. x9z')
|
|
97
|
-
},
|
|
115
|
+
description: 'Provide details about one element reported as exhibiting one issue in one report, including the diagnoses provided by rule engines about how the element exhibited the issue.',
|
|
116
|
+
inputSchema: listDiagnosesSchema,
|
|
117
|
+
outputSchema: listDiagnosesResponseSchema,
|
|
98
118
|
annotations: {
|
|
99
|
-
title: '
|
|
119
|
+
title: 'Provide details about one element reported as exhibiting one issue in one report, including the diagnoses provided by rule engines about how the element exhibited the issue.',
|
|
100
120
|
readOnlyHint: true,
|
|
101
121
|
idempotentHint: true,
|
|
102
122
|
destructiveHint: false,
|
|
103
123
|
openWorldHint: false
|
|
104
124
|
}
|
|
105
125
|
},
|
|
106
|
-
async ({issueID, timeStamp, jobID}) => {
|
|
107
|
-
const result = await
|
|
108
|
-
return {content: [{type: 'text', text: JSON.stringify(result)}]};
|
|
126
|
+
async ({catalogIndex, issueID, timeStamp, jobID}) => {
|
|
127
|
+
const result = await listDiagnosesAPI.response([catalogIndex, issueID, timeStamp, jobID]);
|
|
128
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
server.registerTool(
|
|
132
|
+
'getReport',
|
|
133
|
+
{
|
|
134
|
+
description: 'Get one full report in JSON.',
|
|
135
|
+
inputSchema: getReportSchema,
|
|
136
|
+
outputSchema: getReportResponseSchema,
|
|
137
|
+
annotations: {
|
|
138
|
+
title: 'Get one full report in JSON.',
|
|
139
|
+
readOnlyHint: true,
|
|
140
|
+
idempotentHint: true,
|
|
141
|
+
destructiveHint: false,
|
|
142
|
+
openWorldHint: false
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
async ({timeStamp, jobID}) => {
|
|
146
|
+
const result = await getReportAPI.response([timeStamp, jobID]);
|
|
147
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
109
148
|
}
|
|
110
149
|
);
|
|
111
150
|
server.registerTool(
|
|
112
|
-
'
|
|
151
|
+
'requestTest',
|
|
113
152
|
{
|
|
114
|
-
description: '
|
|
115
|
-
inputSchema:
|
|
116
|
-
|
|
117
|
-
'URL of the web page': z.string().describe('Full HTTPS URL of the page to test'),
|
|
118
|
-
'reason for testing the web page': z.string().describe('Reason for recommending this page for testing')
|
|
119
|
-
},
|
|
153
|
+
description: 'Process my request to test a page about which no report is available yet.',
|
|
154
|
+
inputSchema: requestTestSchema,
|
|
155
|
+
outputSchema: requestTestResponseSchema,
|
|
120
156
|
annotations: {
|
|
121
|
-
title: '
|
|
157
|
+
title: 'Process my request to test a page about which no report is available yet.',
|
|
122
158
|
readOnlyHint: false,
|
|
123
159
|
idempotentHint: false,
|
|
124
160
|
destructiveHint: false,
|
|
125
161
|
openWorldHint: false
|
|
126
162
|
}
|
|
127
163
|
},
|
|
128
|
-
async ({
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
164
|
+
async ({description, URL, reason}) => {
|
|
165
|
+
const result = await requestTestAPI.response([description, URL, reason]);
|
|
166
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
server.registerTool(
|
|
170
|
+
'requestRetest',
|
|
171
|
+
{
|
|
172
|
+
description: 'Process my request to retest a page about which a report is available.',
|
|
173
|
+
inputSchema: requestRetestSchema,
|
|
174
|
+
outputSchema: requestRetestResponseSchema,
|
|
175
|
+
annotations: {
|
|
176
|
+
title: 'Process my request to retest a page about which a report is available.',
|
|
177
|
+
readOnlyHint: false,
|
|
178
|
+
idempotentHint: false,
|
|
179
|
+
destructiveHint: false,
|
|
180
|
+
openWorldHint: false
|
|
135
181
|
}
|
|
136
|
-
|
|
137
|
-
|
|
182
|
+
},
|
|
183
|
+
async ({timeStamp, jobID, reason}) => {
|
|
184
|
+
const result = await requestRetestAPI.response([timeStamp, jobID, reason]);
|
|
185
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
server.registerTool(
|
|
189
|
+
'requestFeature',
|
|
190
|
+
{
|
|
191
|
+
description: 'Process my request to add or improve a feature.',
|
|
192
|
+
inputSchema: requestFeatureSchema,
|
|
193
|
+
outputSchema: requestFeatureResponseSchema,
|
|
194
|
+
annotations: {
|
|
195
|
+
title: 'Process my request to add or improve a feature.',
|
|
196
|
+
readOnlyHint: false,
|
|
197
|
+
idempotentHint: false,
|
|
198
|
+
destructiveHint: false,
|
|
199
|
+
openWorldHint: false
|
|
138
200
|
}
|
|
139
|
-
|
|
140
|
-
|
|
201
|
+
},
|
|
202
|
+
async ({request}) => {
|
|
203
|
+
const result = await requestFeatureAPI.response([request]);
|
|
204
|
+
return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
|
|
141
205
|
}
|
|
142
206
|
);
|
|
143
207
|
return server;
|