88 lines
3.8 KiB
TypeScript
88 lines
3.8 KiB
TypeScript
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
import { z } from "zod";
|
|
import type { BetterNewsClient } from "../client.js";
|
|
import { handleTool } from "../utils.js";
|
|
|
|
export function registerCommentTools(server: McpServer, client: BetterNewsClient) {
|
|
server.tool(
|
|
"list_comments",
|
|
"List comments on a news item. Moderators also see hidden comments. Requires news:read scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
page: z.number().int().positive().optional().describe("Page number (default 1)"),
|
|
limit: z.number().int().min(1).max(50).optional().describe("Items per page (default 20, max 50)"),
|
|
sort: z.enum(["top", "most_disliked", "new", "oldest"]).optional().describe("Sort order: top = most liked (default), most_disliked, new = newest first, oldest"),
|
|
},
|
|
handleTool(async ({ newsItemId, page, limit, sort }) => {
|
|
const data = await client.get<unknown>(`/api/news/${newsItemId}/comments`, { page, limit, sort });
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
|
|
server.tool(
|
|
"create_comment",
|
|
"Post a comment on a published news item. Requires news:comment scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
content: z.string().min(1).max(2000).describe("Comment text"),
|
|
},
|
|
handleTool(async ({ newsItemId, content }) => {
|
|
const data = await client.post<unknown>(`/api/news/${newsItemId}/comments`, { content });
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
|
|
server.tool(
|
|
"delete_comment",
|
|
"Delete a comment. Owners can delete their own; Mod/Admin can delete any. Requires news:comment scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
commentId: z.string().uuid().describe("Comment UUID"),
|
|
},
|
|
handleTool(async ({ newsItemId, commentId }) => {
|
|
const data = await client.delete<unknown>(`/api/news/${newsItemId}/comments/${commentId}`);
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
|
|
server.tool(
|
|
"like_comment",
|
|
"Toggle a like on a comment. Requires news:comment scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
commentId: z.string().uuid().describe("Comment UUID"),
|
|
},
|
|
handleTool(async ({ newsItemId, commentId }) => {
|
|
const data = await client.post<unknown>(`/api/news/${newsItemId}/comments/${commentId}/like`);
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
|
|
server.tool(
|
|
"dislike_comment",
|
|
"Toggle a dislike on a comment. Requires news:comment scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
commentId: z.string().uuid().describe("Comment UUID"),
|
|
},
|
|
handleTool(async ({ newsItemId, commentId }) => {
|
|
const data = await client.post<unknown>(`/api/news/${newsItemId}/comments/${commentId}/dislike`);
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
|
|
server.tool(
|
|
"hide_comment",
|
|
"Hide or unhide a comment. Hidden comments are invisible to regular users but still visible to Mod/Admin. Requires Mod/Admin role and news:moderate scope.",
|
|
{
|
|
newsItemId: z.string().uuid().describe("News item UUID"),
|
|
commentId: z.string().uuid().describe("Comment UUID"),
|
|
hidden: z.boolean().describe("True to hide, false to unhide"),
|
|
},
|
|
handleTool(async ({ newsItemId, commentId, hidden }) => {
|
|
const data = await client.patch<unknown>(`/api/news/${newsItemId}/comments/${commentId}`, { hidden });
|
|
return JSON.stringify(data, null, 2);
|
|
}),
|
|
);
|
|
}
|