@ainyc/canonry 2.14.2 → 2.16.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/memory-patterns.md +9 -9
- package/assets/assets/{index-D1v6Q-fS.js → index-B18l8ugs.js} +97 -97
- package/assets/assets/{index-U2SLimrz.css → index-DMx3Oy9W.css} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-CILBPOHB.js → chunk-CKABU6PE.js} +230 -578
- package/dist/{chunk-7VWSR5F6.js → chunk-HNVRN5QL.js} +927 -8
- package/dist/cli.js +36 -10
- package/dist/index.js +2 -2
- package/dist/mcp.js +9 -796
- package/package.json +9 -9
|
@@ -1310,10 +1310,14 @@ var ga4TrafficSummaryDtoSchema = z12.object({
|
|
|
1310
1310
|
users: z12.number()
|
|
1311
1311
|
})),
|
|
1312
1312
|
aiReferrals: z12.array(ga4AiReferralDtoSchema),
|
|
1313
|
-
/** Deduped AI session total: MAX(sessions) per date+source+medium across attribution dimensions, then summed. */
|
|
1313
|
+
/** Deduped AI session total: MAX(sessions) per date+source+medium across attribution dimensions, then summed. Cross-cutting: can overlap with Direct/Organic/Social via firstUserSource. */
|
|
1314
1314
|
aiSessionsDeduped: z12.number(),
|
|
1315
1315
|
/** Deduped AI user total: MAX(users) per date+source+medium across attribution dimensions, then summed. */
|
|
1316
1316
|
aiUsersDeduped: z12.number(),
|
|
1317
|
+
/** AI sessions whose CURRENT sessionSource matched an AI engine. Disjoint from Direct/Organic/Social — safe for the channel breakdown. */
|
|
1318
|
+
aiSessionsBySession: z12.number(),
|
|
1319
|
+
/** AI users whose CURRENT sessionSource matched an AI engine. Disjoint from Direct/Organic/Social — safe for the channel breakdown. */
|
|
1320
|
+
aiUsersBySession: z12.number(),
|
|
1317
1321
|
socialReferrals: z12.array(ga4SocialReferralDtoSchema),
|
|
1318
1322
|
/** Total social sessions (session-scoped, no cross-dimension dedup needed). */
|
|
1319
1323
|
socialSessions: z12.number(),
|
|
@@ -1321,8 +1325,10 @@ var ga4TrafficSummaryDtoSchema = z12.object({
|
|
|
1321
1325
|
socialUsers: z12.number(),
|
|
1322
1326
|
/** Organic sessions as a percentage of total sessions (0–100, rounded). */
|
|
1323
1327
|
organicSharePct: z12.number(),
|
|
1324
|
-
/** Deduped AI sessions as a percentage of total sessions (0–100, rounded). */
|
|
1328
|
+
/** Deduped AI sessions as a percentage of total sessions (0–100, rounded). Cross-cutting: can overlap with Direct/Organic/Social. */
|
|
1325
1329
|
aiSharePct: z12.number(),
|
|
1330
|
+
/** Session-source-only AI sessions as a percentage of total sessions (0–100, rounded). Disjoint from Direct/Organic/Social. */
|
|
1331
|
+
aiSharePctBySession: z12.number(),
|
|
1326
1332
|
/** Direct-channel sessions as a percentage of total sessions (0–100, rounded). */
|
|
1327
1333
|
directSharePct: z12.number(),
|
|
1328
1334
|
/** Social sessions as a percentage of total sessions (0–100, rounded). */
|
|
@@ -1809,6 +1815,7 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
|
1809
1815
|
"dclid",
|
|
1810
1816
|
"gbraid",
|
|
1811
1817
|
"wbraid",
|
|
1818
|
+
"bingid",
|
|
1812
1819
|
// Mailchimp
|
|
1813
1820
|
"mc_cid",
|
|
1814
1821
|
"mc_eid",
|
|
@@ -1817,7 +1824,16 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
|
1817
1824
|
"_gl",
|
|
1818
1825
|
// Google Tag Manager debug
|
|
1819
1826
|
"gtm_latency",
|
|
1820
|
-
"gtm_debug"
|
|
1827
|
+
"gtm_debug",
|
|
1828
|
+
// WordPress internal noise
|
|
1829
|
+
"preview",
|
|
1830
|
+
"preview_id",
|
|
1831
|
+
"preview_nonce",
|
|
1832
|
+
"_thumbnail_id",
|
|
1833
|
+
// Common cache-busters/versioning
|
|
1834
|
+
"v",
|
|
1835
|
+
"ver",
|
|
1836
|
+
"version"
|
|
1821
1837
|
]);
|
|
1822
1838
|
function shouldStrip(key) {
|
|
1823
1839
|
if (STRIP_KEYS.has(key)) return true;
|
|
@@ -1847,9 +1863,19 @@ function dropTrailingSlash(path2) {
|
|
|
1847
1863
|
}
|
|
1848
1864
|
function normalizeUrlPath(input) {
|
|
1849
1865
|
if (input == null) return null;
|
|
1850
|
-
|
|
1866
|
+
let trimmed = input.trim();
|
|
1851
1867
|
if (trimmed === "") return null;
|
|
1868
|
+
trimmed = trimmed.replace(/ /g, " ").replace(/\s+/g, " ").trim();
|
|
1869
|
+
if (trimmed === "" || trimmed === "/") return "/";
|
|
1852
1870
|
if (trimmed === "(not set)") return null;
|
|
1871
|
+
trimmed = trimmed.replace(/([a-zA-Z0-9])([).]+)$/, "$1");
|
|
1872
|
+
if (trimmed.startsWith("/)") || trimmed.startsWith("/ ")) {
|
|
1873
|
+
trimmed = "/";
|
|
1874
|
+
}
|
|
1875
|
+
if (trimmed.includes(" ")) {
|
|
1876
|
+
trimmed = trimmed.split(" ")[0];
|
|
1877
|
+
}
|
|
1878
|
+
if (trimmed === "" || trimmed === "/") return "/";
|
|
1853
1879
|
let pathPart;
|
|
1854
1880
|
let queryPart;
|
|
1855
1881
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
@@ -2543,6 +2569,901 @@ var ApiClient = class {
|
|
|
2543
2569
|
}
|
|
2544
2570
|
};
|
|
2545
2571
|
|
|
2572
|
+
// src/mcp/tool-registry.ts
|
|
2573
|
+
import { z as z19 } from "zod";
|
|
2574
|
+
|
|
2575
|
+
// src/mcp/schema.ts
|
|
2576
|
+
import { z as z18 } from "zod";
|
|
2577
|
+
var projectNameSchema = z18.string().min(1).describe("Canonry project name.");
|
|
2578
|
+
var runIdSchema = z18.string().min(1).describe("Canonry run ID.");
|
|
2579
|
+
var insightIdSchema = z18.string().min(1).describe("Canonry insight ID.");
|
|
2580
|
+
var analyticsWindowSchema = z18.enum(["7d", "30d", "90d", "all"]).describe("Analytics time window.");
|
|
2581
|
+
var emptyInputSchema = z18.object({});
|
|
2582
|
+
var projectInputSchema = z18.object({
|
|
2583
|
+
project: projectNameSchema
|
|
2584
|
+
});
|
|
2585
|
+
function toJsonSchema(schema, name) {
|
|
2586
|
+
return {
|
|
2587
|
+
...z18.toJSONSchema(schema, { target: "draft-7" }),
|
|
2588
|
+
title: name
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
function compactStringParams(values, keys) {
|
|
2592
|
+
const params = {};
|
|
2593
|
+
for (const key of keys) {
|
|
2594
|
+
const value = values[key];
|
|
2595
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
2596
|
+
params[key] = String(value);
|
|
2597
|
+
}
|
|
2598
|
+
return Object.keys(params).length ? params : void 0;
|
|
2599
|
+
}
|
|
2600
|
+
function uniqueStrings(values) {
|
|
2601
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2602
|
+
const result = [];
|
|
2603
|
+
for (const value of values) {
|
|
2604
|
+
const trimmed = value.trim();
|
|
2605
|
+
if (!trimmed || seen.has(trimmed)) continue;
|
|
2606
|
+
seen.add(trimmed);
|
|
2607
|
+
result.push(trimmed);
|
|
2608
|
+
}
|
|
2609
|
+
return result;
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
// src/mcp/tool-registry.ts
|
|
2613
|
+
var readAnnotations = (openWorldHint) => ({
|
|
2614
|
+
readOnlyHint: true,
|
|
2615
|
+
...openWorldHint ? { openWorldHint } : {}
|
|
2616
|
+
});
|
|
2617
|
+
var writeAnnotations = (opts) => ({
|
|
2618
|
+
readOnlyHint: false,
|
|
2619
|
+
idempotentHint: opts.idempotentHint,
|
|
2620
|
+
destructiveHint: Boolean(opts.destructiveHint),
|
|
2621
|
+
...opts.openWorldHint ? { openWorldHint: opts.openWorldHint } : {}
|
|
2622
|
+
});
|
|
2623
|
+
function defineTool(tool) {
|
|
2624
|
+
return {
|
|
2625
|
+
...tool,
|
|
2626
|
+
inputJsonSchema: toJsonSchema(tool.inputSchema, tool.name)
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
var runTriggerInputSchema = z19.object({
|
|
2630
|
+
project: projectNameSchema,
|
|
2631
|
+
request: runTriggerRequestSchema.optional()
|
|
2632
|
+
});
|
|
2633
|
+
var runsListInputSchema = z19.object({
|
|
2634
|
+
project: projectNameSchema,
|
|
2635
|
+
limit: z19.number().int().positive().max(500).optional()
|
|
2636
|
+
});
|
|
2637
|
+
var runGetInputSchema = z19.object({
|
|
2638
|
+
runId: runIdSchema
|
|
2639
|
+
});
|
|
2640
|
+
var timelineInputSchema = z19.object({
|
|
2641
|
+
project: projectNameSchema,
|
|
2642
|
+
location: z19.string().optional().describe("Location label. Use an empty string for locationless results.")
|
|
2643
|
+
});
|
|
2644
|
+
var snapshotsListInputSchema = z19.object({
|
|
2645
|
+
project: projectNameSchema,
|
|
2646
|
+
limit: z19.number().int().positive().max(500).optional(),
|
|
2647
|
+
offset: z19.number().int().nonnegative().optional(),
|
|
2648
|
+
location: z19.string().optional().describe("Location label. Use an empty string for locationless results.")
|
|
2649
|
+
});
|
|
2650
|
+
var snapshotsDiffInputSchema = z19.object({
|
|
2651
|
+
project: projectNameSchema,
|
|
2652
|
+
run1: runIdSchema,
|
|
2653
|
+
run2: runIdSchema
|
|
2654
|
+
});
|
|
2655
|
+
var insightsListInputSchema = z19.object({
|
|
2656
|
+
project: projectNameSchema,
|
|
2657
|
+
dismissed: z19.boolean().optional(),
|
|
2658
|
+
runId: runIdSchema.optional()
|
|
2659
|
+
});
|
|
2660
|
+
var insightInputSchema = z19.object({
|
|
2661
|
+
project: projectNameSchema,
|
|
2662
|
+
insightId: insightIdSchema
|
|
2663
|
+
});
|
|
2664
|
+
var healthHistoryInputSchema = z19.object({
|
|
2665
|
+
project: projectNameSchema,
|
|
2666
|
+
limit: z19.number().int().positive().max(100).optional()
|
|
2667
|
+
});
|
|
2668
|
+
var gscPerformanceInputSchema = z19.object({
|
|
2669
|
+
project: projectNameSchema,
|
|
2670
|
+
startDate: z19.string().optional(),
|
|
2671
|
+
endDate: z19.string().optional(),
|
|
2672
|
+
query: z19.string().optional(),
|
|
2673
|
+
page: z19.string().optional(),
|
|
2674
|
+
limit: z19.number().int().positive().max(500).optional(),
|
|
2675
|
+
window: analyticsWindowSchema.optional()
|
|
2676
|
+
});
|
|
2677
|
+
var gscInspectionsInputSchema = z19.object({
|
|
2678
|
+
project: projectNameSchema,
|
|
2679
|
+
url: z19.string().optional(),
|
|
2680
|
+
limit: z19.number().int().positive().max(500).optional()
|
|
2681
|
+
});
|
|
2682
|
+
var gscCoverageHistoryInputSchema = z19.object({
|
|
2683
|
+
project: projectNameSchema,
|
|
2684
|
+
limit: z19.number().int().positive().max(500).optional()
|
|
2685
|
+
});
|
|
2686
|
+
var gaWindowInputSchema = z19.object({
|
|
2687
|
+
project: projectNameSchema,
|
|
2688
|
+
window: analyticsWindowSchema.optional()
|
|
2689
|
+
});
|
|
2690
|
+
var gaTrafficInputSchema = gaWindowInputSchema.extend({
|
|
2691
|
+
limit: z19.number().int().positive().max(500).optional()
|
|
2692
|
+
});
|
|
2693
|
+
var keywordsInputSchema = z19.object({
|
|
2694
|
+
project: projectNameSchema,
|
|
2695
|
+
request: keywordBatchRequestSchema
|
|
2696
|
+
});
|
|
2697
|
+
var keywordGenerateInputSchema = z19.object({
|
|
2698
|
+
project: projectNameSchema,
|
|
2699
|
+
request: keywordGenerateRequestSchema
|
|
2700
|
+
});
|
|
2701
|
+
var competitorsInputSchema = z19.object({
|
|
2702
|
+
project: projectNameSchema,
|
|
2703
|
+
request: competitorBatchRequestSchema
|
|
2704
|
+
});
|
|
2705
|
+
var projectUpsertInputSchema = z19.object({
|
|
2706
|
+
project: projectNameSchema,
|
|
2707
|
+
request: projectUpsertRequestSchema
|
|
2708
|
+
});
|
|
2709
|
+
var applyConfigInputSchema = z19.object({
|
|
2710
|
+
config: projectConfigSchema
|
|
2711
|
+
});
|
|
2712
|
+
var scheduleSetInputSchema = z19.object({
|
|
2713
|
+
project: projectNameSchema,
|
|
2714
|
+
schedule: scheduleUpsertRequestSchema
|
|
2715
|
+
});
|
|
2716
|
+
var agentWebhookAttachInputSchema = z19.object({
|
|
2717
|
+
project: projectNameSchema,
|
|
2718
|
+
url: z19.string().url()
|
|
2719
|
+
});
|
|
2720
|
+
var doctorInputSchema = z19.object({
|
|
2721
|
+
project: projectNameSchema.optional().describe("Project name to scope project-level checks. Omit to run global checks (provider keys, config, etc.)."),
|
|
2722
|
+
checks: z19.array(z19.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.')
|
|
2723
|
+
});
|
|
2724
|
+
var contentTargetsInputSchema = z19.object({
|
|
2725
|
+
project: projectNameSchema,
|
|
2726
|
+
limit: z19.number().int().positive().max(500).optional().describe("Max rows. Defaults to all. Use a small number (3-10) when summarizing for the user."),
|
|
2727
|
+
includeInProgress: z19.boolean().optional().describe("Include rows that already have an in-flight tracked action. Default false.")
|
|
2728
|
+
});
|
|
2729
|
+
var backlinksDomainsInputSchema = z19.object({
|
|
2730
|
+
project: projectNameSchema,
|
|
2731
|
+
limit: z19.number().int().positive().max(200).optional().describe("Max linking-domain rows. Default 50, max 200."),
|
|
2732
|
+
release: z19.string().optional().describe("Common Crawl release id (e.g., cc-main-2026-jan-feb-mar). Omit for the most recent release with data.")
|
|
2733
|
+
});
|
|
2734
|
+
var memoryUpsertInputSchema = z19.object({
|
|
2735
|
+
project: projectNameSchema,
|
|
2736
|
+
key: z19.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH).describe(`Stable identifier for the note (max ${AGENT_MEMORY_KEY_MAX_LENGTH} chars). Writing the same key overwrites the prior value.`),
|
|
2737
|
+
value: z19.string().min(1).describe(`Plain-text note body (max ${AGENT_MEMORY_VALUE_MAX_BYTES} bytes). Use for durable operator preferences, migration context, or non-obvious reasoning that should survive future sessions.`)
|
|
2738
|
+
});
|
|
2739
|
+
var memoryForgetInputSchema = z19.object({
|
|
2740
|
+
project: projectNameSchema,
|
|
2741
|
+
key: z19.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH).describe("Exact key of the note to remove. No-op (status=missing) when no note exists for that key.")
|
|
2742
|
+
});
|
|
2743
|
+
var AGENT_WEBHOOK_EVENTS = [
|
|
2744
|
+
notificationEventSchema.enum["run.completed"],
|
|
2745
|
+
notificationEventSchema.enum["insight.critical"],
|
|
2746
|
+
notificationEventSchema.enum["insight.high"],
|
|
2747
|
+
notificationEventSchema.enum["citation.gained"]
|
|
2748
|
+
];
|
|
2749
|
+
var canonryMcpTools = [
|
|
2750
|
+
defineTool({
|
|
2751
|
+
name: "canonry_projects_list",
|
|
2752
|
+
title: "List Canonry projects",
|
|
2753
|
+
description: "List all Canonry projects available through the configured API.",
|
|
2754
|
+
access: "read",
|
|
2755
|
+
tier: "core",
|
|
2756
|
+
inputSchema: emptyInputSchema,
|
|
2757
|
+
annotations: readAnnotations(),
|
|
2758
|
+
openApiOperations: ["GET /api/v1/projects"],
|
|
2759
|
+
handler: (client) => client.listProjects()
|
|
2760
|
+
}),
|
|
2761
|
+
defineTool({
|
|
2762
|
+
name: "canonry_project_get",
|
|
2763
|
+
title: "Get project",
|
|
2764
|
+
description: "Get a Canonry project by name.",
|
|
2765
|
+
access: "read",
|
|
2766
|
+
tier: "core",
|
|
2767
|
+
inputSchema: projectInputSchema,
|
|
2768
|
+
annotations: readAnnotations(),
|
|
2769
|
+
openApiOperations: ["GET /api/v1/projects/{name}"],
|
|
2770
|
+
handler: (client, input) => client.getProject(input.project)
|
|
2771
|
+
}),
|
|
2772
|
+
defineTool({
|
|
2773
|
+
name: "canonry_project_overview",
|
|
2774
|
+
title: "Get project overview (composite)",
|
|
2775
|
+
description: 'One-call summary for "how is project X doing?" \u2014 bundles project info, latest run, top undismissed insights, latest health snapshot, keyword cited rate, per-provider breakdown, and gained/lost/emerging vs the previous run. Prefer this over fanning out to separate tools.',
|
|
2776
|
+
access: "read",
|
|
2777
|
+
tier: "core",
|
|
2778
|
+
inputSchema: projectInputSchema,
|
|
2779
|
+
annotations: readAnnotations(),
|
|
2780
|
+
openApiOperations: ["GET /api/v1/projects/{name}/overview"],
|
|
2781
|
+
handler: (client, input) => client.getProjectOverview(input.project)
|
|
2782
|
+
}),
|
|
2783
|
+
defineTool({
|
|
2784
|
+
name: "canonry_search",
|
|
2785
|
+
title: "Search project (composite)",
|
|
2786
|
+
description: "Search query snapshots and intelligence insights for the given text. Looks at snapshot answer text, cited domains, raw provider responses, and insight title/keyword/recommendation/cause. Returns ranked hits with snippets \u2014 use it instead of paginating snapshots when you need to find a competitor mention or term.",
|
|
2787
|
+
access: "read",
|
|
2788
|
+
tier: "core",
|
|
2789
|
+
inputSchema: z19.object({
|
|
2790
|
+
project: projectNameSchema,
|
|
2791
|
+
q: z19.string().min(2).describe("Search term, at least 2 characters."),
|
|
2792
|
+
limit: z19.number().int().positive().max(50).optional().describe("Max combined hits (1-50, default 25).")
|
|
2793
|
+
}),
|
|
2794
|
+
annotations: readAnnotations(),
|
|
2795
|
+
openApiOperations: ["GET /api/v1/projects/{name}/search"],
|
|
2796
|
+
handler: (client, input) => client.searchProject(input.project, { q: input.q, limit: input.limit })
|
|
2797
|
+
}),
|
|
2798
|
+
defineTool({
|
|
2799
|
+
name: "canonry_doctor",
|
|
2800
|
+
title: "Run health checks",
|
|
2801
|
+
description: 'Run canonry health checks. With `project`, runs project-scoped checks (Google/GA auth, redirect URI, scopes, property access). Without `project`, runs global checks (provider keys, etc.). Use `checks` to filter by exact ID or wildcard prefix (e.g. ["google.auth.*"]). Returns a structured DoctorReport with per-check status, code, summary, remediation, and details \u2014 use this to diagnose Google auth failures (401/403/redirect-mismatch/principal-mismatch) without parsing logs.',
|
|
2802
|
+
access: "read",
|
|
2803
|
+
tier: "core",
|
|
2804
|
+
inputSchema: doctorInputSchema,
|
|
2805
|
+
annotations: readAnnotations(true),
|
|
2806
|
+
openApiOperations: ["GET /api/v1/doctor", "GET /api/v1/projects/{name}/doctor"],
|
|
2807
|
+
handler: (client, input) => client.runDoctor({ project: input.project, checkIds: input.checks })
|
|
2808
|
+
}),
|
|
2809
|
+
defineTool({
|
|
2810
|
+
name: "canonry_project_export",
|
|
2811
|
+
title: "Export project config",
|
|
2812
|
+
description: "Export a Canonry project in config-as-code format.",
|
|
2813
|
+
access: "read",
|
|
2814
|
+
tier: "setup",
|
|
2815
|
+
inputSchema: projectInputSchema,
|
|
2816
|
+
annotations: readAnnotations(),
|
|
2817
|
+
openApiOperations: ["GET /api/v1/projects/{name}/export"],
|
|
2818
|
+
handler: (client, input) => client.getExport(input.project)
|
|
2819
|
+
}),
|
|
2820
|
+
defineTool({
|
|
2821
|
+
name: "canonry_project_history",
|
|
2822
|
+
title: "Get project history",
|
|
2823
|
+
description: "Get audit history for a Canonry project.",
|
|
2824
|
+
access: "read",
|
|
2825
|
+
tier: "monitoring",
|
|
2826
|
+
inputSchema: projectInputSchema,
|
|
2827
|
+
annotations: readAnnotations(),
|
|
2828
|
+
openApiOperations: ["GET /api/v1/projects/{name}/history"],
|
|
2829
|
+
handler: (client, input) => client.getHistory(input.project)
|
|
2830
|
+
}),
|
|
2831
|
+
defineTool({
|
|
2832
|
+
name: "canonry_runs_list",
|
|
2833
|
+
title: "List project runs",
|
|
2834
|
+
description: "List runs for a Canonry project.",
|
|
2835
|
+
access: "read",
|
|
2836
|
+
tier: "monitoring",
|
|
2837
|
+
inputSchema: runsListInputSchema,
|
|
2838
|
+
annotations: readAnnotations(),
|
|
2839
|
+
openApiOperations: ["GET /api/v1/projects/{name}/runs"],
|
|
2840
|
+
handler: (client, input) => client.listRuns(input.project, input.limit)
|
|
2841
|
+
}),
|
|
2842
|
+
defineTool({
|
|
2843
|
+
name: "canonry_runs_latest",
|
|
2844
|
+
title: "Get latest project run",
|
|
2845
|
+
description: "Get the latest run and total run count for a Canonry project.",
|
|
2846
|
+
access: "read",
|
|
2847
|
+
tier: "monitoring",
|
|
2848
|
+
inputSchema: projectInputSchema,
|
|
2849
|
+
annotations: readAnnotations(),
|
|
2850
|
+
openApiOperations: ["GET /api/v1/projects/{name}/runs/latest"],
|
|
2851
|
+
handler: (client, input) => client.getLatestRun(input.project)
|
|
2852
|
+
}),
|
|
2853
|
+
defineTool({
|
|
2854
|
+
name: "canonry_run_get",
|
|
2855
|
+
title: "Get run",
|
|
2856
|
+
description: "Get a Canonry run with its snapshots.",
|
|
2857
|
+
access: "read",
|
|
2858
|
+
tier: "monitoring",
|
|
2859
|
+
inputSchema: runGetInputSchema,
|
|
2860
|
+
annotations: readAnnotations(),
|
|
2861
|
+
openApiOperations: ["GET /api/v1/runs/{id}"],
|
|
2862
|
+
handler: (client, input) => client.getRun(input.runId)
|
|
2863
|
+
}),
|
|
2864
|
+
defineTool({
|
|
2865
|
+
name: "canonry_timeline_get",
|
|
2866
|
+
title: "Get project timeline",
|
|
2867
|
+
description: "Get per-keyword citation history for a Canonry project.",
|
|
2868
|
+
access: "read",
|
|
2869
|
+
tier: "monitoring",
|
|
2870
|
+
inputSchema: timelineInputSchema,
|
|
2871
|
+
annotations: readAnnotations(),
|
|
2872
|
+
openApiOperations: ["GET /api/v1/projects/{name}/timeline"],
|
|
2873
|
+
handler: (client, input) => client.getTimeline(input.project, input.location)
|
|
2874
|
+
}),
|
|
2875
|
+
defineTool({
|
|
2876
|
+
name: "canonry_snapshots_list",
|
|
2877
|
+
title: "List query snapshots",
|
|
2878
|
+
description: "List paginated query snapshots for a Canonry project.",
|
|
2879
|
+
access: "read",
|
|
2880
|
+
tier: "monitoring",
|
|
2881
|
+
inputSchema: snapshotsListInputSchema,
|
|
2882
|
+
annotations: readAnnotations(),
|
|
2883
|
+
openApiOperations: ["GET /api/v1/projects/{name}/snapshots"],
|
|
2884
|
+
handler: (client, input) => client.getSnapshots(input.project, {
|
|
2885
|
+
limit: input.limit,
|
|
2886
|
+
offset: input.offset,
|
|
2887
|
+
location: input.location
|
|
2888
|
+
})
|
|
2889
|
+
}),
|
|
2890
|
+
defineTool({
|
|
2891
|
+
name: "canonry_snapshots_diff",
|
|
2892
|
+
title: "Diff snapshots",
|
|
2893
|
+
description: "Compare query snapshot states between two Canonry runs.",
|
|
2894
|
+
access: "read",
|
|
2895
|
+
tier: "monitoring",
|
|
2896
|
+
inputSchema: snapshotsDiffInputSchema,
|
|
2897
|
+
annotations: readAnnotations(),
|
|
2898
|
+
openApiOperations: ["GET /api/v1/projects/{name}/snapshots/diff"],
|
|
2899
|
+
handler: (client, input) => client.getSnapshotDiff(input.project, input.run1, input.run2)
|
|
2900
|
+
}),
|
|
2901
|
+
defineTool({
|
|
2902
|
+
name: "canonry_insights_list",
|
|
2903
|
+
title: "List insights",
|
|
2904
|
+
description: "List intelligence insights for a Canonry project.",
|
|
2905
|
+
access: "read",
|
|
2906
|
+
tier: "monitoring",
|
|
2907
|
+
inputSchema: insightsListInputSchema,
|
|
2908
|
+
annotations: readAnnotations(),
|
|
2909
|
+
openApiOperations: ["GET /api/v1/projects/{name}/insights"],
|
|
2910
|
+
handler: (client, input) => client.getInsights(input.project, { dismissed: input.dismissed, runId: input.runId })
|
|
2911
|
+
}),
|
|
2912
|
+
defineTool({
|
|
2913
|
+
name: "canonry_insight_get",
|
|
2914
|
+
title: "Get insight",
|
|
2915
|
+
description: "Get one intelligence insight for a Canonry project.",
|
|
2916
|
+
access: "read",
|
|
2917
|
+
tier: "monitoring",
|
|
2918
|
+
inputSchema: insightInputSchema,
|
|
2919
|
+
annotations: readAnnotations(),
|
|
2920
|
+
openApiOperations: ["GET /api/v1/projects/{name}/insights/{id}"],
|
|
2921
|
+
handler: (client, input) => client.getInsight(input.project, input.insightId)
|
|
2922
|
+
}),
|
|
2923
|
+
defineTool({
|
|
2924
|
+
name: "canonry_health_latest",
|
|
2925
|
+
title: "Get latest health",
|
|
2926
|
+
description: 'Get the latest health snapshot for a Canonry project. Always returns a snapshot once the project exists: real data carries `status: "ready"`; newly-created projects (or projects with only failed runs) carry `status: "no-data"` with `reason: "no-runs-yet"` and zeroed metrics.',
|
|
2927
|
+
access: "read",
|
|
2928
|
+
tier: "monitoring",
|
|
2929
|
+
inputSchema: projectInputSchema,
|
|
2930
|
+
annotations: readAnnotations(),
|
|
2931
|
+
openApiOperations: ["GET /api/v1/projects/{name}/health/latest"],
|
|
2932
|
+
handler: (client, input) => client.getHealth(input.project)
|
|
2933
|
+
}),
|
|
2934
|
+
defineTool({
|
|
2935
|
+
name: "canonry_health_history",
|
|
2936
|
+
title: "Get health history",
|
|
2937
|
+
description: "Get health snapshot history for a Canonry project.",
|
|
2938
|
+
access: "read",
|
|
2939
|
+
tier: "monitoring",
|
|
2940
|
+
inputSchema: healthHistoryInputSchema,
|
|
2941
|
+
annotations: readAnnotations(),
|
|
2942
|
+
openApiOperations: ["GET /api/v1/projects/{name}/health/history"],
|
|
2943
|
+
handler: (client, input) => client.getHealthHistory(input.project, input.limit)
|
|
2944
|
+
}),
|
|
2945
|
+
defineTool({
|
|
2946
|
+
name: "canonry_content_targets",
|
|
2947
|
+
title: "Get content targets",
|
|
2948
|
+
description: "Ranked, action-typed content opportunities. Each row is `{query, action \u2208 create|expand|refresh|add-schema, ourBestPage?, winningCompetitor?, score, scoreBreakdown, drivers[], demandSource, actionConfidence}`. Use this to recommend which post the user should write or refresh next.",
|
|
2949
|
+
access: "read",
|
|
2950
|
+
tier: "monitoring",
|
|
2951
|
+
inputSchema: contentTargetsInputSchema,
|
|
2952
|
+
annotations: readAnnotations(),
|
|
2953
|
+
openApiOperations: ["GET /api/v1/projects/{name}/content/targets"],
|
|
2954
|
+
handler: (client, input) => client.getContentTargets(input.project, {
|
|
2955
|
+
limit: input.limit,
|
|
2956
|
+
includeInProgress: input.includeInProgress
|
|
2957
|
+
})
|
|
2958
|
+
}),
|
|
2959
|
+
defineTool({
|
|
2960
|
+
name: "canonry_content_sources",
|
|
2961
|
+
title: "Get grounding sources",
|
|
2962
|
+
description: "URL-level competitive grounding-source map. Per query, lists every URL the LLM cited (our domain vs competitors) with citation count and providers. Read this to understand which specific competitor URL is winning a query.",
|
|
2963
|
+
access: "read",
|
|
2964
|
+
tier: "monitoring",
|
|
2965
|
+
inputSchema: projectInputSchema,
|
|
2966
|
+
annotations: readAnnotations(),
|
|
2967
|
+
openApiOperations: ["GET /api/v1/projects/{name}/content/sources"],
|
|
2968
|
+
handler: (client, input) => client.getContentSources(input.project)
|
|
2969
|
+
}),
|
|
2970
|
+
defineTool({
|
|
2971
|
+
name: "canonry_content_gaps",
|
|
2972
|
+
title: "Get content gaps",
|
|
2973
|
+
description: 'Queries where competitors are cited but our domain is not, ranked by miss rate. The blunt-instrument view of "what competitors are winning that we are not." Use canonry_content_targets for action-typed recommendations on the same data.',
|
|
2974
|
+
access: "read",
|
|
2975
|
+
tier: "monitoring",
|
|
2976
|
+
inputSchema: projectInputSchema,
|
|
2977
|
+
annotations: readAnnotations(),
|
|
2978
|
+
openApiOperations: ["GET /api/v1/projects/{name}/content/gaps"],
|
|
2979
|
+
handler: (client, input) => client.getContentGaps(input.project)
|
|
2980
|
+
}),
|
|
2981
|
+
defineTool({
|
|
2982
|
+
name: "canonry_keywords_list",
|
|
2983
|
+
title: "List keywords",
|
|
2984
|
+
description: "List tracked keywords for a Canonry project.",
|
|
2985
|
+
access: "read",
|
|
2986
|
+
tier: "setup",
|
|
2987
|
+
inputSchema: projectInputSchema,
|
|
2988
|
+
annotations: readAnnotations(),
|
|
2989
|
+
openApiOperations: ["GET /api/v1/projects/{name}/keywords"],
|
|
2990
|
+
handler: (client, input) => client.listKeywords(input.project)
|
|
2991
|
+
}),
|
|
2992
|
+
defineTool({
|
|
2993
|
+
name: "canonry_competitors_list",
|
|
2994
|
+
title: "List competitors",
|
|
2995
|
+
description: "List tracked competitors for a Canonry project.",
|
|
2996
|
+
access: "read",
|
|
2997
|
+
tier: "setup",
|
|
2998
|
+
inputSchema: projectInputSchema,
|
|
2999
|
+
annotations: readAnnotations(),
|
|
3000
|
+
openApiOperations: ["GET /api/v1/projects/{name}/competitors"],
|
|
3001
|
+
handler: (client, input) => client.listCompetitors(input.project)
|
|
3002
|
+
}),
|
|
3003
|
+
defineTool({
|
|
3004
|
+
name: "canonry_schedule_get",
|
|
3005
|
+
title: "Get schedule",
|
|
3006
|
+
description: "Get the scheduled run configuration for a Canonry project.",
|
|
3007
|
+
access: "read",
|
|
3008
|
+
tier: "setup",
|
|
3009
|
+
inputSchema: projectInputSchema,
|
|
3010
|
+
annotations: readAnnotations(),
|
|
3011
|
+
openApiOperations: ["GET /api/v1/projects/{name}/schedule"],
|
|
3012
|
+
handler: (client, input) => client.getSchedule(input.project)
|
|
3013
|
+
}),
|
|
3014
|
+
defineTool({
|
|
3015
|
+
name: "canonry_backlinks_latest_release",
|
|
3016
|
+
title: "Discover latest Common Crawl release",
|
|
3017
|
+
description: "Probes Common Crawl to find the latest published hyperlinkgraph release. Returns the release id and file URLs/sizes ready to feed into a backlinks sync (or null if no candidate slug responded).",
|
|
3018
|
+
access: "read",
|
|
3019
|
+
tier: "setup",
|
|
3020
|
+
inputSchema: emptyInputSchema,
|
|
3021
|
+
annotations: readAnnotations(true),
|
|
3022
|
+
openApiOperations: ["GET /api/v1/backlinks/latest-release"],
|
|
3023
|
+
handler: (client) => client.backlinksLatestRelease()
|
|
3024
|
+
}),
|
|
3025
|
+
defineTool({
|
|
3026
|
+
name: "canonry_backlinks_domains",
|
|
3027
|
+
title: "List backlink domains",
|
|
3028
|
+
description: "Backlink summary and top linking domains from the most recent ready Common Crawl release for a project. Off-site authority signal that correlates with citation likelihood. Returns null summary when no release sync has completed for this workspace.",
|
|
3029
|
+
access: "read",
|
|
3030
|
+
tier: "setup",
|
|
3031
|
+
inputSchema: backlinksDomainsInputSchema,
|
|
3032
|
+
annotations: readAnnotations(),
|
|
3033
|
+
openApiOperations: ["GET /api/v1/projects/{name}/backlinks/domains"],
|
|
3034
|
+
handler: (client, input) => client.backlinksDomains(input.project, {
|
|
3035
|
+
limit: input.limit ?? 50,
|
|
3036
|
+
release: input.release
|
|
3037
|
+
})
|
|
3038
|
+
}),
|
|
3039
|
+
defineTool({
|
|
3040
|
+
name: "canonry_settings_get",
|
|
3041
|
+
title: "Get settings",
|
|
3042
|
+
description: "Get Canonry API settings and configured provider status.",
|
|
3043
|
+
access: "read",
|
|
3044
|
+
tier: "core",
|
|
3045
|
+
inputSchema: emptyInputSchema,
|
|
3046
|
+
annotations: readAnnotations(),
|
|
3047
|
+
openApiOperations: ["GET /api/v1/settings"],
|
|
3048
|
+
handler: (client) => client.getSettings()
|
|
3049
|
+
}),
|
|
3050
|
+
defineTool({
|
|
3051
|
+
name: "canonry_google_connections_list",
|
|
3052
|
+
title: "List Google connections",
|
|
3053
|
+
description: "List configured Google connections for a Canonry project.",
|
|
3054
|
+
access: "read",
|
|
3055
|
+
tier: "gsc",
|
|
3056
|
+
inputSchema: projectInputSchema,
|
|
3057
|
+
annotations: readAnnotations(),
|
|
3058
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/connections"],
|
|
3059
|
+
handler: (client, input) => client.googleConnections(input.project)
|
|
3060
|
+
}),
|
|
3061
|
+
defineTool({
|
|
3062
|
+
name: "canonry_gsc_performance",
|
|
3063
|
+
title: "Get GSC performance",
|
|
3064
|
+
description: "Get stored Google Search Console performance rows for a Canonry project.",
|
|
3065
|
+
access: "read",
|
|
3066
|
+
tier: "gsc",
|
|
3067
|
+
inputSchema: gscPerformanceInputSchema,
|
|
3068
|
+
annotations: readAnnotations(),
|
|
3069
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/performance"],
|
|
3070
|
+
handler: (client, input) => client.gscPerformance(input.project, compactStringParams(input, ["startDate", "endDate", "query", "page", "limit", "window"]))
|
|
3071
|
+
}),
|
|
3072
|
+
defineTool({
|
|
3073
|
+
name: "canonry_gsc_inspections",
|
|
3074
|
+
title: "List GSC inspections",
|
|
3075
|
+
description: "List stored URL inspection rows for a Canonry project.",
|
|
3076
|
+
access: "read",
|
|
3077
|
+
tier: "gsc",
|
|
3078
|
+
inputSchema: gscInspectionsInputSchema,
|
|
3079
|
+
annotations: readAnnotations(),
|
|
3080
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/inspections"],
|
|
3081
|
+
handler: (client, input) => client.gscInspections(input.project, compactStringParams(input, ["url", "limit"]))
|
|
3082
|
+
}),
|
|
3083
|
+
defineTool({
|
|
3084
|
+
name: "canonry_gsc_deindexed",
|
|
3085
|
+
title: "List deindexed GSC URLs",
|
|
3086
|
+
description: "List URLs that appear to have become deindexed in Google Search Console data.",
|
|
3087
|
+
access: "read",
|
|
3088
|
+
tier: "gsc",
|
|
3089
|
+
inputSchema: projectInputSchema,
|
|
3090
|
+
annotations: readAnnotations(),
|
|
3091
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/deindexed"],
|
|
3092
|
+
handler: (client, input) => client.gscDeindexed(input.project)
|
|
3093
|
+
}),
|
|
3094
|
+
defineTool({
|
|
3095
|
+
name: "canonry_gsc_coverage",
|
|
3096
|
+
title: "Get GSC coverage",
|
|
3097
|
+
description: "Get Google Search Console coverage summary for a Canonry project.",
|
|
3098
|
+
access: "read",
|
|
3099
|
+
tier: "gsc",
|
|
3100
|
+
inputSchema: projectInputSchema,
|
|
3101
|
+
annotations: readAnnotations(),
|
|
3102
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/coverage"],
|
|
3103
|
+
handler: (client, input) => client.gscCoverage(input.project)
|
|
3104
|
+
}),
|
|
3105
|
+
defineTool({
|
|
3106
|
+
name: "canonry_gsc_coverage_history",
|
|
3107
|
+
title: "Get GSC coverage history",
|
|
3108
|
+
description: "Get Google Search Console coverage history snapshots for a Canonry project.",
|
|
3109
|
+
access: "read",
|
|
3110
|
+
tier: "gsc",
|
|
3111
|
+
inputSchema: gscCoverageHistoryInputSchema,
|
|
3112
|
+
annotations: readAnnotations(),
|
|
3113
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/coverage/history"],
|
|
3114
|
+
handler: (client, input) => client.gscCoverageHistory(input.project, { limit: input.limit })
|
|
3115
|
+
}),
|
|
3116
|
+
defineTool({
|
|
3117
|
+
name: "canonry_gsc_sitemaps",
|
|
3118
|
+
title: "Get GSC sitemaps",
|
|
3119
|
+
description: "Get sitemap data from Google Search Console for a Canonry project.",
|
|
3120
|
+
access: "read",
|
|
3121
|
+
tier: "gsc",
|
|
3122
|
+
inputSchema: projectInputSchema,
|
|
3123
|
+
annotations: readAnnotations(true),
|
|
3124
|
+
openApiOperations: ["GET /api/v1/projects/{name}/google/gsc/sitemaps"],
|
|
3125
|
+
handler: (client, input) => client.gscSitemaps(input.project)
|
|
3126
|
+
}),
|
|
3127
|
+
defineTool({
|
|
3128
|
+
name: "canonry_ga_status",
|
|
3129
|
+
title: "Get GA status",
|
|
3130
|
+
description: "Get Google Analytics connection status for a Canonry project.",
|
|
3131
|
+
access: "read",
|
|
3132
|
+
tier: "ga",
|
|
3133
|
+
inputSchema: projectInputSchema,
|
|
3134
|
+
annotations: readAnnotations(),
|
|
3135
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/status"],
|
|
3136
|
+
handler: (client, input) => client.gaStatus(input.project)
|
|
3137
|
+
}),
|
|
3138
|
+
defineTool({
|
|
3139
|
+
name: "canonry_ga_traffic",
|
|
3140
|
+
title: "Get GA traffic",
|
|
3141
|
+
description: "Get Google Analytics traffic summary for a Canonry project.",
|
|
3142
|
+
access: "read",
|
|
3143
|
+
tier: "ga",
|
|
3144
|
+
inputSchema: gaTrafficInputSchema,
|
|
3145
|
+
annotations: readAnnotations(),
|
|
3146
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/traffic"],
|
|
3147
|
+
handler: (client, input) => client.gaTraffic(input.project, compactStringParams(input, ["limit", "window"]))
|
|
3148
|
+
}),
|
|
3149
|
+
defineTool({
|
|
3150
|
+
name: "canonry_ga_coverage",
|
|
3151
|
+
title: "Get GA coverage",
|
|
3152
|
+
description: "Get Google Analytics page coverage for a Canonry project.",
|
|
3153
|
+
access: "read",
|
|
3154
|
+
tier: "ga",
|
|
3155
|
+
inputSchema: projectInputSchema,
|
|
3156
|
+
annotations: readAnnotations(),
|
|
3157
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/coverage"],
|
|
3158
|
+
handler: (client, input) => client.gaCoverage(input.project)
|
|
3159
|
+
}),
|
|
3160
|
+
defineTool({
|
|
3161
|
+
name: "canonry_ga_ai_referral_history",
|
|
3162
|
+
title: "Get GA AI referral history",
|
|
3163
|
+
description: "Get AI referral sessions per day grouped by source.",
|
|
3164
|
+
access: "read",
|
|
3165
|
+
tier: "ga",
|
|
3166
|
+
inputSchema: gaWindowInputSchema,
|
|
3167
|
+
annotations: readAnnotations(),
|
|
3168
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/ai-referral-history"],
|
|
3169
|
+
handler: (client, input) => client.gaAiReferralHistory(input.project, compactStringParams(input, ["window"]))
|
|
3170
|
+
}),
|
|
3171
|
+
defineTool({
|
|
3172
|
+
name: "canonry_ga_social_referral_history",
|
|
3173
|
+
title: "Get GA social referral history",
|
|
3174
|
+
description: "Get social referral sessions per day grouped by source.",
|
|
3175
|
+
access: "read",
|
|
3176
|
+
tier: "ga",
|
|
3177
|
+
inputSchema: gaWindowInputSchema,
|
|
3178
|
+
annotations: readAnnotations(),
|
|
3179
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/social-referral-history"],
|
|
3180
|
+
handler: (client, input) => client.gaSocialReferralHistory(input.project, compactStringParams(input, ["window"]))
|
|
3181
|
+
}),
|
|
3182
|
+
defineTool({
|
|
3183
|
+
name: "canonry_ga_social_referral_trend",
|
|
3184
|
+
title: "Get GA social referral trend",
|
|
3185
|
+
description: "Get social referral trend with biggest mover for a Canonry project.",
|
|
3186
|
+
access: "read",
|
|
3187
|
+
tier: "ga",
|
|
3188
|
+
inputSchema: projectInputSchema,
|
|
3189
|
+
annotations: readAnnotations(),
|
|
3190
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/social-referral-trend"],
|
|
3191
|
+
handler: (client, input) => client.gaSocialReferralTrend(input.project)
|
|
3192
|
+
}),
|
|
3193
|
+
defineTool({
|
|
3194
|
+
name: "canonry_ga_attribution_trend",
|
|
3195
|
+
title: "Get GA attribution trend",
|
|
3196
|
+
description: "Get per-channel attribution trends for organic, AI, social, direct, and total sessions.",
|
|
3197
|
+
access: "read",
|
|
3198
|
+
tier: "ga",
|
|
3199
|
+
inputSchema: projectInputSchema,
|
|
3200
|
+
annotations: readAnnotations(),
|
|
3201
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/attribution-trend"],
|
|
3202
|
+
handler: (client, input) => client.gaAttributionTrend(input.project)
|
|
3203
|
+
}),
|
|
3204
|
+
defineTool({
|
|
3205
|
+
name: "canonry_ga_session_history",
|
|
3206
|
+
title: "Get GA session history",
|
|
3207
|
+
description: "Get total sessions per day for a Canonry project.",
|
|
3208
|
+
access: "read",
|
|
3209
|
+
tier: "ga",
|
|
3210
|
+
inputSchema: gaWindowInputSchema,
|
|
3211
|
+
annotations: readAnnotations(),
|
|
3212
|
+
openApiOperations: ["GET /api/v1/projects/{name}/ga/session-history"],
|
|
3213
|
+
handler: (client, input) => client.gaSessionHistory(input.project, compactStringParams(input, ["window"]))
|
|
3214
|
+
}),
|
|
3215
|
+
defineTool({
|
|
3216
|
+
name: "canonry_project_upsert",
|
|
3217
|
+
title: "Create or replace project",
|
|
3218
|
+
description: "Create or replace a Canonry project. PUT semantics \u2014 fields not in the request are reset to their defaults. Provide the full intended project shape.",
|
|
3219
|
+
access: "write",
|
|
3220
|
+
tier: "setup",
|
|
3221
|
+
inputSchema: projectUpsertInputSchema,
|
|
3222
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3223
|
+
openApiOperations: ["PUT /api/v1/projects/{name}"],
|
|
3224
|
+
handler: (client, input) => client.putProject(input.project, input.request)
|
|
3225
|
+
}),
|
|
3226
|
+
defineTool({
|
|
3227
|
+
name: "canonry_apply_config",
|
|
3228
|
+
title: "Apply project config",
|
|
3229
|
+
description: "Apply one Canonry config-as-code project document. Replaces the project to match the config \u2014 fields omitted from the spec are reset to defaults. For multi-document YAML, call this tool once per project document.",
|
|
3230
|
+
access: "write",
|
|
3231
|
+
tier: "core",
|
|
3232
|
+
inputSchema: applyConfigInputSchema,
|
|
3233
|
+
// Declarative apply is safe to repeat, but it replaces configured child state.
|
|
3234
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3235
|
+
openApiOperations: ["POST /api/v1/apply"],
|
|
3236
|
+
handler: (client, input) => client.apply(input.config)
|
|
3237
|
+
}),
|
|
3238
|
+
defineTool({
|
|
3239
|
+
name: "canonry_keywords_generate",
|
|
3240
|
+
title: "Generate keyword suggestions",
|
|
3241
|
+
description: "Generate candidate key phrases using a configured provider. Returns suggestions only; use canonry_keywords_add to persist them.",
|
|
3242
|
+
access: "write",
|
|
3243
|
+
tier: "setup",
|
|
3244
|
+
inputSchema: keywordGenerateInputSchema,
|
|
3245
|
+
annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
|
|
3246
|
+
openApiOperations: ["POST /api/v1/projects/{name}/keywords/generate"],
|
|
3247
|
+
handler: (client, input) => client.generateKeywords(input.project, input.request.provider, input.request.count)
|
|
3248
|
+
}),
|
|
3249
|
+
defineTool({
|
|
3250
|
+
name: "canonry_keywords_replace",
|
|
3251
|
+
title: "Replace keywords",
|
|
3252
|
+
description: "Replace the tracked keyword set for a Canonry project.",
|
|
3253
|
+
access: "write",
|
|
3254
|
+
tier: "setup",
|
|
3255
|
+
inputSchema: keywordsInputSchema,
|
|
3256
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3257
|
+
openApiOperations: ["PUT /api/v1/projects/{name}/keywords"],
|
|
3258
|
+
handler: async (client, input) => {
|
|
3259
|
+
await client.putKeywords(input.project, uniqueStrings(input.request.keywords));
|
|
3260
|
+
}
|
|
3261
|
+
}),
|
|
3262
|
+
defineTool({
|
|
3263
|
+
name: "canonry_run_trigger",
|
|
3264
|
+
title: "Trigger run",
|
|
3265
|
+
description: "Trigger an answer-visibility run for a Canonry project.",
|
|
3266
|
+
access: "write",
|
|
3267
|
+
tier: "core",
|
|
3268
|
+
inputSchema: runTriggerInputSchema,
|
|
3269
|
+
annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
|
|
3270
|
+
openApiOperations: ["POST /api/v1/projects/{name}/runs"],
|
|
3271
|
+
handler: (client, input) => client.triggerRun(input.project, input.request)
|
|
3272
|
+
}),
|
|
3273
|
+
defineTool({
|
|
3274
|
+
name: "canonry_run_cancel",
|
|
3275
|
+
title: "Cancel run",
|
|
3276
|
+
description: "Cancel a queued or running Canonry run.",
|
|
3277
|
+
access: "write",
|
|
3278
|
+
tier: "core",
|
|
3279
|
+
inputSchema: runGetInputSchema,
|
|
3280
|
+
annotations: writeAnnotations({ idempotentHint: false, destructiveHint: true }),
|
|
3281
|
+
openApiOperations: ["POST /api/v1/runs/{id}/cancel"],
|
|
3282
|
+
handler: (client, input) => client.cancelRun(input.runId)
|
|
3283
|
+
}),
|
|
3284
|
+
defineTool({
|
|
3285
|
+
name: "canonry_keywords_add",
|
|
3286
|
+
title: "Add keywords",
|
|
3287
|
+
description: "Append tracked keywords to a Canonry project; existing keywords are skipped by the API.",
|
|
3288
|
+
access: "write",
|
|
3289
|
+
tier: "setup",
|
|
3290
|
+
inputSchema: keywordsInputSchema,
|
|
3291
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3292
|
+
openApiOperations: ["POST /api/v1/projects/{name}/keywords"],
|
|
3293
|
+
handler: async (client, input) => {
|
|
3294
|
+
await client.appendKeywords(input.project, uniqueStrings(input.request.keywords));
|
|
3295
|
+
}
|
|
3296
|
+
}),
|
|
3297
|
+
defineTool({
|
|
3298
|
+
name: "canonry_keywords_remove",
|
|
3299
|
+
title: "Remove keywords",
|
|
3300
|
+
description: "Remove tracked keywords from a Canonry project.",
|
|
3301
|
+
access: "write",
|
|
3302
|
+
tier: "setup",
|
|
3303
|
+
inputSchema: keywordsInputSchema,
|
|
3304
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3305
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/keywords"],
|
|
3306
|
+
handler: async (client, input) => {
|
|
3307
|
+
await client.deleteKeywords(input.project, uniqueStrings(input.request.keywords));
|
|
3308
|
+
}
|
|
3309
|
+
}),
|
|
3310
|
+
defineTool({
|
|
3311
|
+
name: "canonry_competitors_add",
|
|
3312
|
+
title: "Add competitors",
|
|
3313
|
+
description: "Add tracked competitor domains to a Canonry project.",
|
|
3314
|
+
access: "write",
|
|
3315
|
+
tier: "setup",
|
|
3316
|
+
inputSchema: competitorsInputSchema,
|
|
3317
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3318
|
+
openApiOperations: ["POST /api/v1/projects/{name}/competitors"],
|
|
3319
|
+
handler: async (client, input) => {
|
|
3320
|
+
await client.appendCompetitors(input.project, uniqueStrings(input.request.competitors));
|
|
3321
|
+
}
|
|
3322
|
+
}),
|
|
3323
|
+
defineTool({
|
|
3324
|
+
name: "canonry_competitors_remove",
|
|
3325
|
+
title: "Remove competitors",
|
|
3326
|
+
description: "Remove tracked competitor domains from a Canonry project.",
|
|
3327
|
+
access: "write",
|
|
3328
|
+
tier: "setup",
|
|
3329
|
+
inputSchema: competitorsInputSchema,
|
|
3330
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3331
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/competitors"],
|
|
3332
|
+
handler: async (client, input) => {
|
|
3333
|
+
await client.deleteCompetitors(input.project, uniqueStrings(input.request.competitors));
|
|
3334
|
+
}
|
|
3335
|
+
}),
|
|
3336
|
+
defineTool({
|
|
3337
|
+
name: "canonry_schedule_set",
|
|
3338
|
+
title: "Set schedule",
|
|
3339
|
+
description: "Create or replace the scheduled run configuration for a Canonry project.",
|
|
3340
|
+
access: "write",
|
|
3341
|
+
tier: "setup",
|
|
3342
|
+
inputSchema: scheduleSetInputSchema,
|
|
3343
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3344
|
+
openApiOperations: ["PUT /api/v1/projects/{name}/schedule"],
|
|
3345
|
+
handler: (client, input) => client.putSchedule(input.project, input.schedule)
|
|
3346
|
+
}),
|
|
3347
|
+
defineTool({
|
|
3348
|
+
name: "canonry_schedule_delete",
|
|
3349
|
+
title: "Delete schedule",
|
|
3350
|
+
description: "Delete the scheduled run configuration for a Canonry project.",
|
|
3351
|
+
access: "write",
|
|
3352
|
+
tier: "setup",
|
|
3353
|
+
inputSchema: projectInputSchema,
|
|
3354
|
+
annotations: writeAnnotations({ idempotentHint: false, destructiveHint: true }),
|
|
3355
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/schedule"],
|
|
3356
|
+
handler: async (client, input) => {
|
|
3357
|
+
await client.deleteSchedule(input.project);
|
|
3358
|
+
}
|
|
3359
|
+
}),
|
|
3360
|
+
defineTool({
|
|
3361
|
+
name: "canonry_insight_dismiss",
|
|
3362
|
+
title: "Dismiss insight",
|
|
3363
|
+
description: "Dismiss an intelligence insight for a Canonry project.",
|
|
3364
|
+
access: "write",
|
|
3365
|
+
tier: "setup",
|
|
3366
|
+
inputSchema: insightInputSchema,
|
|
3367
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3368
|
+
openApiOperations: ["POST /api/v1/projects/{name}/insights/{id}/dismiss"],
|
|
3369
|
+
handler: (client, input) => client.dismissInsight(input.project, input.insightId)
|
|
3370
|
+
}),
|
|
3371
|
+
defineTool({
|
|
3372
|
+
name: "canonry_memory_list",
|
|
3373
|
+
title: "List agent memory",
|
|
3374
|
+
description: "Read project-scoped durable notes Aero has stored via canonry_memory_set (plus compaction summaries). Returns entries newest-first. The N most-recent entries are also injected into the system prompt at session start, so you usually do not need to call this \u2014 reach for it when you need older context or the full note value.",
|
|
3375
|
+
access: "read",
|
|
3376
|
+
tier: "agent",
|
|
3377
|
+
inputSchema: projectInputSchema,
|
|
3378
|
+
annotations: readAnnotations(),
|
|
3379
|
+
openApiOperations: ["GET /api/v1/projects/{name}/agent/memory"],
|
|
3380
|
+
handler: (client, input) => client.listAgentMemory(input.project)
|
|
3381
|
+
}),
|
|
3382
|
+
defineTool({
|
|
3383
|
+
name: "canonry_memory_set",
|
|
3384
|
+
title: "Upsert agent memory",
|
|
3385
|
+
description: 'Persist a project-scoped durable note visible to every future Aero session for this project. Upsert \u2014 writing the same key replaces the prior value. Capped at 2 KB per note. Reserved key prefix "compaction:" is rejected.',
|
|
3386
|
+
access: "write",
|
|
3387
|
+
tier: "agent",
|
|
3388
|
+
inputSchema: memoryUpsertInputSchema,
|
|
3389
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3390
|
+
openApiOperations: ["PUT /api/v1/projects/{name}/agent/memory"],
|
|
3391
|
+
handler: (client, input) => client.setAgentMemory(input.project, { key: input.key, value: input.value })
|
|
3392
|
+
}),
|
|
3393
|
+
defineTool({
|
|
3394
|
+
name: "canonry_memory_forget",
|
|
3395
|
+
title: "Delete agent memory",
|
|
3396
|
+
description: 'Delete a durable note by key. Returns status="missing" (non-error) when the key did not exist. Reserved key prefix "compaction:" cannot be forgotten directly \u2014 those notes are pruned automatically.',
|
|
3397
|
+
access: "write",
|
|
3398
|
+
tier: "agent",
|
|
3399
|
+
inputSchema: memoryForgetInputSchema,
|
|
3400
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3401
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/agent/memory"],
|
|
3402
|
+
handler: (client, input) => client.forgetAgentMemory(input.project, input.key)
|
|
3403
|
+
}),
|
|
3404
|
+
defineTool({
|
|
3405
|
+
name: "canonry_agent_clear",
|
|
3406
|
+
title: "Clear agent transcript",
|
|
3407
|
+
description: "Clear the rolling Aero conversation for a project \u2014 wipes the transcript, the in-memory pending follow-up buffer, and the persisted follow-up queue. Memory entries (canonry_memory_*) are preserved. Use when starting a fresh dialogue or when the operator wants to reset context.",
|
|
3408
|
+
access: "write",
|
|
3409
|
+
tier: "agent",
|
|
3410
|
+
inputSchema: projectInputSchema,
|
|
3411
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3412
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/agent/transcript"],
|
|
3413
|
+
handler: async (client, input) => {
|
|
3414
|
+
await client.resetAgentTranscript(input.project);
|
|
3415
|
+
return { status: "cleared", project: input.project };
|
|
3416
|
+
}
|
|
3417
|
+
}),
|
|
3418
|
+
defineTool({
|
|
3419
|
+
name: "canonry_agent_webhook_attach",
|
|
3420
|
+
title: "Attach agent webhook",
|
|
3421
|
+
description: "Attach an external agent webhook to project run and insight events.",
|
|
3422
|
+
access: "write",
|
|
3423
|
+
tier: "core",
|
|
3424
|
+
inputSchema: agentWebhookAttachInputSchema,
|
|
3425
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
3426
|
+
openApiOperations: ["GET /api/v1/projects/{name}/notifications", "POST /api/v1/projects/{name}/notifications"],
|
|
3427
|
+
handler: async (client, input) => {
|
|
3428
|
+
const existing = await client.listNotifications(input.project);
|
|
3429
|
+
const agentNotification = existing.find((notification2) => notification2.source === "agent");
|
|
3430
|
+
if (agentNotification) {
|
|
3431
|
+
return { status: "already-attached", project: input.project, notificationId: agentNotification.id };
|
|
3432
|
+
}
|
|
3433
|
+
const request = notificationCreateRequestSchema.parse({
|
|
3434
|
+
channel: "webhook",
|
|
3435
|
+
url: input.url,
|
|
3436
|
+
events: AGENT_WEBHOOK_EVENTS,
|
|
3437
|
+
source: "agent"
|
|
3438
|
+
});
|
|
3439
|
+
const notification = await client.createNotification(input.project, request);
|
|
3440
|
+
return { status: "attached", project: input.project, notificationId: notification.id };
|
|
3441
|
+
}
|
|
3442
|
+
}),
|
|
3443
|
+
defineTool({
|
|
3444
|
+
name: "canonry_agent_webhook_detach",
|
|
3445
|
+
title: "Detach agent webhook",
|
|
3446
|
+
description: "Detach the external agent webhook for a Canonry project.",
|
|
3447
|
+
access: "write",
|
|
3448
|
+
tier: "agent",
|
|
3449
|
+
inputSchema: projectInputSchema,
|
|
3450
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
3451
|
+
openApiOperations: ["GET /api/v1/projects/{name}/notifications", "DELETE /api/v1/projects/{name}/notifications/{id}"],
|
|
3452
|
+
handler: async (client, input) => {
|
|
3453
|
+
const existing = await client.listNotifications(input.project);
|
|
3454
|
+
const agentNotification = existing.find((notification) => notification.source === "agent");
|
|
3455
|
+
if (!agentNotification) {
|
|
3456
|
+
return { status: "not-attached", project: input.project };
|
|
3457
|
+
}
|
|
3458
|
+
await client.deleteNotification(input.project, agentNotification.id);
|
|
3459
|
+
return { status: "detached", project: input.project };
|
|
3460
|
+
}
|
|
3461
|
+
})
|
|
3462
|
+
];
|
|
3463
|
+
var CANONRY_MCP_TOOL_COUNT = canonryMcpTools.length;
|
|
3464
|
+
var CANONRY_MCP_READ_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.access === "read").length;
|
|
3465
|
+
var CANONRY_MCP_CORE_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.tier === "core").length;
|
|
3466
|
+
|
|
2546
3467
|
export {
|
|
2547
3468
|
getConfigDir,
|
|
2548
3469
|
getConfigPath,
|
|
@@ -2562,11 +3483,9 @@ export {
|
|
|
2562
3483
|
resolveProviderInput,
|
|
2563
3484
|
locationContextSchema,
|
|
2564
3485
|
notificationEventSchema,
|
|
2565
|
-
notificationCreateRequestSchema,
|
|
2566
3486
|
findDuplicateLocationLabels,
|
|
2567
3487
|
hasLocationLabel,
|
|
2568
3488
|
projectUpsertRequestSchema,
|
|
2569
|
-
keywordBatchRequestSchema,
|
|
2570
3489
|
keywordGenerateRequestSchema,
|
|
2571
3490
|
competitorBatchRequestSchema,
|
|
2572
3491
|
normalizeProjectDomain,
|
|
@@ -2611,7 +3530,6 @@ export {
|
|
|
2611
3530
|
brandKeyFromText,
|
|
2612
3531
|
MemorySources,
|
|
2613
3532
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
2614
|
-
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
2615
3533
|
agentMemoryUpsertRequestSchema,
|
|
2616
3534
|
agentMemoryDeleteRequestSchema,
|
|
2617
3535
|
CcReleaseSyncStatuses,
|
|
@@ -2621,5 +3539,6 @@ export {
|
|
|
2621
3539
|
summarizeCheckResults,
|
|
2622
3540
|
normalizeUrlPath,
|
|
2623
3541
|
createApiClient,
|
|
2624
|
-
ApiClient
|
|
3542
|
+
ApiClient,
|
|
3543
|
+
canonryMcpTools
|
|
2625
3544
|
};
|