@jrpool/kilotest 61.0.0 → 62.0.0

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.test.ts CHANGED
@@ -37,10 +37,10 @@ test('mcpPath is /mcp', () => {
37
37
  assert.equal(mcpPath, '/mcp');
38
38
  });
39
39
 
40
- test('createMCPServer registers all 12 tools', () => {
40
+ test('createMCPServer registers all 13 tools', () => {
41
41
  const server = createMCPServer();
42
42
  const toolNames = Object.keys((server as any)._registeredTools);
43
- assert.equal(toolNames.length, 12);
43
+ assert.equal(toolNames.length, 13);
44
44
  assert.deepEqual(toolNames, [
45
45
  'getKilotestOverview',
46
46
  'listPages',
@@ -51,6 +51,7 @@ test('createMCPServer registers all 12 tools', () => {
51
51
  'requestNewTest',
52
52
  'requestRetest',
53
53
  'requestFeature',
54
+ 'reportDisagreement',
54
55
  'orderNewTest',
55
56
  'orderRetest',
56
57
  'awaitTest'
@@ -197,6 +198,23 @@ test('requestFeature handler returns content and structuredContent', async () =>
197
198
  assert.equal(getToolCallCount('requestFeature'), countBefore + 1);
198
199
  });
199
200
 
201
+ test('reportDisagreement handler returns content and structuredContent', async () => {
202
+ const server = createMCPServer();
203
+ const countBefore = getToolCallCount('reportDisagreement');
204
+ const result = await (server as any)._registeredTools.reportDisagreement.handler({
205
+ issueID: 'linkNoText',
206
+ reportID: '260101T0000-mix',
207
+ catalogIndex: '0',
208
+ engineID: 'axe',
209
+ ruleID: 'r11',
210
+ reason: 'The element does have an accessible name'
211
+ });
212
+ assert.ok(result.content);
213
+ assert.equal(result.content[0].type, 'text');
214
+ assert.ok(result.structuredContent);
215
+ assert.equal(getToolCallCount('reportDisagreement'), countBefore + 1);
216
+ });
217
+
200
218
  test('orderNewTest handler returns content and structuredContent, and enqueues a job', async () => {
201
219
  const {jobsPath} = await import('./util.ts');
202
220
  const server = createMCPServer();
@@ -349,7 +367,7 @@ test('handleMCP responds to initialize with server info', async () => {
349
367
  }
350
368
  });
351
369
 
352
- test('handleMCP lists all 12 tools via tools/list', async () => {
370
+ test('handleMCP lists all 13 tools via tools/list', async () => {
353
371
  const server = await startMCPServer();
354
372
  try {
355
373
  const port = server.address().port;
@@ -357,7 +375,7 @@ test('handleMCP lists all 12 tools via tools/list', async () => {
357
375
  assert.equal(res.statusCode, 200);
358
376
  const result = parseSSEResult(res.body);
359
377
  const toolNames = result.result.tools.map((t: any) => t.name);
360
- assert.equal(toolNames.length, 12);
378
+ assert.equal(toolNames.length, 13);
361
379
  assert.deepEqual(toolNames, [
362
380
  'getKilotestOverview',
363
381
  'listPages',
@@ -368,6 +386,7 @@ test('handleMCP lists all 12 tools via tools/list', async () => {
368
386
  'requestNewTest',
369
387
  'requestRetest',
370
388
  'requestFeature',
389
+ 'reportDisagreement',
371
390
  'orderNewTest',
372
391
  'orderRetest',
373
392
  'awaitTest'
package/mcp.ts CHANGED
@@ -19,6 +19,7 @@ import * as requestFeatureAPI from './api/requestFeature.ts';
19
19
  import * as orderNewTestAPI from './api/orderNewTest.ts';
20
20
  import * as orderRetestAPI from './api/orderRetest.ts';
21
21
  import * as awaitTestAPI from './api/awaitTest.ts';
22
+ import * as reportDisagreementAPI from './api/reportDisagreement.ts';
22
23
  import {version} from './api/version.ts';
23
24
  import {recordMetric} from './util.ts';
24
25
 
@@ -33,6 +34,7 @@ import {
33
34
  orderNewTestSchema,
34
35
  orderRetestSchema,
35
36
  awaitTestSchema,
37
+ reportDisagreementSchema,
36
38
  listPagesResponseSchema,
37
39
  listIssuesResponseSchema,
38
40
  listViolatorsResponseSchema,
@@ -43,7 +45,8 @@ import {
43
45
  requestFeatureResponseSchema,
44
46
  orderNewTestResponseSchema,
45
47
  orderRetestResponseSchema,
46
- awaitTestResponseSchema
48
+ awaitTestResponseSchema,
49
+ reportDisagreementResponseSchema
47
50
  } from './api/schemas.ts';
48
51
 
49
52
  // CONSTANTS
@@ -257,6 +260,26 @@ export const createMCPServer = (): McpServer => {
257
260
  return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
258
261
  }
259
262
  );
263
+ server.registerTool(
264
+ 'reportDisagreement',
265
+ {
266
+ description: 'Reports that you disagree with a diagnosis shown by the listDiagnoses tool; queued for manager review. Use this after listDiagnoses when you believe a rule violation was incorrectly diagnosed or classified into an issue, providing the engineID and ruleID shown in the diagnosis and your reason. Returns a confirmation with disposition details.',
267
+ inputSchema: reportDisagreementSchema,
268
+ outputSchema: reportDisagreementResponseSchema,
269
+ annotations: {
270
+ title: 'Report disagreement with a diagnosis',
271
+ readOnlyHint: false,
272
+ idempotentHint: false,
273
+ destructiveHint: false,
274
+ openWorldHint: false
275
+ }
276
+ },
277
+ async ({issueID, reportID, catalogIndex, engineID, ruleID, reason}) => {
278
+ const result = await reportDisagreementAPI.response([issueID, reportID, catalogIndex, engineID, ruleID, reason]);
279
+ await recordMetric('mcpToolCalls', 'reportDisagreement');
280
+ return {content: [{type: 'text', text: JSON.stringify(result)}], structuredContent: result};
281
+ }
282
+ );
260
283
  server.registerTool(
261
284
  'orderNewTest',
262
285
  {
package/openapi-3.0.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.0.3
2
2
  info:
3
3
  title: Kilotest API
4
4
  description: 'Kilotest is an ensemble testing and reporting service for front-end web quality. It uses an ensemble of 12 rule engines to test web pages for front-end quality (accessibility, usability, and web standards, including HTML, CSS, ARIA, and WCAG). Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
5
- version: 61.0.0
5
+ version: 62.0.0
6
6
  license:
7
7
  name: MIT
8
8
  url: https://github.com/jrpool/kilotest/blob/main/LICENSE
@@ -560,15 +560,15 @@ paths:
560
560
  how to get details about the element:
561
561
  type: object
562
562
  properties:
563
- URL:
564
- type: string
565
- request method:
563
+ method:
566
564
  type: string
567
565
  enum:
568
566
  - GET
567
+ URL:
568
+ type: string
569
569
  required:
570
+ - method
570
571
  - URL
571
- - request method
572
572
  additionalProperties: false
573
573
  web users can get details about the element at:
574
574
  type: string
@@ -713,6 +713,8 @@ paths:
713
713
  items:
714
714
  type: object
715
715
  properties:
716
+ identifier of the rule engine:
717
+ description: Copied from the report act (which); type not guaranteed.
716
718
  identifier of the violated rule:
717
719
  description: Copied from the report instance (ruleID); type not guaranteed.
718
720
  description of the violation:
@@ -721,11 +723,41 @@ paths:
721
723
  description: Copied from the report instance (ordinalSeverity); type not guaranteed.
722
724
  count of violations of the rule by the element:
723
725
  type: number
726
+ how to report that you disagree with this diagnosis:
727
+ type: object
728
+ properties:
729
+ method:
730
+ type: string
731
+ enum:
732
+ - POST
733
+ URL:
734
+ type: string
735
+ request body:
736
+ type: object
737
+ properties:
738
+ engineID:
739
+ type: string
740
+ ruleID:
741
+ type: string
742
+ reason:
743
+ type: string
744
+ required:
745
+ - engineID
746
+ - ruleID
747
+ - reason
748
+ additionalProperties: false
749
+ required:
750
+ - method
751
+ - URL
752
+ - request body
753
+ additionalProperties: false
724
754
  required:
755
+ - identifier of the rule engine
725
756
  - identifier of the violated rule
726
757
  - description of the violation
727
758
  - severity of the violation on a 0-to-3 scale
728
759
  - count of violations of the rule by the element
760
+ - how to report that you disagree with this diagnosis
729
761
  additionalProperties: false
730
762
  - type: object
731
763
  properties:
@@ -1191,6 +1223,156 @@ paths:
1191
1223
  - response metadata
1192
1224
  - response content
1193
1225
  additionalProperties: false
1226
+ /api/reportDisagreement/{issueID}/{reportID}/{catalogIndex}:
1227
+ post:
1228
+ operationId: reportDisagreement
1229
+ summary: Report disagreement with a diagnosis
1230
+ parameters:
1231
+ - in: path
1232
+ name: issueID
1233
+ schema:
1234
+ type: string
1235
+ description: 'Issue identifier (example: contrastPoor)'
1236
+ required: true
1237
+ description: 'Issue identifier (example: contrastPoor)'
1238
+ - in: path
1239
+ name: reportID
1240
+ schema:
1241
+ type: string
1242
+ description: 'Identifier of the report (example: 260503T0432-x9z)'
1243
+ required: true
1244
+ description: 'Identifier of the report (example: 260503T0432-x9z)'
1245
+ - in: path
1246
+ name: catalogIndex
1247
+ schema:
1248
+ type: string
1249
+ description: 'Identifier of the issue-exhibiting element in the catalog of elements on the page (example: 372)'
1250
+ required: true
1251
+ description: 'Identifier of the issue-exhibiting element in the catalog of elements on the page (example: 372)'
1252
+ requestBody:
1253
+ content:
1254
+ application/json:
1255
+ schema:
1256
+ type: object
1257
+ properties:
1258
+ engineID:
1259
+ type: string
1260
+ description: 'Identifier of the rule engine that produced the disputed diagnosis (example: axe), as shown in the listDiagnoses output'
1261
+ ruleID:
1262
+ type: string
1263
+ description: 'Identifier of the rule whose diagnosis is disputed, as shown in the listDiagnoses output (example: color-contrast); if that output shows null for the rule identifier, use its description of the violation instead'
1264
+ reason:
1265
+ type: string
1266
+ description: 20- to 1000-character explanation of why the diagnosis is disputed
1267
+ required:
1268
+ - engineID
1269
+ - ruleID
1270
+ - reason
1271
+ responses:
1272
+ '200':
1273
+ description: Report disagreement with a diagnosis
1274
+ content:
1275
+ application/json:
1276
+ schema:
1277
+ type: object
1278
+ properties:
1279
+ tool collection:
1280
+ $ref: '#/components/schemas/ToolsFacts'
1281
+ tool name:
1282
+ type: string
1283
+ this request:
1284
+ type: object
1285
+ properties:
1286
+ description:
1287
+ type: string
1288
+ method:
1289
+ type: string
1290
+ enum:
1291
+ - POST
1292
+ URL:
1293
+ type: string
1294
+ body:
1295
+ type: object
1296
+ properties:
1297
+ engineID:
1298
+ type: string
1299
+ description: 'Identifier of the rule engine that produced the disputed diagnosis (example: axe), as shown in the listDiagnoses output'
1300
+ ruleID:
1301
+ type: string
1302
+ description: 'Identifier of the rule whose diagnosis is disputed, as shown in the listDiagnoses output (example: color-contrast); if that output shows null for the rule identifier, use its description of the violation instead'
1303
+ reason:
1304
+ type: string
1305
+ description: 20- to 1000-character explanation of why the diagnosis is disputed
1306
+ required:
1307
+ - engineID
1308
+ - ruleID
1309
+ - reason
1310
+ additionalProperties: false
1311
+ closest ancestor request:
1312
+ allOf:
1313
+ - $ref: '#/components/schemas/RequestReference'
1314
+ type: object
1315
+ nullable: true
1316
+ required:
1317
+ - description
1318
+ - method
1319
+ - URL
1320
+ - body
1321
+ - closest ancestor request
1322
+ additionalProperties: false
1323
+ URLs of similar requests for web users:
1324
+ type: object
1325
+ nullable: true
1326
+ response metadata:
1327
+ $ref: '#/components/schemas/ResponseMetadata'
1328
+ response content:
1329
+ type: object
1330
+ properties:
1331
+ details about your request:
1332
+ anyOf:
1333
+ - type: object
1334
+ properties:
1335
+ error:
1336
+ type: string
1337
+ required:
1338
+ - error
1339
+ additionalProperties: false
1340
+ - type: object
1341
+ properties:
1342
+ date and time received:
1343
+ type: string
1344
+ diagnosis you disagree with:
1345
+ type: object
1346
+ properties:
1347
+ issue identifier:
1348
+ type: string
1349
+ identifier of the rule engine:
1350
+ type: string
1351
+ identifier of the violated rule:
1352
+ type: string
1353
+ required:
1354
+ - issue identifier
1355
+ - identifier of the rule engine
1356
+ - identifier of the violated rule
1357
+ additionalProperties: false
1358
+ disposition:
1359
+ type: string
1360
+ required:
1361
+ - date and time received
1362
+ - diagnosis you disagree with
1363
+ - disposition
1364
+ additionalProperties: false
1365
+ required:
1366
+ - details about your request
1367
+ additionalProperties: false
1368
+ required:
1369
+ - tool collection
1370
+ - tool name
1371
+ - this request
1372
+ - URLs of similar requests for web users
1373
+ - response metadata
1374
+ - response content
1375
+ additionalProperties: false
1194
1376
  /api/orderNewTest:
1195
1377
  post:
1196
1378
  operationId: orderNewTest
package/openapi.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.1.0
2
2
  info:
3
3
  title: Kilotest API
4
4
  description: 'Kilotest is an ensemble testing and reporting service for front-end web quality. It uses an ensemble of 12 rule engines to test web pages for front-end quality (accessibility, usability, and web standards, including HTML, CSS, ARIA, and WCAG). Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
5
- version: 61.0.0
5
+ version: 62.0.0
6
6
  license:
7
7
  name: MIT
8
8
  identifier: MIT
@@ -559,14 +559,14 @@ paths:
559
559
  how to get details about the element:
560
560
  type: object
561
561
  properties:
562
- URL:
563
- type: string
564
- request method:
562
+ method:
565
563
  type: string
566
564
  const: GET
565
+ URL:
566
+ type: string
567
567
  required:
568
+ - method
568
569
  - URL
569
- - request method
570
570
  additionalProperties: false
571
571
  web users can get details about the element at:
572
572
  type: string
@@ -709,6 +709,8 @@ paths:
709
709
  items:
710
710
  type: object
711
711
  properties:
712
+ identifier of the rule engine:
713
+ description: Copied from the report act (which); type not guaranteed.
712
714
  identifier of the violated rule:
713
715
  description: Copied from the report instance (ruleID); type not guaranteed.
714
716
  description of the violation:
@@ -717,11 +719,40 @@ paths:
717
719
  description: Copied from the report instance (ordinalSeverity); type not guaranteed.
718
720
  count of violations of the rule by the element:
719
721
  type: number
722
+ how to report that you disagree with this diagnosis:
723
+ type: object
724
+ properties:
725
+ method:
726
+ type: string
727
+ const: POST
728
+ URL:
729
+ type: string
730
+ request body:
731
+ type: object
732
+ properties:
733
+ engineID:
734
+ type: string
735
+ ruleID:
736
+ type: string
737
+ reason:
738
+ type: string
739
+ required:
740
+ - engineID
741
+ - ruleID
742
+ - reason
743
+ additionalProperties: false
744
+ required:
745
+ - method
746
+ - URL
747
+ - request body
748
+ additionalProperties: false
720
749
  required:
750
+ - identifier of the rule engine
721
751
  - identifier of the violated rule
722
752
  - description of the violation
723
753
  - severity of the violation on a 0-to-3 scale
724
754
  - count of violations of the rule by the element
755
+ - how to report that you disagree with this diagnosis
725
756
  additionalProperties: false
726
757
  - type: object
727
758
  properties:
@@ -1179,6 +1210,153 @@ paths:
1179
1210
  - response metadata
1180
1211
  - response content
1181
1212
  additionalProperties: false
1213
+ /api/reportDisagreement/{issueID}/{reportID}/{catalogIndex}:
1214
+ post:
1215
+ operationId: reportDisagreement
1216
+ summary: Report disagreement with a diagnosis
1217
+ parameters:
1218
+ - in: path
1219
+ name: issueID
1220
+ schema:
1221
+ type: string
1222
+ description: 'Issue identifier (example: contrastPoor)'
1223
+ required: true
1224
+ description: 'Issue identifier (example: contrastPoor)'
1225
+ - in: path
1226
+ name: reportID
1227
+ schema:
1228
+ type: string
1229
+ description: 'Identifier of the report (example: 260503T0432-x9z)'
1230
+ required: true
1231
+ description: 'Identifier of the report (example: 260503T0432-x9z)'
1232
+ - in: path
1233
+ name: catalogIndex
1234
+ schema:
1235
+ type: string
1236
+ description: 'Identifier of the issue-exhibiting element in the catalog of elements on the page (example: 372)'
1237
+ required: true
1238
+ description: 'Identifier of the issue-exhibiting element in the catalog of elements on the page (example: 372)'
1239
+ requestBody:
1240
+ content:
1241
+ application/json:
1242
+ schema:
1243
+ type: object
1244
+ properties:
1245
+ engineID:
1246
+ type: string
1247
+ description: 'Identifier of the rule engine that produced the disputed diagnosis (example: axe), as shown in the listDiagnoses output'
1248
+ ruleID:
1249
+ type: string
1250
+ description: 'Identifier of the rule whose diagnosis is disputed, as shown in the listDiagnoses output (example: color-contrast); if that output shows null for the rule identifier, use its description of the violation instead'
1251
+ reason:
1252
+ type: string
1253
+ description: 20- to 1000-character explanation of why the diagnosis is disputed
1254
+ required:
1255
+ - engineID
1256
+ - ruleID
1257
+ - reason
1258
+ responses:
1259
+ '200':
1260
+ description: Report disagreement with a diagnosis
1261
+ content:
1262
+ application/json:
1263
+ schema:
1264
+ type: object
1265
+ properties:
1266
+ tool collection:
1267
+ $ref: '#/components/schemas/ToolsFacts'
1268
+ tool name:
1269
+ type: string
1270
+ this request:
1271
+ type: object
1272
+ properties:
1273
+ description:
1274
+ type: string
1275
+ method:
1276
+ type: string
1277
+ const: POST
1278
+ URL:
1279
+ type: string
1280
+ body:
1281
+ type: object
1282
+ properties:
1283
+ engineID:
1284
+ type: string
1285
+ description: 'Identifier of the rule engine that produced the disputed diagnosis (example: axe), as shown in the listDiagnoses output'
1286
+ ruleID:
1287
+ type: string
1288
+ description: 'Identifier of the rule whose diagnosis is disputed, as shown in the listDiagnoses output (example: color-contrast); if that output shows null for the rule identifier, use its description of the violation instead'
1289
+ reason:
1290
+ type: string
1291
+ description: 20- to 1000-character explanation of why the diagnosis is disputed
1292
+ required:
1293
+ - engineID
1294
+ - ruleID
1295
+ - reason
1296
+ additionalProperties: false
1297
+ closest ancestor request:
1298
+ anyOf:
1299
+ - $ref: '#/components/schemas/RequestReference'
1300
+ - type: 'null'
1301
+ required:
1302
+ - description
1303
+ - method
1304
+ - URL
1305
+ - body
1306
+ - closest ancestor request
1307
+ additionalProperties: false
1308
+ URLs of similar requests for web users:
1309
+ type: 'null'
1310
+ response metadata:
1311
+ $ref: '#/components/schemas/ResponseMetadata'
1312
+ response content:
1313
+ type: object
1314
+ properties:
1315
+ details about your request:
1316
+ anyOf:
1317
+ - type: object
1318
+ properties:
1319
+ error:
1320
+ type: string
1321
+ required:
1322
+ - error
1323
+ additionalProperties: false
1324
+ - type: object
1325
+ properties:
1326
+ date and time received:
1327
+ type: string
1328
+ diagnosis you disagree with:
1329
+ type: object
1330
+ properties:
1331
+ issue identifier:
1332
+ type: string
1333
+ identifier of the rule engine:
1334
+ type: string
1335
+ identifier of the violated rule:
1336
+ type: string
1337
+ required:
1338
+ - issue identifier
1339
+ - identifier of the rule engine
1340
+ - identifier of the violated rule
1341
+ additionalProperties: false
1342
+ disposition:
1343
+ type: string
1344
+ required:
1345
+ - date and time received
1346
+ - diagnosis you disagree with
1347
+ - disposition
1348
+ additionalProperties: false
1349
+ required:
1350
+ - details about your request
1351
+ additionalProperties: false
1352
+ required:
1353
+ - tool collection
1354
+ - tool name
1355
+ - this request
1356
+ - URLs of similar requests for web users
1357
+ - response metadata
1358
+ - response content
1359
+ additionalProperties: false
1182
1360
  /api/orderNewTest:
1183
1361
  post:
1184
1362
  operationId: orderNewTest
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "61.0.0",
3
+ "version": "62.0.0",
4
4
  "description": "Ensemble testing for front-end web quality",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/server.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/jrpool/kilotest",
7
7
  "source": "github"
8
8
  },
9
- "version": "61.0.0",
9
+ "version": "62.0.0",
10
10
  "remotes": [
11
11
  {
12
12
  "type": "streamable-http",