@ainyc/canonry 2.8.2 → 2.9.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/dist/mcp.js +208 -7
- package/package.json +7 -7
package/dist/mcp.js
CHANGED
|
@@ -18,6 +18,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
18
18
|
|
|
19
19
|
// src/mcp/server.ts
|
|
20
20
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
21
|
+
import { z as z3 } from "zod";
|
|
21
22
|
|
|
22
23
|
// src/package-version.ts
|
|
23
24
|
import { createRequire } from "module";
|
|
@@ -184,6 +185,7 @@ var canonryMcpTools = [
|
|
|
184
185
|
title: "List Canonry projects",
|
|
185
186
|
description: "List all Canonry projects available through the configured API.",
|
|
186
187
|
access: "read",
|
|
188
|
+
tier: "core",
|
|
187
189
|
inputSchema: emptyInputSchema,
|
|
188
190
|
annotations: readAnnotations(),
|
|
189
191
|
openApiOperations: ["GET /api/v1/projects"],
|
|
@@ -194,6 +196,7 @@ var canonryMcpTools = [
|
|
|
194
196
|
title: "Get project",
|
|
195
197
|
description: "Get a Canonry project by name.",
|
|
196
198
|
access: "read",
|
|
199
|
+
tier: "core",
|
|
197
200
|
inputSchema: projectInputSchema,
|
|
198
201
|
annotations: readAnnotations(),
|
|
199
202
|
openApiOperations: ["GET /api/v1/projects/{name}"],
|
|
@@ -204,6 +207,7 @@ var canonryMcpTools = [
|
|
|
204
207
|
title: "Export project config",
|
|
205
208
|
description: "Export a Canonry project in config-as-code format.",
|
|
206
209
|
access: "read",
|
|
210
|
+
tier: "setup",
|
|
207
211
|
inputSchema: projectInputSchema,
|
|
208
212
|
annotations: readAnnotations(),
|
|
209
213
|
openApiOperations: ["GET /api/v1/projects/{name}/export"],
|
|
@@ -214,6 +218,7 @@ var canonryMcpTools = [
|
|
|
214
218
|
title: "Get project history",
|
|
215
219
|
description: "Get audit history for a Canonry project.",
|
|
216
220
|
access: "read",
|
|
221
|
+
tier: "monitoring",
|
|
217
222
|
inputSchema: projectInputSchema,
|
|
218
223
|
annotations: readAnnotations(),
|
|
219
224
|
openApiOperations: ["GET /api/v1/projects/{name}/history"],
|
|
@@ -224,6 +229,7 @@ var canonryMcpTools = [
|
|
|
224
229
|
title: "List project runs",
|
|
225
230
|
description: "List runs for a Canonry project.",
|
|
226
231
|
access: "read",
|
|
232
|
+
tier: "monitoring",
|
|
227
233
|
inputSchema: runsListInputSchema,
|
|
228
234
|
annotations: readAnnotations(),
|
|
229
235
|
openApiOperations: ["GET /api/v1/projects/{name}/runs"],
|
|
@@ -234,6 +240,7 @@ var canonryMcpTools = [
|
|
|
234
240
|
title: "Get latest project run",
|
|
235
241
|
description: "Get the latest run and total run count for a Canonry project.",
|
|
236
242
|
access: "read",
|
|
243
|
+
tier: "monitoring",
|
|
237
244
|
inputSchema: projectInputSchema,
|
|
238
245
|
annotations: readAnnotations(),
|
|
239
246
|
openApiOperations: ["GET /api/v1/projects/{name}/runs/latest"],
|
|
@@ -244,6 +251,7 @@ var canonryMcpTools = [
|
|
|
244
251
|
title: "Get run",
|
|
245
252
|
description: "Get a Canonry run with its snapshots.",
|
|
246
253
|
access: "read",
|
|
254
|
+
tier: "monitoring",
|
|
247
255
|
inputSchema: runGetInputSchema,
|
|
248
256
|
annotations: readAnnotations(),
|
|
249
257
|
openApiOperations: ["GET /api/v1/runs/{id}"],
|
|
@@ -254,6 +262,7 @@ var canonryMcpTools = [
|
|
|
254
262
|
title: "Get project timeline",
|
|
255
263
|
description: "Get per-keyword citation history for a Canonry project.",
|
|
256
264
|
access: "read",
|
|
265
|
+
tier: "monitoring",
|
|
257
266
|
inputSchema: timelineInputSchema,
|
|
258
267
|
annotations: readAnnotations(),
|
|
259
268
|
openApiOperations: ["GET /api/v1/projects/{name}/timeline"],
|
|
@@ -264,6 +273,7 @@ var canonryMcpTools = [
|
|
|
264
273
|
title: "List query snapshots",
|
|
265
274
|
description: "List paginated query snapshots for a Canonry project.",
|
|
266
275
|
access: "read",
|
|
276
|
+
tier: "monitoring",
|
|
267
277
|
inputSchema: snapshotsListInputSchema,
|
|
268
278
|
annotations: readAnnotations(),
|
|
269
279
|
openApiOperations: ["GET /api/v1/projects/{name}/snapshots"],
|
|
@@ -278,6 +288,7 @@ var canonryMcpTools = [
|
|
|
278
288
|
title: "Diff snapshots",
|
|
279
289
|
description: "Compare query snapshot states between two Canonry runs.",
|
|
280
290
|
access: "read",
|
|
291
|
+
tier: "monitoring",
|
|
281
292
|
inputSchema: snapshotsDiffInputSchema,
|
|
282
293
|
annotations: readAnnotations(),
|
|
283
294
|
openApiOperations: ["GET /api/v1/projects/{name}/snapshots/diff"],
|
|
@@ -288,6 +299,7 @@ var canonryMcpTools = [
|
|
|
288
299
|
title: "List insights",
|
|
289
300
|
description: "List intelligence insights for a Canonry project.",
|
|
290
301
|
access: "read",
|
|
302
|
+
tier: "monitoring",
|
|
291
303
|
inputSchema: insightsListInputSchema,
|
|
292
304
|
annotations: readAnnotations(),
|
|
293
305
|
openApiOperations: ["GET /api/v1/projects/{name}/insights"],
|
|
@@ -298,6 +310,7 @@ var canonryMcpTools = [
|
|
|
298
310
|
title: "Get insight",
|
|
299
311
|
description: "Get one intelligence insight for a Canonry project.",
|
|
300
312
|
access: "read",
|
|
313
|
+
tier: "monitoring",
|
|
301
314
|
inputSchema: insightInputSchema,
|
|
302
315
|
annotations: readAnnotations(),
|
|
303
316
|
openApiOperations: ["GET /api/v1/projects/{name}/insights/{id}"],
|
|
@@ -308,6 +321,7 @@ var canonryMcpTools = [
|
|
|
308
321
|
title: "Get latest health",
|
|
309
322
|
description: "Get the latest health snapshot for a Canonry project.",
|
|
310
323
|
access: "read",
|
|
324
|
+
tier: "monitoring",
|
|
311
325
|
inputSchema: projectInputSchema,
|
|
312
326
|
annotations: readAnnotations(),
|
|
313
327
|
openApiOperations: ["GET /api/v1/projects/{name}/health/latest"],
|
|
@@ -318,6 +332,7 @@ var canonryMcpTools = [
|
|
|
318
332
|
title: "Get health history",
|
|
319
333
|
description: "Get health snapshot history for a Canonry project.",
|
|
320
334
|
access: "read",
|
|
335
|
+
tier: "monitoring",
|
|
321
336
|
inputSchema: healthHistoryInputSchema,
|
|
322
337
|
annotations: readAnnotations(),
|
|
323
338
|
openApiOperations: ["GET /api/v1/projects/{name}/health/history"],
|
|
@@ -328,6 +343,7 @@ var canonryMcpTools = [
|
|
|
328
343
|
title: "List keywords",
|
|
329
344
|
description: "List tracked keywords for a Canonry project.",
|
|
330
345
|
access: "read",
|
|
346
|
+
tier: "setup",
|
|
331
347
|
inputSchema: projectInputSchema,
|
|
332
348
|
annotations: readAnnotations(),
|
|
333
349
|
openApiOperations: ["GET /api/v1/projects/{name}/keywords"],
|
|
@@ -338,6 +354,7 @@ var canonryMcpTools = [
|
|
|
338
354
|
title: "List competitors",
|
|
339
355
|
description: "List tracked competitors for a Canonry project.",
|
|
340
356
|
access: "read",
|
|
357
|
+
tier: "setup",
|
|
341
358
|
inputSchema: projectInputSchema,
|
|
342
359
|
annotations: readAnnotations(),
|
|
343
360
|
openApiOperations: ["GET /api/v1/projects/{name}/competitors"],
|
|
@@ -348,6 +365,7 @@ var canonryMcpTools = [
|
|
|
348
365
|
title: "Get schedule",
|
|
349
366
|
description: "Get the scheduled run configuration for a Canonry project.",
|
|
350
367
|
access: "read",
|
|
368
|
+
tier: "setup",
|
|
351
369
|
inputSchema: projectInputSchema,
|
|
352
370
|
annotations: readAnnotations(),
|
|
353
371
|
openApiOperations: ["GET /api/v1/projects/{name}/schedule"],
|
|
@@ -358,6 +376,7 @@ var canonryMcpTools = [
|
|
|
358
376
|
title: "Get settings",
|
|
359
377
|
description: "Get Canonry API settings and configured provider status.",
|
|
360
378
|
access: "read",
|
|
379
|
+
tier: "core",
|
|
361
380
|
inputSchema: emptyInputSchema,
|
|
362
381
|
annotations: readAnnotations(),
|
|
363
382
|
openApiOperations: ["GET /api/v1/settings"],
|
|
@@ -368,6 +387,7 @@ var canonryMcpTools = [
|
|
|
368
387
|
title: "List Google connections",
|
|
369
388
|
description: "List configured Google connections for a Canonry project.",
|
|
370
389
|
access: "read",
|
|
390
|
+
tier: "gsc",
|
|
371
391
|
inputSchema: projectInputSchema,
|
|
372
392
|
annotations: readAnnotations(),
|
|
373
393
|
openApiOperations: ["GET /api/v1/projects/{name}/google/connections"],
|
|
@@ -378,6 +398,7 @@ var canonryMcpTools = [
|
|
|
378
398
|
title: "Get GSC performance",
|
|
379
399
|
description: "Get stored Google Search Console performance rows for a Canonry project.",
|
|
380
400
|
access: "read",
|
|
401
|
+
tier: "gsc",
|
|
381
402
|
inputSchema: gscPerformanceInputSchema,
|
|
382
403
|
annotations: readAnnotations(),
|
|
383
404
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/performance"],
|
|
@@ -388,6 +409,7 @@ var canonryMcpTools = [
|
|
|
388
409
|
title: "List GSC inspections",
|
|
389
410
|
description: "List stored URL inspection rows for a Canonry project.",
|
|
390
411
|
access: "read",
|
|
412
|
+
tier: "gsc",
|
|
391
413
|
inputSchema: gscInspectionsInputSchema,
|
|
392
414
|
annotations: readAnnotations(),
|
|
393
415
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/inspections"],
|
|
@@ -398,6 +420,7 @@ var canonryMcpTools = [
|
|
|
398
420
|
title: "List deindexed GSC URLs",
|
|
399
421
|
description: "List URLs that appear to have become deindexed in Google Search Console data.",
|
|
400
422
|
access: "read",
|
|
423
|
+
tier: "gsc",
|
|
401
424
|
inputSchema: projectInputSchema,
|
|
402
425
|
annotations: readAnnotations(),
|
|
403
426
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/deindexed"],
|
|
@@ -408,6 +431,7 @@ var canonryMcpTools = [
|
|
|
408
431
|
title: "Get GSC coverage",
|
|
409
432
|
description: "Get Google Search Console coverage summary for a Canonry project.",
|
|
410
433
|
access: "read",
|
|
434
|
+
tier: "gsc",
|
|
411
435
|
inputSchema: projectInputSchema,
|
|
412
436
|
annotations: readAnnotations(),
|
|
413
437
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/coverage"],
|
|
@@ -418,6 +442,7 @@ var canonryMcpTools = [
|
|
|
418
442
|
title: "Get GSC coverage history",
|
|
419
443
|
description: "Get Google Search Console coverage history snapshots for a Canonry project.",
|
|
420
444
|
access: "read",
|
|
445
|
+
tier: "gsc",
|
|
421
446
|
inputSchema: gscCoverageHistoryInputSchema,
|
|
422
447
|
annotations: readAnnotations(),
|
|
423
448
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/coverage/history"],
|
|
@@ -428,6 +453,7 @@ var canonryMcpTools = [
|
|
|
428
453
|
title: "Get GSC sitemaps",
|
|
429
454
|
description: "Get sitemap data from Google Search Console for a Canonry project.",
|
|
430
455
|
access: "read",
|
|
456
|
+
tier: "gsc",
|
|
431
457
|
inputSchema: projectInputSchema,
|
|
432
458
|
annotations: readAnnotations(true),
|
|
433
459
|
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/sitemaps"],
|
|
@@ -438,6 +464,7 @@ var canonryMcpTools = [
|
|
|
438
464
|
title: "Get GA status",
|
|
439
465
|
description: "Get Google Analytics connection status for a Canonry project.",
|
|
440
466
|
access: "read",
|
|
467
|
+
tier: "ga",
|
|
441
468
|
inputSchema: projectInputSchema,
|
|
442
469
|
annotations: readAnnotations(),
|
|
443
470
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/status"],
|
|
@@ -448,6 +475,7 @@ var canonryMcpTools = [
|
|
|
448
475
|
title: "Get GA traffic",
|
|
449
476
|
description: "Get Google Analytics traffic summary for a Canonry project.",
|
|
450
477
|
access: "read",
|
|
478
|
+
tier: "ga",
|
|
451
479
|
inputSchema: gaTrafficInputSchema,
|
|
452
480
|
annotations: readAnnotations(),
|
|
453
481
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/traffic"],
|
|
@@ -458,6 +486,7 @@ var canonryMcpTools = [
|
|
|
458
486
|
title: "Get GA coverage",
|
|
459
487
|
description: "Get Google Analytics page coverage for a Canonry project.",
|
|
460
488
|
access: "read",
|
|
489
|
+
tier: "ga",
|
|
461
490
|
inputSchema: projectInputSchema,
|
|
462
491
|
annotations: readAnnotations(),
|
|
463
492
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/coverage"],
|
|
@@ -468,6 +497,7 @@ var canonryMcpTools = [
|
|
|
468
497
|
title: "Get GA AI referral history",
|
|
469
498
|
description: "Get AI referral sessions per day grouped by source.",
|
|
470
499
|
access: "read",
|
|
500
|
+
tier: "ga",
|
|
471
501
|
inputSchema: gaWindowInputSchema,
|
|
472
502
|
annotations: readAnnotations(),
|
|
473
503
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/ai-referral-history"],
|
|
@@ -478,6 +508,7 @@ var canonryMcpTools = [
|
|
|
478
508
|
title: "Get GA social referral history",
|
|
479
509
|
description: "Get social referral sessions per day grouped by source.",
|
|
480
510
|
access: "read",
|
|
511
|
+
tier: "ga",
|
|
481
512
|
inputSchema: gaWindowInputSchema,
|
|
482
513
|
annotations: readAnnotations(),
|
|
483
514
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/social-referral-history"],
|
|
@@ -488,6 +519,7 @@ var canonryMcpTools = [
|
|
|
488
519
|
title: "Get GA social referral trend",
|
|
489
520
|
description: "Get social referral trend with biggest mover for a Canonry project.",
|
|
490
521
|
access: "read",
|
|
522
|
+
tier: "ga",
|
|
491
523
|
inputSchema: projectInputSchema,
|
|
492
524
|
annotations: readAnnotations(),
|
|
493
525
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/social-referral-trend"],
|
|
@@ -498,6 +530,7 @@ var canonryMcpTools = [
|
|
|
498
530
|
title: "Get GA attribution trend",
|
|
499
531
|
description: "Get per-channel attribution trends for organic, AI, social, and total sessions.",
|
|
500
532
|
access: "read",
|
|
533
|
+
tier: "ga",
|
|
501
534
|
inputSchema: projectInputSchema,
|
|
502
535
|
annotations: readAnnotations(),
|
|
503
536
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/attribution-trend"],
|
|
@@ -508,6 +541,7 @@ var canonryMcpTools = [
|
|
|
508
541
|
title: "Get GA session history",
|
|
509
542
|
description: "Get total sessions per day for a Canonry project.",
|
|
510
543
|
access: "read",
|
|
544
|
+
tier: "ga",
|
|
511
545
|
inputSchema: gaWindowInputSchema,
|
|
512
546
|
annotations: readAnnotations(),
|
|
513
547
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/session-history"],
|
|
@@ -518,6 +552,7 @@ var canonryMcpTools = [
|
|
|
518
552
|
title: "Create or replace project",
|
|
519
553
|
description: "Create or replace a Canonry project. PUT semantics \u2014 fields not in the request are reset to their defaults. Provide the full intended project shape.",
|
|
520
554
|
access: "write",
|
|
555
|
+
tier: "setup",
|
|
521
556
|
inputSchema: projectUpsertInputSchema,
|
|
522
557
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
523
558
|
openApiOperations: ["PUT /api/v1/projects/{name}"],
|
|
@@ -528,6 +563,7 @@ var canonryMcpTools = [
|
|
|
528
563
|
title: "Apply project config",
|
|
529
564
|
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config \u2014 fields omitted from the spec are reset to defaults. For multi-document YAML, call this tool once per project document.",
|
|
530
565
|
access: "write",
|
|
566
|
+
tier: "core",
|
|
531
567
|
inputSchema: applyConfigInputSchema,
|
|
532
568
|
// Declarative apply is safe to repeat, but it replaces configured child state.
|
|
533
569
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
@@ -539,6 +575,7 @@ var canonryMcpTools = [
|
|
|
539
575
|
title: "Generate keyword suggestions",
|
|
540
576
|
description: "Generate candidate key phrases using a configured provider. Returns suggestions only; use canonry_keywords_add to persist them.",
|
|
541
577
|
access: "write",
|
|
578
|
+
tier: "setup",
|
|
542
579
|
inputSchema: keywordGenerateInputSchema,
|
|
543
580
|
annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
|
|
544
581
|
openApiOperations: ["POST /api/v1/projects/{name}/keywords/generate"],
|
|
@@ -549,6 +586,7 @@ var canonryMcpTools = [
|
|
|
549
586
|
title: "Replace keywords",
|
|
550
587
|
description: "Replace the tracked keyword set for a Canonry project.",
|
|
551
588
|
access: "write",
|
|
589
|
+
tier: "setup",
|
|
552
590
|
inputSchema: keywordsInputSchema,
|
|
553
591
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
554
592
|
openApiOperations: ["PUT /api/v1/projects/{name}/keywords"],
|
|
@@ -561,6 +599,7 @@ var canonryMcpTools = [
|
|
|
561
599
|
title: "Trigger run",
|
|
562
600
|
description: "Trigger an answer-visibility run for a Canonry project.",
|
|
563
601
|
access: "write",
|
|
602
|
+
tier: "core",
|
|
564
603
|
inputSchema: runTriggerInputSchema,
|
|
565
604
|
annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
|
|
566
605
|
openApiOperations: ["POST /api/v1/projects/{name}/runs"],
|
|
@@ -571,6 +610,7 @@ var canonryMcpTools = [
|
|
|
571
610
|
title: "Cancel run",
|
|
572
611
|
description: "Cancel a queued or running Canonry run.",
|
|
573
612
|
access: "write",
|
|
613
|
+
tier: "core",
|
|
574
614
|
inputSchema: runGetInputSchema,
|
|
575
615
|
annotations: writeAnnotations({ idempotentHint: false, destructiveHint: true }),
|
|
576
616
|
openApiOperations: ["POST /api/v1/runs/{id}/cancel"],
|
|
@@ -581,6 +621,7 @@ var canonryMcpTools = [
|
|
|
581
621
|
title: "Add keywords",
|
|
582
622
|
description: "Append tracked keywords to a Canonry project; existing keywords are skipped by the API.",
|
|
583
623
|
access: "write",
|
|
624
|
+
tier: "setup",
|
|
584
625
|
inputSchema: keywordsInputSchema,
|
|
585
626
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
586
627
|
openApiOperations: ["POST /api/v1/projects/{name}/keywords"],
|
|
@@ -593,6 +634,7 @@ var canonryMcpTools = [
|
|
|
593
634
|
title: "Remove keywords",
|
|
594
635
|
description: "Remove tracked keywords from a Canonry project.",
|
|
595
636
|
access: "write",
|
|
637
|
+
tier: "setup",
|
|
596
638
|
inputSchema: keywordsInputSchema,
|
|
597
639
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
598
640
|
openApiOperations: ["DELETE /api/v1/projects/{name}/keywords"],
|
|
@@ -605,6 +647,7 @@ var canonryMcpTools = [
|
|
|
605
647
|
title: "Add competitors",
|
|
606
648
|
description: "Add tracked competitor domains to a Canonry project.",
|
|
607
649
|
access: "write",
|
|
650
|
+
tier: "setup",
|
|
608
651
|
inputSchema: competitorsInputSchema,
|
|
609
652
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
610
653
|
openApiOperations: ["POST /api/v1/projects/{name}/competitors"],
|
|
@@ -617,6 +660,7 @@ var canonryMcpTools = [
|
|
|
617
660
|
title: "Remove competitors",
|
|
618
661
|
description: "Remove tracked competitor domains from a Canonry project.",
|
|
619
662
|
access: "write",
|
|
663
|
+
tier: "setup",
|
|
620
664
|
inputSchema: competitorsInputSchema,
|
|
621
665
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
622
666
|
openApiOperations: ["DELETE /api/v1/projects/{name}/competitors"],
|
|
@@ -629,6 +673,7 @@ var canonryMcpTools = [
|
|
|
629
673
|
title: "Set schedule",
|
|
630
674
|
description: "Create or replace the scheduled run configuration for a Canonry project.",
|
|
631
675
|
access: "write",
|
|
676
|
+
tier: "setup",
|
|
632
677
|
inputSchema: scheduleSetInputSchema,
|
|
633
678
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
634
679
|
openApiOperations: ["PUT /api/v1/projects/{name}/schedule"],
|
|
@@ -639,6 +684,7 @@ var canonryMcpTools = [
|
|
|
639
684
|
title: "Delete schedule",
|
|
640
685
|
description: "Delete the scheduled run configuration for a Canonry project.",
|
|
641
686
|
access: "write",
|
|
687
|
+
tier: "setup",
|
|
642
688
|
inputSchema: projectInputSchema,
|
|
643
689
|
annotations: writeAnnotations({ idempotentHint: false, destructiveHint: true }),
|
|
644
690
|
openApiOperations: ["DELETE /api/v1/projects/{name}/schedule"],
|
|
@@ -651,6 +697,7 @@ var canonryMcpTools = [
|
|
|
651
697
|
title: "Dismiss insight",
|
|
652
698
|
description: "Dismiss an intelligence insight for a Canonry project.",
|
|
653
699
|
access: "write",
|
|
700
|
+
tier: "setup",
|
|
654
701
|
inputSchema: insightInputSchema,
|
|
655
702
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
656
703
|
openApiOperations: ["POST /api/v1/projects/{name}/insights/{id}/dismiss"],
|
|
@@ -661,6 +708,7 @@ var canonryMcpTools = [
|
|
|
661
708
|
title: "Attach agent webhook",
|
|
662
709
|
description: "Attach an external agent webhook to project run and insight events.",
|
|
663
710
|
access: "write",
|
|
711
|
+
tier: "core",
|
|
664
712
|
inputSchema: agentWebhookAttachInputSchema,
|
|
665
713
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
666
714
|
openApiOperations: ["GET /api/v1/projects/{name}/notifications", "POST /api/v1/projects/{name}/notifications"],
|
|
@@ -685,6 +733,7 @@ var canonryMcpTools = [
|
|
|
685
733
|
title: "Detach agent webhook",
|
|
686
734
|
description: "Detach the external agent webhook for a Canonry project.",
|
|
687
735
|
access: "write",
|
|
736
|
+
tier: "agent",
|
|
688
737
|
inputSchema: projectInputSchema,
|
|
689
738
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
690
739
|
openApiOperations: ["GET /api/v1/projects/{name}/notifications", "DELETE /api/v1/projects/{name}/notifications/{id}"],
|
|
@@ -701,6 +750,7 @@ var canonryMcpTools = [
|
|
|
701
750
|
];
|
|
702
751
|
var CANONRY_MCP_TOOL_COUNT = canonryMcpTools.length;
|
|
703
752
|
var CANONRY_MCP_READ_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.access === "read").length;
|
|
753
|
+
var CANONRY_MCP_CORE_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.tier === "core").length;
|
|
704
754
|
|
|
705
755
|
// src/mcp/results.ts
|
|
706
756
|
function jsonToolResult(value) {
|
|
@@ -772,8 +822,119 @@ function hasErrorEnvelope(value) {
|
|
|
772
822
|
return Boolean(error && typeof error === "object");
|
|
773
823
|
}
|
|
774
824
|
|
|
825
|
+
// src/mcp/toolkits.ts
|
|
826
|
+
var CANONRY_MCP_TOOLKIT_NAMES = ["monitoring", "setup", "gsc", "ga", "agent"];
|
|
827
|
+
var CANONRY_MCP_TOOLKITS = [
|
|
828
|
+
{
|
|
829
|
+
name: "monitoring",
|
|
830
|
+
title: "Runs, snapshots, insights, health",
|
|
831
|
+
description: "Inspect run history, query snapshots, intelligence insights, and health timelines.",
|
|
832
|
+
whenToLoad: "Load when investigating regressions, comparing runs, or reviewing insights and health history."
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
name: "setup",
|
|
836
|
+
title: "Project configuration",
|
|
837
|
+
description: "Manage keywords, competitors, schedules, project upsert, and config-as-code roundtrips.",
|
|
838
|
+
whenToLoad: "Load when onboarding a new project or editing tracked keywords, competitors, or schedules."
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
name: "gsc",
|
|
842
|
+
title: "Google Search Console",
|
|
843
|
+
description: "Read GSC performance, inspections, coverage, sitemaps, and deindexed URLs.",
|
|
844
|
+
whenToLoad: "Load when you need indexing, coverage, or sitemap data from Google Search Console."
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
name: "ga",
|
|
848
|
+
title: "Google Analytics 4",
|
|
849
|
+
description: "Read GA traffic, AI/social referral history, attribution trend, and session history.",
|
|
850
|
+
whenToLoad: "Load when you need traffic, referral, or attribution data from Google Analytics 4."
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
name: "agent",
|
|
854
|
+
title: "Agent webhook lifecycle",
|
|
855
|
+
description: "Detach the configured external-agent webhook from a project.",
|
|
856
|
+
whenToLoad: "Load when removing an agent webhook subscription. (Attach lives in the core tier.)"
|
|
857
|
+
}
|
|
858
|
+
];
|
|
859
|
+
function isCanonryMcpToolkitName(value) {
|
|
860
|
+
return CANONRY_MCP_TOOLKIT_NAMES.includes(value);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/mcp/dynamic-catalog.ts
|
|
864
|
+
var DynamicToolCatalog = class {
|
|
865
|
+
entries;
|
|
866
|
+
loaded = /* @__PURE__ */ new Set();
|
|
867
|
+
eager;
|
|
868
|
+
scope;
|
|
869
|
+
constructor(entries, scope, options = {}) {
|
|
870
|
+
this.entries = entries;
|
|
871
|
+
this.scope = scope;
|
|
872
|
+
this.eager = Boolean(options.eager);
|
|
873
|
+
if (this.eager) {
|
|
874
|
+
for (const toolkit of CANONRY_MCP_TOOLKITS) {
|
|
875
|
+
if (this.toolsForToolkit(toolkit.name).length > 0) {
|
|
876
|
+
this.loaded.add(toolkit.name);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
applyInitialEnablement() {
|
|
882
|
+
if (this.eager) return;
|
|
883
|
+
for (const entry of this.entries) {
|
|
884
|
+
if (entry.tool.tier !== "core") entry.registered.disable();
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
loadToolkit(rawName) {
|
|
888
|
+
if (!isCanonryMcpToolkitName(rawName)) {
|
|
889
|
+
const valid = CANONRY_MCP_TOOLKITS.map((t) => t.name).join(", ");
|
|
890
|
+
throw new Error(`Unknown toolkit "${rawName}". Available: ${valid}.`);
|
|
891
|
+
}
|
|
892
|
+
const name = rawName;
|
|
893
|
+
const matches = this.entries.filter((entry) => entry.tool.tier === name);
|
|
894
|
+
if (matches.length === 0) {
|
|
895
|
+
return { status: "empty", name, tools: [] };
|
|
896
|
+
}
|
|
897
|
+
if (this.loaded.has(name)) {
|
|
898
|
+
return { status: "already-loaded", name, tools: matches.map((entry) => entry.tool.name) };
|
|
899
|
+
}
|
|
900
|
+
for (const entry of matches) {
|
|
901
|
+
entry.registered.enable();
|
|
902
|
+
}
|
|
903
|
+
this.loaded.add(name);
|
|
904
|
+
return { status: "loaded", name, tools: matches.map((entry) => entry.tool.name) };
|
|
905
|
+
}
|
|
906
|
+
helpResult() {
|
|
907
|
+
return {
|
|
908
|
+
scope: this.scope,
|
|
909
|
+
eager: this.eager,
|
|
910
|
+
loadedToolkits: [...this.loaded].sort(),
|
|
911
|
+
coreTools: this.entries.filter((entry) => entry.tool.tier === "core").map((entry) => entry.tool.name),
|
|
912
|
+
toolkits: CANONRY_MCP_TOOLKITS.map((toolkit) => this.toolkitEntry(toolkit)).filter((entry) => entry.toolCount > 0),
|
|
913
|
+
usage: "Call canonry_load_toolkit with one of the toolkit names listed in `toolkits[].name` to register its tools for the rest of this session."
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
toolkitEntry(toolkit) {
|
|
917
|
+
const tools = this.toolsForToolkit(toolkit.name);
|
|
918
|
+
return {
|
|
919
|
+
name: toolkit.name,
|
|
920
|
+
title: toolkit.title,
|
|
921
|
+
description: toolkit.description,
|
|
922
|
+
whenToLoad: toolkit.whenToLoad,
|
|
923
|
+
toolCount: tools.length,
|
|
924
|
+
tools,
|
|
925
|
+
loaded: this.loaded.has(toolkit.name)
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
toolsForToolkit(name) {
|
|
929
|
+
return this.entries.filter((entry) => entry.tool.tier === name).map((entry) => entry.tool.name);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
|
|
775
933
|
// src/mcp/server.ts
|
|
776
934
|
function createCanonryMcpServer(options = {}) {
|
|
935
|
+
return createCanonryMcpServerWithCatalog(options).server;
|
|
936
|
+
}
|
|
937
|
+
function createCanonryMcpServerWithCatalog(options = {}) {
|
|
777
938
|
const clientFactory = options.clientFactory ?? createApiClient;
|
|
778
939
|
const client = clientFactory();
|
|
779
940
|
const scope = options.scope ?? "all";
|
|
@@ -781,10 +942,11 @@ function createCanonryMcpServer(options = {}) {
|
|
|
781
942
|
name: "canonry",
|
|
782
943
|
version: PACKAGE_VERSION
|
|
783
944
|
});
|
|
945
|
+
const entries = [];
|
|
784
946
|
for (const registryTool of getCanonryMcpTools(scope)) {
|
|
785
947
|
const tool = registryTool;
|
|
786
948
|
const handler = tool.handler;
|
|
787
|
-
server.registerTool(
|
|
949
|
+
const registered = server.registerTool(
|
|
788
950
|
tool.name,
|
|
789
951
|
{
|
|
790
952
|
title: tool.title,
|
|
@@ -794,8 +956,36 @@ function createCanonryMcpServer(options = {}) {
|
|
|
794
956
|
},
|
|
795
957
|
async (input) => withToolErrors(() => handler(client, input))
|
|
796
958
|
);
|
|
959
|
+
entries.push({ tool, registered });
|
|
797
960
|
}
|
|
798
|
-
|
|
961
|
+
const catalog = new DynamicToolCatalog(entries, scope, { eager: options.eager });
|
|
962
|
+
catalog.applyInitialEnablement();
|
|
963
|
+
registerMetaTools(server, catalog);
|
|
964
|
+
return { server, catalog };
|
|
965
|
+
}
|
|
966
|
+
function registerMetaTools(server, catalog) {
|
|
967
|
+
server.registerTool(
|
|
968
|
+
"canonry_help",
|
|
969
|
+
{
|
|
970
|
+
title: "List Canonry MCP toolkits",
|
|
971
|
+
description: "List available toolkits and which are loaded. Call before canonry_load_toolkit if unsure which to load.",
|
|
972
|
+
inputSchema: {},
|
|
973
|
+
annotations: { readOnlyHint: true }
|
|
974
|
+
},
|
|
975
|
+
async () => withToolErrors(async () => catalog.helpResult())
|
|
976
|
+
);
|
|
977
|
+
server.registerTool(
|
|
978
|
+
"canonry_load_toolkit",
|
|
979
|
+
{
|
|
980
|
+
title: "Load a Canonry MCP toolkit",
|
|
981
|
+
description: "Register a toolkit's tools for this session and emit notifications/tools/list_changed. Idempotent. Loaded toolkits remain loaded for the rest of the session.",
|
|
982
|
+
inputSchema: {
|
|
983
|
+
name: z3.enum(CANONRY_MCP_TOOLKIT_NAMES).describe("Toolkit name. List options with canonry_help.")
|
|
984
|
+
},
|
|
985
|
+
annotations: { readOnlyHint: false, idempotentHint: true, destructiveHint: false }
|
|
986
|
+
},
|
|
987
|
+
async ({ name }) => withToolErrors(async () => catalog.loadToolkit(name))
|
|
988
|
+
);
|
|
799
989
|
}
|
|
800
990
|
function getCanonryMcpTools(scope = "all") {
|
|
801
991
|
return scope === "read-only" ? canonryMcpTools.filter((tool) => tool.access === "read") : [...canonryMcpTools];
|
|
@@ -803,17 +993,23 @@ function getCanonryMcpTools(scope = "all") {
|
|
|
803
993
|
|
|
804
994
|
// src/mcp/cli.ts
|
|
805
995
|
async function main(argv = process.argv.slice(2)) {
|
|
806
|
-
const
|
|
996
|
+
const options = parseCliOptions(argv);
|
|
997
|
+
const server = createCanonryMcpServer({ scope: options.scope, eager: options.eager });
|
|
807
998
|
await server.connect(new StdioServerTransport());
|
|
808
999
|
}
|
|
809
|
-
function
|
|
810
|
-
let scope = normalizeScope(
|
|
1000
|
+
function parseCliOptions(argv, env = process.env) {
|
|
1001
|
+
let scope = normalizeScope(env.CANONRY_MCP_SCOPE);
|
|
1002
|
+
let eager = parseEagerEnv(env.CANONRY_MCP_EAGER);
|
|
811
1003
|
for (let i = 0; i < argv.length; i += 1) {
|
|
812
1004
|
const arg = argv[i];
|
|
813
1005
|
if (arg === "--read-only") {
|
|
814
1006
|
scope = "read-only";
|
|
815
1007
|
continue;
|
|
816
1008
|
}
|
|
1009
|
+
if (arg === "--eager") {
|
|
1010
|
+
eager = true;
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
817
1013
|
if (arg === "--scope") {
|
|
818
1014
|
const next = argv[i + 1];
|
|
819
1015
|
if (!next) throw new Error("Missing value for --scope");
|
|
@@ -827,13 +1023,18 @@ function parseScope(argv, envScope = process.env.CANONRY_MCP_SCOPE) {
|
|
|
827
1023
|
}
|
|
828
1024
|
throw new Error(`Unknown canonry-mcp argument: ${arg}`);
|
|
829
1025
|
}
|
|
830
|
-
return scope;
|
|
1026
|
+
return { scope, eager };
|
|
831
1027
|
}
|
|
832
1028
|
function normalizeScope(value) {
|
|
833
1029
|
if (!value || value === "all") return "all";
|
|
834
1030
|
if (value === "read-only") return "read-only";
|
|
835
1031
|
throw new Error(`Invalid MCP scope "${value}". Expected "all" or "read-only".`);
|
|
836
1032
|
}
|
|
1033
|
+
function parseEagerEnv(value) {
|
|
1034
|
+
if (!value) return false;
|
|
1035
|
+
const normalized = value.trim().toLowerCase();
|
|
1036
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
1037
|
+
}
|
|
837
1038
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
838
1039
|
main().catch((error) => {
|
|
839
1040
|
const message = error instanceof Error ? error.message : "canonry-mcp failed";
|
|
@@ -844,5 +1045,5 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
844
1045
|
}
|
|
845
1046
|
export {
|
|
846
1047
|
main,
|
|
847
|
-
|
|
1048
|
+
parseCliOptions
|
|
848
1049
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -61,19 +61,19 @@
|
|
|
61
61
|
"tsx": "^4.19.0",
|
|
62
62
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
63
63
|
"@ainyc/canonry-config": "0.0.0",
|
|
64
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
64
65
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
65
66
|
"@ainyc/canonry-db": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
67
67
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
68
|
-
"@ainyc/canonry-integration-
|
|
68
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
69
69
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-integration-
|
|
71
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
72
72
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
73
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
75
73
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-provider-
|
|
74
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
76
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
79
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|