@ainyc/canonry 4.194.0 → 4.195.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/canonry/SKILL.md +71 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +30 -0
- package/assets/assets/{AuditHistoryPanel-C8hUWnaD.js → AuditHistoryPanel-vWUtVXOI.js} +1 -1
- package/assets/assets/{BacklinksPage-BcIdghvA.js → BacklinksPage-CSzuMEuv.js} +1 -1
- package/assets/assets/{HistoryPage-DF7PLFi1.js → HistoryPage-DtCTQ7CQ.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-BTlXQbYt.js → MeasurementPropertyPage-B7gTMWNs.js} +1 -1
- package/assets/assets/{ProjectPage-YiZ_i5eX.js → ProjectPage-Bsm0_jUY.js} +1 -1
- package/assets/assets/{RunRow-CfzuyTSM.js → RunRow-D5k4Rdo4.js} +1 -1
- package/assets/assets/{RunsPage-Diu_-YWl.js → RunsPage-DIXBB2Om.js} +1 -1
- package/assets/assets/{SettingsPage-g93aqkg2.js → SettingsPage-wYhBm6Az.js} +1 -1
- package/assets/assets/{SiteHealthSection-DroMQJVF.js → SiteHealthSection-YebzsgDh.js} +3 -3
- package/assets/assets/{TrafficPage-BhHjy5Ee.js → TrafficPage-DtnSRFO8.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DI3aZIHo.js → TrafficSourceDetailPage-DYQ6mpYq.js} +1 -1
- package/assets/assets/{extract-error-message-DjXzzSl3.js → extract-error-message-BdChrkmo.js} +1 -1
- package/assets/assets/{index-33ZEL6A5.js → index-C_E2NRYY.js} +26 -26
- package/assets/assets/{react-sigma_core.esm.min-BlfsZb5G.js → react-sigma_core.esm.min-sKWUk_tG.js} +1 -1
- package/assets/assets/{v2-overview-adapter-C6cROMod.js → v2-overview-adapter-CkPt-sRK.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-X5AE3GNC.js → chunk-3WODA4JF.js} +276 -5
- package/dist/{chunk-7XXXNNE2.js → chunk-B2XM6AQ6.js} +280 -26
- package/dist/{chunk-ZA2QVBQO.js → chunk-H3RVNMOO.js} +73 -36
- package/dist/{chunk-AO5QJJE6.js → chunk-LJKAB4CX.js} +2 -2
- package/dist/{chunk-QVYGI6CL.js → chunk-UMU3IBXM.js} +1225 -474
- package/dist/cli.js +233 -154
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-M4V3YPFZ.js → intelligence-service-MGQRJW4V.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +11 -11
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
adsOperationReconcileRequestSchema,
|
|
22
22
|
adsPauseRequestSchema,
|
|
23
23
|
adsUnresolvedOperationListQuerySchema,
|
|
24
|
+
apiKeyDtoSchema,
|
|
24
25
|
backlinkSourceSchema,
|
|
25
26
|
canonicalizeGtmAccountId,
|
|
26
27
|
canonicalizeGtmResourceSelection,
|
|
@@ -38,8 +39,10 @@ import {
|
|
|
38
39
|
googleAdsMetricsWindowSchema,
|
|
39
40
|
gscPerformanceOrderBySchema,
|
|
40
41
|
isReadOnlyKey,
|
|
42
|
+
isSensitiveDiagnosticQueryKey,
|
|
41
43
|
keywordBatchRequestSchema,
|
|
42
44
|
keywordGenerateRequestSchema,
|
|
45
|
+
logQuerySchema,
|
|
43
46
|
measurementChangesQuerySchema,
|
|
44
47
|
measurementDataQualityQuerySchema,
|
|
45
48
|
measurementDiscoveryRequestSchema,
|
|
@@ -79,12 +82,15 @@ import {
|
|
|
79
82
|
measurementQueryTemplateApplyRequestSchema,
|
|
80
83
|
measurementQueryTemplateUpsertRequestSchema,
|
|
81
84
|
measurementQuestionResultQuerySchema,
|
|
85
|
+
normalizeTelemetryStatus,
|
|
82
86
|
notificationCreateRequestSchema,
|
|
83
87
|
notificationEventSchema,
|
|
88
|
+
operationalLogListDtoSchema,
|
|
84
89
|
organicEvidencePeriodSchema,
|
|
85
90
|
projectConfigSchema,
|
|
86
91
|
projectUpsertRequestSchema,
|
|
87
92
|
providerQuotaPolicySchema,
|
|
93
|
+
providerSummaryEntryDtoSchema,
|
|
88
94
|
queryBatchRequestSchema,
|
|
89
95
|
queryGenerateRequestSchema,
|
|
90
96
|
queryTrackingCommitRequestSchema,
|
|
@@ -97,16 +103,19 @@ import {
|
|
|
97
103
|
runListFilterQuerySchema,
|
|
98
104
|
runTriggerRequestSchema,
|
|
99
105
|
schedulableRunKindSchema,
|
|
106
|
+
scheduleDtoSchema,
|
|
100
107
|
scheduleUpsertRequestSchema,
|
|
108
|
+
settingsDtoSchema,
|
|
101
109
|
skillsClientSchema,
|
|
102
110
|
snapshotRequestInputSchema,
|
|
111
|
+
telemetryStatusDtoSchema,
|
|
103
112
|
trafficConnectCloudRunRequestSchema,
|
|
104
113
|
trafficConnectVercelRequestSchema,
|
|
105
114
|
trafficConnectWordpressRequestSchema,
|
|
106
115
|
trafficEventKindSchema,
|
|
107
116
|
trafficSeriesGranularitySchema,
|
|
108
117
|
visibilityReportRequestSchema
|
|
109
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-3WODA4JF.js";
|
|
110
119
|
|
|
111
120
|
// src/cli-error.ts
|
|
112
121
|
function isMachineFormat(format) {
|
|
@@ -593,6 +602,58 @@ function configExists() {
|
|
|
593
602
|
return fs.existsSync(getConfigPath());
|
|
594
603
|
}
|
|
595
604
|
|
|
605
|
+
// src/client-reliability.ts
|
|
606
|
+
function parseRetryAfterMs(header, now = Date.now()) {
|
|
607
|
+
if (!header) return void 0;
|
|
608
|
+
const value = header.trim();
|
|
609
|
+
if (!value) return void 0;
|
|
610
|
+
if (/^\d+(?:\.\d+)?$/.test(value)) {
|
|
611
|
+
const delayMs2 = Number(value) * 1e3;
|
|
612
|
+
return Number.isFinite(delayMs2) && delayMs2 >= 0 && delayMs2 <= Number.MAX_SAFE_INTEGER ? delayMs2 : void 0;
|
|
613
|
+
}
|
|
614
|
+
if (!/^[a-z]{3},\s/i.test(value)) return void 0;
|
|
615
|
+
const target = Date.parse(value);
|
|
616
|
+
if (!Number.isFinite(target)) return void 0;
|
|
617
|
+
const delayMs = Math.max(0, target - now);
|
|
618
|
+
return Number.isSafeInteger(delayMs) ? delayMs : void 0;
|
|
619
|
+
}
|
|
620
|
+
function httpErrorDetails(serverDetails, response) {
|
|
621
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
622
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("request-id");
|
|
623
|
+
return {
|
|
624
|
+
...serverDetails && typeof serverDetails === "object" && !Array.isArray(serverDetails) ? serverDetails : {},
|
|
625
|
+
httpStatus: response.status,
|
|
626
|
+
...retryAfterMs === void 0 ? {} : { retryAfterMs },
|
|
627
|
+
...requestId ? { requestId } : {}
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
function isConnectionFailure(message) {
|
|
631
|
+
return message.includes("fetch failed") || message.includes("ECONNREFUSED") || message.includes("connect ECONNREFUSED");
|
|
632
|
+
}
|
|
633
|
+
function connectionFailureMessage(target) {
|
|
634
|
+
return `Could not connect to canonry server at ${redactRequestTarget(target)}. Check that this URL is reachable and the server is running. For a local Canonry instance, start it with "canonry serve" (or "canonry serve &" to run in background).`;
|
|
635
|
+
}
|
|
636
|
+
function redactRequestTarget(target) {
|
|
637
|
+
try {
|
|
638
|
+
const url = new URL(target);
|
|
639
|
+
url.username = "";
|
|
640
|
+
url.password = "";
|
|
641
|
+
for (const key of [...url.searchParams.keys()]) {
|
|
642
|
+
if (isSensitiveDiagnosticQueryKey(key)) {
|
|
643
|
+
url.searchParams.set(key, "<redacted>");
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return url.toString();
|
|
647
|
+
} catch {
|
|
648
|
+
return target.replace(/\/\/[^/@]*@/, "//");
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// src/package-version.ts
|
|
653
|
+
import { createRequire } from "module";
|
|
654
|
+
var _require = createRequire(import.meta.url);
|
|
655
|
+
var PACKAGE_VERSION = _require("../package.json").version;
|
|
656
|
+
|
|
596
657
|
// ../api-client-generated/src/generated/core/bodySerializer.gen.ts
|
|
597
658
|
var jsonBodySerializer = {
|
|
598
659
|
bodySerializer: (body) => JSON.stringify(
|
|
@@ -2930,6 +2991,22 @@ var putApiV1SettingsProvidersByName = (options) => {
|
|
|
2930
2991
|
}
|
|
2931
2992
|
});
|
|
2932
2993
|
};
|
|
2994
|
+
var putApiV1SettingsGoogle = (options) => {
|
|
2995
|
+
return (options.client ?? client).put({
|
|
2996
|
+
security: [
|
|
2997
|
+
{
|
|
2998
|
+
scheme: "bearer",
|
|
2999
|
+
type: "http"
|
|
3000
|
+
}
|
|
3001
|
+
],
|
|
3002
|
+
url: "/api/v1/settings/google",
|
|
3003
|
+
...options,
|
|
3004
|
+
headers: {
|
|
3005
|
+
"Content-Type": "application/json",
|
|
3006
|
+
...options.headers
|
|
3007
|
+
}
|
|
3008
|
+
});
|
|
3009
|
+
};
|
|
2933
3010
|
var getApiV1Keys = (options) => {
|
|
2934
3011
|
return (options?.client ?? client).get({
|
|
2935
3012
|
security: [
|
|
@@ -3078,6 +3155,30 @@ var putApiV1ProjectsByNameSchedule = (options) => {
|
|
|
3078
3155
|
}
|
|
3079
3156
|
});
|
|
3080
3157
|
};
|
|
3158
|
+
var getApiV1ProjectsByNameSchedules = (options) => {
|
|
3159
|
+
return (options.client ?? client).get({
|
|
3160
|
+
security: [
|
|
3161
|
+
{
|
|
3162
|
+
scheme: "bearer",
|
|
3163
|
+
type: "http"
|
|
3164
|
+
}
|
|
3165
|
+
],
|
|
3166
|
+
url: "/api/v1/projects/{name}/schedules",
|
|
3167
|
+
...options
|
|
3168
|
+
});
|
|
3169
|
+
};
|
|
3170
|
+
var getApiV1NotificationsEvents = (options) => {
|
|
3171
|
+
return (options?.client ?? client).get({
|
|
3172
|
+
security: [
|
|
3173
|
+
{
|
|
3174
|
+
scheme: "bearer",
|
|
3175
|
+
type: "http"
|
|
3176
|
+
}
|
|
3177
|
+
],
|
|
3178
|
+
url: "/api/v1/notifications/events",
|
|
3179
|
+
...options
|
|
3180
|
+
});
|
|
3181
|
+
};
|
|
3081
3182
|
var getApiV1ProjectsByNameNotifications = (options) => {
|
|
3082
3183
|
return (options.client ?? client).get({
|
|
3083
3184
|
security: [
|
|
@@ -3130,6 +3231,18 @@ var postApiV1ProjectsByNameNotificationsByIdTest = (options) => {
|
|
|
3130
3231
|
...options
|
|
3131
3232
|
});
|
|
3132
3233
|
};
|
|
3234
|
+
var getApiV1OperationsLogs = (options) => {
|
|
3235
|
+
return (options?.client ?? client).get({
|
|
3236
|
+
security: [
|
|
3237
|
+
{
|
|
3238
|
+
scheme: "bearer",
|
|
3239
|
+
type: "http"
|
|
3240
|
+
}
|
|
3241
|
+
],
|
|
3242
|
+
url: "/api/v1/operations/logs",
|
|
3243
|
+
...options
|
|
3244
|
+
});
|
|
3245
|
+
};
|
|
3133
3246
|
var getApiV1Telemetry = (options) => {
|
|
3134
3247
|
return (options?.client ?? client).get({
|
|
3135
3248
|
security: [
|
|
@@ -5901,10 +6014,18 @@ function createClient2(opts) {
|
|
|
5901
6014
|
}
|
|
5902
6015
|
|
|
5903
6016
|
// src/client.ts
|
|
5904
|
-
|
|
6017
|
+
var SAFE_CLIENT_NAME = /^\w[\w./-]{0,127}$/;
|
|
6018
|
+
var SAFE_ACTOR_SESSION = /^\w[\w.:-]{0,127}$/;
|
|
6019
|
+
function safeClientName(value) {
|
|
6020
|
+
return value && SAFE_CLIENT_NAME.test(value) ? value : `canonry-cli/${PACKAGE_VERSION}`;
|
|
6021
|
+
}
|
|
6022
|
+
function safeActorSession(value) {
|
|
6023
|
+
return value && SAFE_ACTOR_SESSION.test(value) ? value : void 0;
|
|
6024
|
+
}
|
|
6025
|
+
function createApiClient(opts = {}) {
|
|
5905
6026
|
const config = loadConfig();
|
|
5906
6027
|
const basePathResolved = !!config.basePath || "CANONRY_BASE_PATH" in process.env;
|
|
5907
|
-
return new ApiClient(config.apiUrl, config.apiKey, { skipProbe: basePathResolved });
|
|
6028
|
+
return new ApiClient(config.apiUrl, config.apiKey, { ...opts, skipProbe: basePathResolved || opts.skipProbe });
|
|
5908
6029
|
}
|
|
5909
6030
|
var ApiClient = class {
|
|
5910
6031
|
originUrl;
|
|
@@ -5912,6 +6033,7 @@ var ApiClient = class {
|
|
|
5912
6033
|
probePromise = null;
|
|
5913
6034
|
probeSkipped;
|
|
5914
6035
|
heyClient;
|
|
6036
|
+
requestHeaders;
|
|
5915
6037
|
/** Tracks the base URL most recently applied to `heyClient` so probe-driven updates only re-configure when something actually changed. */
|
|
5916
6038
|
heyClientBaseUrl;
|
|
5917
6039
|
constructor(baseUrl, apiKey, opts) {
|
|
@@ -5919,7 +6041,13 @@ var ApiClient = class {
|
|
|
5919
6041
|
this.apiKey = apiKey;
|
|
5920
6042
|
this.probeSkipped = opts?.skipProbe ?? false;
|
|
5921
6043
|
this.heyClientBaseUrl = this.originUrl;
|
|
5922
|
-
|
|
6044
|
+
const actorSession = safeActorSession(opts?.actorSession);
|
|
6045
|
+
this.requestHeaders = {
|
|
6046
|
+
authorization: `Bearer ${this.apiKey}`,
|
|
6047
|
+
"user-agent": safeClientName(opts?.clientName),
|
|
6048
|
+
...actorSession ? { "x-canonry-actor-session": actorSession } : {}
|
|
6049
|
+
};
|
|
6050
|
+
this.heyClient = createClient2({ baseUrl: this.originUrl, apiKey: this.apiKey, headers: this.requestHeaders });
|
|
5923
6051
|
}
|
|
5924
6052
|
/**
|
|
5925
6053
|
* On first API call, probe /health to auto-discover basePath when the user
|
|
@@ -5954,7 +6082,7 @@ var ApiClient = class {
|
|
|
5954
6082
|
/** Apply the probe's discovered base URL to `heyClient` if it changed since last call. */
|
|
5955
6083
|
refreshHeyClientBaseUrl() {
|
|
5956
6084
|
if (this.originUrl !== this.heyClientBaseUrl) {
|
|
5957
|
-
this.heyClient.setConfig({ baseUrl: this.originUrl, headers:
|
|
6085
|
+
this.heyClient.setConfig({ baseUrl: this.originUrl, headers: this.requestHeaders });
|
|
5958
6086
|
this.heyClientBaseUrl = this.originUrl;
|
|
5959
6087
|
}
|
|
5960
6088
|
}
|
|
@@ -5978,10 +6106,10 @@ var ApiClient = class {
|
|
|
5978
6106
|
process.stderr.write(`[trace] (sdk-call) \u2192 ERROR (${Date.now() - traceStart}ms): ${msg}
|
|
5979
6107
|
`);
|
|
5980
6108
|
}
|
|
5981
|
-
if (
|
|
6109
|
+
if (isConnectionFailure(msg)) {
|
|
5982
6110
|
throw new CliError({
|
|
5983
6111
|
code: "CONNECTION_ERROR",
|
|
5984
|
-
message:
|
|
6112
|
+
message: connectionFailureMessage(this.originUrl),
|
|
5985
6113
|
exitCode: EXIT_SYSTEM_ERROR
|
|
5986
6114
|
});
|
|
5987
6115
|
}
|
|
@@ -5990,7 +6118,7 @@ var ApiClient = class {
|
|
|
5990
6118
|
if (traceEnabled) {
|
|
5991
6119
|
const durMs = Date.now() - traceStart;
|
|
5992
6120
|
process.stderr.write(
|
|
5993
|
-
`[trace] ${result.request.method} ${result.request.url} \u2192 ${result.response.status} (${durMs}ms)
|
|
6121
|
+
`[trace] ${result.request.method} ${redactRequestTarget(result.request.url)} \u2192 ${result.response.status} (${durMs}ms)
|
|
5994
6122
|
`
|
|
5995
6123
|
);
|
|
5996
6124
|
}
|
|
@@ -5998,17 +6126,17 @@ var ApiClient = class {
|
|
|
5998
6126
|
if (result.response.ok && contentType?.toLowerCase().startsWith("text/html")) {
|
|
5999
6127
|
throw new CliError({
|
|
6000
6128
|
code: "UNEXPECTED_RESPONSE_FORMAT",
|
|
6001
|
-
message: `Expected a JSON response from the canonry API at ${result.request.url}, but received ${contentType} (HTTP ${result.response.status}). Check the server URL and base path.`,
|
|
6129
|
+
message: `Expected a JSON response from the canonry API at ${redactRequestTarget(result.request.url)}, but received ${contentType} (HTTP ${result.response.status}). Check the server URL and base path.`,
|
|
6002
6130
|
exitCode: EXIT_SYSTEM_ERROR,
|
|
6003
6131
|
details: {
|
|
6004
|
-
requestUrl: result.request.url,
|
|
6132
|
+
requestUrl: redactRequestTarget(result.request.url),
|
|
6005
6133
|
contentType,
|
|
6006
6134
|
httpStatus: result.response.status
|
|
6007
6135
|
}
|
|
6008
6136
|
});
|
|
6009
6137
|
}
|
|
6010
6138
|
if (result.error !== void 0 && result.error !== null) {
|
|
6011
|
-
const errorObj = typeof result.error === "object" &&
|
|
6139
|
+
const errorObj = typeof result.error === "object" && "error" in result.error && typeof result.error.error === "object" && result.error.error !== null ? result.error.error : null;
|
|
6012
6140
|
const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${result.response.status}: ${result.response.statusText}`;
|
|
6013
6141
|
const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
|
|
6014
6142
|
const exitCode = result.response.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
|
|
@@ -6016,7 +6144,7 @@ var ApiClient = class {
|
|
|
6016
6144
|
code,
|
|
6017
6145
|
message: msg,
|
|
6018
6146
|
exitCode,
|
|
6019
|
-
details:
|
|
6147
|
+
details: httpErrorDetails(errorObj?.details, result.response)
|
|
6020
6148
|
});
|
|
6021
6149
|
}
|
|
6022
6150
|
return result.data;
|
|
@@ -6081,7 +6209,7 @@ var ApiClient = class {
|
|
|
6081
6209
|
await this.probeBasePath();
|
|
6082
6210
|
const url = `${this.originUrl}/api/v1${path3}`;
|
|
6083
6211
|
const headers = {
|
|
6084
|
-
|
|
6212
|
+
...this.requestHeaders,
|
|
6085
6213
|
"Content-Type": "application/json",
|
|
6086
6214
|
Accept: "text/event-stream"
|
|
6087
6215
|
};
|
|
@@ -6091,10 +6219,10 @@ var ApiClient = class {
|
|
|
6091
6219
|
} catch (err) {
|
|
6092
6220
|
if (err instanceof CliError) throw err;
|
|
6093
6221
|
const msg = describeError(err);
|
|
6094
|
-
if (
|
|
6222
|
+
if (isConnectionFailure(msg)) {
|
|
6095
6223
|
throw new CliError({
|
|
6096
6224
|
code: "CONNECTION_ERROR",
|
|
6097
|
-
message:
|
|
6225
|
+
message: connectionFailureMessage(this.originUrl),
|
|
6098
6226
|
exitCode: EXIT_SYSTEM_ERROR
|
|
6099
6227
|
});
|
|
6100
6228
|
}
|
|
@@ -6111,7 +6239,7 @@ var ApiClient = class {
|
|
|
6111
6239
|
const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${res.status}: ${res.statusText}`;
|
|
6112
6240
|
const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
|
|
6113
6241
|
const exitCode = res.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
|
|
6114
|
-
throw new CliError({ code, message: msg, exitCode, details:
|
|
6242
|
+
throw new CliError({ code, message: msg, exitCode, details: httpErrorDetails(errorObj?.details, res) });
|
|
6115
6243
|
}
|
|
6116
6244
|
return res;
|
|
6117
6245
|
}
|
|
@@ -6962,16 +7090,32 @@ var ApiClient = class {
|
|
|
6962
7090
|
() => putApiV1SettingsProvidersByName({ client: this.heyClient, path: { name }, body })
|
|
6963
7091
|
);
|
|
6964
7092
|
}
|
|
7093
|
+
async updateGoogleSettings(body) {
|
|
7094
|
+
return this.invoke(
|
|
7095
|
+
() => putApiV1SettingsGoogle({ client: this.heyClient, body })
|
|
7096
|
+
);
|
|
7097
|
+
}
|
|
6965
7098
|
async createSnapshot(body) {
|
|
6966
7099
|
return this.invoke(() => postApiV1Snapshot({ client: this.heyClient, body }));
|
|
6967
7100
|
}
|
|
6968
7101
|
async getTelemetry() {
|
|
6969
|
-
return this.invoke(() => getApiV1Telemetry({ client: this.heyClient }));
|
|
7102
|
+
return normalizeTelemetryStatus(await this.invoke(() => getApiV1Telemetry({ client: this.heyClient })));
|
|
7103
|
+
}
|
|
7104
|
+
async listOperationalLogs(query = {}) {
|
|
7105
|
+
return this.invoke(() => getApiV1OperationsLogs({ client: this.heyClient, query }));
|
|
6970
7106
|
}
|
|
6971
7107
|
async updateTelemetry(enabled) {
|
|
6972
|
-
return this.invoke(() => putApiV1Telemetry({ client: this.heyClient, body: { enabled } }));
|
|
7108
|
+
return normalizeTelemetryStatus(await this.invoke(() => putApiV1Telemetry({ client: this.heyClient, body: { enabled } })));
|
|
6973
7109
|
}
|
|
6974
7110
|
// ── Schedules / notifications / locations ───────────────────────────────
|
|
7111
|
+
async listSchedules(project) {
|
|
7112
|
+
return this.invoke(
|
|
7113
|
+
() => getApiV1ProjectsByNameSchedules({ client: this.heyClient, path: { name: project } })
|
|
7114
|
+
);
|
|
7115
|
+
}
|
|
7116
|
+
async listNotificationEvents() {
|
|
7117
|
+
return this.invoke(() => getApiV1NotificationsEvents({ client: this.heyClient }));
|
|
7118
|
+
}
|
|
6975
7119
|
async putSchedule(project, body) {
|
|
6976
7120
|
return this.invoke(
|
|
6977
7121
|
() => putApiV1ProjectsByNameSchedule({
|
|
@@ -8791,11 +8935,6 @@ var ApiClient = class {
|
|
|
8791
8935
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8792
8936
|
import { z as z5 } from "zod";
|
|
8793
8937
|
|
|
8794
|
-
// src/package-version.ts
|
|
8795
|
-
import { createRequire } from "module";
|
|
8796
|
-
var _require = createRequire(import.meta.url);
|
|
8797
|
-
var PACKAGE_VERSION = _require("../package.json").version;
|
|
8798
|
-
|
|
8799
8938
|
// src/mcp/tool-registry.ts
|
|
8800
8939
|
import { z as z4 } from "zod";
|
|
8801
8940
|
|
|
@@ -9479,6 +9618,8 @@ var scheduleReadInputSchema = z4.object({
|
|
|
9479
9618
|
project: projectNameSchema,
|
|
9480
9619
|
kind: schedulableRunKindSchema.optional().describe('Schedulable run kind. Defaults to "answer-visibility" if omitted.')
|
|
9481
9620
|
});
|
|
9621
|
+
var scheduleListOutputSchema = z4.object({ items: z4.array(scheduleDtoSchema) });
|
|
9622
|
+
var notificationEventsOutputSchema = z4.object({ items: z4.array(notificationEventSchema) });
|
|
9482
9623
|
var agentWebhookAttachInputSchema = z4.object({
|
|
9483
9624
|
project: projectNameSchema,
|
|
9484
9625
|
url: z4.string().url()
|
|
@@ -10275,6 +10416,30 @@ var canonryMcpTools = [
|
|
|
10275
10416
|
openApiOperations: ["GET /api/v1/projects/{name}/schedule"],
|
|
10276
10417
|
handler: (client2, input) => client2.getSchedule(input.project, input.kind)
|
|
10277
10418
|
}),
|
|
10419
|
+
defineTool({
|
|
10420
|
+
name: "canonry_schedules_list",
|
|
10421
|
+
title: "List project schedules",
|
|
10422
|
+
description: "List every stored schedule for a Canonry project, including each schedulable run kind. This reads configuration only and never starts work.",
|
|
10423
|
+
access: "read",
|
|
10424
|
+
tier: "setup",
|
|
10425
|
+
inputSchema: projectInputSchema,
|
|
10426
|
+
outputSchema: scheduleListOutputSchema,
|
|
10427
|
+
annotations: readAnnotations(),
|
|
10428
|
+
openApiOperations: ["GET /api/v1/projects/{name}/schedules"],
|
|
10429
|
+
handler: (client2, input) => client2.listSchedules(input.project)
|
|
10430
|
+
}),
|
|
10431
|
+
defineTool({
|
|
10432
|
+
name: "canonry_notification_events",
|
|
10433
|
+
title: "List notification event types",
|
|
10434
|
+
description: "List the supported stored notification event names. This is a static capability read; it does not send, test, or change notifications.",
|
|
10435
|
+
access: "read",
|
|
10436
|
+
tier: "setup",
|
|
10437
|
+
inputSchema: emptyInputSchema,
|
|
10438
|
+
outputSchema: notificationEventsOutputSchema,
|
|
10439
|
+
annotations: readAnnotations(),
|
|
10440
|
+
openApiOperations: ["GET /api/v1/notifications/events"],
|
|
10441
|
+
handler: (client2) => client2.listNotificationEvents()
|
|
10442
|
+
}),
|
|
10278
10443
|
defineTool({
|
|
10279
10444
|
name: "canonry_backlinks_latest_release",
|
|
10280
10445
|
title: "Discover latest Common Crawl release",
|
|
@@ -10319,10 +10484,73 @@ var canonryMcpTools = [
|
|
|
10319
10484
|
access: "read",
|
|
10320
10485
|
tier: "core",
|
|
10321
10486
|
inputSchema: emptyInputSchema,
|
|
10487
|
+
outputSchema: settingsDtoSchema,
|
|
10322
10488
|
annotations: readAnnotations(),
|
|
10323
10489
|
openApiOperations: ["GET /api/v1/settings"],
|
|
10324
10490
|
handler: (client2) => client2.getSettings()
|
|
10325
10491
|
}),
|
|
10492
|
+
defineTool({
|
|
10493
|
+
name: "canonry_key_self",
|
|
10494
|
+
title: "Get current API key identity",
|
|
10495
|
+
description: "Read safe metadata for the credential backing this MCP connection, including its scopes, project reach, and derived read-only status. It never exposes the bearer token or stored hash and does not grant mutation access.",
|
|
10496
|
+
access: "read",
|
|
10497
|
+
tier: "core",
|
|
10498
|
+
inputSchema: emptyInputSchema,
|
|
10499
|
+
outputSchema: apiKeyDtoSchema,
|
|
10500
|
+
annotations: readAnnotations(),
|
|
10501
|
+
openApiOperations: ["GET /api/v1/keys/self"],
|
|
10502
|
+
handler: (client2) => client2.getApiKeySelf()
|
|
10503
|
+
}),
|
|
10504
|
+
defineTool({
|
|
10505
|
+
name: "canonry_logs_list",
|
|
10506
|
+
title: "Read runtime logs",
|
|
10507
|
+
description: "Read bounded, redacted runtime logs, including application and HTTP failures. Filter by actor, request, run, project, level, module, or time. Inspect retention, retentionPolicy, dropped, and captureErrors for coverage; file-backed hosts retain logs across restarts. Separate from audit history. Requires instance-wide logs.read (or wildcard), and an admin role for user sessions; project-scoped keys are refused even with a project filter. Cursors expire on retention eviction; reuse with the same filters. No provider calls.",
|
|
10508
|
+
access: "read",
|
|
10509
|
+
tier: "setup",
|
|
10510
|
+
inputSchema: logQuerySchema,
|
|
10511
|
+
outputSchema: operationalLogListDtoSchema,
|
|
10512
|
+
annotations: readAnnotations(false),
|
|
10513
|
+
openApiOperations: ["GET /api/v1/operations/logs"],
|
|
10514
|
+
handler: async (client2, input) => client2.listOperationalLogs(input)
|
|
10515
|
+
}),
|
|
10516
|
+
defineTool({
|
|
10517
|
+
name: "canonry_telemetry_update",
|
|
10518
|
+
title: "Update server telemetry preference",
|
|
10519
|
+
description: "Set the connected server telemetry preference with explicit approval and settings.write. Returns effective state including environment overrides. Does not change the agent machine configuration.",
|
|
10520
|
+
access: "write",
|
|
10521
|
+
requiredScope: "settings.write",
|
|
10522
|
+
tier: "setup",
|
|
10523
|
+
inputSchema: z4.object({ enabled: z4.boolean() }).strict(),
|
|
10524
|
+
outputSchema: telemetryStatusDtoSchema,
|
|
10525
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
10526
|
+
openApiOperations: ["PUT /api/v1/telemetry"],
|
|
10527
|
+
handler: async (client2, input) => client2.updateTelemetry(input.enabled)
|
|
10528
|
+
}),
|
|
10529
|
+
defineTool({
|
|
10530
|
+
name: "canonry_provider_settings_update",
|
|
10531
|
+
title: "Update non-secret provider settings",
|
|
10532
|
+
description: "Change model or quota for an already-configured provider, with explicit approval and settings.write. Preserves existing credentials. Does not accept API keys, base URLs, or credential rotation; use the secure operator setup flow for those.",
|
|
10533
|
+
access: "write",
|
|
10534
|
+
requiredScope: "settings.write",
|
|
10535
|
+
tier: "setup",
|
|
10536
|
+
inputSchema: z4.object({ provider: z4.string().min(1), model: z4.string().trim().min(1).optional(), quota: providerQuotaPolicySchema.partial().strict().optional() }).strict().refine((input) => input.model !== void 0 || input.quota !== void 0 && Object.keys(input.quota).length > 0, "Provide a model or at least one quota field"),
|
|
10537
|
+
outputSchema: providerSummaryEntryDtoSchema,
|
|
10538
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
10539
|
+
openApiOperations: ["PUT /api/v1/settings/providers/{name}"],
|
|
10540
|
+
handler: async (client2, { provider, ...request }) => client2.updateProvider(provider, request)
|
|
10541
|
+
}),
|
|
10542
|
+
defineTool({
|
|
10543
|
+
name: "canonry_telemetry_get",
|
|
10544
|
+
title: "Get telemetry status",
|
|
10545
|
+
description: "Read the server telemetry status and effective reason. This safe settings read does not change telemetry collection.",
|
|
10546
|
+
access: "read",
|
|
10547
|
+
tier: "setup",
|
|
10548
|
+
inputSchema: emptyInputSchema,
|
|
10549
|
+
outputSchema: telemetryStatusDtoSchema,
|
|
10550
|
+
annotations: readAnnotations(),
|
|
10551
|
+
openApiOperations: ["GET /api/v1/telemetry"],
|
|
10552
|
+
handler: (client2) => client2.getTelemetry()
|
|
10553
|
+
}),
|
|
10326
10554
|
defineTool({
|
|
10327
10555
|
name: "canonry_google_connections_list",
|
|
10328
10556
|
title: "List Google connections",
|
|
@@ -12410,6 +12638,7 @@ import { ZodError } from "zod";
|
|
|
12410
12638
|
function jsonToolResult(value) {
|
|
12411
12639
|
const result = value === void 0 ? { ok: true } : value;
|
|
12412
12640
|
return {
|
|
12641
|
+
structuredContent: toStructuredContent(result),
|
|
12413
12642
|
content: [
|
|
12414
12643
|
{
|
|
12415
12644
|
type: "text",
|
|
@@ -12419,16 +12648,23 @@ function jsonToolResult(value) {
|
|
|
12419
12648
|
};
|
|
12420
12649
|
}
|
|
12421
12650
|
function errorToolResult(error) {
|
|
12651
|
+
const envelope = toCanonryErrorEnvelope(error);
|
|
12422
12652
|
return {
|
|
12423
12653
|
isError: true,
|
|
12654
|
+
structuredContent: envelope,
|
|
12424
12655
|
content: [
|
|
12425
12656
|
{
|
|
12426
12657
|
type: "text",
|
|
12427
|
-
text: JSON.stringify(
|
|
12658
|
+
text: JSON.stringify(envelope, null, 2)
|
|
12428
12659
|
}
|
|
12429
12660
|
]
|
|
12430
12661
|
};
|
|
12431
12662
|
}
|
|
12663
|
+
function toStructuredContent(value) {
|
|
12664
|
+
if (Array.isArray(value)) return { items: value };
|
|
12665
|
+
if (value !== null && typeof value === "object") return value;
|
|
12666
|
+
return { value };
|
|
12667
|
+
}
|
|
12432
12668
|
async function withToolErrors(handler) {
|
|
12433
12669
|
try {
|
|
12434
12670
|
return jsonToolResult(await handler());
|
|
@@ -12714,6 +12950,23 @@ var OPERATIONS_GUIDE = {
|
|
|
12714
12950
|
"approvalRule": "Get explicit approval for the exact target, action, and bounded provider work before crossing a boundary. Existing approval covers only its stated scope; stop on refusal or ambiguous results.",
|
|
12715
12951
|
"authority": "Guidance and tool visibility are not permission grants. Server-side roles, scopes, project boundaries, quotas, and approval receipts remain authoritative. Never bypass a refusal with different credentials or endpoints.",
|
|
12716
12952
|
"workflows": {
|
|
12953
|
+
"operations": {
|
|
12954
|
+
"keywords": [
|
|
12955
|
+
"operations",
|
|
12956
|
+
"permissions",
|
|
12957
|
+
"settings",
|
|
12958
|
+
"telemetry",
|
|
12959
|
+
"logs",
|
|
12960
|
+
"configuration"
|
|
12961
|
+
],
|
|
12962
|
+
"next": [
|
|
12963
|
+
"canonry_key_self",
|
|
12964
|
+
"canonry_settings_get",
|
|
12965
|
+
"canonry_telemetry_get",
|
|
12966
|
+
"canonry_logs_list"
|
|
12967
|
+
],
|
|
12968
|
+
"guidance": "Inspect current credential and server state before proposing changes. Runtime logs require instance-wide logs.read; inspect retention, dropped, and captureErrors before drawing conclusions. File-backed hosts retain bounded redacted logs across restarts. Logs are separate from audit history. Respect a 403; never substitute credentials to bypass it. Settings writes require settings.write and explicit approval."
|
|
12969
|
+
},
|
|
12717
12970
|
"status": {
|
|
12718
12971
|
"keywords": [
|
|
12719
12972
|
"status",
|
|
@@ -12810,7 +13063,7 @@ var OPERATIONS_GUIDE = {
|
|
|
12810
13063
|
"guidance": "Read the stored report for the selected project and period. Retain evidence dates, scope, sample sizes, missing data, and separate mention/citation signals; do not generate fresh runs implicitly."
|
|
12811
13064
|
}
|
|
12812
13065
|
},
|
|
12813
|
-
"markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `prospecting`, `measurement`, `integrations`, `reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Keep sample sizes and ties visible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
|
|
13066
|
+
"markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `operations`, `prospecting`, `measurement`, `integrations`,\n`reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Keep sample sizes and ties visible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\n### Agent operations\n\nUse `canonry_key_self` to inspect the current credential's scopes and project\nboundary without exposing its token. `canonry_settings_get` and\n`canonry_telemetry_get` describe the connected server, not the agent's local\nmachine. Telemetry reports configured preference, effective state, and any\nenvironment override; inspecting status never creates an anonymous identifier.\nAfter approval, `canonry_telemetry_update` changes that preference and\n`canonry_provider_settings_update` changes an already-configured provider's\nmodel/quota. Both require `settings.write`; neither accepts credentials.\n\n`canonry_logs_list` reads bounded, redacted runtime events from both the\napplication logger and Fastify request/error logging. It requires an\ninstance-wide `logs.read` grant (or wildcard), and\nadmin role for signed-in users. Project-scoped keys cannot use it, even with a\nproject filter. A `logs.read`-only key is read-only automatically, without a\nsecond `read` marker. Named `*.read` scopes cannot grant mutations; an explicit\nwrite grant is needed and remains subject to its route gates. Returned messages\nare sanitized and bounded; raw request or response bodies, headers, cookies,\nprovider payloads, and stacks are not\npart of the queryable surface. The same secret-redaction policy runs before\nconsole output and storage. Do not deliberately log secrets: redaction is a\ndefense in depth, not permission to put credentials into diagnostic strings.\nOpaque escaped payloads containing secret assignments are omitted when safe\npartial masking cannot be guaranteed; correlate their retained error codes and IDs.\n\nFile-backed hosts retain runtime logs in SQLite across restarts, bounded to\n10,000 events and seven days. In-memory hosts report `retention: \"process\"`.\nFilter by `actor`, `requestId`, `runId`, `projectId`, `module`, `level`, or an\ninclusive `since`/`until` interval. Keep filters unchanged when resuming an\nopaque cursor; retention eviction can invalidate it. Inspect `retentionPolicy`,\n`captureErrors`, `dropped`, `truncated`, and `retention` before drawing\nconclusions. Missing logs are not proof that an action did not happen. Use\n`canonry_project_history` or `canonry_history_global` for persistent audit events;\noffset pages have deterministic ordering but are not snapshots of concurrent writes.\n\nAudit `actor` comes from authenticated identity (`user:<id>` or `api-key:<id>`),\nnot a caller-supplied header. A delegated MCP credential records its originating\nuser as actor and the actual credential in `credentialId`. `requestId` correlates\nHTTP events; `userAgent` and `actorSession` are bounded, untrusted client hints,\nnever identity or permission grants. Older audit rows are not backfilled with\nidentities the server cannot prove.\n\nBoth shipped HTTP hosts issue restart-safe UUID request IDs and return them in\n`x-request-id`. Use that value to correlate a CLI/API failure with log entries;\nHTTP diagnostics retain the method and route template, not raw URL parameters.\nRequest-bound loggers retain completion attribution, while generic background\ncontinuations stop inheriting caller identity after the response completes.\nCapture covers the owning server process after initialization, not arbitrary\nconsole output, other worker processes, or host/container logs. Run one server\ninstance per process and database, as required by the single-tenant deployment\nmodel; this is not a cross-tenant or distributed log collector.\n\nFor CLI use, settings reads are remote. Google setup and telemetry retain their\nlocal defaults: pass `--target server` explicitly to configure the connected\nserver. `schedule list <project>` lists all schedule kinds, and\n`notify events --target server` discovers the server's event catalog.\n\nMCP returns legacy text JSON plus structured results. Objects keep their shape;\narrays use `{items: [...]}` in `structuredContent`, and scalars use `{value: ...}`.\nErrors preserve the existing envelope and CLI exit codes: HTTP 4xx (including\n429 policy limits) use exit 1; HTTP 5xx use exit 2. Server-provided `Retry-After`\nand request IDs are exposed as `retryAfterMs` and `requestId` when available;\nclients do not infer retryability from HTTP 429 or retry automatically.\nFor a write with an ambiguous outcome, inspect saved state or its receipt before\nretrying; a retry hint is not proof that repeating a write is safe.\n\n### Action boundaries\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
|
|
12814
13067
|
};
|
|
12815
13068
|
|
|
12816
13069
|
// src/mcp/operations-guide.ts
|
|
@@ -12853,7 +13106,7 @@ function createCanonryMcpServer(options = {}) {
|
|
|
12853
13106
|
}
|
|
12854
13107
|
var SERVER_INSTRUCTIONS = OPERATIONS_GUIDE.initialize;
|
|
12855
13108
|
function createCanonryMcpServerWithCatalog(options = {}) {
|
|
12856
|
-
const clientFactory = options.clientFactory ?? createApiClient;
|
|
13109
|
+
const clientFactory = options.clientFactory ?? (() => createApiClient({ clientName: "canonry-mcp" }));
|
|
12857
13110
|
const client2 = clientFactory();
|
|
12858
13111
|
const scope = options.scope ?? "all";
|
|
12859
13112
|
const server = new McpServer({
|
|
@@ -12873,6 +13126,7 @@ function createCanonryMcpServerWithCatalog(options = {}) {
|
|
|
12873
13126
|
title: tool.title,
|
|
12874
13127
|
description: tool.description,
|
|
12875
13128
|
inputSchema: tool.inputSchema,
|
|
13129
|
+
outputSchema: tool.outputSchema,
|
|
12876
13130
|
annotations: tool.annotations
|
|
12877
13131
|
},
|
|
12878
13132
|
async (input) => withToolErrors(async () => {
|