@yoryoboy/bi-mcp 1.0.1
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/README.md +346 -0
- package/bin/bi-mcp.js +2 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.js +768 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp-use.json +7 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/icon.svg +6 -0
- package/dist/src/analytics/ga4-channel-groups.js +20 -0
- package/dist/src/analytics/ga4-channel-groups.js.map +7 -0
- package/dist/src/analytics/ga4-report-utils.js +117 -0
- package/dist/src/analytics/ga4-report-utils.js.map +7 -0
- package/dist/src/config/benchmarks.js +128 -0
- package/dist/src/config/benchmarks.js.map +7 -0
- package/dist/src/config/google.js +41 -0
- package/dist/src/config/google.js.map +7 -0
- package/dist/src/config/vtex.js +26 -0
- package/dist/src/config/vtex.js.map +7 -0
- package/dist/src/google-ads/report-utils.js +78 -0
- package/dist/src/google-ads/report-utils.js.map +7 -0
- package/dist/src/prompts/reporte-ventas.js +75 -0
- package/dist/src/prompts/reporte-ventas.js.map +7 -0
- package/dist/src/search-console/search-console-utils.js +275 -0
- package/dist/src/search-console/search-console-utils.js.map +7 -0
- package/dist/src/services/analytics/ga4-client.js +69 -0
- package/dist/src/services/analytics/ga4-client.js.map +7 -0
- package/dist/src/services/analytics/oauth.js +30 -0
- package/dist/src/services/analytics/oauth.js.map +7 -0
- package/dist/src/services/google-ads/google-ads-client.js +54 -0
- package/dist/src/services/google-ads/google-ads-client.js.map +7 -0
- package/dist/src/services/search-console/search-console-client.js +45 -0
- package/dist/src/services/search-console/search-console-client.js.map +7 -0
- package/dist/src/services/vtex/vtex-api.js +51 -0
- package/dist/src/services/vtex/vtex-api.js.map +7 -0
- package/dist/src/services/vtex/vtex-catalog.js +18 -0
- package/dist/src/services/vtex/vtex-catalog.js.map +7 -0
- package/dist/src/services/vtex/vtex-logistics.js +151 -0
- package/dist/src/services/vtex/vtex-logistics.js.map +7 -0
- package/dist/src/services/vtex/vtex-orders.js +143 -0
- package/dist/src/services/vtex/vtex-orders.js.map +7 -0
- package/dist/src/services/vtex/vtex-pricing.js +17 -0
- package/dist/src/services/vtex/vtex-pricing.js.map +7 -0
- package/dist/src/tools/analytics/attribution-gaps.js +109 -0
- package/dist/src/tools/analytics/attribution-gaps.js.map +7 -0
- package/dist/src/tools/analytics/channel-mix.js +74 -0
- package/dist/src/tools/analytics/channel-mix.js.map +7 -0
- package/dist/src/tools/analytics/ecommerce-tracking-health.js +89 -0
- package/dist/src/tools/analytics/ecommerce-tracking-health.js.map +7 -0
- package/dist/src/tools/analytics/engagement-overview.js +71 -0
- package/dist/src/tools/analytics/engagement-overview.js.map +7 -0
- package/dist/src/tools/analytics/index.js +12 -0
- package/dist/src/tools/analytics/index.js.map +7 -0
- package/dist/src/tools/analytics/list-accessible-properties.js +46 -0
- package/dist/src/tools/analytics/list-accessible-properties.js.map +7 -0
- package/dist/src/tools/analytics/property-info.js +54 -0
- package/dist/src/tools/analytics/property-info.js.map +7 -0
- package/dist/src/tools/analytics/revenue-by-channel.js +70 -0
- package/dist/src/tools/analytics/revenue-by-channel.js.map +7 -0
- package/dist/src/tools/analytics/revenue-overview.js +77 -0
- package/dist/src/tools/analytics/revenue-overview.js.map +7 -0
- package/dist/src/tools/analytics/revenue-trend.js +69 -0
- package/dist/src/tools/analytics/revenue-trend.js.map +7 -0
- package/dist/src/tools/analytics/source-medium-breakdown.js +86 -0
- package/dist/src/tools/analytics/source-medium-breakdown.js.map +7 -0
- package/dist/src/tools/analytics/top-landing-pages.js +79 -0
- package/dist/src/tools/analytics/top-landing-pages.js.map +7 -0
- package/dist/src/tools/google-ads/account-overview.js +103 -0
- package/dist/src/tools/google-ads/account-overview.js.map +7 -0
- package/dist/src/tools/google-ads/account-risks.js +267 -0
- package/dist/src/tools/google-ads/account-risks.js.map +7 -0
- package/dist/src/tools/google-ads/break-even-analysis.js +107 -0
- package/dist/src/tools/google-ads/break-even-analysis.js.map +7 -0
- package/dist/src/tools/google-ads/campaign-performance.js +157 -0
- package/dist/src/tools/google-ads/campaign-performance.js.map +7 -0
- package/dist/src/tools/google-ads/channel-mix.js +129 -0
- package/dist/src/tools/google-ads/channel-mix.js.map +7 -0
- package/dist/src/tools/google-ads/compare-accounts.js +122 -0
- package/dist/src/tools/google-ads/compare-accounts.js.map +7 -0
- package/dist/src/tools/google-ads/customer-clients.js +77 -0
- package/dist/src/tools/google-ads/customer-clients.js.map +7 -0
- package/dist/src/tools/google-ads/customer-info.js +64 -0
- package/dist/src/tools/google-ads/customer-info.js.map +7 -0
- package/dist/src/tools/google-ads/index.js +12 -0
- package/dist/src/tools/google-ads/index.js.map +7 -0
- package/dist/src/tools/google-ads/scaling-health.js +174 -0
- package/dist/src/tools/google-ads/scaling-health.js.map +7 -0
- package/dist/src/tools/google-ads/search-terms-summary.js +131 -0
- package/dist/src/tools/google-ads/search-terms-summary.js.map +7 -0
- package/dist/src/tools/google-ads/time-series.js +126 -0
- package/dist/src/tools/google-ads/time-series.js.map +7 -0
- package/dist/src/tools/index.js +5 -0
- package/dist/src/tools/index.js.map +7 -0
- package/dist/src/tools/search-console/country-breakdown.js +85 -0
- package/dist/src/tools/search-console/country-breakdown.js.map +7 -0
- package/dist/src/tools/search-console/device-breakdown.js +85 -0
- package/dist/src/tools/search-console/device-breakdown.js.map +7 -0
- package/dist/src/tools/search-console/high-impression-low-click-queries.js +95 -0
- package/dist/src/tools/search-console/high-impression-low-click-queries.js.map +7 -0
- package/dist/src/tools/search-console/index.js +15 -0
- package/dist/src/tools/search-console/index.js.map +7 -0
- package/dist/src/tools/search-console/list-accessible-sites.js +42 -0
- package/dist/src/tools/search-console/list-accessible-sites.js.map +7 -0
- package/dist/src/tools/search-console/low-ctr-opportunities.js +98 -0
- package/dist/src/tools/search-console/low-ctr-opportunities.js.map +7 -0
- package/dist/src/tools/search-console/page-performance.js +104 -0
- package/dist/src/tools/search-console/page-performance.js.map +7 -0
- package/dist/src/tools/search-console/product-demand-low-capture-queries.js +93 -0
- package/dist/src/tools/search-console/product-demand-low-capture-queries.js.map +7 -0
- package/dist/src/tools/search-console/query-page-matrix.js +99 -0
- package/dist/src/tools/search-console/query-page-matrix.js.map +7 -0
- package/dist/src/tools/search-console/query-performance.js +109 -0
- package/dist/src/tools/search-console/query-performance.js.map +7 -0
- package/dist/src/tools/search-console/quick-win-opportunities.js +93 -0
- package/dist/src/tools/search-console/quick-win-opportunities.js.map +7 -0
- package/dist/src/tools/search-console/rising-non-brand-queries.js +121 -0
- package/dist/src/tools/search-console/rising-non-brand-queries.js.map +7 -0
- package/dist/src/tools/search-console/search-performance.js +89 -0
- package/dist/src/tools/search-console/search-performance.js.map +7 -0
- package/dist/src/tools/search-console/site-context.js +43 -0
- package/dist/src/tools/search-console/site-context.js.map +7 -0
- package/dist/src/tools/search-console/visibility-declines.js +146 -0
- package/dist/src/tools/search-console/visibility-declines.js.map +7 -0
- package/dist/src/tools/vtex/computed-price.js +48 -0
- package/dist/src/tools/vtex/computed-price.js.map +7 -0
- package/dist/src/tools/vtex/index.js +11 -0
- package/dist/src/tools/vtex/index.js.map +7 -0
- package/dist/src/tools/vtex/inventory-check.js +148 -0
- package/dist/src/tools/vtex/inventory-check.js.map +7 -0
- package/dist/src/tools/vtex/order-details.js +56 -0
- package/dist/src/tools/vtex/order-details.js.map +7 -0
- package/dist/src/tools/vtex/orders-summary.js +83 -0
- package/dist/src/tools/vtex/orders-summary.js.map +7 -0
- package/dist/src/tools/vtex/product-offers.js +28 -0
- package/dist/src/tools/vtex/product-offers.js.map +7 -0
- package/dist/src/tools/vtex/sku-offers.js +30 -0
- package/dist/src/tools/vtex/sku-offers.js.map +7 -0
- package/dist/src/tools/vtex/sku-price.js +42 -0
- package/dist/src/tools/vtex/sku-price.js.map +7 -0
- package/dist/src/tools/vtex/update-inventory.js +43 -0
- package/dist/src/tools/vtex/update-inventory.js.map +7 -0
- package/dist/src/tools/vtex/update-lead-time.js +32 -0
- package/dist/src/tools/vtex/update-lead-time.js.map +7 -0
- package/dist/src/tools/vtex/warehouse-inventory.js +42 -0
- package/dist/src/tools/vtex/warehouse-inventory.js.map +7 -0
- package/dist/src/utils/case-conversion.js +21 -0
- package/dist/src/utils/case-conversion.js.map +7 -0
- package/dist/src/utils/currency.js +52 -0
- package/dist/src/utils/currency.js.map +7 -0
- package/dist/src/utils/format-order-details.js +137 -0
- package/dist/src/utils/format-order-details.js.map +7 -0
- package/dist/src/utils/google-ads.js +78 -0
- package/dist/src/utils/google-ads.js.map +7 -0
- package/dist/src/utils/money.js +83 -0
- package/dist/src/utils/money.js.map +7 -0
- package/dist/src/utils/order-status.js +11 -0
- package/dist/src/utils/order-status.js.map +7 -0
- package/dist/src/utils/pagination.js +45 -0
- package/dist/src/utils/pagination.js.map +7 -0
- package/dist/src/utils/strip-payload.js +40 -0
- package/dist/src/utils/strip-payload.js.map +7 -0
- package/dist/src/utils/type-guards.js +7 -0
- package/dist/src/utils/type-guards.js.map +7 -0
- package/package.json +66 -0
- package/public/favicon.ico +0 -0
- package/public/icon.svg +6 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/product-demand-low-capture-queries.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n brandTermsSchemaField,\n buildSearchConsoleQueryBody,\n classifyBrandLabel,\n endDateSchemaField,\n looksLikeProductQuery,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n rowLimitSchemaField,\n searchTypeSchemaField,\n siteUrlSchemaField,\n startDateSchemaField,\n normalizeSearchConsoleRow,\n scoreHighImpressionLowClickOpportunity,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleProductDemandLowCaptureQueriesSchema = z.object({\n startDate: startDateSchemaField,\n endDate: endDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n brandTerms: brandTermsSchemaField,\n productTerms: z\n .array(z.string().min(1))\n .max(100)\n .optional()\n .describe(\"Optional product tokens used to better detect product-intent queries.\"),\n minImpressions: z\n .number()\n .min(1)\n .optional()\n .describe(\"Minimum impressions required to consider a product query.\"),\n maxCtr: z\n .number()\n .min(0)\n .max(100)\n .optional()\n .describe(\"Maximum CTR percentage allowed to count as low capture.\"),\n maxPosition: z\n .number()\n .min(1)\n .max(100)\n .optional()\n .describe(\"Maximum average position allowed to keep only queries with some ranking potential.\"),\n rowLimit: rowLimitSchemaField,\n});\n\nexport async function searchConsoleProductDemandLowCaptureQueriesHandler(\n params: z.infer<typeof searchConsoleProductDemandLowCaptureQueriesSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const minImpressions = params.minImpressions ?? 80;\n const maxCtr = params.maxCtr ?? 4;\n const maxPosition = params.maxPosition ?? 20;\n\n const response = await querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.startDate,\n endDate: params.endDate,\n dimensions: [\"query\", \"page\"],\n searchType: params.searchType,\n rowLimit: params.rowLimit ?? 250,\n })\n );\n\n const opportunities = (response.rows ?? [])\n .map((row) => normalizeSearchConsoleRow(row, [\"query\", \"page\"]))\n .filter((row) => looksLikeProductQuery(row.dimensions.query, params.productTerms))\n .map((row) => ({\n query: row.dimensions.query,\n page: row.dimensions.page,\n clicks: row.clicks,\n impressions: row.impressions,\n ctr_percent: row.ctr_percent,\n position: row.position,\n brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms),\n }))\n .filter(\n (row) =>\n row.impressions >= minImpressions &&\n row.ctr_percent <= maxCtr &&\n row.position > 0 &&\n row.position <= maxPosition\n )\n .map((row) => ({\n ...row,\n opportunity_score: scoreHighImpressionLowClickOpportunity({\n impressions: row.impressions,\n ctrPercent: row.ctr_percent,\n position: row.position,\n }),\n reason: \"Product-intent query shows demand but weak click capture.\",\n }))\n .sort((left, right) => right.opportunity_score - left.opportunity_score);\n\n return object(\n stripNulls({\n site_url: siteUrl,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n thresholds: {\n min_impressions: minImpressions,\n max_ctr_percent: maxCtr,\n max_position: maxPosition,\n },\n opportunities,\n })\n );\n } catch (err) {\n return error(\n err instanceof Error\n ? err.message\n : \"Failed to find Search Console product demand low-capture queries\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
|
|
4
|
+
import {
|
|
5
|
+
buildPaginationMetadata,
|
|
6
|
+
buildSearchConsoleQueryBody,
|
|
7
|
+
endDateSchemaField,
|
|
8
|
+
profileIdSchemaField,
|
|
9
|
+
resolveSearchConsoleSiteUrl,
|
|
10
|
+
rowLimitSchemaField,
|
|
11
|
+
searchTypeSchemaField,
|
|
12
|
+
siteUrlSchemaField,
|
|
13
|
+
startDateSchemaField,
|
|
14
|
+
startRowSchemaField,
|
|
15
|
+
normalizeSearchConsoleRow
|
|
16
|
+
} from "../../search-console/search-console-utils.js";
|
|
17
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
18
|
+
const searchConsoleQueryPageMatrixSchema = z.object({
|
|
19
|
+
startDate: startDateSchemaField,
|
|
20
|
+
endDate: endDateSchemaField,
|
|
21
|
+
siteUrl: siteUrlSchemaField,
|
|
22
|
+
profileId: profileIdSchemaField,
|
|
23
|
+
searchType: searchTypeSchemaField,
|
|
24
|
+
queryContains: z.string().optional().describe("Optional substring that queries must contain."),
|
|
25
|
+
pageContains: z.string().optional().describe("Optional substring that landing pages must contain."),
|
|
26
|
+
rowLimit: rowLimitSchemaField,
|
|
27
|
+
startRow: startRowSchemaField
|
|
28
|
+
});
|
|
29
|
+
async function searchConsoleQueryPageMatrixHandler(params) {
|
|
30
|
+
try {
|
|
31
|
+
const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
|
|
32
|
+
const dimensionFilters = [];
|
|
33
|
+
if (params.queryContains?.trim()) {
|
|
34
|
+
dimensionFilters.push({
|
|
35
|
+
dimension: "query",
|
|
36
|
+
operator: "contains",
|
|
37
|
+
expression: params.queryContains.trim()
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (params.pageContains?.trim()) {
|
|
41
|
+
dimensionFilters.push({
|
|
42
|
+
dimension: "page",
|
|
43
|
+
operator: "contains",
|
|
44
|
+
expression: params.pageContains.trim()
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const response = await querySearchConsolePerformance(
|
|
48
|
+
siteUrl,
|
|
49
|
+
buildSearchConsoleQueryBody({
|
|
50
|
+
startDate: params.startDate,
|
|
51
|
+
endDate: params.endDate,
|
|
52
|
+
dimensions: ["query", "page"],
|
|
53
|
+
searchType: params.searchType,
|
|
54
|
+
dimensionFilters,
|
|
55
|
+
rowLimit: params.rowLimit,
|
|
56
|
+
startRow: params.startRow
|
|
57
|
+
})
|
|
58
|
+
);
|
|
59
|
+
const rows = (response.rows ?? []).map(
|
|
60
|
+
(row) => normalizeSearchConsoleRow(row, ["query", "page"])
|
|
61
|
+
);
|
|
62
|
+
return object(
|
|
63
|
+
stripNulls({
|
|
64
|
+
site_url: siteUrl,
|
|
65
|
+
date_range: {
|
|
66
|
+
start_date: params.startDate,
|
|
67
|
+
end_date: params.endDate
|
|
68
|
+
},
|
|
69
|
+
filters: {
|
|
70
|
+
search_type: params.searchType ?? "web",
|
|
71
|
+
query_contains: params.queryContains,
|
|
72
|
+
page_contains: params.pageContains
|
|
73
|
+
},
|
|
74
|
+
rows: rows.map((row) => ({
|
|
75
|
+
query: row.dimensions.query,
|
|
76
|
+
page: row.dimensions.page,
|
|
77
|
+
clicks: row.clicks,
|
|
78
|
+
impressions: row.impressions,
|
|
79
|
+
ctr_percent: row.ctr_percent,
|
|
80
|
+
position: row.position
|
|
81
|
+
})),
|
|
82
|
+
metadata: buildPaginationMetadata({
|
|
83
|
+
startRow: params.startRow,
|
|
84
|
+
rowLimit: params.rowLimit,
|
|
85
|
+
returnedRows: rows.length
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
return error(
|
|
91
|
+
err instanceof Error ? err.message : "Failed to fetch Search Console query-page matrix"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
searchConsoleQueryPageMatrixHandler,
|
|
97
|
+
searchConsoleQueryPageMatrixSchema
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=query-page-matrix.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/query-page-matrix.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n buildPaginationMetadata,\n buildSearchConsoleQueryBody,\n endDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n rowLimitSchemaField,\n searchTypeSchemaField,\n siteUrlSchemaField,\n startDateSchemaField,\n startRowSchemaField,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleQueryPageMatrixSchema = z.object({\n startDate: startDateSchemaField,\n endDate: endDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n queryContains: z\n .string()\n .optional()\n .describe(\"Optional substring that queries must contain.\"),\n pageContains: z\n .string()\n .optional()\n .describe(\"Optional substring that landing pages must contain.\"),\n rowLimit: rowLimitSchemaField,\n startRow: startRowSchemaField,\n});\n\nexport async function searchConsoleQueryPageMatrixHandler(\n params: z.infer<typeof searchConsoleQueryPageMatrixSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const dimensionFilters = [];\n\n if (params.queryContains?.trim()) {\n dimensionFilters.push({\n dimension: \"query\",\n operator: \"contains\",\n expression: params.queryContains.trim(),\n });\n }\n\n if (params.pageContains?.trim()) {\n dimensionFilters.push({\n dimension: \"page\",\n operator: \"contains\",\n expression: params.pageContains.trim(),\n });\n }\n\n const response = await querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.startDate,\n endDate: params.endDate,\n dimensions: [\"query\", \"page\"],\n searchType: params.searchType,\n dimensionFilters,\n rowLimit: params.rowLimit,\n startRow: params.startRow,\n })\n );\n\n const rows = (response.rows ?? []).map((row) =>\n normalizeSearchConsoleRow(row, [\"query\", \"page\"])\n );\n\n return object(\n stripNulls({\n site_url: siteUrl,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n filters: {\n search_type: params.searchType ?? \"web\",\n query_contains: params.queryContains,\n page_contains: params.pageContains,\n },\n rows: rows.map((row) => ({\n query: row.dimensions.query,\n page: row.dimensions.page,\n clicks: row.clicks,\n impressions: row.impressions,\n ctr_percent: row.ctr_percent,\n position: row.position,\n })),\n metadata: buildPaginationMetadata({\n startRow: params.startRow,\n rowLimit: params.rowLimit,\n returnedRows: rows.length,\n }),\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to fetch Search Console query-page matrix\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,qCAAqC,EAAE,OAAO;AAAA,EACzD,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,eAAe,EACZ,OAAO,EACP,SAAS,EACT,SAAS,+CAA+C;AAAA,EAC3D,cAAc,EACX,OAAO,EACP,SAAS,EACT,SAAS,qDAAqD;AAAA,EACjE,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAED,eAAsB,oCACpB,QACA;AACA,MAAI;AACF,UAAM,UAAU,4BAA4B,OAAO,SAAS,OAAO,SAAS;AAC5E,UAAM,mBAAmB,CAAC;AAE1B,QAAI,OAAO,eAAe,KAAK,GAAG;AAChC,uBAAiB,KAAK;AAAA,QACpB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,YAAY,OAAO,cAAc,KAAK;AAAA,MACxC,CAAC;AAAA,IACH;AAEA,QAAI,OAAO,cAAc,KAAK,GAAG;AAC/B,uBAAiB,KAAK;AAAA,QACpB,WAAW;AAAA,QACX,UAAU;AAAA,QACV,YAAY,OAAO,aAAa,KAAK;AAAA,MACvC,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,4BAA4B;AAAA,QAC1B,WAAW,OAAO;AAAA,QAClB,SAAS,OAAO;AAAA,QAChB,YAAY,CAAC,SAAS,MAAM;AAAA,QAC5B,YAAY,OAAO;AAAA,QACnB;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,SAAS,QAAQ,CAAC,GAAG;AAAA,MAAI,CAAC,QACtC,0BAA0B,KAAK,CAAC,SAAS,MAAM,CAAC;AAAA,IAClD;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,SAAS;AAAA,UACP,aAAa,OAAO,cAAc;AAAA,UAClC,gBAAgB,OAAO;AAAA,UACvB,eAAe,OAAO;AAAA,QACxB;AAAA,QACA,MAAM,KAAK,IAAI,CAAC,SAAS;AAAA,UACvB,OAAO,IAAI,WAAW;AAAA,UACtB,MAAM,IAAI,WAAW;AAAA,UACrB,QAAQ,IAAI;AAAA,UACZ,aAAa,IAAI;AAAA,UACjB,aAAa,IAAI;AAAA,UACjB,UAAU,IAAI;AAAA,QAChB,EAAE;AAAA,QACF,UAAU,wBAAwB;AAAA,UAChC,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,UACjB,cAAc,KAAK;AAAA,QACrB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
|
|
4
|
+
import {
|
|
5
|
+
brandTermsSchemaField,
|
|
6
|
+
buildPaginationMetadata,
|
|
7
|
+
buildSearchConsoleQueryBody,
|
|
8
|
+
classifyBrandLabel,
|
|
9
|
+
endDateSchemaField,
|
|
10
|
+
profileIdSchemaField,
|
|
11
|
+
resolveSearchConsoleSiteUrl,
|
|
12
|
+
rowLimitSchemaField,
|
|
13
|
+
searchTypeSchemaField,
|
|
14
|
+
siteUrlSchemaField,
|
|
15
|
+
startDateSchemaField,
|
|
16
|
+
startRowSchemaField,
|
|
17
|
+
sumSearchConsoleRows,
|
|
18
|
+
normalizeSearchConsoleRow
|
|
19
|
+
} from "../../search-console/search-console-utils.js";
|
|
20
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
21
|
+
const searchConsoleQueryPerformanceSchema = z.object({
|
|
22
|
+
startDate: startDateSchemaField,
|
|
23
|
+
endDate: endDateSchemaField,
|
|
24
|
+
siteUrl: siteUrlSchemaField,
|
|
25
|
+
profileId: profileIdSchemaField,
|
|
26
|
+
searchType: searchTypeSchemaField,
|
|
27
|
+
brandTerms: brandTermsSchemaField,
|
|
28
|
+
includeBrand: z.enum(["all", "only_brand", "only_non_brand"]).optional().describe("How to filter the query list when brandTerms are provided."),
|
|
29
|
+
rowLimit: rowLimitSchemaField,
|
|
30
|
+
startRow: startRowSchemaField
|
|
31
|
+
});
|
|
32
|
+
async function searchConsoleQueryPerformanceHandler(params) {
|
|
33
|
+
try {
|
|
34
|
+
const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
|
|
35
|
+
const response = await querySearchConsolePerformance(
|
|
36
|
+
siteUrl,
|
|
37
|
+
buildSearchConsoleQueryBody({
|
|
38
|
+
startDate: params.startDate,
|
|
39
|
+
endDate: params.endDate,
|
|
40
|
+
dimensions: ["query"],
|
|
41
|
+
searchType: params.searchType,
|
|
42
|
+
rowLimit: params.rowLimit,
|
|
43
|
+
startRow: params.startRow
|
|
44
|
+
})
|
|
45
|
+
);
|
|
46
|
+
const includeBrand = params.includeBrand ?? "all";
|
|
47
|
+
const rows = (response.rows ?? []).map((row) => normalizeSearchConsoleRow(row, ["query"])).map((row) => ({
|
|
48
|
+
query: row.dimensions.query,
|
|
49
|
+
clicks: row.clicks,
|
|
50
|
+
impressions: row.impressions,
|
|
51
|
+
ctr_percent: row.ctr_percent,
|
|
52
|
+
position: row.position,
|
|
53
|
+
brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms)
|
|
54
|
+
})).filter((row) => {
|
|
55
|
+
if (includeBrand === "only_brand") {
|
|
56
|
+
return row.brand_classification === "brand";
|
|
57
|
+
}
|
|
58
|
+
if (includeBrand === "only_non_brand") {
|
|
59
|
+
return row.brand_classification === "non_brand";
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
const totals = sumSearchConsoleRows(
|
|
64
|
+
rows.map((row) => ({
|
|
65
|
+
keys: [row.query],
|
|
66
|
+
dimensions: { query: row.query },
|
|
67
|
+
clicks: row.clicks,
|
|
68
|
+
impressions: row.impressions,
|
|
69
|
+
ctr_percent: row.ctr_percent,
|
|
70
|
+
position: row.position
|
|
71
|
+
}))
|
|
72
|
+
);
|
|
73
|
+
return object(
|
|
74
|
+
stripNulls({
|
|
75
|
+
site_url: siteUrl,
|
|
76
|
+
date_range: {
|
|
77
|
+
start_date: params.startDate,
|
|
78
|
+
end_date: params.endDate
|
|
79
|
+
},
|
|
80
|
+
filters: {
|
|
81
|
+
search_type: params.searchType ?? "web",
|
|
82
|
+
include_brand: includeBrand,
|
|
83
|
+
brand_terms: params.brandTerms
|
|
84
|
+
},
|
|
85
|
+
overview: {
|
|
86
|
+
total_clicks: totals.clicks,
|
|
87
|
+
total_impressions: totals.impressions,
|
|
88
|
+
average_ctr_percent: totals.ctrPercent,
|
|
89
|
+
average_position: totals.averagePosition
|
|
90
|
+
},
|
|
91
|
+
queries: rows,
|
|
92
|
+
metadata: buildPaginationMetadata({
|
|
93
|
+
startRow: params.startRow,
|
|
94
|
+
rowLimit: params.rowLimit,
|
|
95
|
+
returnedRows: response.rows?.length ?? 0
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
return error(
|
|
101
|
+
err instanceof Error ? err.message : "Failed to fetch Search Console query performance"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
searchConsoleQueryPerformanceHandler,
|
|
107
|
+
searchConsoleQueryPerformanceSchema
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=query-performance.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/query-performance.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n brandTermsSchemaField,\n buildPaginationMetadata,\n buildSearchConsoleQueryBody,\n classifyBrandLabel,\n endDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n rowLimitSchemaField,\n searchTypeSchemaField,\n siteUrlSchemaField,\n startDateSchemaField,\n startRowSchemaField,\n sumSearchConsoleRows,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleQueryPerformanceSchema = z.object({\n startDate: startDateSchemaField,\n endDate: endDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n brandTerms: brandTermsSchemaField,\n includeBrand: z\n .enum([\"all\", \"only_brand\", \"only_non_brand\"])\n .optional()\n .describe(\"How to filter the query list when brandTerms are provided.\"),\n rowLimit: rowLimitSchemaField,\n startRow: startRowSchemaField,\n});\n\nexport async function searchConsoleQueryPerformanceHandler(\n params: z.infer<typeof searchConsoleQueryPerformanceSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const response = await querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.startDate,\n endDate: params.endDate,\n dimensions: [\"query\"],\n searchType: params.searchType,\n rowLimit: params.rowLimit,\n startRow: params.startRow,\n })\n );\n\n const includeBrand = params.includeBrand ?? \"all\";\n const rows = (response.rows ?? [])\n .map((row) => normalizeSearchConsoleRow(row, [\"query\"]))\n .map((row) => ({\n query: row.dimensions.query,\n clicks: row.clicks,\n impressions: row.impressions,\n ctr_percent: row.ctr_percent,\n position: row.position,\n brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms),\n }))\n .filter((row) => {\n if (includeBrand === \"only_brand\") {\n return row.brand_classification === \"brand\";\n }\n\n if (includeBrand === \"only_non_brand\") {\n return row.brand_classification === \"non_brand\";\n }\n\n return true;\n });\n\n const totals = sumSearchConsoleRows(\n rows.map((row) => ({\n keys: [row.query],\n dimensions: { query: row.query },\n clicks: row.clicks,\n impressions: row.impressions,\n ctr_percent: row.ctr_percent,\n position: row.position,\n }))\n );\n\n return object(\n stripNulls({\n site_url: siteUrl,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n filters: {\n search_type: params.searchType ?? \"web\",\n include_brand: includeBrand,\n brand_terms: params.brandTerms,\n },\n overview: {\n total_clicks: totals.clicks,\n total_impressions: totals.impressions,\n average_ctr_percent: totals.ctrPercent,\n average_position: totals.averagePosition,\n },\n queries: rows,\n metadata: buildPaginationMetadata({\n startRow: params.startRow,\n rowLimit: params.rowLimit,\n returnedRows: response.rows?.length ?? 0,\n }),\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to fetch Search Console query performance\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,sCAAsC,EAAE,OAAO;AAAA,EAC1D,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,cAAc,EACX,KAAK,CAAC,OAAO,cAAc,gBAAgB,CAAC,EAC5C,SAAS,EACT,SAAS,4DAA4D;AAAA,EACxE,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAED,eAAsB,qCACpB,QACA;AACA,MAAI;AACF,UAAM,UAAU,4BAA4B,OAAO,SAAS,OAAO,SAAS;AAC5E,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,4BAA4B;AAAA,QAC1B,WAAW,OAAO;AAAA,QAClB,SAAS,OAAO;AAAA,QAChB,YAAY,CAAC,OAAO;AAAA,QACpB,YAAY,OAAO;AAAA,QACnB,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,OAAO,gBAAgB;AAC5C,UAAM,QAAQ,SAAS,QAAQ,CAAC,GAC7B,IAAI,CAAC,QAAQ,0BAA0B,KAAK,CAAC,OAAO,CAAC,CAAC,EACtD,IAAI,CAAC,SAAS;AAAA,MACb,OAAO,IAAI,WAAW;AAAA,MACtB,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,MACjB,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,sBAAsB,mBAAmB,IAAI,WAAW,OAAO,OAAO,UAAU;AAAA,IAClF,EAAE,EACD,OAAO,CAAC,QAAQ;AACf,UAAI,iBAAiB,cAAc;AACjC,eAAO,IAAI,yBAAyB;AAAA,MACtC;AAEA,UAAI,iBAAiB,kBAAkB;AACrC,eAAO,IAAI,yBAAyB;AAAA,MACtC;AAEA,aAAO;AAAA,IACT,CAAC;AAEH,UAAM,SAAS;AAAA,MACb,KAAK,IAAI,CAAC,SAAS;AAAA,QACjB,MAAM,CAAC,IAAI,KAAK;AAAA,QAChB,YAAY,EAAE,OAAO,IAAI,MAAM;AAAA,QAC/B,QAAQ,IAAI;AAAA,QACZ,aAAa,IAAI;AAAA,QACjB,aAAa,IAAI;AAAA,QACjB,UAAU,IAAI;AAAA,MAChB,EAAE;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,SAAS;AAAA,UACP,aAAa,OAAO,cAAc;AAAA,UAClC,eAAe;AAAA,UACf,aAAa,OAAO;AAAA,QACtB;AAAA,QACA,UAAU;AAAA,UACR,cAAc,OAAO;AAAA,UACrB,mBAAmB,OAAO;AAAA,UAC1B,qBAAqB,OAAO;AAAA,UAC5B,kBAAkB,OAAO;AAAA,QAC3B;AAAA,QACA,SAAS;AAAA,QACT,UAAU,wBAAwB;AAAA,UAChC,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,UACjB,cAAc,SAAS,MAAM,UAAU;AAAA,QACzC,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
|
|
4
|
+
import {
|
|
5
|
+
brandTermsSchemaField,
|
|
6
|
+
buildSearchConsoleQueryBody,
|
|
7
|
+
classifyBrandLabel,
|
|
8
|
+
classifyQuickWinType,
|
|
9
|
+
endDateSchemaField,
|
|
10
|
+
profileIdSchemaField,
|
|
11
|
+
resolveSearchConsoleSiteUrl,
|
|
12
|
+
scoreQuickWinOpportunity,
|
|
13
|
+
searchTypeSchemaField,
|
|
14
|
+
siteUrlSchemaField,
|
|
15
|
+
startDateSchemaField,
|
|
16
|
+
normalizeSearchConsoleRow
|
|
17
|
+
} from "../../search-console/search-console-utils.js";
|
|
18
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
19
|
+
const searchConsoleQuickWinOpportunitiesSchema = z.object({
|
|
20
|
+
startDate: startDateSchemaField,
|
|
21
|
+
endDate: endDateSchemaField,
|
|
22
|
+
siteUrl: siteUrlSchemaField,
|
|
23
|
+
profileId: profileIdSchemaField,
|
|
24
|
+
searchType: searchTypeSchemaField,
|
|
25
|
+
brandTerms: brandTermsSchemaField,
|
|
26
|
+
minImpressions: z.number().min(1).optional().describe("Minimum impressions required to consider a quick win."),
|
|
27
|
+
quickWinMode: z.enum(["ctr", "position", "mixed"]).optional().describe("Whether to prioritize CTR fixes, ranking improvements, or both.")
|
|
28
|
+
});
|
|
29
|
+
async function searchConsoleQuickWinOpportunitiesHandler(params) {
|
|
30
|
+
try {
|
|
31
|
+
const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
|
|
32
|
+
const minImpressions = params.minImpressions ?? 80;
|
|
33
|
+
const quickWinMode = params.quickWinMode ?? "mixed";
|
|
34
|
+
const response = await querySearchConsolePerformance(
|
|
35
|
+
siteUrl,
|
|
36
|
+
buildSearchConsoleQueryBody({
|
|
37
|
+
startDate: params.startDate,
|
|
38
|
+
endDate: params.endDate,
|
|
39
|
+
dimensions: ["query"],
|
|
40
|
+
searchType: params.searchType,
|
|
41
|
+
rowLimit: 250
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
const opportunities = (response.rows ?? []).map((row) => normalizeSearchConsoleRow(row, ["query"])).filter((row) => row.impressions >= minImpressions).map((row) => {
|
|
45
|
+
const quickWinType = classifyQuickWinType(row.position, row.ctr_percent);
|
|
46
|
+
return {
|
|
47
|
+
query: row.dimensions.query,
|
|
48
|
+
clicks: row.clicks,
|
|
49
|
+
impressions: row.impressions,
|
|
50
|
+
ctr_percent: row.ctr_percent,
|
|
51
|
+
position: row.position,
|
|
52
|
+
quick_win_type: quickWinType,
|
|
53
|
+
brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms),
|
|
54
|
+
opportunity_score: scoreQuickWinOpportunity({
|
|
55
|
+
impressions: row.impressions,
|
|
56
|
+
ctrPercent: row.ctr_percent,
|
|
57
|
+
position: row.position
|
|
58
|
+
})
|
|
59
|
+
};
|
|
60
|
+
}).filter((row) => {
|
|
61
|
+
if (quickWinMode === "mixed") {
|
|
62
|
+
return row.position > 0 && row.position <= 20;
|
|
63
|
+
}
|
|
64
|
+
return row.quick_win_type === quickWinMode;
|
|
65
|
+
}).sort((left, right) => right.opportunity_score - left.opportunity_score).map((row) => ({
|
|
66
|
+
...row,
|
|
67
|
+
reason: row.quick_win_type === "ctr" ? "The query already ranks fairly well, so a CTR lift is the fastest path." : "The query has traction, but ranking improvement appears to be the faster lever."
|
|
68
|
+
}));
|
|
69
|
+
return object(
|
|
70
|
+
stripNulls({
|
|
71
|
+
site_url: siteUrl,
|
|
72
|
+
date_range: {
|
|
73
|
+
start_date: params.startDate,
|
|
74
|
+
end_date: params.endDate
|
|
75
|
+
},
|
|
76
|
+
thresholds: {
|
|
77
|
+
min_impressions: minImpressions,
|
|
78
|
+
quick_win_mode: quickWinMode
|
|
79
|
+
},
|
|
80
|
+
opportunities
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return error(
|
|
85
|
+
err instanceof Error ? err.message : "Failed to find Search Console quick-win opportunities"
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
searchConsoleQuickWinOpportunitiesHandler,
|
|
91
|
+
searchConsoleQuickWinOpportunitiesSchema
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=quick-win-opportunities.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/quick-win-opportunities.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n brandTermsSchemaField,\n buildSearchConsoleQueryBody,\n classifyBrandLabel,\n classifyQuickWinType,\n endDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n scoreQuickWinOpportunity,\n searchTypeSchemaField,\n siteUrlSchemaField,\n startDateSchemaField,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleQuickWinOpportunitiesSchema = z.object({\n startDate: startDateSchemaField,\n endDate: endDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n brandTerms: brandTermsSchemaField,\n minImpressions: z\n .number()\n .min(1)\n .optional()\n .describe(\"Minimum impressions required to consider a quick win.\"),\n quickWinMode: z\n .enum([\"ctr\", \"position\", \"mixed\"])\n .optional()\n .describe(\"Whether to prioritize CTR fixes, ranking improvements, or both.\"),\n});\n\nexport async function searchConsoleQuickWinOpportunitiesHandler(\n params: z.infer<typeof searchConsoleQuickWinOpportunitiesSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const minImpressions = params.minImpressions ?? 80;\n const quickWinMode = params.quickWinMode ?? \"mixed\";\n\n const response = await querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.startDate,\n endDate: params.endDate,\n dimensions: [\"query\"],\n searchType: params.searchType,\n rowLimit: 250,\n })\n );\n\n const opportunities = (response.rows ?? [])\n .map((row) => normalizeSearchConsoleRow(row, [\"query\"]))\n .filter((row) => row.impressions >= minImpressions)\n .map((row) => {\n const quickWinType = classifyQuickWinType(row.position, row.ctr_percent);\n return {\n query: row.dimensions.query,\n clicks: row.clicks,\n impressions: row.impressions,\n ctr_percent: row.ctr_percent,\n position: row.position,\n quick_win_type: quickWinType,\n brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms),\n opportunity_score: scoreQuickWinOpportunity({\n impressions: row.impressions,\n ctrPercent: row.ctr_percent,\n position: row.position,\n }),\n };\n })\n .filter((row) => {\n if (quickWinMode === \"mixed\") {\n return row.position > 0 && row.position <= 20;\n }\n\n return row.quick_win_type === quickWinMode;\n })\n .sort((left, right) => right.opportunity_score - left.opportunity_score)\n .map((row) => ({\n ...row,\n reason:\n row.quick_win_type === \"ctr\"\n ? \"The query already ranks fairly well, so a CTR lift is the fastest path.\"\n : \"The query has traction, but ranking improvement appears to be the faster lever.\",\n }));\n\n return object(\n stripNulls({\n site_url: siteUrl,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n thresholds: {\n min_impressions: minImpressions,\n quick_win_mode: quickWinMode,\n },\n opportunities,\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to find Search Console quick-win opportunities\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,2CAA2C,EAAE,OAAO;AAAA,EAC/D,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,gBAAgB,EACb,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT,SAAS,uDAAuD;AAAA,EACnE,cAAc,EACX,KAAK,CAAC,OAAO,YAAY,OAAO,CAAC,EACjC,SAAS,EACT,SAAS,iEAAiE;AAC/E,CAAC;AAED,eAAsB,0CACpB,QACA;AACA,MAAI;AACF,UAAM,UAAU,4BAA4B,OAAO,SAAS,OAAO,SAAS;AAC5E,UAAM,iBAAiB,OAAO,kBAAkB;AAChD,UAAM,eAAe,OAAO,gBAAgB;AAE5C,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,4BAA4B;AAAA,QAC1B,WAAW,OAAO;AAAA,QAClB,SAAS,OAAO;AAAA,QAChB,YAAY,CAAC,OAAO;AAAA,QACpB,YAAY,OAAO;AAAA,QACnB,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,UAAM,iBAAiB,SAAS,QAAQ,CAAC,GACtC,IAAI,CAAC,QAAQ,0BAA0B,KAAK,CAAC,OAAO,CAAC,CAAC,EACtD,OAAO,CAAC,QAAQ,IAAI,eAAe,cAAc,EACjD,IAAI,CAAC,QAAQ;AACZ,YAAM,eAAe,qBAAqB,IAAI,UAAU,IAAI,WAAW;AACvE,aAAO;AAAA,QACL,OAAO,IAAI,WAAW;AAAA,QACtB,QAAQ,IAAI;AAAA,QACZ,aAAa,IAAI;AAAA,QACjB,aAAa,IAAI;AAAA,QACjB,UAAU,IAAI;AAAA,QACd,gBAAgB;AAAA,QAChB,sBAAsB,mBAAmB,IAAI,WAAW,OAAO,OAAO,UAAU;AAAA,QAChF,mBAAmB,yBAAyB;AAAA,UAC1C,aAAa,IAAI;AAAA,UACjB,YAAY,IAAI;AAAA,UAChB,UAAU,IAAI;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,CAAC,EACA,OAAO,CAAC,QAAQ;AACf,UAAI,iBAAiB,SAAS;AAC5B,eAAO,IAAI,WAAW,KAAK,IAAI,YAAY;AAAA,MAC7C;AAEA,aAAO,IAAI,mBAAmB;AAAA,IAChC,CAAC,EACA,KAAK,CAAC,MAAM,UAAU,MAAM,oBAAoB,KAAK,iBAAiB,EACtE,IAAI,CAAC,SAAS;AAAA,MACb,GAAG;AAAA,MACH,QACE,IAAI,mBAAmB,QACnB,4EACA;AAAA,IACR,EAAE;AAEJ,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,YAAY;AAAA,UACV,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,QAClB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
|
|
4
|
+
import {
|
|
5
|
+
brandTermsSchemaField,
|
|
6
|
+
buildComparisonMap,
|
|
7
|
+
buildSearchConsoleQueryBody,
|
|
8
|
+
classifyBrandLabel,
|
|
9
|
+
computeChangePercent,
|
|
10
|
+
currentEndDateSchemaField,
|
|
11
|
+
currentStartDateSchemaField,
|
|
12
|
+
previousEndDateSchemaField,
|
|
13
|
+
previousStartDateSchemaField,
|
|
14
|
+
profileIdSchemaField,
|
|
15
|
+
resolveSearchConsoleSiteUrl,
|
|
16
|
+
searchTypeSchemaField,
|
|
17
|
+
siteUrlSchemaField,
|
|
18
|
+
normalizeSearchConsoleRow
|
|
19
|
+
} from "../../search-console/search-console-utils.js";
|
|
20
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
21
|
+
const searchConsoleRisingNonBrandQueriesSchema = z.object({
|
|
22
|
+
currentStartDate: currentStartDateSchemaField,
|
|
23
|
+
currentEndDate: currentEndDateSchemaField,
|
|
24
|
+
previousStartDate: previousStartDateSchemaField,
|
|
25
|
+
previousEndDate: previousEndDateSchemaField,
|
|
26
|
+
siteUrl: siteUrlSchemaField,
|
|
27
|
+
profileId: profileIdSchemaField,
|
|
28
|
+
searchType: searchTypeSchemaField,
|
|
29
|
+
brandTerms: brandTermsSchemaField,
|
|
30
|
+
minImpressions: z.number().min(1).optional().describe("Minimum current-period impressions required to include a query."),
|
|
31
|
+
minGrowthRate: z.number().min(0).optional().describe("Minimum impressions growth percentage required to consider a query rising.")
|
|
32
|
+
});
|
|
33
|
+
async function searchConsoleRisingNonBrandQueriesHandler(params) {
|
|
34
|
+
try {
|
|
35
|
+
const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
|
|
36
|
+
const minImpressions = params.minImpressions ?? 50;
|
|
37
|
+
const minGrowthRate = params.minGrowthRate ?? 20;
|
|
38
|
+
const [currentResponse, previousResponse] = await Promise.all([
|
|
39
|
+
querySearchConsolePerformance(
|
|
40
|
+
siteUrl,
|
|
41
|
+
buildSearchConsoleQueryBody({
|
|
42
|
+
startDate: params.currentStartDate,
|
|
43
|
+
endDate: params.currentEndDate,
|
|
44
|
+
dimensions: ["query"],
|
|
45
|
+
searchType: params.searchType,
|
|
46
|
+
rowLimit: 250
|
|
47
|
+
})
|
|
48
|
+
),
|
|
49
|
+
querySearchConsolePerformance(
|
|
50
|
+
siteUrl,
|
|
51
|
+
buildSearchConsoleQueryBody({
|
|
52
|
+
startDate: params.previousStartDate,
|
|
53
|
+
endDate: params.previousEndDate,
|
|
54
|
+
dimensions: ["query"],
|
|
55
|
+
searchType: params.searchType,
|
|
56
|
+
rowLimit: 250
|
|
57
|
+
})
|
|
58
|
+
)
|
|
59
|
+
]);
|
|
60
|
+
const currentRows = (currentResponse.rows ?? []).map(
|
|
61
|
+
(row) => normalizeSearchConsoleRow(row, ["query"])
|
|
62
|
+
);
|
|
63
|
+
const previousRows = (previousResponse.rows ?? []).map(
|
|
64
|
+
(row) => normalizeSearchConsoleRow(row, ["query"])
|
|
65
|
+
);
|
|
66
|
+
const previousMap = buildComparisonMap(previousRows, (row) => row.dimensions.query);
|
|
67
|
+
const risingQueries = currentRows.map((row) => {
|
|
68
|
+
const previousRow = previousMap.get(row.dimensions.query);
|
|
69
|
+
return {
|
|
70
|
+
query: row.dimensions.query,
|
|
71
|
+
current_clicks: row.clicks,
|
|
72
|
+
previous_clicks: previousRow?.clicks ?? 0,
|
|
73
|
+
current_impressions: row.impressions,
|
|
74
|
+
previous_impressions: previousRow?.impressions ?? 0,
|
|
75
|
+
current_ctr_percent: row.ctr_percent,
|
|
76
|
+
previous_ctr_percent: previousRow?.ctr_percent ?? 0,
|
|
77
|
+
current_position: row.position,
|
|
78
|
+
previous_position: previousRow?.position ?? 0,
|
|
79
|
+
brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms)
|
|
80
|
+
};
|
|
81
|
+
}).filter((row) => row.brand_classification === "non_brand").filter((row) => row.current_impressions >= minImpressions).map((row) => ({
|
|
82
|
+
...row,
|
|
83
|
+
impressions_growth_percent: computeChangePercent(
|
|
84
|
+
row.current_impressions,
|
|
85
|
+
row.previous_impressions
|
|
86
|
+
),
|
|
87
|
+
clicks_growth_percent: computeChangePercent(row.current_clicks, row.previous_clicks)
|
|
88
|
+
})).filter((row) => (row.impressions_growth_percent ?? 0) >= minGrowthRate).sort(
|
|
89
|
+
(left, right) => (right.impressions_growth_percent ?? 0) - (left.impressions_growth_percent ?? 0)
|
|
90
|
+
);
|
|
91
|
+
return object(
|
|
92
|
+
stripNulls({
|
|
93
|
+
site_url: siteUrl,
|
|
94
|
+
comparison: {
|
|
95
|
+
current_period: {
|
|
96
|
+
start_date: params.currentStartDate,
|
|
97
|
+
end_date: params.currentEndDate
|
|
98
|
+
},
|
|
99
|
+
previous_period: {
|
|
100
|
+
start_date: params.previousStartDate,
|
|
101
|
+
end_date: params.previousEndDate
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
thresholds: {
|
|
105
|
+
min_impressions: minImpressions,
|
|
106
|
+
min_growth_rate_percent: minGrowthRate
|
|
107
|
+
},
|
|
108
|
+
rising_queries: risingQueries
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
return error(
|
|
113
|
+
err instanceof Error ? err.message : "Failed to find Search Console rising non-brand queries"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
searchConsoleRisingNonBrandQueriesHandler,
|
|
119
|
+
searchConsoleRisingNonBrandQueriesSchema
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=rising-non-brand-queries.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/rising-non-brand-queries.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n brandTermsSchemaField,\n buildComparisonMap,\n buildSearchConsoleQueryBody,\n classifyBrandLabel,\n computeChangePercent,\n currentEndDateSchemaField,\n currentStartDateSchemaField,\n previousEndDateSchemaField,\n previousStartDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n searchTypeSchemaField,\n siteUrlSchemaField,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleRisingNonBrandQueriesSchema = z.object({\n currentStartDate: currentStartDateSchemaField,\n currentEndDate: currentEndDateSchemaField,\n previousStartDate: previousStartDateSchemaField,\n previousEndDate: previousEndDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n brandTerms: brandTermsSchemaField,\n minImpressions: z\n .number()\n .min(1)\n .optional()\n .describe(\"Minimum current-period impressions required to include a query.\"),\n minGrowthRate: z\n .number()\n .min(0)\n .optional()\n .describe(\"Minimum impressions growth percentage required to consider a query rising.\"),\n});\n\nexport async function searchConsoleRisingNonBrandQueriesHandler(\n params: z.infer<typeof searchConsoleRisingNonBrandQueriesSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const minImpressions = params.minImpressions ?? 50;\n const minGrowthRate = params.minGrowthRate ?? 20;\n\n const [currentResponse, previousResponse] = await Promise.all([\n querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.currentStartDate,\n endDate: params.currentEndDate,\n dimensions: [\"query\"],\n searchType: params.searchType,\n rowLimit: 250,\n })\n ),\n querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.previousStartDate,\n endDate: params.previousEndDate,\n dimensions: [\"query\"],\n searchType: params.searchType,\n rowLimit: 250,\n })\n ),\n ]);\n\n const currentRows = (currentResponse.rows ?? []).map((row) =>\n normalizeSearchConsoleRow(row, [\"query\"])\n );\n const previousRows = (previousResponse.rows ?? []).map((row) =>\n normalizeSearchConsoleRow(row, [\"query\"])\n );\n const previousMap = buildComparisonMap(previousRows, (row) => row.dimensions.query);\n\n const risingQueries = currentRows\n .map((row) => {\n const previousRow = previousMap.get(row.dimensions.query);\n return {\n query: row.dimensions.query,\n current_clicks: row.clicks,\n previous_clicks: previousRow?.clicks ?? 0,\n current_impressions: row.impressions,\n previous_impressions: previousRow?.impressions ?? 0,\n current_ctr_percent: row.ctr_percent,\n previous_ctr_percent: previousRow?.ctr_percent ?? 0,\n current_position: row.position,\n previous_position: previousRow?.position ?? 0,\n brand_classification: classifyBrandLabel(row.dimensions.query, params.brandTerms),\n };\n })\n .filter((row) => row.brand_classification === \"non_brand\")\n .filter((row) => row.current_impressions >= minImpressions)\n .map((row) => ({\n ...row,\n impressions_growth_percent: computeChangePercent(\n row.current_impressions,\n row.previous_impressions\n ),\n clicks_growth_percent: computeChangePercent(row.current_clicks, row.previous_clicks),\n }))\n .filter((row) => (row.impressions_growth_percent ?? 0) >= minGrowthRate)\n .sort(\n (left, right) =>\n (right.impressions_growth_percent ?? 0) - (left.impressions_growth_percent ?? 0)\n );\n\n return object(\n stripNulls({\n site_url: siteUrl,\n comparison: {\n current_period: {\n start_date: params.currentStartDate,\n end_date: params.currentEndDate,\n },\n previous_period: {\n start_date: params.previousStartDate,\n end_date: params.previousEndDate,\n },\n },\n thresholds: {\n min_impressions: minImpressions,\n min_growth_rate_percent: minGrowthRate,\n },\n rising_queries: risingQueries,\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to find Search Console rising non-brand queries\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,2CAA2C,EAAE,OAAO;AAAA,EAC/D,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,gBAAgB,EACb,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT,SAAS,iEAAiE;AAAA,EAC7E,eAAe,EACZ,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT,SAAS,4EAA4E;AAC1F,CAAC;AAED,eAAsB,0CACpB,QACA;AACA,MAAI;AACF,UAAM,UAAU,4BAA4B,OAAO,SAAS,OAAO,SAAS;AAC5E,UAAM,iBAAiB,OAAO,kBAAkB;AAChD,UAAM,gBAAgB,OAAO,iBAAiB;AAE9C,UAAM,CAAC,iBAAiB,gBAAgB,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC5D;AAAA,QACE;AAAA,QACA,4BAA4B;AAAA,UAC1B,WAAW,OAAO;AAAA,UAClB,SAAS,OAAO;AAAA,UAChB,YAAY,CAAC,OAAO;AAAA,UACpB,YAAY,OAAO;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,MACA;AAAA,QACE;AAAA,QACA,4BAA4B;AAAA,UAC1B,WAAW,OAAO;AAAA,UAClB,SAAS,OAAO;AAAA,UAChB,YAAY,CAAC,OAAO;AAAA,UACpB,YAAY,OAAO;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,UAAM,eAAe,gBAAgB,QAAQ,CAAC,GAAG;AAAA,MAAI,CAAC,QACpD,0BAA0B,KAAK,CAAC,OAAO,CAAC;AAAA,IAC1C;AACA,UAAM,gBAAgB,iBAAiB,QAAQ,CAAC,GAAG;AAAA,MAAI,CAAC,QACtD,0BAA0B,KAAK,CAAC,OAAO,CAAC;AAAA,IAC1C;AACA,UAAM,cAAc,mBAAmB,cAAc,CAAC,QAAQ,IAAI,WAAW,KAAK;AAElF,UAAM,gBAAgB,YACnB,IAAI,CAAC,QAAQ;AACZ,YAAM,cAAc,YAAY,IAAI,IAAI,WAAW,KAAK;AACxD,aAAO;AAAA,QACL,OAAO,IAAI,WAAW;AAAA,QACtB,gBAAgB,IAAI;AAAA,QACpB,iBAAiB,aAAa,UAAU;AAAA,QACxC,qBAAqB,IAAI;AAAA,QACzB,sBAAsB,aAAa,eAAe;AAAA,QAClD,qBAAqB,IAAI;AAAA,QACzB,sBAAsB,aAAa,eAAe;AAAA,QAClD,kBAAkB,IAAI;AAAA,QACtB,mBAAmB,aAAa,YAAY;AAAA,QAC5C,sBAAsB,mBAAmB,IAAI,WAAW,OAAO,OAAO,UAAU;AAAA,MAClF;AAAA,IACF,CAAC,EACA,OAAO,CAAC,QAAQ,IAAI,yBAAyB,WAAW,EACxD,OAAO,CAAC,QAAQ,IAAI,uBAAuB,cAAc,EACzD,IAAI,CAAC,SAAS;AAAA,MACb,GAAG;AAAA,MACH,4BAA4B;AAAA,QAC1B,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,MACA,uBAAuB,qBAAqB,IAAI,gBAAgB,IAAI,eAAe;AAAA,IACrF,EAAE,EACD,OAAO,CAAC,SAAS,IAAI,8BAA8B,MAAM,aAAa,EACtE;AAAA,MACC,CAAC,MAAM,WACJ,MAAM,8BAA8B,MAAM,KAAK,8BAA8B;AAAA,IAClF;AAEF,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,UACV,gBAAgB;AAAA,YACd,YAAY,OAAO;AAAA,YACnB,UAAU,OAAO;AAAA,UACnB;AAAA,UACA,iBAAiB;AAAA,YACf,YAAY,OAAO;AAAA,YACnB,UAAU,OAAO;AAAA,UACnB;AAAA,QACF;AAAA,QACA,YAAY;AAAA,UACV,iBAAiB;AAAA,UACjB,yBAAyB;AAAA,QAC3B;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { error, object } from "mcp-use/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
|
|
4
|
+
import {
|
|
5
|
+
buildPaginationMetadata,
|
|
6
|
+
buildSearchConsoleQueryBody,
|
|
7
|
+
endDateSchemaField,
|
|
8
|
+
profileIdSchemaField,
|
|
9
|
+
resolveSearchConsoleSiteUrl,
|
|
10
|
+
rowLimitSchemaField,
|
|
11
|
+
searchConsoleAggregationTypes,
|
|
12
|
+
searchConsoleDimensionFilterSchema,
|
|
13
|
+
searchConsoleDimensions,
|
|
14
|
+
searchTypeSchemaField,
|
|
15
|
+
siteUrlSchemaField,
|
|
16
|
+
startDateSchemaField,
|
|
17
|
+
startRowSchemaField,
|
|
18
|
+
sumSearchConsoleRows,
|
|
19
|
+
normalizeSearchConsoleRow
|
|
20
|
+
} from "../../search-console/search-console-utils.js";
|
|
21
|
+
import { stripNulls } from "../../utils/strip-payload.js";
|
|
22
|
+
const searchConsoleSearchPerformanceSchema = z.object({
|
|
23
|
+
startDate: startDateSchemaField,
|
|
24
|
+
endDate: endDateSchemaField,
|
|
25
|
+
siteUrl: siteUrlSchemaField,
|
|
26
|
+
profileId: profileIdSchemaField,
|
|
27
|
+
dimensions: z.array(z.enum(searchConsoleDimensions)).max(5).optional().describe("Dimensions to group the Search Console query by."),
|
|
28
|
+
searchType: searchTypeSchemaField,
|
|
29
|
+
dimensionFilters: z.array(searchConsoleDimensionFilterSchema).max(10).optional().describe("Optional Search Console dimension filters."),
|
|
30
|
+
aggregationType: z.enum(searchConsoleAggregationTypes).optional().describe("Aggregation type for the Search Console query."),
|
|
31
|
+
rowLimit: rowLimitSchemaField,
|
|
32
|
+
startRow: startRowSchemaField
|
|
33
|
+
});
|
|
34
|
+
async function searchConsoleSearchPerformanceHandler(params) {
|
|
35
|
+
try {
|
|
36
|
+
const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
|
|
37
|
+
const dimensions = params.dimensions ?? [];
|
|
38
|
+
const body = buildSearchConsoleQueryBody({
|
|
39
|
+
startDate: params.startDate,
|
|
40
|
+
endDate: params.endDate,
|
|
41
|
+
dimensions,
|
|
42
|
+
searchType: params.searchType,
|
|
43
|
+
dimensionFilters: params.dimensionFilters,
|
|
44
|
+
aggregationType: params.aggregationType,
|
|
45
|
+
rowLimit: params.rowLimit,
|
|
46
|
+
startRow: params.startRow
|
|
47
|
+
});
|
|
48
|
+
const response = await querySearchConsolePerformance(siteUrl, body);
|
|
49
|
+
const rows = (response.rows ?? []).map((row) => normalizeSearchConsoleRow(row, dimensions));
|
|
50
|
+
const totals = sumSearchConsoleRows(rows);
|
|
51
|
+
return object(
|
|
52
|
+
stripNulls({
|
|
53
|
+
site_url: siteUrl,
|
|
54
|
+
profile_id: params.profileId?.trim() || void 0,
|
|
55
|
+
date_range: {
|
|
56
|
+
start_date: params.startDate,
|
|
57
|
+
end_date: params.endDate
|
|
58
|
+
},
|
|
59
|
+
query: {
|
|
60
|
+
dimensions,
|
|
61
|
+
search_type: params.searchType ?? "web",
|
|
62
|
+
aggregation_type: params.aggregationType ?? response.responseAggregationType,
|
|
63
|
+
dimension_filters: params.dimensionFilters
|
|
64
|
+
},
|
|
65
|
+
overview: {
|
|
66
|
+
total_clicks: totals.clicks,
|
|
67
|
+
total_impressions: totals.impressions,
|
|
68
|
+
average_ctr_percent: totals.ctrPercent,
|
|
69
|
+
average_position: totals.averagePosition
|
|
70
|
+
},
|
|
71
|
+
rows,
|
|
72
|
+
metadata: buildPaginationMetadata({
|
|
73
|
+
startRow: params.startRow,
|
|
74
|
+
rowLimit: params.rowLimit,
|
|
75
|
+
returnedRows: rows.length
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
return error(
|
|
81
|
+
err instanceof Error ? err.message : "Failed to fetch Search Console search performance"
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
searchConsoleSearchPerformanceHandler,
|
|
87
|
+
searchConsoleSearchPerformanceSchema
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=search-performance.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/search-console/search-performance.ts"],
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n buildPaginationMetadata,\n buildSearchConsoleQueryBody,\n endDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n rowLimitSchemaField,\n searchConsoleAggregationTypes,\n searchConsoleDimensionFilterSchema,\n searchConsoleDimensions,\n searchTypeSchemaField,\n siteUrlSchemaField,\n startDateSchemaField,\n startRowSchemaField,\n sumSearchConsoleRows,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleSearchPerformanceSchema = z.object({\n startDate: startDateSchemaField,\n endDate: endDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n dimensions: z\n .array(z.enum(searchConsoleDimensions))\n .max(5)\n .optional()\n .describe(\"Dimensions to group the Search Console query by.\"),\n searchType: searchTypeSchemaField,\n dimensionFilters: z\n .array(searchConsoleDimensionFilterSchema)\n .max(10)\n .optional()\n .describe(\"Optional Search Console dimension filters.\"),\n aggregationType: z\n .enum(searchConsoleAggregationTypes)\n .optional()\n .describe(\"Aggregation type for the Search Console query.\"),\n rowLimit: rowLimitSchemaField,\n startRow: startRowSchemaField,\n});\n\nexport async function searchConsoleSearchPerformanceHandler(\n params: z.infer<typeof searchConsoleSearchPerformanceSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const dimensions = params.dimensions ?? [];\n const body = buildSearchConsoleQueryBody({\n startDate: params.startDate,\n endDate: params.endDate,\n dimensions,\n searchType: params.searchType,\n dimensionFilters: params.dimensionFilters,\n aggregationType: params.aggregationType,\n rowLimit: params.rowLimit,\n startRow: params.startRow,\n });\n\n const response = await querySearchConsolePerformance(siteUrl, body);\n const rows = (response.rows ?? []).map((row) => normalizeSearchConsoleRow(row, dimensions));\n const totals = sumSearchConsoleRows(rows);\n\n return object(\n stripNulls({\n site_url: siteUrl,\n profile_id: params.profileId?.trim() || undefined,\n date_range: {\n start_date: params.startDate,\n end_date: params.endDate,\n },\n query: {\n dimensions,\n search_type: params.searchType ?? \"web\",\n aggregation_type: params.aggregationType ?? response.responseAggregationType,\n dimension_filters: params.dimensionFilters,\n },\n overview: {\n total_clicks: totals.clicks,\n total_impressions: totals.impressions,\n average_ctr_percent: totals.ctrPercent,\n average_position: totals.averagePosition,\n },\n rows,\n metadata: buildPaginationMetadata({\n startRow: params.startRow,\n rowLimit: params.rowLimit,\n returnedRows: rows.length,\n }),\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to fetch Search Console search performance\"\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,qCAAqC;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,uCAAuC,EAAE,OAAO;AAAA,EAC3D,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY,EACT,MAAM,EAAE,KAAK,uBAAuB,CAAC,EACrC,IAAI,CAAC,EACL,SAAS,EACT,SAAS,kDAAkD;AAAA,EAC9D,YAAY;AAAA,EACZ,kBAAkB,EACf,MAAM,kCAAkC,EACxC,IAAI,EAAE,EACN,SAAS,EACT,SAAS,4CAA4C;AAAA,EACxD,iBAAiB,EACd,KAAK,6BAA6B,EAClC,SAAS,EACT,SAAS,gDAAgD;AAAA,EAC5D,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAED,eAAsB,sCACpB,QACA;AACA,MAAI;AACF,UAAM,UAAU,4BAA4B,OAAO,SAAS,OAAO,SAAS;AAC5E,UAAM,aAAa,OAAO,cAAc,CAAC;AACzC,UAAM,OAAO,4BAA4B;AAAA,MACvC,WAAW,OAAO;AAAA,MAClB,SAAS,OAAO;AAAA,MAChB;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,kBAAkB,OAAO;AAAA,MACzB,iBAAiB,OAAO;AAAA,MACxB,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,IACnB,CAAC;AAED,UAAM,WAAW,MAAM,8BAA8B,SAAS,IAAI;AAClE,UAAM,QAAQ,SAAS,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,0BAA0B,KAAK,UAAU,CAAC;AAC1F,UAAM,SAAS,qBAAqB,IAAI;AAExC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,YAAY,OAAO,WAAW,KAAK,KAAK;AAAA,QACxC,YAAY;AAAA,UACV,YAAY,OAAO;AAAA,UACnB,UAAU,OAAO;AAAA,QACnB;AAAA,QACA,OAAO;AAAA,UACL;AAAA,UACA,aAAa,OAAO,cAAc;AAAA,UAClC,kBAAkB,OAAO,mBAAmB,SAAS;AAAA,UACrD,mBAAmB,OAAO;AAAA,QAC5B;AAAA,QACA,UAAU;AAAA,UACR,cAAc,OAAO;AAAA,UACrB,mBAAmB,OAAO;AAAA,UAC1B,qBAAqB,OAAO;AAAA,UAC5B,kBAAkB,OAAO;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,UAAU,wBAAwB;AAAA,UAChC,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO;AAAA,UACjB,cAAc,KAAK;AAAA,QACrB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,eAAe,QAAQ,IAAI,UAAU;AAAA,IACvC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|