From 25798d85230f60ab8540c2da6d52faa951e6e04f Mon Sep 17 00:00:00 2001 From: Baho73 <7726417@gmail.com> Date: Sat, 30 May 2026 08:07:09 +0300 Subject: [PATCH] Fix docs_resolve_comment by posting a reply with action="resolve" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation called `comments.update({resolved: True})`, which fails in Drive v3 for two reasons: 1. The API rejects the call with HTTP 400 "Comment content is required" because every comments.update body must include a non-empty `content` field, even when the only intended change is the `resolved` flag. 2. Even if `content` is supplied (e.g. by re-sending the existing comment text), the `resolved` field on the Comment resource is effectively read-only via comments.update — empirically the call succeeds but the comment remains open in both the Drive UI and the API. The canonical way to close a comment in Drive v3 — and what the Docs UI does internally — is to post a reply with `action="resolve"`. This also preserves any final-reply text the caller passed in, so it can replace the previous two-step flow (replies.create + comments.update) with a single atomic call. When no `reply` text is provided, fall back to the short placeholder "Resolved." because Drive requires non-empty `content` on every reply. The function now also returns `reply_id` and `reply_content` so callers can audit the closing reply. Verified end-to-end against a live document: both the `reply=""` and `reply="..."` paths flip `resolved` to true and the resulting comment is shown as resolved in the Drive UI. --- server.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/server.py b/server.py index 50b490e..91fdf4e 100644 --- a/server.py +++ b/server.py @@ -360,21 +360,28 @@ def docs_resolve_comment(doc_id: str, comment_id: str, reply: str = "") -> str: creds = docs_edit._load_creds() drive = build("drive", "v3", credentials=creds) - if reply: - drive.replies().create( - fileId=doc_id, - commentId=comment_id, - body={"content": reply}, - fields="id", - ).execute() - - drive.comments().update( + # In Drive v3, the `resolved` field on the Comment resource is effectively + # set by posting a reply with action="resolve" — `comments.update` either + # rejects the call (missing `content` -> 400) or silently no-ops on + # `resolved`. The canonical way to close a comment is replies.create with + # action="resolve", which also matches what the Docs UI does internally. + # + # The Drive API requires non-empty `content` on every reply, so when the + # caller didn't supply one we fall back to a short placeholder. + content = reply if reply else "Resolved." + result = drive.replies().create( fileId=doc_id, commentId=comment_id, - body={"resolved": True}, - fields="id,resolved", + body={"content": content, "action": "resolve"}, + fields="id,action,content", ).execute() - return json.dumps({"ok": True, "comment_id": comment_id, "resolved": True}, indent=2) + return json.dumps({ + "ok": True, + "comment_id": comment_id, + "resolved": True, + "reply_id": result.get("id"), + "reply_content": result.get("content"), + }, indent=2) @mcp.tool