T7yrttrd's picture
Upload 24 files
9d94d64 verified
Raw History Blame Contribute Delete
15.7 kB
import json
from connector_base import call_google_api
DOCS_GET_DOCUMENT_TOOL = {
"type": "function",
"function": {
"name": "docs_get_document",
"description": "Retrieve full document content, paragraphs, headings, tables, and document metadata of a Google Doc by ID.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
}
},
"required": ["document_id"]
}
}
}
DOCS_CREATE_DOCUMENT_TOOL = {
"type": "function",
"function": {
"name": "docs_create_document",
"description": "Create a new Google Doc with specified title and optional initial text.",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title of the new Google Doc."
},
"initial_text": {
"type": "string",
"description": "Optional starting text to insert into document."
}
},
"required": ["title"]
}
}
}
DOCS_APPEND_TEXT_TOOL = {
"type": "function",
"function": {
"name": "docs_append_text",
"description": "Append text or paragraphs to the end of an existing Google Doc.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the Google Doc."
},
"text": {
"type": "string",
"description": "Text content to insert at the end of the document."
}
},
"required": ["document_id", "text"]
}
}
}
DOCS_BATCH_UPDATE_TOOL = {
"type": "function",
"function": {
"name": "docs_batch_update",
"description": "Apply structural updates to a Google Doc (insertText, deleteContentRange, replaceAllText, updateTextStyle).",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
},
"requests": {
"type": "array",
"items": {"type": "object"},
"description": "List of update Request objects following Google Docs API schema."
}
},
"required": ["document_id", "requests"]
}
}
}
DOCS_FORMAT_TEXT_TOOL = {
"type": "function",
"function": {
"name": "docs_format_text",
"description": "Apply bold, italic, underline, or heading style to a specific range of text in a Google Doc.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
},
"start_index": {
"type": "integer",
"description": "The start index of the text range."
},
"end_index": {
"type": "integer",
"description": "The end index of the text range."
},
"bold": {
"type": "boolean",
"description": "Apply bold formatting."
},
"italic": {
"type": "boolean",
"description": "Apply italic formatting."
},
"underline": {
"type": "boolean",
"description": "Apply underline formatting."
},
"heading": {
"type": "string",
"enum": ["1", "2", "3", "4", "5", "6"],
"description": "Apply heading style (1 to 6)."
}
},
"required": ["document_id", "start_index", "end_index"]
}
}
}
DOCS_CREATE_LIST_TOOL = {
"type": "function",
"function": {
"name": "docs_create_list",
"description": "Create a bulleted or numbered list within a specific range of a Google Doc.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
},
"start_index": {
"type": "integer",
"description": "The start index of the range."
},
"end_index": {
"type": "integer",
"description": "The end index of the range."
},
"list_type": {
"type": "string",
"enum": ["bullet", "numbered"],
"description": "Type of list to create."
}
},
"required": ["document_id", "start_index", "end_index", "list_type"]
}
}
}
DOCS_ADD_COMMENT_TOOL = {
"type": "function",
"function": {
"name": "docs_add_comment",
"description": "Add a comment to a Google Doc using the Drive API.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document (also known as file ID)."
},
"text": {
"type": "string",
"description": "The comment text content."
}
},
"required": ["document_id", "text"]
}
}
}
DOCS_SHARE_DOCUMENT_TOOL = {
"type": "function",
"function": {
"name": "docs_share_document",
"description": "Share a Google Doc with a specific user email and role using the Drive API.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
},
"email": {
"type": "string",
"description": "The email address of the user to share with."
},
"role": {
"type": "string",
"enum": ["reader", "writer", "commenter"],
"description": "The permission role."
}
},
"required": ["document_id", "email"]
}
}
}
DOCS_GET_DOCUMENT_STRUCTURE_TOOL = {
"type": "function",
"function": {
"name": "docs_get_document_structure",
"description": "Parse and return a structured summary of headings and tables from a Google Doc for easier AI comprehension.",
"parameters": {
"type": "object",
"properties": {
"document_id": {
"type": "string",
"description": "The ID of the document."
}
},
"required": ["document_id"]
}
}
}
ALL_DOCS_MCP_TOOLS = [
DOCS_GET_DOCUMENT_TOOL,
DOCS_CREATE_DOCUMENT_TOOL,
DOCS_APPEND_TEXT_TOOL,
DOCS_BATCH_UPDATE_TOOL,
DOCS_FORMAT_TEXT_TOOL,
DOCS_CREATE_LIST_TOOL,
DOCS_ADD_COMMENT_TOOL,
DOCS_SHARE_DOCUMENT_TOOL,
DOCS_GET_DOCUMENT_STRUCTURE_TOOL
]
def get_docs_metadata(func_name: str, args: dict):
if func_name == "docs_get_document":
return "docs", "Getting document content"
elif func_name == "docs_create_document":
title = args.get("title", "")
return "docs", f"Creating document: {title}" if title else "Creating document"
elif func_name == "docs_append_text":
return "docs", "Appending text to document"
elif func_name == "docs_batch_update":
return "docs", "Batch updating document"
elif func_name == "docs_format_text":
return "docs", "Formatting text in document"
elif func_name == "docs_create_list":
return "docs", "Creating list in document"
elif func_name == "docs_add_comment":
return "docs", "Adding comment to document"
elif func_name == "docs_share_document":
return "docs", "Sharing document"
elif func_name == "docs_get_document_structure":
return "docs", "Getting document structure"
return "docs", func_name
async def execute_docs_tool(user_id: str, fn_name: str, args: dict) -> str:
base_url = "https://docs.googleapis.com/v1/documents"
drive_url = "https://www.googleapis.com/drive/v3/files"
if fn_name == "docs_get_document":
doc_id = args.get("document_id")
status, body = await call_google_api(user_id, "docs", "GET", f"{base_url}/{doc_id}")
return body
elif fn_name == "docs_create_document":
title = args.get("title", "Untitled Document")
status, body = await call_google_api(user_id, "docs", "POST", base_url, json_body={"title": title})
if status not in [200, 201]:
return body
initial_text = args.get("initial_text")
if initial_text:
try:
d = json.loads(body)
created_id = d.get("documentId")
if created_id:
ins_payload = {
"requests": [
{
"insertText": {
"location": {"index": 1},
"text": initial_text
}
}
]
}
await call_google_api(user_id, "docs", "POST", f"{base_url}/{created_id}:batchUpdate", json_body=ins_payload)
except Exception:
pass
return body
elif fn_name == "docs_append_text":
doc_id = args.get("document_id")
text = args.get("text", "")
payload = {
"requests": [
{
"insertText": {
"endOfSegmentLocation": {},
"text": text
}
}
]
}
status, body = await call_google_api(user_id, "docs", "POST", f"{base_url}/{doc_id}:batchUpdate", json_body=payload)
return body
elif fn_name == "docs_batch_update":
doc_id = args.get("document_id")
payload = {"requests": args.get("requests", [])}
status, body = await call_google_api(user_id, "docs", "POST", f"{base_url}/{doc_id}:batchUpdate", json_body=payload)
return body
elif fn_name == "docs_format_text":
doc_id = args.get("document_id")
start_idx = args.get("start_index")
end_idx = args.get("end_index")
bold = args.get("bold", False)
italic = args.get("italic", False)
underline = args.get("underline", False)
heading = args.get("heading")
requests = []
if heading:
style_type = f"HEADING_{heading}" if heading.isdigit() and 1 <= int(heading) <= 6 else "NORMAL_TEXT"
requests.append({
"updateParagraphStyle": {
"range": {"startIndex": start_idx, "endIndex": end_idx},
"paragraphStyle": {"namedStyleType": style_type},
"fields": "namedStyleType"
}
})
if bold or italic or underline:
style = {}
if bold:
style["bold"] = True
if italic:
style["italic"] = True
if underline:
style["underline"] = True
requests.append({
"updateTextStyle": {
"range": {"startIndex": start_idx, "endIndex": end_idx},
"textStyle": style,
"fields": ",".join(style.keys())
}
})
payload = {"requests": requests}
status, body = await call_google_api(user_id, "docs", "POST", f"{base_url}/{doc_id}:batchUpdate", json_body=payload)
return body
elif fn_name == "docs_create_list":
doc_id = args.get("document_id")
start_idx = args.get("start_index")
end_idx = args.get("end_index")
list_type = args.get("list_type", "bullet")
bullet_preset = "NUMBERED" if list_type == "numbered" else "BULLET"
payload = {
"requests": [
{
"createParagraphBullets": {
"range": {"startIndex": start_idx, "endIndex": end_idx},
"bulletPreset": bullet_preset
}
}
]
}
status, body = await call_google_api(user_id, "docs", "POST", f"{base_url}/{doc_id}:batchUpdate", json_body=payload)
return body
elif fn_name == "docs_add_comment":
doc_id = args.get("document_id")
text = args.get("text", "")
comment_payload = {"content": text}
status, body = await call_google_api(user_id, "drive", "POST", f"{drive_url}/{doc_id}/comments", json_body=comment_payload)
return body
elif fn_name == "docs_share_document":
doc_id = args.get("document_id")
email = args.get("email")
role = args.get("role", "reader")
permission_payload = {
"type": "user",
"role": role,
"emailAddress": email
}
status, body = await call_google_api(user_id, "drive", "POST", f"{drive_url}/{doc_id}/permissions", json_body=permission_payload)
return body
elif fn_name == "docs_get_document_structure":
doc_id = args.get("document_id")
status, body = await call_google_api(user_id, "docs", "GET", f"{base_url}/{doc_id}")
if status not in [200, 201]:
return body
try:
data = json.loads(body)
content = data.get("body", {}).get("content", [])
headings = []
tables = []
for item in content:
if "paragraph" in item:
para = item["paragraph"]
elements = para.get("elements", [])
if elements:
text_run = elements[0].get("textRun", {})
text = text_run.get("content", "").strip()
if text:
style = para.get("paragraphStyle", {})
named_style = style.get("namedStyleType", "")
if named_style.startswith("HEADING_"):
level = named_style.replace("HEADING_", "")
if level.isdigit():
headings.append({"level": int(level), "text": text})
elif "table" in item:
table_data = item["table"]
rows = table_data.get("tableRows", [])
tables.append({"row_count": len(rows)})
structured = {"headings": headings, "tables": tables}
return json.dumps(structured)
except Exception:
return body
return json.dumps({"error": f"Unsupported Docs tool: {fn_name}"})