Skip to content

Conversation

tuannvm
Copy link
Owner

@tuannvm tuannvm commented Aug 20, 2025

Summary by CodeRabbit

  • New Features

    • Added explain_query MCP tool to analyze Trino query execution plans (optional format: LOGICAL, DISTRIBUTED, VALIDATE, IO).
    • Tool handlers gain optional OAuth middleware support for authenticated tool execution.
  • Documentation

    • Updated MCP Tools diagram and added an explain_query section with sample prompt, request/response example, and an End-to-End Example.
    • Enhanced descriptions and parameter details for existing tools; show_table_stats remains unchanged.

Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
Copy link

coderabbitai bot commented Aug 20, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Adds an explain_query MCP tool and documentation, implements TrinoHandlers.ExplainQuery and Client.ExplainQuery, updates tool registrations to optionally apply OAuth middleware, and formats explain results as indented JSON text. No public API breaking changes detected.

Changes

Cohort / File(s) Summary
Documentation: MCP tools
README.md
Added dedicated explain_query docs (purpose, sample prompt, example request/response JSON, End-to-End example) and updated MCP Tools diagram to include explain_query.
MCP handlers and tool registration
internal/mcp/handlers.go
Added TrinoHandlers.ExplainQuery; register explain_query tool with parameters (query required, format optional); integrated optional OAuth middleware via GetOAuthMiddleware and applyMiddleware; handlers marshal results with json.MarshalIndent and return text.
Trino client methods
internal/trino/client.go
Added func (c *Client) ExplainQuery(query string, format string) ([]map[string]interface{}, error) which validates allowed EXPLAIN formats (LOGICAL, DISTRIBUTED, VALIDATE, IO), constructs EXPLAIN statement, and executes it returning rows.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant MCP as MCP Server
  participant H as TrinoHandlers
  participant M as OAuthMiddleware (optional)
  participant C as TrinoClient
  participant DB as Trino

  rect rgb(240,248,255)
    note over User,MCP: explain_query flow
    User->>MCP: callTool(explain_query, {query, format?})
    MCP->>H: invoke handler
    alt OAuth enabled
      H->>M: apply middleware -> handler
      M->>H: authenticated call
    end
    H->>C: ExplainQuery(query, format?)
    C->>DB: EXPLAIN [TYPE <FORMAT>] <query>
    DB-->>C: plan rows
    C-->>H: []map[string]interface{}
    H-->>MCP: CallToolResult{text: JSON(plan)}
    MCP-->>User: result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Feat/additional tools #85 — Adds an ExplainQuery handler and Client.ExplainQuery implementation (overlaps on explain functionality; that PR also includes ShowTableStats).

Poem

I nibble docs and trace each plan,
EXPLAIN reveals the path I scan.
I hop through schemas, formats I pick,
A rabbit’s glance makes queries quick. 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f35e7c2 and 206b4e9.

