Skip to main content
Glama

run_sql_plus_plus_query

Execute SQL++ queries on Couchbase scopes to retrieve JSON data results for analysis and data access.

Instructions

Run a SQL++ query on a scope and return the results as a list of JSON objects.

The query will be run on the specified scope in the specified bucket.
The query should use collection names directly without bucket/scope prefixes, as the scope context is automatically set.

Example:
    query = "SELECT * FROM users WHERE age > 18"
    # Incorrect: "SELECT * FROM bucket.scope.users WHERE age > 18"

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bucket_nameYes
scope_nameYes
queryYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The handler function that executes the SQL++ query on the specified bucket and scope. Includes read-only mode validation using Lark parser to check for data/structure modifications, connects to the scope, runs the query, and returns results as list of dicts.
    def run_sql_plus_plus_query(
        ctx: Context, bucket_name: str, scope_name: str, query: str
    ) -> list[dict[str, Any]]:
        """Run a SQL++ query on a scope and return the results as a list of JSON objects.
    
        The query will be run on the specified scope in the specified bucket.
        The query should use collection names directly without bucket/scope prefixes, as the scope context is automatically set.
    
        Example:
            query = "SELECT * FROM users WHERE age > 18"
            # Incorrect: "SELECT * FROM bucket.scope.users WHERE age > 18"
        """
        cluster = get_cluster_connection(ctx)
    
        bucket = connect_to_bucket(cluster, bucket_name)
    
        app_context = ctx.request_context.lifespan_context
        read_only_query_mode = app_context.read_only_query_mode
        logger.info(f"Running SQL++ queries in read-only mode: {read_only_query_mode}")
    
        try:
            scope = bucket.scope(scope_name)
    
            results = []
            # If read-only mode is enabled, check if the query is a data or structure modification query
            if read_only_query_mode:
                parsed_query = parse_sqlpp(query)
                data_modification_query = modifies_data(parsed_query)
                structure_modification_query = modifies_structure(parsed_query)
    
                if data_modification_query:
                    logger.error("Data modification query is not allowed in read-only mode")
                    raise ValueError(
                        "Data modification query is not allowed in read-only mode"
                    )
                if structure_modification_query:
                    logger.error(
                        "Structure modification query is not allowed in read-only mode"
                    )
                    raise ValueError(
                        "Structure modification query is not allowed in read-only mode"
                    )
    
            # Run the query if it is not a data or structure modification query
            result = scope.query(query)
            for row in result:
                results.append(row)
            return results
        except Exception as e:
            logger.error(f"Error running query: {e!s}", exc_info=True)
            raise
  • Registers the run_sql_plus_plus_query tool (along with others) by adding functions from tools.ALL_TOOLS to the FastMCP server instance.
    # Register all tools
    for tool in ALL_TOOLS:
        mcp.add_tool(tool)
  • Imports the run_sql_plus_plus_query handler from query.py into the tools package, making it available for export and inclusion in ALL_TOOLS.
    # Query tools
    from .query import (
        get_longest_running_queries,
        get_most_frequent_queries,
        get_queries_not_selective,
        get_queries_not_using_covering_index,
        get_queries_using_primary_index,
        get_queries_with_large_result_count,
        get_queries_with_largest_response_sizes,
        get_schema_for_collection,
        run_sql_plus_plus_query,
    )
  • Includes run_sql_plus_plus_query in the ALL_TOOLS list used by mcp_server.py for registration with the MCP server.
    ALL_TOOLS = [
        get_buckets_in_cluster,
        get_server_configuration_status,
        test_cluster_connection,
        get_scopes_and_collections_in_bucket,
        get_collections_in_scope,
        get_scopes_in_bucket,
        get_document_by_id,
        upsert_document_by_id,
        delete_document_by_id,
        get_schema_for_collection,
        run_sql_plus_plus_query,
        get_index_advisor_recommendations,
        list_indexes,
        get_cluster_health_and_services,
        get_queries_not_selective,
        get_queries_not_using_covering_index,
        get_queries_using_primary_index,
        get_queries_with_large_result_count,
        get_queries_with_largest_response_sizes,
        get_longest_running_queries,
        get_most_frequent_queries,
    ]
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 of behavioral disclosure. It states the tool runs a query and returns results, but doesn't disclose critical behavioral traits such as whether this is a read-only or write operation (though 'run' implies execution, it could be read or write), authentication requirements, rate limits, error handling, or performance implications. The example clarifies syntax but doesn't address operational behavior.

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 appropriately sized and front-loaded: the first sentence clearly states the core purpose, followed by explanatory details and an example. Every sentence earns its place by clarifying scope usage and preventing common errors. No redundant or verbose language is present.

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

Completeness3/5

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

Given the tool's complexity (executing queries with potential read/write operations), no annotations, and an output schema (which handles return values), the description is moderately complete. It covers the basic purpose and query syntax but lacks behavioral context (e.g., safety, permissions) and full parameter semantics. The output schema mitigates some gaps, but for a tool with 3 parameters and no annotations, more guidance on usage and behavior would be beneficial.

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

Parameters4/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 adds meaningful context for the 'query' parameter by explaining that collection names should be used directly without bucket/scope prefixes and providing an example. However, it doesn't elaborate on 'bucket_name' or 'scope_name' parameters (e.g., what they represent, valid values). Since there are 3 parameters and the description partially covers one, it earns a 4 for adding value beyond the bare schema.

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 tool's purpose: 'Run a SQL++ query on a scope and return the results as a list of JSON objects.' It specifies the verb (run), resource (SQL++ query), and output format. However, it doesn't explicitly differentiate from sibling tools like 'get_longest_running_queries' or 'get_queries_with_largest_response_sizes' which are read-only query analysis tools, though the distinction is implied through the action-oriented nature.

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 provides implied usage guidance by specifying that queries should use collection names directly without bucket/scope prefixes, as scope context is automatically set. It includes an example to illustrate correct vs. incorrect usage. However, it lacks explicit when-to-use guidance compared to alternatives (e.g., when to use this vs. other query-related tools like 'get_queries_not_selective'), and doesn't 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/Couchbase-Ecosystem/mcp-server-couchbase'

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