@ainyc/canonry 2.15.1 → 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-D0BgyJJT.js → index-B18l8ugs.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-KANIG6ES.js → chunk-CKABU6PE.js} +203 -560
- package/dist/{chunk-OX24LLIH.js → chunk-HNVRN5QL.js} +908 -5
- package/dist/cli.js +11 -2
- package/dist/index.js +2 -2
- package/dist/mcp.js +9 -796
- package/package.json +8 -8
|
@@ -1815,6 +1815,7 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
|
1815
1815
|
"dclid",
|
|
1816
1816
|
"gbraid",
|
|
1817
1817
|
"wbraid",
|
|
1818
|
+
"bingid",
|
|
1818
1819
|
// Mailchimp
|
|
1819
1820
|
"mc_cid",
|
|
1820
1821
|
"mc_eid",
|
|
@@ -1823,7 +1824,16 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
|
1823
1824
|
"_gl",
|
|
1824
1825
|
// Google Tag Manager debug
|
|
1825
1826
|
"gtm_latency",
|
|
1826
|
-
"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"
|
|
1827
1837
|
]);
|
|
1828
1838
|
function shouldStrip(key) {
|
|
1829
1839
|
if (STRIP_KEYS.has(key)) return true;
|
|
@@ -2559,6 +2569,901 @@ var ApiClient = class {
|
|
|
2559
2569
|
}
|
|
2560
2570
|
};
|
|
2561
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
|
+
|
|
2562
3467
|
export {
|
|
2563
3468
|
getConfigDir,
|
|
2564
3469
|
getConfigPath,
|
|
@@ -2578,11 +3483,9 @@ export {
|
|
|
2578
3483
|
resolveProviderInput,
|
|
2579
3484
|
locationContextSchema,
|
|
2580
3485
|
notificationEventSchema,
|
|
2581
|
-
notificationCreateRequestSchema,
|
|
2582
3486
|
findDuplicateLocationLabels,
|
|
2583
3487
|
hasLocationLabel,
|
|
2584
3488
|
projectUpsertRequestSchema,
|
|
2585
|
-
keywordBatchRequestSchema,
|
|
2586
3489
|
keywordGenerateRequestSchema,
|
|
2587
3490
|
competitorBatchRequestSchema,
|
|
2588
3491
|
normalizeProjectDomain,
|
|
@@ -2627,7 +3530,6 @@ export {
|
|
|
2627
3530
|
brandKeyFromText,
|
|
2628
3531
|
MemorySources,
|
|
2629
3532
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
2630
|
-
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
2631
3533
|
agentMemoryUpsertRequestSchema,
|
|
2632
3534
|
agentMemoryDeleteRequestSchema,
|
|
2633
3535
|
CcReleaseSyncStatuses,
|
|
@@ -2637,5 +3539,6 @@ export {
|
|
|
2637
3539
|
summarizeCheckResults,
|
|
2638
3540
|
normalizeUrlPath,
|
|
2639
3541
|
createApiClient,
|
|
2640
|
-
ApiClient
|
|
3542
|
+
ApiClient,
|
|
3543
|
+
canonryMcpTools
|
|
2641
3544
|
};
|