📒 Files selected for processing (3)
  • README.md (2 hunks)
  • internal/mcp/handlers.go (2 hunks)
  • internal/trino/client.go (3 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/additional-tools

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/trino/client.go (1)

131-136: Log a warning when write queries are allowed (per guidelines).

When TRINO_ALLOW_WRITE_QUERIES=true (c.config.AllowWriteQueries), the client must log a warning before executing non-read-only queries. This is currently missing.

Apply this diff to add the warning while avoiding duplicate isReadOnly checks:

-	// SQL injection protection: only allow read-only queries unless explicitly allowed in config
-	if !c.config.AllowWriteQueries && !isReadOnlyQuery(query) {
+	// SQL injection protection: only allow read-only queries unless explicitly allowed in config
+	isRO := isReadOnlyQuery(query)
+	if !c.config.AllowWriteQueries && !isRO {
 		return nil, fmt.Errorf("security restriction: only SELECT, SHOW, DESCRIBE, and EXPLAIN queries are allowed. " +
 			"Set TRINO_ALLOW_WRITE_QUERIES=true to enable write operations (at your own risk)")
 	}
+	if c.config.AllowWriteQueries && !isRO {
+		log.Printf("WARNING: executing non-read-only query with TRINO_ALLOW_WRITE_QUERIES=true. Proceed with caution.")
+	}
🧹 Nitpick comments (4)
internal/trino/client.go (1)

300-322: Optional hardening: quote identifiers in SHOW STATS table reference.

Currently table identifiers are interpolated directly. While we restrict to read-only statements, defensive quoting of identifiers (catalog/schema/table parts) avoids malformed identifiers or accidental token injection.

Consider a helper like:

  • Split the fully-qualified name into parts, escape embedded double quotes by doubling them, wrap each with ".

Example inside this method:

  • For 3 parts: SHOW STATS FOR "cat"."sch"."tbl"
  • For 2 parts: SHOW STATS FOR "cat".<parts[0]>."<parts[1]>"
  • For 1 part: SHOW STATS FOR "cat"."sch"."tbl"

I can draft a small quoteIdent helper if you want to proceed.

README.md (1)

586-675: Doc-response shape likely does not match actual server output for EXPLAIN.

Handlers/client return raw rows/columns from Trino (marshaled JSON), typically a single text column "Query Plan" for EXPLAIN/EXPLAIN (TYPE DISTRIBUTED). The documented response under explain_query shows a structured execution_plan array with stages/operations, which the code does not produce.

Please either:

  • Update the docs to reflect the actual raw EXPLAIN output (e.g., {"columns":["Query Plan"], "data":[["Fragment 0 ...\n..."]]}), or
  • Enhance the handler to parse Trino’s plan text into the documented structured execution_plan.

Additionally, the parameter description says “DISTRIBUTED (default)”. With current code, default is Trino’s LOGICAL plan unless a format is provided. Align the description after deciding on code behavior. I can prepare a doc update patch once you decide.

internal/mcp/handlers.go (2)

197-236: Minor validation hardening: reject empty query strings.

The handler checks type but not emptiness. Empty/whitespace-only queries will produce avoidable errors downstream.

Add a trim/emptiness check after extracting query:

  • If empty, return a tool error “query parameter must not be empty”.

I can provide a small patch (will require adding strings import) if you want it in this PR.


238-282: Minor validation hardening: reject empty table names.

Similarly, validate the required table parameter for emptiness after type assertion to avoid downstream SQL errors.

Add a whitespace trim and ensure non-empty before proceeding. I can send a small patch (will require strings import).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0455cd0 and 9c162c9.

📒 Files selected for processing (3)
  • README.md (2 hunks)
  • internal/mcp/handlers.go (2 hunks)
  • internal/trino/client.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/trino/client.go

📄 CodeRabbit Inference Engine (CLAUDE.md)

internal/trino/client.go: The client layer in internal/trino/client.go must manage database connections with pooling, enforce SQL injection protection via read-only query enforcement, handle context-based timeouts for queries, and process/format query results.
The isReadOnlyQuery() function in internal/trino/client.go must allow only SELECT, SHOW, DESCRIBE, EXPLAIN, and WITH (CTEs) queries by default, blocking INSERT, UPDATE, DELETE, CREATE, DROP, and ALTER unless TRINO_ALLOW_WRITE_QUERIES=true is set, in which case a warning must be logged.
The connection pool must be configured with a maximum of 10 open connections, 5 max idle connections, and a 5-minute maximum lifetime.

Files:

  • internal/trino/client.go
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : The handler layer in internal/handlers/trino_handlers.go must implement MCP tools with JSON response formatting, parameter validation, error handling, consistent logging, and tool result standardization.
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : The handler layer in internal/handlers/trino_handlers.go must implement MCP tools with JSON response formatting, parameter validation, error handling, consistent logging, and tool result standardization.

Applied to files:

  • internal/mcp/handlers.go
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : All MCP tool endpoints (execute_query, list_catalogs, list_schemas, list_tables, get_table_schema) must return JSON-formatted responses and handle parameter validation.

Applied to files:

  • internal/mcp/handlers.go
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : All MCP tool endpoints must handle parameter validation and error handling consistently.

Applied to files:

  • internal/mcp/handlers.go
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : Tool result standardization must be enforced in handler responses.

Applied to files:

  • internal/mcp/handlers.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build Verification
🔇 Additional comments (2)
README.md (1)

45-45: Diagram update looks good.

Tools list includes the two new entries and remains consistent with the rest of the doc.

internal/mcp/handlers.go (1)

326-331: I need to inspect the ExplainQuery handler implementation to verify the actual default and accepted format values. Let me run a quick search in internal/mcp/handlers.go to see how "format" is parsed and what defaults are applied.

Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
internal/mcp/handlers.go (1)

308-311: Resolved: Schema-browsing description now matches behavior (single catalog).

This addresses the earlier review about “all catalogs” wording. Thanks for fixing.

🧹 Nitpick comments (5)
internal/mcp/handlers.go (5)

197-236: Validate format against allowed values in ExplainQuery.

Prevent avoidable round-trips by rejecting invalid plan types early.

Apply this diff inside ExplainQuery to validate format:

   // Extract optional format parameter
   var format string
   if formatParam, ok := args["format"].(string); ok {
     format = formatParam
   }
 
+  // Validate format value (if provided)
+  if format != "" {
+    switch format {
+    case "LOGICAL", "DISTRIBUTED", "VALIDATE", "IO":
+      // ok
+    default:
+      mcpErr := fmt.Errorf("invalid format %q; must be one of LOGICAL, DISTRIBUTED, VALIDATE, IO", format)
+      return mcp.NewToolResultErrorFromErr(mcpErr.Error(), mcpErr), nil
+    }
+  }
 
   // Execute the explain query
   results, err := h.TrinoClient.ExplainQuery(query, format)

228-236: Optional: Standardize tool responses with a simple envelope.

You currently return raw JSON for each tool. For consistency across tools and to make future evolution easier, consider a small envelope like {"data": ...}. This aligns with the “tool result standardization” preference in prior guidance.

Outside this block, you could add:

type toolResponse struct {
  Data any `json:"data"`
}

And replace:

  • json.MarshalIndent(results, "", " ")
    with:
  • json.MarshalIndent(toolResponse{Data: results}, "", " ")

241-246: Minor: Factor out repeated argument parsing.

The map assertion + error pattern is repeated across handlers. A tiny helper reduces duplication and keeps error messages consistent.

Example helper (place at package level):

func parseArgs(req mcp.CallToolRequest) (map[string]interface{}, error) {
  args, ok := req.Params.Arguments.(map[string]interface{})
  if !ok {
    return nil, fmt.Errorf("invalid arguments format: got %T", req.Params.Arguments)
  }
  return args, nil
}

Then replace this block with:

args, err := parseArgs(request)
if err != nil {
  return mcp.NewToolResultErrorFromErr(err.Error(), err), nil
}

300-304: Nit: Clarify overlap between execute_query and explain_query.

Since a dedicated explain_query tool now exists, hint users to prefer it for plan analysis.

-    mcp.WithDescription("Execute SQL queries on Trino's fast distributed query engine for big data analytics. Run SELECT, SHOW, DESCRIBE, EXPLAIN statements across multiple data sources simultaneously. Perfect for complex analytics, aggregations, joins, and cross-system data exploration on large datasets."),
+    mcp.WithDescription("Execute SQL queries on Trino's fast distributed query engine for big data analytics. Run SELECT, SHOW, DESCRIBE, EXPLAIN statements across multiple data sources simultaneously. Perfect for complex analytics, aggregations, joins, and cross-system data exploration on large datasets. For plan analysis without execution, prefer the `explain_query` tool."),

314-317: Align list_tables description with actual scoping behavior.

“Browse all available data across the distributed system” over-promises; the handler lists tables for one catalog/schema (with optional defaults).

-    mcp.WithDescription("Discover tables and views available for querying in Trino schemas. Essential for finding datasets to analyze. Can scope to specific catalog/schema or browse all available data across the distributed system."),
-    mcp.WithString("catalog", mcp.Description("Trino catalog name (optional)")),
-    mcp.WithString("schema", mcp.Description("Schema name within catalog (optional)"))),
+    mcp.WithDescription("Discover tables and views available for querying in Trino schemas. Essential for finding datasets to analyze. Scope to a specific catalog/schema; if omitted, the server default(s) are used."),
+    mcp.WithString("catalog", mcp.Description("Trino catalog name (optional; defaults to server configuration if omitted)")),
+    mcp.WithString("schema", mcp.Description("Schema name within catalog (optional; defaults to server configuration if omitted)"))),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9c162c9 and f35e7c2.

