Skip to main content
Glama

create_table_with_data

Generate and populate a table in Google Docs using a 2D list of data. Requires index from inspect_doc_structure for accurate document positioning. Ensures proper formatting and structure for reliable table creation.

Instructions

Creates a table and populates it with data in one reliable operation.

CRITICAL: YOU MUST CALL inspect_doc_structure FIRST TO GET THE INDEX!

MANDATORY WORKFLOW - DO THESE STEPS IN ORDER:

Step 1: ALWAYS call inspect_doc_structure first Step 2: Use the 'total_length' value from inspect_doc_structure as your index Step 3: Format data as 2D list: [["col1", "col2"], ["row1col1", "row1col2"]] Step 4: Call this function with the correct index and data

EXAMPLE DATA FORMAT: table_data = [ ["Header1", "Header2", "Header3"], # Row 0 - headers ["Data1", "Data2", "Data3"], # Row 1 - first data row ["Data4", "Data5", "Data6"] # Row 2 - second data row ]

CRITICAL INDEX REQUIREMENTS:

  • NEVER use index values like 1, 2, 10 without calling inspect_doc_structure first

  • ALWAYS get index from inspect_doc_structure 'total_length' field

  • Index must be a valid insertion point in the document

DATA FORMAT REQUIREMENTS:

  • Must be 2D list of strings only

  • Each inner list = one table row

  • All rows MUST have same number of columns

  • Use empty strings "" for empty cells, never None

  • Use debug_table_structure after creation to verify results

Args: user_google_email: User's Google email address document_id: ID of the document to update table_data: 2D list of strings - EXACT format: [["col1", "col2"], ["row1col1", "row1col2"]] index: Document position (MANDATORY: get from inspect_doc_structure 'total_length') bold_headers: Whether to make first row bold (default: true)

Returns: str: Confirmation with table details and link

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bold_headersNo
document_idYes
indexYes
table_dataYes
user_google_emailYes

Implementation Reference

  • Main MCP tool handler for 'create_table_with_data'. Includes @server.tool() registration, input validation, error handling, and delegates core logic to TableOperationManager. Input schema defined by function parameters and type hints.
    @server.tool() @handle_http_errors("create_table_with_data", service_type="docs") @require_google_service("docs", "docs_write") async def create_table_with_data( service, user_google_email: str, document_id: str, table_data: list, index: int, bold_headers: bool = True, ) -> str: """ Creates a table and populates it with data in one reliable operation. CRITICAL: YOU MUST CALL inspect_doc_structure FIRST TO GET THE INDEX! MANDATORY WORKFLOW - DO THESE STEPS IN ORDER: Step 1: ALWAYS call inspect_doc_structure first Step 2: Use the 'total_length' value from inspect_doc_structure as your index Step 3: Format data as 2D list: [["col1", "col2"], ["row1col1", "row1col2"]] Step 4: Call this function with the correct index and data EXAMPLE DATA FORMAT: table_data = [ ["Header1", "Header2", "Header3"], # Row 0 - headers ["Data1", "Data2", "Data3"], # Row 1 - first data row ["Data4", "Data5", "Data6"] # Row 2 - second data row ] CRITICAL INDEX REQUIREMENTS: - NEVER use index values like 1, 2, 10 without calling inspect_doc_structure first - ALWAYS get index from inspect_doc_structure 'total_length' field - Index must be a valid insertion point in the document DATA FORMAT REQUIREMENTS: - Must be 2D list of strings only - Each inner list = one table row - All rows MUST have same number of columns - Use empty strings "" for empty cells, never None - Use debug_table_structure after creation to verify results Args: user_google_email: User's Google email address document_id: ID of the document to update table_data: 2D list of strings - EXACT format: [["col1", "col2"], ["row1col1", "row1col2"]] index: Document position (MANDATORY: get from inspect_doc_structure 'total_length') bold_headers: Whether to make first row bold (default: true) Returns: str: Confirmation with table details and link """ logger.debug(f"[create_table_with_data] Doc={document_id}, index={index}") # Input validation validator = ValidationManager() is_valid, error_msg = validator.validate_document_id(document_id) if not is_valid: return f"ERROR: {error_msg}" is_valid, error_msg = validator.validate_table_data(table_data) if not is_valid: return f"ERROR: {error_msg}" is_valid, error_msg = validator.validate_index(index, "Index") if not is_valid: return f"ERROR: {error_msg}" # Use TableOperationManager to handle the complex logic table_manager = TableOperationManager(service) # Try to create the table, and if it fails due to index being at document end, retry with index-1 success, message, metadata = await table_manager.create_and_populate_table( document_id, table_data, index, bold_headers ) # If it failed due to index being at or beyond document end, retry with adjusted index if not success and "must be less than the end index" in message: logger.debug(f"Index {index} is at document boundary, retrying with index {index - 1}") success, message, metadata = await table_manager.create_and_populate_table( document_id, table_data, index - 1, bold_headers ) if success: link = f"https://docs.google.com/document/d/{document_id}/edit" rows = metadata.get('rows', 0) columns = metadata.get('columns', 0) return f"SUCCESS: {message}. Table: {rows}x{columns}, Index: {index}. Link: {link}" else: return f"ERROR: {message}"
  • Core helper method in TableOperationManager that implements the table creation and population logic. Handles multi-step process: create empty table, refresh structure, populate cells one-by-one with index correction to avoid shifting issues.
    async def create_and_populate_table( self, document_id: str, table_data: List[List[str]], index: int, bold_headers: bool = True ) -> Tuple[bool, str, Dict[str, Any]]: """ Creates a table and populates it with data in a reliable multi-step process. This method extracts the complex logic from create_table_with_data tool function. Args: document_id: ID of the document to update table_data: 2D list of strings for table content index: Position to insert the table bold_headers: Whether to make the first row bold Returns: Tuple of (success, message, metadata) """ logger.debug(f"Creating table at index {index}, dimensions: {len(table_data)}x{len(table_data[0]) if table_data and len(table_data) > 0 else 0}") # Validate input data is_valid, error_msg = validate_table_data(table_data) if not is_valid: return False, f"Invalid table data: {error_msg}", {} rows = len(table_data) cols = len(table_data[0]) try: # Step 1: Create empty table await self._create_empty_table(document_id, index, rows, cols) # Step 2: Get fresh document structure to find actual cell positions fresh_tables = await self._get_document_tables(document_id) if not fresh_tables: return False, "Could not find table after creation", {} # Step 3: Populate each cell with proper index refreshing population_count = await self._populate_table_cells( document_id, table_data, bold_headers ) metadata = { 'rows': rows, 'columns': cols, 'populated_cells': population_count, 'table_index': len(fresh_tables) - 1 } return True, f"Successfully created {rows}x{cols} table and populated {population_count} cells", metadata except Exception as e: logger.error(f"Failed to create and populate table: {str(e)}") return False, f"Table creation failed: {str(e)}", {}
  • Input validation function for table_data parameter. Checks for 2D list format, consistent dimensions, size limits, no None values. Provides LLM-friendly error messages with examples.
    def validate_table_data(data: List[List[str]]) -> Tuple[bool, str]: """ Validates table data format and provides specific error messages for LLMs. WHAT THIS CHECKS: - Data is a 2D list (list of lists) - All rows have consistent column counts - Dimensions are within Google Docs limits - No None or undefined values VALID FORMAT EXAMPLE: [ ["Header1", "Header2"], # Row 0 - 2 columns ["Data1", "Data2"], # Row 1 - 2 columns ["Data3", "Data4"] # Row 2 - 2 columns ] INVALID FORMATS: - [["col1"], ["col1", "col2"]] # Inconsistent column counts - ["col1", "col2"] # Not 2D (missing inner lists) - [["col1", None]] # Contains None values - [] or [[]] # Empty data Args: data: 2D array of data to validate Returns: Tuple of (is_valid, error_message_with_examples) """ if not data: return False, "Data is empty. Use format: [['col1', 'col2'], ['row1col1', 'row1col2']]" if not isinstance(data, list): return False, f"Data must be a list, got {type(data).__name__}. Use format: [['col1', 'col2'], ['row1col1', 'row1col2']]" if not all(isinstance(row, list) for row in data): return False, f"Data must be a 2D list (list of lists). Each row must be a list. Check your format: {data}" # Check for consistent column count col_counts = [len(row) for row in data] if len(set(col_counts)) > 1: return False, f"All rows must have same number of columns. Found: {col_counts}. Fix your data format." # Check for reasonable size rows = len(data) cols = col_counts[0] if col_counts else 0 if rows > 1000: return False, f"Too many rows ({rows}). Google Docs limit is 1000 rows." if cols > 20: return False, f"Too many columns ({cols}). Google Docs limit is 20 columns." return True, f"Valid table data: {rows}x{cols} table format"
  • MCP tool registration via @server.tool() decorator on the handler function, with error handling and auth requirements.
    @server.tool()

Other Tools

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/ZatesloFL/google_workspace_mcp'

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