import { z } from "zod";
import { type InferSchema } from "xmcp";
import { youtubeApiRequest } from "../utils/youtube-api";
import { withToolUsageLogging } from "../utils/tool-usage-log";
export const schema = {
videoId: z.string().describe("YouTube video ID"),
sortBy: z.enum(["TOP_COMMENTS", "NEWEST_FIRST"]).default("TOP_COMMENTS").describe("Sort order for comments"),
maxResults: z.number().min(1).max(100).default(20).describe("Maximum number of comments to return"),
includeReplies: z.boolean().default(false).describe("Whether to include replies to each top-level comment"),
};
export const metadata = {
name: "get_video_comments",
description: "Get comments for a YouTube video",
annotations: {
title: "Get Video Comments",
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
},
};
async function get_video_comments({ videoId, sortBy, maxResults, includeReplies }: InferSchema<typeof schema>) {
// Map sortBy to API's order param
const order = sortBy === "NEWEST_FIRST" ? "time" : "relevance";
// If includeReplies, request replies part as well
const part = includeReplies ? "snippet,replies" : "snippet";
const response = await youtubeApiRequest<any>("commentThreads", {
part,
videoId,
maxResults,
order,
textFormat: "plainText",
});
const items = (response.items || []).map((item: any) => {
const topComment = item.snippet?.topLevelComment?.snippet || {};
const commentObj: any = {
author: topComment.authorDisplayName,
text: topComment.textDisplay,
likeCount: topComment.likeCount,
publishedTime: topComment.publishedAt,
};
if (includeReplies && item.replies && Array.isArray(item.replies.comments)) {
commentObj.replies = item.replies.comments.map((reply: any) => {
const replySnippet = reply.snippet || {};
return {
author: replySnippet.authorDisplayName,
text: replySnippet.textDisplay,
likeCount: replySnippet.likeCount,
publishedTime: replySnippet.publishedAt,
};
});
}
return commentObj;
});
return {
content: [
{
type: "text",
text: JSON.stringify(items, null, 2),
},
],
};
}
export default withToolUsageLogging(get_video_comments, metadata.name);