📒 Files selected for processing (2)
  • internal/mcp/handlers.go (2 hunks)
  • internal/trino/client.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/trino/client.go
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : The handler layer in internal/handlers/trino_handlers.go must implement MCP tools with JSON response formatting, parameter validation, error handling, consistent logging, and tool result standardization.
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : The handler layer in internal/handlers/trino_handlers.go must implement MCP tools with JSON response formatting, parameter validation, error handling, consistent logging, and tool result standardization.

Applied to files:

  • internal/mcp/handlers.go
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : All MCP tool endpoints (execute_query, list_catalogs, list_schemas, list_tables, get_table_schema) must return JSON-formatted responses and handle parameter validation.

Applied to files:

  • internal/mcp/handlers.go
📚 Learning: 2025-07-25T23:51:10.585Z
Learnt from: CR
PR: tuannvm/mcp-trino#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-25T23:51:10.585Z
Learning: Applies to internal/handlers/trino_handlers.go : All MCP tool endpoints must handle parameter validation and error handling consistently.

Applied to files:

  • internal/mcp/handlers.go
🧬 Code Graph Analysis (1)
internal/mcp/handlers.go (1)
internal/mcp/server.go (1)
  • createMCPServer (50-69)
🔇 Additional comments (9)
internal/mcp/handlers.go (9)

