Skip to main content
Glama
list-comments.ts3.69 kB
import type { OAuth2Client } from "google-auth-library"; import { google } from "googleapis"; import { z } from "zod"; export const tool = { name: "gdrive_list_doc_comments", description: "List all comment threads on a Google Doc, including the quoted text, comment content, replies, status (resolved/open), assignees, and timestamps. Accepts either a Google Docs URL or a document ID.", inputSchema: z.object({ doc_id_or_url: z .string() .describe( "Google Docs URL (e.g., https://docs.google.com/document/d/...) or document ID", ), }), annotations: { readOnlyHint: true, idempotentHint: true, }, } as const; export const handler = async ( args: z.infer<typeof tool.inputSchema>, auth: OAuth2Client, ) => { const { doc_id_or_url } = args; try { const comments = await listComments(auth, doc_id_or_url); return { content: [ { type: "text" as const, text: comments, }, ], }; } catch (error: unknown) { if (error instanceof Error) { return { content: [ { type: "text" as const, text: `Error: ${error.message}`, }, ], isError: true, }; } throw error; } }; const extractDocId = (input: string): string | null => { // Try to extract document ID from URL const urlMatch = input.match(/\/document\/d\/([a-zA-Z0-9-_]+)/); if (urlMatch) { return urlMatch[1] ?? null; } // If it's not a URL, assume it's already a document ID if (/^[a-zA-Z0-9-_]+$/.test(input)) { return input; } return null; }; const listComments = async ( auth: OAuth2Client, docIdOrUrl: string, ): Promise<string> => { const docId = extractDocId(docIdOrUrl); if (!docId) { throw new Error("Invalid document ID or URL"); } const drive = google.drive({ version: "v3", auth }); try { // Get all comments on the document const response = await drive.comments.list({ fileId: docId, fields: "comments(id,content,quotedFileContent,anchor,resolved,createdTime,modifiedTime,author,replies)", includeDeleted: false, }); const comments = response.data.comments || []; if (comments.length === 0) { return "No comments found on this document."; } // Format comments with all details let output = `Found ${comments.length} comment thread(s):\n\n`; for (const comment of comments) { output += `${"─".repeat(80)}\n`; output += `Comment ID: ${comment.id}\n`; output += `Created: ${comment.createdTime}\n`; output += `Modified: ${comment.modifiedTime}\n`; output += `Author: ${comment.author?.displayName || "Unknown"} (${comment.author?.emailAddress || "N/A"})\n`; output += `Status: ${comment.resolved ? "RESOLVED" : "OPEN"}\n`; if (comment.quotedFileContent?.value) { output += `\nQuoted text: "${comment.quotedFileContent.value}"\n`; } if (comment.anchor) { output += `Anchor: ${comment.anchor}\n`; } output += `\nComment: ${comment.content}\n`; // Add replies if any if (comment.replies && comment.replies.length > 0) { output += `\nReplies (${comment.replies.length}):\n`; for (const reply of comment.replies) { output += ` • ${reply.author?.displayName || "Unknown"} (${reply.createdTime}):\n`; output += ` ${reply.content}\n`; } } output += "\n"; } return output; } catch (error: unknown) { if (error instanceof Error) { throw new Error(`Failed to get comments: ${error.message}`); } throw error; } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/benjamine/gdrive-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server