query_channel_analytics
Retrieve YouTube Analytics data for your channel, including views, watch time, and traffic sources. Supports date ranges and optional grouping by dimensions like day or video.
Instructions
Query YouTube Analytics for the authenticated channel. Returns tabular data — useful for views/watch-time/retention/traffic-source reports. Date-ranged and optionally grouped by dimensions.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | Yes | YYYY-MM-DD (inclusive) | |
| end_date | Yes | YYYY-MM-DD (inclusive) | |
| metrics | No | Comma-separated metric names (see YouTube Analytics API). Defaults cover the most common creator-dashboard stats. | views,estimatedMinutesWatched,averageViewDuration,subscribersGained |
| dimensions | No | Comma-separated dimensions, e.g. 'day', 'video', 'country'. Omit for channel totals. | |
| filters | No | Filter expression, e.g. 'video==VIDEO_ID' to scope to one video, or 'country==US'. | |
| sort | No | Sort spec, e.g. '-views' for descending by views | |
| max_results | No |
Implementation Reference
- src/tools/analytics.ts:41-68 (handler)The handler function that executes the query_channel_analytics tool logic. It calls client.analyticsQuery() with the parsed arguments and formats the result as a tabular text response.
async (args) => { const res = await client.analyticsQuery({ startDate: args.start_date, endDate: args.end_date, metrics: args.metrics, dimensions: args.dimensions, filters: args.filters, sort: args.sort, maxResults: args.max_results, }); const header = res.columnHeaders.map((c) => c.name).join(" | "); const rows = res.rows.map((r) => r.join(" | ")); return { content: [ { type: "text" as const, text: [ `Analytics ${args.start_date} → ${args.end_date}:`, "", header, "-".repeat(Math.max(10, header.length)), ...rows, ].join("\n"), }, ], }; }, ); - src/tools/analytics.ts:5-34 (schema)Input schema for query_channel_analytics, defined with zod. Defines start_date, end_date, metrics (with defaults), dimensions, filters, sort, and max_results.
const analyticsSchema = { start_date: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/) .describe("YYYY-MM-DD (inclusive)"), end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("YYYY-MM-DD (inclusive)"), metrics: z .string() .default("views,estimatedMinutesWatched,averageViewDuration,subscribersGained") .describe( "Comma-separated metric names (see YouTube Analytics API). Defaults cover the most common creator-dashboard stats.", ), dimensions: z .string() .optional() .describe( "Comma-separated dimensions, e.g. 'day', 'video', 'country'. Omit for channel totals.", ), filters: z .string() .optional() .describe( "Filter expression, e.g. 'video==VIDEO_ID' to scope to one video, or 'country==US'.", ), sort: z .string() .optional() .describe("Sort spec, e.g. '-views' for descending by views"), max_results: z.number().int().min(1).max(200).optional(), }; - src/tools/analytics.ts:36-69 (registration)Registration of the tool via server.tool() with name 'query_channel_analytics', description, schema, and handler.
export function registerAnalyticsTool(server: McpServer, client: YouTubeClient): void { server.tool( "query_channel_analytics", "Query YouTube Analytics for the authenticated channel. Returns tabular data — useful for views/watch-time/retention/traffic-source reports. Date-ranged and optionally grouped by dimensions.", analyticsSchema, async (args) => { const res = await client.analyticsQuery({ startDate: args.start_date, endDate: args.end_date, metrics: args.metrics, dimensions: args.dimensions, filters: args.filters, sort: args.sort, maxResults: args.max_results, }); const header = res.columnHeaders.map((c) => c.name).join(" | "); const rows = res.rows.map((r) => r.join(" | ")); return { content: [ { type: "text" as const, text: [ `Analytics ${args.start_date} → ${args.end_date}:`, "", header, "-".repeat(Math.max(10, header.length)), ...rows, ].join("\n"), }, ], }; }, ); } - src/youtube/client.ts:298-317 (helper)Helper method on YouTubeClient that builds and sends the YouTube Analytics API request with channel==MINE and the provided parameters.
async analyticsQuery(params: { startDate: string; endDate: string; metrics: string; dimensions?: string; filters?: string; sort?: string; maxResults?: number; }): Promise<AnalyticsResponse> { return this.analyticsGet<AnalyticsResponse>("/reports", { ids: "channel==MINE", "start-date": params.startDate, "end-date": params.endDate, metrics: params.metrics, dimensions: params.dimensions, filters: params.filters, sort: params.sort, maxResults: params.maxResults ? String(params.maxResults) : undefined, }); } - src/youtube/client.ts:91-97 (helper)Low-level helper that constructs the YouTube Analytics API URL with query parameters and performs a GET request via the shared request method.
async analyticsGet<T>(path: string, params: Record<string, string | undefined>): Promise<T> { const url = new URL(`${ANALYTICS_API}${path}`); for (const [k, v] of Object.entries(params)) { if (v !== undefined) url.searchParams.set(k, v); } return this.request<T>(url.toString(), { method: "GET" }); }