259-266: LGTM: Required table parameter is enforced correctly.

Clear validation with an actionable error; consistent with other handlers.


267-276: LGTM: Client call and error handling look consistent.

Logs, wraps, and returns MCP error results in the expected format.


305-305: LGTM: list_catalogs description is clear and user-friendly.


320-324: LGTM: get_table_schema parameters and descriptions are precise.


326-331: LGTM: explain_query tool registration is comprehensive.

Parameters and description match the handler; enumeration listed for format.


332-337: LGTM: show_table_stats tool registration is clear and aligned with handler.


220-225: TrinoClient.ExplainQuery signature verified

The ExplainQuery(query string, format string) ([]map[string]interface{}, error) method is defined on *Client in internal/trino/client.go:289. No changes needed.


267-272: ShowTableStats client method confirmed.
The ShowTableStats(catalog, schema, table) method is implemented in internal/trino/client.go:306, with signature

func (c *Client) ShowTableStats(catalog, schema, table string) ([]map[string]interface{}, error)

This return type is natively JSON-marshalable. No changes needed.


286-298: OAuth middleware hook correctly implemented

Verified that GetOAuthMiddleware is defined in internal/mcp/server.go and returns

func(*server.MCPServer) func(server.ToolHandlerFunc) server.ToolHandlerFunc

which matches the expected signature. No further changes required.

…ation

Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
Signed-off-by: Tommy Nguyen <tuannvm@hotmail.com>
@tuannvm tuannvm merged commit 0133f1d into main Aug 20, 2025
6 of 7 checks passed
@tuannvm tuannvm deleted the feat/additional-tools branch August 20, 2025 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant