@canonry/canonry 7.32.0 → 7.44.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/assets/agent-workspace/skills/aero/references/agent-operations.md +9 -0
- package/assets/agent-workspace/skills/aero/references/site-health.md +12 -0
- package/assets/agent-workspace/skills/canonry/SKILL.md +9 -0
- package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +24 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +207 -4
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +14 -2
- package/assets/assets/{AuditHistoryPanel-cQyVA85P.js → AuditHistoryPanel-CvANw3ds.js} +1 -1
- package/assets/assets/{BacklinksPage-UGZ_9N7F.js → BacklinksPage-C6x9ELjk.js} +1 -1
- package/assets/assets/{HistoryPage-UJVFZ5LK.js → HistoryPage-r36HX1cC.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-ChpOxQfx.js → MeasurementPropertyPage-ComoCzR4.js} +3 -3
- package/assets/assets/ProjectPage-CIeU-buk.js +8 -0
- package/assets/assets/RunsPage-DI6eJATZ.js +1 -0
- package/assets/assets/{SettingsPage-DeKxjuTr.js → SettingsPage-Bw7GdXxs.js} +1 -1
- package/assets/assets/{SiteHealthSection-COeVsgop.js → SiteHealthSection-C-JaNKpS.js} +3 -3
- package/assets/assets/{TrafficPage-DmMmeJKK.js → TrafficPage-Cnsp276v.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-CUehseZe.js → TrafficSourceDetailPage-CBIaJk7e.js} +1 -1
- package/assets/assets/{extract-error-message-BsxdS7Po.js → extract-error-message-C_Owa0n9.js} +1 -1
- package/assets/assets/index-ZS9sSTMS.js +86 -0
- package/assets/assets/{react-sigma_core.esm.min--MbbBWzJ.js → react-sigma_core.esm.min-ugyh-ooq.js} +1 -1
- package/assets/assets/{v2-overview-adapter-D-IScpdp.js → v2-overview-adapter-BLSrVQ7K.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/chunk-3JVF3ULD.js +550 -0
- package/dist/chunk-45Z5RJZW.js +562 -0
- package/dist/{chunk-QFXD7GR5.js → chunk-5LY7EG4U.js} +238 -20
- package/dist/chunk-EJRV7RBZ.js +23066 -0
- package/dist/{chunk-WRHA54BN.js → chunk-G47XJVAS.js} +5885 -3900
- package/dist/{chunk-42XUY243.js → chunk-GZ2KIONF.js} +11507 -10391
- package/dist/chunk-HGMYEDAQ.js +79 -0
- package/dist/{chunk-2C6NWFN4.js → chunk-JVBI6VBT.js} +2 -2
- package/dist/{chunk-ZIETXJYU.js → chunk-MPWBFKGK.js} +201 -104
- package/dist/{chunk-K5EGSSXC.js → chunk-QQYQDTFZ.js} +142 -47
- package/dist/{chunk-FW4GX2LO.js → chunk-SW54HXSZ.js} +3 -3
- package/dist/cli-catalog-PNJEQV5H.js +15 -0
- package/dist/cli-commands-4UT2CRXX.js +15 -0
- package/dist/cli.js +136 -22525
- package/dist/{demo-server-G5OK7SWE.js → demo-server-WRHR25HF.js} +5 -4
- package/dist/index.js +7 -6
- package/dist/{intelligence-service-3ZUVTIO7.js → intelligence-service-QXXRUB2G.js} +2 -2
- package/dist/mcp.js +30 -15
- package/package.json +10 -10
- package/assets/assets/ProjectPage-CvxuPSiC.js +0 -8
- package/assets/assets/RunsPage-C6U_YcDY.js +0 -1
- package/assets/assets/index-ahEr6Oc-.js +0 -86
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliError,
|
|
3
|
+
EXIT_SYSTEM_ERROR
|
|
4
|
+
} from "./chunk-HGMYEDAQ.js";
|
|
1
5
|
import {
|
|
2
6
|
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
3
7
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
@@ -7,6 +11,7 @@ import {
|
|
|
7
11
|
GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX,
|
|
8
12
|
LATEST_RUN_ID,
|
|
9
13
|
MEASUREMENT_DEFAULT_QUERY_CLASS,
|
|
14
|
+
OperationAccesses,
|
|
10
15
|
PROVIDER_ACCOUNT_FAILURE_STREAK,
|
|
11
16
|
PROVIDER_ACCOUNT_RETRY_HOURS,
|
|
12
17
|
RESEARCH_RUN_SCOPE,
|
|
@@ -27,6 +32,7 @@ import {
|
|
|
27
32
|
adsUnresolvedOperationListQuerySchema,
|
|
28
33
|
agentConversationCreateSchema,
|
|
29
34
|
apiKeyDtoSchema,
|
|
35
|
+
auditHistoryQuerySchema,
|
|
30
36
|
backlinkSourceSchema,
|
|
31
37
|
calendarDateSchema,
|
|
32
38
|
canonicalizeGtmAccountId,
|
|
@@ -35,7 +41,9 @@ import {
|
|
|
35
41
|
competitorAliasesRequestSchema,
|
|
36
42
|
competitorAppendRequestSchema,
|
|
37
43
|
competitorBatchRequestSchema,
|
|
44
|
+
competitorChangePreviewRequestSchema,
|
|
38
45
|
competitorLandscapeQuerySchema,
|
|
46
|
+
competitorSuggestionsQuerySchema,
|
|
39
47
|
contentTargetDismissRequestSchema,
|
|
40
48
|
describeError,
|
|
41
49
|
discoveryBucketSchema,
|
|
@@ -44,14 +52,17 @@ import {
|
|
|
44
52
|
discoveryRunRequestSchema,
|
|
45
53
|
feedbackAcceptedDtoSchema,
|
|
46
54
|
feedbackSubmissionSchema,
|
|
55
|
+
gaAcquisitionQuerySchema,
|
|
47
56
|
gaMeasurementAnalysisWindowSchema,
|
|
48
57
|
gaMeasurementHostScopeSchema,
|
|
49
58
|
gaSearchLandingWindowSchema,
|
|
50
59
|
googleAdsMetricsWindowSchema,
|
|
51
60
|
gscPerformanceOrderBySchema,
|
|
61
|
+
instanceStatusDtoSchema,
|
|
52
62
|
keywordBatchRequestSchema,
|
|
53
63
|
keywordGenerateRequestSchema,
|
|
54
64
|
logQuerySchema,
|
|
65
|
+
maxOperationAccess,
|
|
55
66
|
measurementChangesQuerySchema,
|
|
56
67
|
measurementDataQualityQuerySchema,
|
|
57
68
|
measurementDiscoveryRequestSchema,
|
|
@@ -94,9 +105,11 @@ import {
|
|
|
94
105
|
measurementQuestionResultQuerySchema,
|
|
95
106
|
notificationCreateRequestSchema,
|
|
96
107
|
notificationEventSchema,
|
|
108
|
+
operationAccess,
|
|
97
109
|
operationalLogListReadSchema,
|
|
98
110
|
organicEvidencePeriodSchema,
|
|
99
111
|
projectConfigSchema,
|
|
112
|
+
projectPatchRequestSchema,
|
|
100
113
|
projectUpsertRequestSchema,
|
|
101
114
|
providerQuotaPolicySchema,
|
|
102
115
|
providerReloadRequestSchema,
|
|
@@ -134,6 +147,9 @@ import {
|
|
|
134
147
|
sentimentSummaryIncludeSchema,
|
|
135
148
|
sentimentSummaryReadSchema,
|
|
136
149
|
settingsDtoSchema,
|
|
150
|
+
siteAuditIssueListQuerySchema,
|
|
151
|
+
siteAuditIssuePagesResponseSchema,
|
|
152
|
+
siteAuditIssuesResponseSchema,
|
|
137
153
|
siteAuditPageBudgetSchema,
|
|
138
154
|
snapshotRequestInputSchema,
|
|
139
155
|
telemetryStatusDtoSchema,
|
|
@@ -142,77 +158,11 @@ import {
|
|
|
142
158
|
trafficConnectVercelRequestSchema,
|
|
143
159
|
trafficConnectWordpressRequestSchema,
|
|
144
160
|
trafficEventKindSchema,
|
|
161
|
+
trafficSamplesQuerySchema,
|
|
145
162
|
trafficSeriesGranularitySchema,
|
|
146
163
|
visibilityCompareSelectionSchema,
|
|
147
164
|
visibilityReportRequestSchema
|
|
148
|
-
} from "./chunk-
|
|
149
|
-
|
|
150
|
-
// src/support-links.ts
|
|
151
|
-
var CANONRY_DISCORD_URL = "https://discord.gg/jnJ2H2z5Xh";
|
|
152
|
-
var CANONRY_ISSUES_URL = "https://github.com/Canonry/canonry/issues";
|
|
153
|
-
|
|
154
|
-
// src/cli-error.ts
|
|
155
|
-
function isMachineFormat(format) {
|
|
156
|
-
return format === "json" || format === "jsonl";
|
|
157
|
-
}
|
|
158
|
-
var EXIT_USER_ERROR = 1;
|
|
159
|
-
var EXIT_SYSTEM_ERROR = 2;
|
|
160
|
-
var CliError = class extends Error {
|
|
161
|
-
code;
|
|
162
|
-
displayMessage;
|
|
163
|
-
details;
|
|
164
|
-
exitCode;
|
|
165
|
-
constructor(options) {
|
|
166
|
-
super(options.message);
|
|
167
|
-
this.name = "CliError";
|
|
168
|
-
this.code = options.code;
|
|
169
|
-
this.displayMessage = options.displayMessage;
|
|
170
|
-
this.details = options.details;
|
|
171
|
-
this.exitCode = options.exitCode ?? EXIT_USER_ERROR;
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
function usageError(displayMessage, options) {
|
|
175
|
-
const firstLine = displayMessage.split("\n", 1)[0] ?? "Error: invalid command usage";
|
|
176
|
-
return new CliError({
|
|
177
|
-
code: "CLI_USAGE_ERROR",
|
|
178
|
-
message: options?.message ?? firstLine.replace(/^Error:\s*/, ""),
|
|
179
|
-
displayMessage,
|
|
180
|
-
details: options?.details
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
function isEndpointMissing(err) {
|
|
184
|
-
if (!(err instanceof CliError)) return false;
|
|
185
|
-
const status = err.details?.httpStatus;
|
|
186
|
-
return status === 404 || status === 405;
|
|
187
|
-
}
|
|
188
|
-
function systemError(message, options) {
|
|
189
|
-
return new CliError({
|
|
190
|
-
code: "CLI_SYSTEM_ERROR",
|
|
191
|
-
message,
|
|
192
|
-
displayMessage: options?.displayMessage,
|
|
193
|
-
details: options?.details,
|
|
194
|
-
exitCode: EXIT_SYSTEM_ERROR
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
function printCliError(err, format) {
|
|
198
|
-
if (isMachineFormat(format)) {
|
|
199
|
-
const envelope = err instanceof CliError ? { error: { code: err.code, message: err.message, ...err.details ? { details: err.details } : {} } } : { error: { code: "CLI_ERROR", message: err instanceof Error ? err.message : "An unexpected error occurred" } };
|
|
200
|
-
console.error(JSON.stringify(envelope, null, format === "jsonl" ? 0 : 2));
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (err instanceof CliError && err.displayMessage) {
|
|
204
|
-
console.error(err.displayMessage);
|
|
205
|
-
} else if (err instanceof Error) {
|
|
206
|
-
console.error(`Error: ${err.message}`);
|
|
207
|
-
} else {
|
|
208
|
-
console.error("An unexpected error occurred");
|
|
209
|
-
}
|
|
210
|
-
const unexpected = !(err instanceof CliError) || err.exitCode === EXIT_SYSTEM_ERROR;
|
|
211
|
-
if (unexpected && process.stderr.isTTY) {
|
|
212
|
-
console.error(`
|
|
213
|
-
Need help? Run 'canonry support' or ask in the Canonry Discord: ${CANONRY_DISCORD_URL}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
165
|
+
} from "./chunk-GZ2KIONF.js";
|
|
216
166
|
|
|
217
167
|
// src/package-version.ts
|
|
218
168
|
import { createRequire } from "module";
|
|
@@ -389,6 +339,13 @@ var writeAnnotations = (opts) => ({
|
|
|
389
339
|
destructiveHint: Boolean(opts.destructiveHint),
|
|
390
340
|
...opts.openWorldHint ? { openWorldHint: opts.openWorldHint } : {}
|
|
391
341
|
});
|
|
342
|
+
function toolOperationAccess(tool) {
|
|
343
|
+
const derived = maxOperationAccess(tool.openApiOperations.map((operation) => {
|
|
344
|
+
const separator = operation.indexOf(" ");
|
|
345
|
+
return separator < 0 ? OperationAccesses.stored : operationAccess(operation.slice(0, separator), operation.slice(separator + 1));
|
|
346
|
+
}));
|
|
347
|
+
return tool.access === "write" ? OperationAccesses.write : derived;
|
|
348
|
+
}
|
|
392
349
|
function defineTool(tool) {
|
|
393
350
|
return {
|
|
394
351
|
...tool,
|
|
@@ -542,6 +499,7 @@ var measurementDraftActionOpenApiOperations = [
|
|
|
542
499
|
"POST /api/v1/projects/{name}/measurement-plan/draft/actions/discard"
|
|
543
500
|
];
|
|
544
501
|
var runsListInputSchema = z3.object({
|
|
502
|
+
since: z3.string().optional().describe("Inclusive ISO 8601 lower bound on creation time. Omit to read all dates."),
|
|
545
503
|
project: projectNameSchema,
|
|
546
504
|
limit: z3.number().int().positive().max(500).optional(),
|
|
547
505
|
kind: runListFilterQuerySchema.shape.kind.describe('Restrict to a single run kind (e.g. "answer-visibility"). Unknown values are rejected.'),
|
|
@@ -563,12 +521,9 @@ var timelineInputSchema = z3.object({
|
|
|
563
521
|
limit: z3.number().int().positive().max(100).optional().describe("Restrict history to the most recent N project runs.")
|
|
564
522
|
});
|
|
565
523
|
var historyFilterShape = {
|
|
524
|
+
...auditHistoryQuerySchema.shape,
|
|
566
525
|
limit: z3.number().int().positive().max(500).optional(),
|
|
567
|
-
offset: z3.number().int().nonnegative().optional()
|
|
568
|
-
since: z3.string().optional().describe("ISO 8601 lower bound."),
|
|
569
|
-
action: z3.string().optional().describe("Exact audit action filter."),
|
|
570
|
-
actor: z3.string().optional().describe("Exact actor filter."),
|
|
571
|
-
entityType: z3.string().optional().describe("Exact entity type filter.")
|
|
526
|
+
offset: z3.number().int().nonnegative().optional()
|
|
572
527
|
};
|
|
573
528
|
var projectHistoryInputSchema = z3.object({ project: projectNameSchema, ...historyFilterShape });
|
|
574
529
|
var globalHistoryInputSchema = z3.object(historyFilterShape);
|
|
@@ -939,6 +894,12 @@ var competitorsAddInputSchema = z3.object({
|
|
|
939
894
|
project: projectNameSchema,
|
|
940
895
|
request: competitorAppendRequestSchema
|
|
941
896
|
});
|
|
897
|
+
var competitorChangePreviewInputSchema = z3.discriminatedUnion("change", [
|
|
898
|
+
competitorChangePreviewRequestSchema.options[0].extend({ project: projectNameSchema }),
|
|
899
|
+
competitorChangePreviewRequestSchema.options[1].extend({ project: projectNameSchema }),
|
|
900
|
+
competitorChangePreviewRequestSchema.options[2].extend({ project: projectNameSchema }),
|
|
901
|
+
competitorChangePreviewRequestSchema.options[3].extend({ project: projectNameSchema })
|
|
902
|
+
]);
|
|
942
903
|
var competitorDomainInputSchema = z3.string().trim().min(1).describe("Tracked competitor domain (any spelling; it resolves to the stored registrable domain).");
|
|
943
904
|
var competitorAliasesInputSchema = competitorAliasesRequestSchema.safeExtend({
|
|
944
905
|
project: projectNameSchema,
|
|
@@ -953,6 +914,9 @@ var competitorLandscapeInputSchema = competitorLandscapeQuerySchema.safeExtend({
|
|
|
953
914
|
project: projectNameSchema,
|
|
954
915
|
runId: z3.string().trim().min(1).optional().describe(latestSweepRunIdDescription)
|
|
955
916
|
}).strict();
|
|
917
|
+
var competitorSuggestionsInputSchema = competitorSuggestionsQuerySchema.safeExtend({
|
|
918
|
+
project: projectNameSchema
|
|
919
|
+
}).strict();
|
|
956
920
|
function latestSweepUnlessPooled(query) {
|
|
957
921
|
if (query.runId !== void 0 || query.window !== void 0) return query;
|
|
958
922
|
if (query.queryClass !== "branded" && query.queryClass !== "non-brand") return query;
|
|
@@ -962,6 +926,10 @@ var projectUpsertInputSchema = z3.object({
|
|
|
962
926
|
project: projectNameSchema,
|
|
963
927
|
request: projectUpsertRequestSchema
|
|
964
928
|
});
|
|
929
|
+
var projectPatchInputSchema = z3.object({
|
|
930
|
+
project: projectNameSchema,
|
|
931
|
+
request: projectPatchRequestSchema
|
|
932
|
+
});
|
|
965
933
|
var applyConfigInputSchema = z3.object({
|
|
966
934
|
config: projectConfigSchema
|
|
967
935
|
});
|
|
@@ -984,6 +952,10 @@ var doctorInputSchema = z3.object({
|
|
|
984
952
|
project: projectNameSchema.optional().describe("Project name to scope project-level checks. Omit to run global checks (provider keys, config, etc.)."),
|
|
985
953
|
checks: z3.array(z3.string().min(1)).optional().describe('Optional check IDs or wildcard prefixes (e.g. "google.auth.*", "config.providers"). Empty/omitted runs all matching checks for the chosen scope.')
|
|
986
954
|
});
|
|
955
|
+
var statusInputSchema = z3.object({
|
|
956
|
+
project: projectNameSchema.optional().describe("Optional project name. Omit to read every visible project."),
|
|
957
|
+
problems: z3.boolean().optional().describe("Return only failing, stale, or never-synced projects and integrations.")
|
|
958
|
+
});
|
|
987
959
|
var contentTargetsInputSchema = z3.object({
|
|
988
960
|
project: projectNameSchema,
|
|
989
961
|
limit: z3.number().int().positive().max(500).optional().describe("Max rows. Defaults to all. Use a small number (3-10) when summarizing for the user."),
|
|
@@ -1137,6 +1109,14 @@ var technicalAeoCrawlInputSchema = z3.object({
|
|
|
1137
1109
|
runId: crawlRunIdSchema,
|
|
1138
1110
|
date: calendarDateSchema.optional().describe("Exact UTC scan date YYYY-MM-DD, mutually exclusive with runId. A dated no-data result may include availableScanDates. When the user omitted the year, resolve it from matchingMonthDayDates and request that exact returned date before concluding the scan is missing. Never silently select another date.")
|
|
1139
1111
|
});
|
|
1112
|
+
var siteHealthIssuesInputSchema = siteAuditIssueListQuerySchema.extend({
|
|
1113
|
+
project: projectNameSchema,
|
|
1114
|
+
runId: siteAuditIssueListQuerySchema.shape.runId.describe("Select an exact saved scan. Omit for the default scan; use its returned runId for subsequent pages and issue details."),
|
|
1115
|
+
cursor: siteAuditIssueListQuerySchema.shape.cursor.describe("Opaque nextCursor from this same scan and issue feed.")
|
|
1116
|
+
});
|
|
1117
|
+
var siteHealthIssuePagesInputSchema = siteHealthIssuesInputSchema.extend({
|
|
1118
|
+
issueId: z3.string().min(1).describe("Exact issue ID from canonry_site_health_issues. Keep the returned runId when inspecting affected pages.")
|
|
1119
|
+
});
|
|
1140
1120
|
var siteHealthPageAuditInputSchema = z3.object({
|
|
1141
1121
|
project: projectNameSchema,
|
|
1142
1122
|
runId: crawlRunIdSchema,
|
|
@@ -1286,7 +1266,7 @@ var sentimentPreviewInputSchema = sentimentBackfillSelectionSchema.safeExtend({
|
|
|
1286
1266
|
if (input.from && input.to && Date.parse(input.from) > Date.parse(input.to)) ctx.addIssue({ code: "custom", message: "from must be at or before to" });
|
|
1287
1267
|
});
|
|
1288
1268
|
var sentimentBackfillInputSchema = sentimentBackfillRequestSchema.extend({ project: projectNameSchema });
|
|
1289
|
-
var
|
|
1269
|
+
var rawCanonryMcpTools = [
|
|
1290
1270
|
defineTool({
|
|
1291
1271
|
name: "canonry_sentiment_settings",
|
|
1292
1272
|
title: "Read sentiment readiness and settings",
|
|
@@ -1592,6 +1572,34 @@ var canonryMcpTools = [
|
|
|
1592
1572
|
return client.getCompetitorLandscape(project, latestSweepUnlessPooled(query));
|
|
1593
1573
|
}
|
|
1594
1574
|
}),
|
|
1575
|
+
defineTool({
|
|
1576
|
+
name: "canonry_competitors_suggest",
|
|
1577
|
+
title: "Suggest competitors from stored evidence",
|
|
1578
|
+
description: "Read stored completed and partial answer evidence and rank possible direct competitors. Candidate naming and citation counts are separate, cited-only domains are excluded, listing and marketplace surfaces are excluded, and the response discloses the answer and sweep denominator. No provider, discovery, classifier, or write operation runs. A Simple project without a usable brand alias pools all query classes and echoes queryClass=all. Use the returned evidence and sample URLs to review a candidate before tracking it.",
|
|
1579
|
+
access: "read",
|
|
1580
|
+
tier: "setup",
|
|
1581
|
+
inputSchema: competitorSuggestionsInputSchema,
|
|
1582
|
+
annotations: readAnnotations(),
|
|
1583
|
+
openApiOperations: ["GET /api/v1/projects/{name}/competitor-suggestions"],
|
|
1584
|
+
handler: (client, input) => {
|
|
1585
|
+
const { project, ...query } = input;
|
|
1586
|
+
return client.suggestCompetitors(project, query);
|
|
1587
|
+
}
|
|
1588
|
+
}),
|
|
1589
|
+
defineTool({
|
|
1590
|
+
name: "canonry_competitors_change_preview",
|
|
1591
|
+
title: "Preview competitor change impact",
|
|
1592
|
+
description: "Preview the stored-evidence share impact of one explicit competitor add, remove, replace, or curated alias change. It reads the latest completed or partial sweep and never writes competitors, aliases, history, or provider state. Use this before a separate write when an operator wants the before and after denominator and percentage-point delta. Ordinary competitor writes do not call this implicitly.",
|
|
1593
|
+
access: "read",
|
|
1594
|
+
tier: "setup",
|
|
1595
|
+
inputSchema: competitorChangePreviewInputSchema,
|
|
1596
|
+
annotations: readAnnotations(),
|
|
1597
|
+
openApiOperations: ["POST /api/v1/projects/{name}/competitor-changes/preview"],
|
|
1598
|
+
handler: (client, input) => {
|
|
1599
|
+
const { project, ...request } = input;
|
|
1600
|
+
return client.previewCompetitorChange(project, request);
|
|
1601
|
+
}
|
|
1602
|
+
}),
|
|
1595
1603
|
defineTool({
|
|
1596
1604
|
name: "canonry_search",
|
|
1597
1605
|
title: "Search project (composite)",
|
|
@@ -1618,10 +1626,22 @@ var canonryMcpTools = [
|
|
|
1618
1626
|
openApiOperations: ["GET /api/v1/doctor", "GET /api/v1/projects/{name}/doctor"],
|
|
1619
1627
|
handler: (client, input) => client.runDoctor({ project: input.project, checkIds: input.checks, ...input.reportMonth ? { reportMonth: input.reportMonth } : {} })
|
|
1620
1628
|
}),
|
|
1629
|
+
defineTool({
|
|
1630
|
+
name: "canonry_status",
|
|
1631
|
+
title: "Read integration status",
|
|
1632
|
+
description: "Read stored synchronization status for one project or the instance. This is a read-only local database read and never calls providers or runs doctor checks.",
|
|
1633
|
+
access: "read",
|
|
1634
|
+
tier: "core",
|
|
1635
|
+
inputSchema: statusInputSchema,
|
|
1636
|
+
outputSchema: instanceStatusDtoSchema,
|
|
1637
|
+
annotations: readAnnotations(),
|
|
1638
|
+
openApiOperations: ["GET /api/v1/status"],
|
|
1639
|
+
handler: (client, input) => client.getStatus({ project: input.project, problems: input.problems })
|
|
1640
|
+
}),
|
|
1621
1641
|
defineTool({
|
|
1622
1642
|
name: "canonry_project_export",
|
|
1623
1643
|
title: "Export project config",
|
|
1624
|
-
description: "Export a Canonry project in config-as-code format.",
|
|
1644
|
+
description: "Export a Canonry project in config-as-code format. Notification webhook URLs are always redacted for MCP.",
|
|
1625
1645
|
access: "read",
|
|
1626
1646
|
tier: "setup",
|
|
1627
1647
|
inputSchema: projectInputSchema,
|
|
@@ -1653,6 +1673,10 @@ var canonryMcpTools = [
|
|
|
1653
1673
|
limit: input.limit,
|
|
1654
1674
|
offset: input.offset,
|
|
1655
1675
|
since: input.since,
|
|
1676
|
+
until: input.until,
|
|
1677
|
+
actionPrefix: input.actionPrefix,
|
|
1678
|
+
excludeEntityTypes: input.excludeEntityTypes,
|
|
1679
|
+
entityId: input.entityId,
|
|
1656
1680
|
action: input.action,
|
|
1657
1681
|
actor: input.actor,
|
|
1658
1682
|
entityType: input.entityType
|
|
@@ -1672,13 +1696,13 @@ var canonryMcpTools = [
|
|
|
1672
1696
|
defineTool({
|
|
1673
1697
|
name: "canonry_runs_list",
|
|
1674
1698
|
title: "List project runs",
|
|
1675
|
-
description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications
|
|
1699
|
+
description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications; filter by `trigger !== 'probe'` if you only want runs that feed project metrics. Narrow with `kind` and/or `status` (e.g. status='running' lists only in-flight work). Use `excludeKind` or `excludeKinds` to remove kinds before applying the limit. `since` bounds creation time; omitting limit returns every matching run.",
|
|
1676
1700
|
access: "read",
|
|
1677
1701
|
tier: "monitoring",
|
|
1678
1702
|
inputSchema: runsListInputSchema,
|
|
1679
1703
|
annotations: readAnnotations(),
|
|
1680
1704
|
openApiOperations: ["GET /api/v1/projects/{name}/runs"],
|
|
1681
|
-
handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status, input.excludeKind, input.excludeKinds)
|
|
1705
|
+
handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status, input.excludeKind, input.excludeKinds, input.since)
|
|
1682
1706
|
}),
|
|
1683
1707
|
defineTool({
|
|
1684
1708
|
name: "canonry_runs_latest",
|
|
@@ -2265,11 +2289,11 @@ var canonryMcpTools = [
|
|
|
2265
2289
|
defineTool({
|
|
2266
2290
|
name: "canonry_bing_coverage",
|
|
2267
2291
|
title: "Get Bing coverage",
|
|
2268
|
-
description: "Read
|
|
2269
|
-
access: "
|
|
2292
|
+
description: "Read Bing index coverage counts and URL inspections for a Canonry project. The route records an idempotent daily coverage snapshot while returning the result, but does not call Bing or start a sync. Preserves indexed, not indexed and unknown evidence, the server percentage and last inspection time. Project-wide for Simple and Advanced portfolios; Property, Target and market attribution are unavailable. Requires the existing Bing connection.",
|
|
2293
|
+
access: "write",
|
|
2270
2294
|
tier: "bing",
|
|
2271
2295
|
inputSchema: projectInputSchema,
|
|
2272
|
-
annotations:
|
|
2296
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
2273
2297
|
openApiOperations: ["GET /api/v1/projects/{name}/bing/coverage"],
|
|
2274
2298
|
handler: (client, input) => client.bingCoverage(input.project)
|
|
2275
2299
|
}),
|
|
@@ -2317,6 +2341,20 @@ var canonryMcpTools = [
|
|
|
2317
2341
|
openApiOperations: ["GET /api/v1/projects/{name}/ga/properties"],
|
|
2318
2342
|
handler: (client, input) => client.gaProperties(input.project)
|
|
2319
2343
|
}),
|
|
2344
|
+
defineTool({
|
|
2345
|
+
name: "canonry_ga_acquisition",
|
|
2346
|
+
title: "Read stored GA4 acquisition",
|
|
2347
|
+
description: "Read stored GA4 sessions by day, channel, source/medium, host and normalized landing page. Sessions only; totalSessions is the full filtered total, independent of grouping and pagination. No Google calls. Project-only attribution; stored rows cannot distinguish an older connected GA4 property. Meaningful page query parameters remain distinct.",
|
|
2348
|
+
access: "read",
|
|
2349
|
+
tier: "ga",
|
|
2350
|
+
inputSchema: gaAcquisitionQuerySchema.extend({ project: projectNameSchema, limit: z3.number().int().min(1).max(500).optional() }),
|
|
2351
|
+
annotations: readAnnotations(),
|
|
2352
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/acquisition"],
|
|
2353
|
+
handler: (client, input) => {
|
|
2354
|
+
const { project, ...query } = input;
|
|
2355
|
+
return client.gaAcquisition(project, query);
|
|
2356
|
+
}
|
|
2357
|
+
}),
|
|
2320
2358
|
defineTool({
|
|
2321
2359
|
name: "canonry_ga_measurement_analysis",
|
|
2322
2360
|
title: "Analyze GA acquisition and search demand",
|
|
@@ -2463,7 +2501,7 @@ var canonryMcpTools = [
|
|
|
2463
2501
|
access: "write",
|
|
2464
2502
|
tier: "gbp",
|
|
2465
2503
|
inputSchema: gbpDiscoverInputSchema,
|
|
2466
|
-
annotations: writeAnnotations({ idempotentHint: true }),
|
|
2504
|
+
annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
|
|
2467
2505
|
openApiOperations: ["POST /api/v1/projects/{name}/gbp/locations/discover"],
|
|
2468
2506
|
handler: (client, input) => client.discoverGbpLocations(input.project, {
|
|
2469
2507
|
selectAllNew: input.selectAllNew,
|
|
@@ -2501,7 +2539,7 @@ var canonryMcpTools = [
|
|
|
2501
2539
|
access: "write",
|
|
2502
2540
|
tier: "gbp",
|
|
2503
2541
|
inputSchema: gbpSyncInputSchema,
|
|
2504
|
-
annotations: writeAnnotations({ idempotentHint: true }),
|
|
2542
|
+
annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
|
|
2505
2543
|
openApiOperations: ["POST /api/v1/projects/{name}/gbp/sync"],
|
|
2506
2544
|
handler: (client, input) => client.triggerGbpSync(input.project, {
|
|
2507
2545
|
locationNames: input.locationNames,
|
|
@@ -2655,6 +2693,20 @@ var canonryMcpTools = [
|
|
|
2655
2693
|
return client.trafficReferralAssessment(project, query);
|
|
2656
2694
|
}
|
|
2657
2695
|
}),
|
|
2696
|
+
defineTool({
|
|
2697
|
+
name: "canonry_traffic_samples",
|
|
2698
|
+
title: "Read stored traffic samples",
|
|
2699
|
+
description: "Read the stored sampled tail of server-side traffic with 30-day retention. Sample rows are not a count of visits. Default kind excludes unknown requests. Project/source only; Property, Target and market dimensions are unavailable. No provider call or write.",
|
|
2700
|
+
access: "read",
|
|
2701
|
+
tier: "traffic",
|
|
2702
|
+
inputSchema: trafficSamplesQuerySchema.extend({ project: projectNameSchema }),
|
|
2703
|
+
annotations: readAnnotations(),
|
|
2704
|
+
openApiOperations: ["GET /api/v1/projects/{name}/traffic/samples"],
|
|
2705
|
+
handler: (client, input) => {
|
|
2706
|
+
const { project, ...query } = input;
|
|
2707
|
+
return client.trafficListSamples(project, query);
|
|
2708
|
+
}
|
|
2709
|
+
}),
|
|
2658
2710
|
defineTool({
|
|
2659
2711
|
name: "canonry_traffic_events",
|
|
2660
2712
|
title: "List traffic events",
|
|
@@ -2763,10 +2815,21 @@ var canonryMcpTools = [
|
|
|
2763
2815
|
openApiOperations: ["PUT /api/v1/projects/{name}"],
|
|
2764
2816
|
handler: (client, input) => client.putProject(input.project, input.request)
|
|
2765
2817
|
}),
|
|
2818
|
+
defineTool({
|
|
2819
|
+
name: "canonry_project_update",
|
|
2820
|
+
title: "Update project fields",
|
|
2821
|
+
description: "Update named fields on an existing Canonry project with PATCH semantics. Omitted fields keep their stored values, measurement merges one level, and expectedConfigRevision prevents overwriting a newer edit. Prefer this for targeted changes over canonry_project_upsert.",
|
|
2822
|
+
access: "write",
|
|
2823
|
+
tier: "setup",
|
|
2824
|
+
inputSchema: projectPatchInputSchema,
|
|
2825
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
2826
|
+
openApiOperations: ["PATCH /api/v1/projects/{name}"],
|
|
2827
|
+
handler: (client, input) => client.patchProject(input.project, input.request)
|
|
2828
|
+
}),
|
|
2766
2829
|
defineTool({
|
|
2767
2830
|
name: "canonry_apply_config",
|
|
2768
2831
|
title: "Apply project config",
|
|
2769
|
-
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode (off, preview or apply). For multi-document YAML, call this tool once per project document.",
|
|
2832
|
+
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode (off, preview or apply). For multi-document YAML, call this tool once per project document. Call canonry_apply_config_preview first.",
|
|
2770
2833
|
access: "write",
|
|
2771
2834
|
tier: "core",
|
|
2772
2835
|
inputSchema: applyConfigInputSchema,
|
|
@@ -2775,6 +2838,17 @@ var canonryMcpTools = [
|
|
|
2775
2838
|
openApiOperations: ["POST /api/v1/apply"],
|
|
2776
2839
|
handler: (client, input) => client.apply(input.config)
|
|
2777
2840
|
}),
|
|
2841
|
+
defineTool({
|
|
2842
|
+
name: "canonry_apply_config_preview",
|
|
2843
|
+
title: "Preview project config apply",
|
|
2844
|
+
description: "Preview one Canonry config-as-code project document. Returns per-field and child-resource changes with notification hosts only; the server resolves notification DNS to preserve the real apply verdict, then rolls back the transaction before responding, so no database writes, audit rows, or callbacks persist.",
|
|
2845
|
+
access: "read",
|
|
2846
|
+
tier: "core",
|
|
2847
|
+
inputSchema: applyConfigInputSchema,
|
|
2848
|
+
annotations: readAnnotations(),
|
|
2849
|
+
openApiOperations: ["POST /api/v1/apply/preview"],
|
|
2850
|
+
handler: (client, input) => client.previewApply(input.config)
|
|
2851
|
+
}),
|
|
2778
2852
|
defineTool({
|
|
2779
2853
|
name: "canonry_queries_generate",
|
|
2780
2854
|
title: "Generate query suggestions",
|
|
@@ -3329,20 +3403,18 @@ var canonryMcpTools = [
|
|
|
3329
3403
|
defineTool({
|
|
3330
3404
|
name: "canonry_competitors_add",
|
|
3331
3405
|
title: "Add competitors",
|
|
3332
|
-
description: "Add tracked competitor domains to a Canonry project. Each entry is a domain, or `{ domain, aliases }` to also add curated answer-text names to that competitor (tracked already or not; existing aliases are kept, the same rules as canonry_competitors_aliases_set apply). A new domain whose name overlaps another competitor's curated alias, or the label or a curated alias of a competitor an Advanced market pins (one brand key contains the other, so the alias \"Tune\" claims tunespoke.example), is rejected until that name is removed, and so is the project's own site. Already tracked domains (any spelling) are skipped.",
|
|
3406
|
+
description: "Use canonry_competitors_change_preview to inspect the stored share impact before this separate write. Measured projects require `acknowledgeBulkAdd: true` when new domains plus recent additions exceed the shared five-domain, 24-hour guard. Review with canonry_competitors_suggest or canonry_competitors_change_preview first; the built-in agent cannot acknowledge bulk growth. Add tracked competitor domains to a Canonry project. Each entry is a domain, or `{ domain, aliases }` to also add curated answer-text names to that competitor (tracked already or not; existing aliases are kept, the same rules as canonry_competitors_aliases_set apply). A new domain whose name overlaps another competitor's curated alias, or the label or a curated alias of a competitor an Advanced market pins (one brand key contains the other, so the alias \"Tune\" claims tunespoke.example), is rejected until that name is removed, and so is the project's own site. Already tracked domains (any spelling) are skipped.",
|
|
3333
3407
|
access: "write",
|
|
3334
3408
|
tier: "setup",
|
|
3335
3409
|
inputSchema: competitorsAddInputSchema,
|
|
3336
3410
|
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3337
3411
|
openApiOperations: ["POST /api/v1/projects/{name}/competitors"],
|
|
3338
|
-
handler:
|
|
3339
|
-
await client.appendCompetitors(input.project, input.request.competitors);
|
|
3340
|
-
}
|
|
3412
|
+
handler: (client, input) => client.appendCompetitors(input.project, input.request.competitors, { acknowledgeBulkAdd: input.request.acknowledgeBulkAdd })
|
|
3341
3413
|
}),
|
|
3342
3414
|
defineTool({
|
|
3343
3415
|
name: "canonry_competitors_aliases_set",
|
|
3344
3416
|
title: "Set competitor aliases",
|
|
3345
|
-
description: 'Set one tracked competitor\'s operator-curated aliases exactly (`[]` clears): the brand names it goes by in answer text when they differ from its domain, e.g. "TuneSpoke" for spoketuneworks.example or a 3-letter brand the domain label floor drops. Every competitor mention matcher (mention share, competitor landscape, mention gaps, run and history signals) uses them on stored answers at read time. Rejected: aliases under 3 letters or digits, over 80 characters, more than 10, or whose brand key contains, or sits inside, one of the project\'s own names or hosts or a name another tracked competitor answers to (its aliases, domain label or written host), because answers may split or join the words: "Tune" cannot belong to one competitor while another answers to "Tune Spoke", "TuneSpoke" or tunespoke.example, and joined-word lookalikes ("Tune" and "Tuner") are refused too. A competitor an Advanced market pins (active revision, pending draft, or a superseded revision the project\'s runs were measured under) counts as another competitor. Names detected automatically from stored answers (`autoAliases`) are matched the same way; a curated alias always wins, so an auto name the new list overlaps is dropped. Idempotent; returns the competitor.',
|
|
3417
|
+
description: 'Use canonry_competitors_change_preview to inspect the stored share impact before this separate write. Set one tracked competitor\'s operator-curated aliases exactly (`[]` clears): the brand names it goes by in answer text when they differ from its domain, e.g. "TuneSpoke" for spoketuneworks.example or a 3-letter brand the domain label floor drops. Every competitor mention matcher (mention share, competitor landscape, mention gaps, run and history signals) uses them on stored answers at read time. Rejected: aliases under 3 letters or digits, over 80 characters, more than 10, or whose brand key contains, or sits inside, one of the project\'s own names or hosts or a name another tracked competitor answers to (its aliases, domain label or written host), because answers may split or join the words: "Tune" cannot belong to one competitor while another answers to "Tune Spoke", "TuneSpoke" or tunespoke.example, and joined-word lookalikes ("Tune" and "Tuner") are refused too. A competitor an Advanced market pins (active revision, pending draft, or a superseded revision the project\'s runs were measured under) counts as another competitor. Names detected automatically from stored answers (`autoAliases`) are matched the same way; a curated alias always wins, so an auto name the new list overlaps is dropped. Idempotent; returns the competitor.',
|
|
3346
3418
|
access: "write",
|
|
3347
3419
|
tier: "setup",
|
|
3348
3420
|
inputSchema: competitorAliasesInputSchema,
|
|
@@ -3364,7 +3436,7 @@ var canonryMcpTools = [
|
|
|
3364
3436
|
defineTool({
|
|
3365
3437
|
name: "canonry_competitors_auto_aliases_apply",
|
|
3366
3438
|
title: "Apply competitor auto-aliases",
|
|
3367
|
-
description: "Run automatic competitor alias detection now from the project's stored answers and store the result, whatever the project's competitorAutoAliases mode (a one-off apply; a project in `apply` mode also gets this pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins). Stored names restate history at read time: every period's competitor counts change, and so does share of voice for a tracked competitor; competitorIdentityChangedAt on the landscape, project-frame visibility-compare and analytics metrics marks when. Idempotent: unchanged answers write nothing. Curated aliases and blocked names always win. A change is audited as the system pass plus competitors.auto-aliases-apply-requested naming who asked. Not available to the built-in Aero agent. Returns what was stored, per competitor, with evidence.",
|
|
3439
|
+
description: "Use canonry_competitors_auto_aliases_detect first to preview names and their stored share impact. Run automatic competitor alias detection now from the project's stored answers and store the result, whatever the project's competitorAutoAliases mode (a one-off apply; a project in `apply` mode also gets this pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins). Stored names restate history at read time: every period's competitor counts change, and so does share of voice for a tracked competitor; competitorIdentityChangedAt on the landscape, project-frame visibility-compare and analytics metrics marks when. Idempotent: unchanged answers write nothing. Curated aliases and blocked names always win. A change is audited as the system pass plus competitors.auto-aliases-apply-requested naming who asked. Not available to the built-in Aero agent. Returns what was stored, per competitor, with evidence.",
|
|
3368
3440
|
access: "write",
|
|
3369
3441
|
tier: "setup",
|
|
3370
3442
|
inputSchema: projectInputSchema,
|
|
@@ -3397,15 +3469,13 @@ var canonryMcpTools = [
|
|
|
3397
3469
|
defineTool({
|
|
3398
3470
|
name: "canonry_competitors_remove",
|
|
3399
3471
|
title: "Remove competitors",
|
|
3400
|
-
description: "Remove tracked competitor domains from a Canonry project.",
|
|
3472
|
+
description: "Use canonry_competitors_change_preview to inspect the stored share impact before this separate write. Remove tracked competitor domains from a Canonry project.",
|
|
3401
3473
|
access: "write",
|
|
3402
3474
|
tier: "setup",
|
|
3403
3475
|
inputSchema: competitorsInputSchema,
|
|
3404
3476
|
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3405
3477
|
openApiOperations: ["DELETE /api/v1/projects/{name}/competitors"],
|
|
3406
|
-
handler:
|
|
3407
|
-
await client.deleteCompetitors(input.project, uniqueStrings(input.request.competitors));
|
|
3408
|
-
}
|
|
3478
|
+
handler: (client, input) => client.deleteCompetitors(input.project, uniqueStrings(input.request.competitors))
|
|
3409
3479
|
}),
|
|
3410
3480
|
defineTool({
|
|
3411
3481
|
name: "canonry_schedule_set",
|
|
@@ -3714,6 +3784,38 @@ var canonryMcpTools = [
|
|
|
3714
3784
|
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo/crawl"],
|
|
3715
3785
|
handler: (client, input) => client.getTechnicalAeoCrawl(input.project, { runId: input.runId, date: input.date })
|
|
3716
3786
|
}),
|
|
3787
|
+
defineTool({
|
|
3788
|
+
name: "canonry_site_health_issues",
|
|
3789
|
+
title: "List stored Site Health issues",
|
|
3790
|
+
description: "Read paginated finding groups from a saved audit, including duplicate metadata and critical defects regardless of aggregate score. Never starts a crawl. Preserve scan date, run/attempt identity, coverage and partial/unavailable states: an empty result does not prove the site is clean. Disposition separates actionable findings, advisory guidance, unverified checks and information; severity retains the recorded critical-defect level. recommendationsScope distinguishes issue-specific defect guidance from whole-factor advice. stableIdentity=false means the ID cannot establish continuity across scans. Follow nextCursor with the returned runId, or inspect one issue with canonry_site_health_issue_pages.",
|
|
3791
|
+
access: "read",
|
|
3792
|
+
tier: "monitoring",
|
|
3793
|
+
inputSchema: siteHealthIssuesInputSchema,
|
|
3794
|
+
outputSchema: siteAuditIssuesResponseSchema,
|
|
3795
|
+
annotations: readAnnotations(),
|
|
3796
|
+
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo/issues"],
|
|
3797
|
+
handler: (client, input) => client.getSiteAuditIssues(input.project, {
|
|
3798
|
+
runId: input.runId,
|
|
3799
|
+
cursor: input.cursor,
|
|
3800
|
+
limit: input.limit
|
|
3801
|
+
})
|
|
3802
|
+
}),
|
|
3803
|
+
defineTool({
|
|
3804
|
+
name: "canonry_site_health_issue_pages",
|
|
3805
|
+
title: "Read pages affected by a saved audit issue",
|
|
3806
|
+
description: "Read paginated affected URLs and saved messages for one issue in the selected audit. Use the issue ID and runId from canonry_site_health_issues; continue with nextCursor without changing the selection. Null node keys and unavailable/partial coverage remain explicit. recommendationsScope identifies issue-specific defect guidance or broader factor advice; do not present factor advice as an exact fix for this finding. This stored read never crawls, changes content or authorizes edits.",
|
|
3807
|
+
access: "read",
|
|
3808
|
+
tier: "monitoring",
|
|
3809
|
+
inputSchema: siteHealthIssuePagesInputSchema,
|
|
3810
|
+
outputSchema: siteAuditIssuePagesResponseSchema,
|
|
3811
|
+
annotations: readAnnotations(),
|
|
3812
|
+
openApiOperations: ["GET /api/v1/projects/{name}/technical-aeo/issues/{issueId}/pages"],
|
|
3813
|
+
handler: (client, input) => client.getSiteAuditIssuePages(input.project, input.issueId, {
|
|
3814
|
+
runId: input.runId,
|
|
3815
|
+
cursor: input.cursor,
|
|
3816
|
+
limit: input.limit
|
|
3817
|
+
})
|
|
3818
|
+
}),
|
|
3717
3819
|
defineTool({
|
|
3718
3820
|
name: "canonry_site_health_page_audit",
|
|
3719
3821
|
title: "Get Site Health page audit",
|
|
@@ -4435,29 +4537,24 @@ var canonryMcpTools = [
|
|
|
4435
4537
|
access: "write",
|
|
4436
4538
|
tier: "ads",
|
|
4437
4539
|
inputSchema: projectInputSchema,
|
|
4438
|
-
annotations: writeAnnotations({ idempotentHint: true }),
|
|
4540
|
+
annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
|
|
4439
4541
|
openApiOperations: ["POST /api/v1/projects/{name}/ads/sync"],
|
|
4440
4542
|
handler: (client, input) => client.triggerAdsSync(input.project)
|
|
4441
4543
|
})
|
|
4442
4544
|
];
|
|
4545
|
+
var canonryMcpTools = rawCanonryMcpTools.map((tool) => {
|
|
4546
|
+
if (tool.access !== "read" || toolOperationAccess(tool) !== OperationAccesses.live) return tool;
|
|
4547
|
+
return { ...tool, annotations: { ...tool.annotations, openWorldHint: true } };
|
|
4548
|
+
});
|
|
4443
4549
|
var CanonryMcpToolNames = Object.freeze(
|
|
4444
4550
|
Object.fromEntries(canonryMcpTools.map((tool) => [tool.name, tool.name]))
|
|
4445
4551
|
);
|
|
4446
4552
|
|
|
4447
4553
|
export {
|
|
4448
|
-
CANONRY_DISCORD_URL,
|
|
4449
|
-
CANONRY_ISSUES_URL,
|
|
4450
|
-
isMachineFormat,
|
|
4451
|
-
EXIT_USER_ERROR,
|
|
4452
|
-
EXIT_SYSTEM_ERROR,
|
|
4453
|
-
CliError,
|
|
4454
|
-
usageError,
|
|
4455
|
-
isEndpointMissing,
|
|
4456
|
-
systemError,
|
|
4457
|
-
printCliError,
|
|
4458
4554
|
PACKAGE_VERSION,
|
|
4459
4555
|
measurementDraftOperationSchema,
|
|
4460
4556
|
runMeasurementDraftAction,
|
|
4557
|
+
toolOperationAccess,
|
|
4461
4558
|
canonryMcpTools,
|
|
4462
4559
|
CanonryMcpToolNames
|
|
4463
4560
|
};
|