Skip to main content
Glama
nolleh
by nolleh

execute_query

Run SQL queries against Vertica databases to retrieve data results. Supports optional database targeting for flexible query execution.

Instructions

Execute a SQL query and return the results.

Args:
    ctx: FastMCP context for progress reporting and logging
    query: SQL query to execute
    database: Optional database name to execute the query against

Returns:
    Query results as a string

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes

Implementation Reference

  • The `execute_query` tool is registered via the `@mcp.tool()` decorator on line 200, which makes it available as an MCP tool.
    @mcp.tool()
    async def execute_query(ctx: Context, query: str) -> str:
        """Execute a SQL query and return the results.
    
        Args:
            ctx: FastMCP context for progress reporting and logging
            query: SQL query to execute
            database: Optional database name to execute the query against
    
        Returns:
            Query results as a string
        """
        await ctx.info(f"Executing query: {query}")
    
        # Get or create connection manager
        manager = await get_or_create_manager(ctx)
        if not manager:
            return "Error: Failed to initialize database connection. Check configuration."
    
        # Extract schema from query if not provided
        schema = extract_schema_from_query(query)
        # Check operation permissions
        operation = extract_operation_type(query)
        if operation and not manager.is_operation_allowed(schema or "default", operation):
            error_msg = f"Operation {operation.name} not allowed for schema {schema}"
            await ctx.error(error_msg)
            return error_msg
    
        conn = None
        cursor = None
        try:
            conn = manager.get_connection()  # Always use default DB connection
            cursor = conn.cursor()
            cursor.execute(query)
            results = cursor.fetchall()
            await ctx.info(f"Query executed successfully, returned {len(results)} rows")
            return str(results)
        except Exception as e:
            error_msg = f"Error executing query: {str(e)}"
            await ctx.error(error_msg)
            return error_msg
        finally:
            if cursor:
                cursor.close()
            if conn:
                manager.release_connection(conn)
  • The `execute_query` function is the handler that executes a SQL query. It extracts the operation type and schema from the query, checks permissions, executes the query via the Vertica connection pool, fetches all results, and returns them as a string.
    @mcp.tool()
    async def execute_query(ctx: Context, query: str) -> str:
        """Execute a SQL query and return the results.
    
        Args:
            ctx: FastMCP context for progress reporting and logging
            query: SQL query to execute
            database: Optional database name to execute the query against
    
        Returns:
            Query results as a string
        """
        await ctx.info(f"Executing query: {query}")
    
        # Get or create connection manager
        manager = await get_or_create_manager(ctx)
        if not manager:
            return "Error: Failed to initialize database connection. Check configuration."
    
        # Extract schema from query if not provided
        schema = extract_schema_from_query(query)
        # Check operation permissions
        operation = extract_operation_type(query)
        if operation and not manager.is_operation_allowed(schema or "default", operation):
            error_msg = f"Operation {operation.name} not allowed for schema {schema}"
            await ctx.error(error_msg)
            return error_msg
    
        conn = None
        cursor = None
        try:
            conn = manager.get_connection()  # Always use default DB connection
            cursor = conn.cursor()
            cursor.execute(query)
            results = cursor.fetchall()
            await ctx.info(f"Query executed successfully, returned {len(results)} rows")
            return str(results)
        except Exception as e:
            error_msg = f"Error executing query: {str(e)}"
            await ctx.error(error_msg)
            return error_msg
        finally:
            if cursor:
                cursor.close()
            if conn:
                manager.release_connection(conn)
  • `extract_operation_type` helper used by `execute_query` to determine if the query is INSERT, UPDATE, DELETE, or DDL for permission checking.
    def extract_operation_type(query: str) -> OperationType | None:
        """Extract the operation type from a SQL query."""
        query = query.strip().upper()
    
        if query.startswith("INSERT"):
            return OperationType.INSERT
        elif query.startswith("UPDATE"):
            return OperationType.UPDATE
        elif query.startswith("DELETE"):
            return OperationType.DELETE
        elif any(query.startswith(op) for op in ["CREATE", "ALTER", "DROP", "TRUNCATE"]):
            return OperationType.DDL
        return None
  • `extract_schema_from_query` helper used by `execute_query` to parse the schema name from a fully-qualified table reference in the SQL query.
    def extract_schema_from_query(query: str) -> str | None:
        """Extract schema name from a SQL query."""
        # database.table 또는 schema.table 패턴에서 schema 추출
        match = re.search(r"([a-zA-Z0-9_]+)\.[a-zA-Z0-9_]+", query)
        if match:
            return match.group(1)
        return None
  • `is_operation_allowed` method on `VerticaConnectionManager` used by `execute_query` to check if a given operation type is permitted for the target schema.
    def is_operation_allowed(self, database: str, operation: OperationType) -> bool:
        """Check if an operation is allowed for a specific database."""
        if not self.config:
            return False
    
        # Get schema permissions
        schema_permissions = self.config.schema_permissions or {}
        schema_perms = schema_permissions.get(database)
    
        # Check schema-specific permissions first
        if schema_perms:
            if operation == OperationType.INSERT:
                return schema_perms.insert
            elif operation == OperationType.UPDATE:
                return schema_perms.update
            elif operation == OperationType.DELETE:
                return schema_perms.delete
            elif operation == OperationType.DDL:
                return schema_perms.ddl
    
        # Fall back to global permissions
        if operation == OperationType.INSERT:
            return self.config.allow_insert
        elif operation == OperationType.UPDATE:
            return self.config.allow_update
        elif operation == OperationType.DELETE:
            return self.config.allow_delete
        elif operation == OperationType.DDL:
            return self.config.allow_ddl
    
        return False
Behavior2/5

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

With no annotations, the description must disclose behavioral traits. It only states the action and return type, omitting crucial details such as whether the query is read-only, impacts on data, or required permissions.

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

Conciseness4/5

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

The description is reasonably concise with a clear structure (Args, Returns). The purpose sentence is front-loaded, and every sentence serves a purpose despite the parameter mismatch.

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 that there is no output schema and no annotations, the description is insufficient. It lacks details about error handling, supported SQL syntax, database selection, and whether the tool is safe for read-only queries.

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?

The description adds meaning for the 'query' parameter ('SQL query to execute'), but it also mentions 'ctx' and 'database' which are not in the input schema, causing confusion. Schema description coverage is 0%, so the description should compensate but instead introduces inconsistency.

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 'Execute a SQL query and return the results,' which is a specific verb and resource. However, the mention of parameters not present in the input schema (ctx, database) slightly reduces clarity.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus siblings like stream_query or copy_data. The description does not specify prerequisites or alternatives.

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/nolleh/mcp-vertica'

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