Skip to main content
Glama
samhavens

Databricks MCP Server

by samhavens

execute_sql

Execute SQL statements on Databricks to query data, run analytics, and manage databases through direct SQL execution with completion waiting.

Instructions

Execute a SQL statement and wait for completion (blocking)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
statementYes
warehouse_idYes
catalogNo
schema_nameNo

Implementation Reference

  • The main MCP tool handler for 'execute_sql'. Registers the tool via @mcp.tool() decorator and implements the logic by calling the sql.execute_and_wait helper, handling errors, and returning JSON.
    @mcp.tool()
    async def execute_sql(
        statement: str,
        warehouse_id: str,
        catalog: Optional[str] = None,
        schema_name: Optional[str] = None
    ) -> str:
        """Execute a SQL statement and wait for completion (blocking)"""
        logger.info(f"Executing SQL statement (blocking): {statement[:100]}...")
        try:
            result = await sql.execute_and_wait(
                statement=statement,
                warehouse_id=warehouse_id, 
                catalog=catalog,
                schema=schema_name,
                timeout_seconds=300  # 5 minutes max
            )
            return json.dumps(result)
        except Exception as e:
            logger.error(f"Error executing SQL: {str(e)}")
            return json.dumps({"error": str(e)})
  • Helper function that starts SQL execution using execute_statement and polls the status until completion or timeout. This is the core blocking SQL execution logic used by the tool handler.
    async def execute_and_wait(
        statement: str,
        warehouse_id: str,
        catalog: Optional[str] = None,
        schema: Optional[str] = None,
        parameters: Optional[Dict[str, Any]] = None,
        timeout_seconds: int = 300,  # 5 minutes
        poll_interval_seconds: int = 1,
    ) -> Dict[str, Any]:
        """
        Execute a SQL statement and wait for completion.
        
        Args:
            statement: The SQL statement to execute
            warehouse_id: ID of the SQL warehouse to use
            catalog: Optional catalog to use
            schema: Optional schema to use
            parameters: Optional statement parameters
            timeout_seconds: Maximum time to wait for completion
            poll_interval_seconds: How often to poll for status
            
        Returns:
            Response containing query results
            
        Raises:
            DatabricksAPIError: If the API request fails
            TimeoutError: If query execution times out
        """
        import asyncio
        import time
        
        logger.info(f"Executing SQL statement with waiting: {statement[:100]}...")
        
        # Start execution
        response = await execute_statement(
            statement=statement,
            warehouse_id=warehouse_id,
            catalog=catalog,
            schema=schema,
            parameters=parameters,
        )
        
        statement_id = response.get("statement_id")
        if not statement_id:
            raise ValueError("No statement_id returned from execution")
        
        # Poll for completion
        start_time = time.time()
        status = response.get("status", {}).get("state", "")
        
        while status in ["PENDING", "RUNNING"]:
            # Check timeout
            if time.time() - start_time > timeout_seconds:
                raise TimeoutError(f"Query execution timed out after {timeout_seconds} seconds")
            
            # Wait before polling again
            await asyncio.sleep(poll_interval_seconds)
            
            # Check status
            status_response = await get_statement_status(statement_id)
            status = status_response.get("status", {}).get("state", "")
            
            if status == "SUCCEEDED":
                return status_response
            elif status in ["FAILED", "CANCELED", "CLOSED"]:
                error_message = status_response.get("status", {}).get("error", {}).get("message", "Unknown error")
                raise DatabricksAPIError(f"Query execution failed: {error_message}", response=status_response)
        
        return response
  • Low-level helper that submits the SQL statement to Databricks SQL API (tries classic endpoint first, falls back to newer), used by execute_and_wait.
    async def execute_statement(
        statement: str,
        warehouse_id: str,
        catalog: Optional[str] = None,
        schema: Optional[str] = None,
        parameters: Optional[Dict[str, Any]] = None,
        row_limit: int = 10000,
        byte_limit: int = 26214400,  # 25MB max allowed
    ) -> Dict[str, Any]:
        """
        Execute a SQL statement.
        
        Args:
            statement: The SQL statement to execute
            warehouse_id: ID of the SQL warehouse to use
            catalog: Optional catalog to use
            schema: Optional schema to use
            parameters: Optional statement parameters
            row_limit: Maximum number of rows to return
            byte_limit: Maximum number of bytes to return
            
        Returns:
            Response containing query results
            
        Raises:
            DatabricksAPIError: If the API request fails
        """
        logger.info(f"Executing SQL statement: {statement[:100]}...")
        
        request_data = {
            "statement": statement,
            "warehouse_id": warehouse_id,
            "wait_timeout": "0s",  # Return immediately, don't wait
            "row_limit": row_limit,
            "byte_limit": byte_limit,
        }
        
        if catalog:
            request_data["catalog"] = catalog
            
        if schema:
            request_data["schema"] = schema
            
        if parameters:
            request_data["parameters"] = parameters
            
        # Try the classic SQL API first (works on most workspaces)
        try:
            return make_api_request("POST", "/api/2.0/sql/statements", data=request_data)
        except Exception as e:
            # If that fails, try the newer SQL execution API
            logger.warning(f"Classic SQL API failed: {e}. Trying newer SQL execution API...")
            return make_api_request("POST", "/api/2.0/sql/statements/execute", data=request_data)
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the blocking behavior, which is useful, but lacks critical details such as permissions required, potential side effects (e.g., data modification), error handling, or performance implications. For a tool that executes SQL statements, this is a significant gap in behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action ('Execute a SQL statement') and adds essential behavioral detail ('wait for completion (blocking)'). There is no wasted verbiage, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of executing SQL (potentially involving data mutation, permissions, and performance), no annotations, no output schema, and low parameter semantics, the description is incomplete. It lacks details on return values, error cases, and the broader context of SQL execution in this environment, making it insufficient for safe and effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It mentions 'SQL statement' which relates to the 'statement' parameter, but doesn't explain the purpose of 'warehouse_id', 'catalog', or 'schema_name', nor does it provide any syntax or format guidance. With 4 parameters and no schema descriptions, this is inadequate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Execute a SQL statement') and specifies the blocking behavior ('wait for completion'), which distinguishes it from the sibling 'execute_sql_nonblocking'. However, it doesn't specify the resource or context (e.g., database, warehouse) beyond what's implied by the tool name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by mentioning 'blocking', which suggests this tool should be used when waiting for SQL execution completion is required, as opposed to the non-blocking sibling. However, it doesn't explicitly state when to use this versus alternatives like 'execute_sql_nonblocking' or other SQL-related tools, nor does it mention prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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/samhavens/databricks-mcp-server'

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