From 62820b6640f8b8a46eb4447faff6ff6c3403db7a Mon Sep 17 00:00:00 2001 From: triepod-ai Date: Tue, 23 Dec 2025 08:37:01 -0600 Subject: [PATCH] feat: Add tool annotations for improved LLM tool understanding Add readOnlyHint and destructiveHint annotations to all MCP tools to help LLMs better understand tool behavior and make safer decisions. Changes: - Added readOnlyHint: true to listTables (read-only query) - Added readOnlyHint: true to describeTable (read-only schema lookup) - Added destructiveHint: true to executeQuery (can execute INSERT/UPDATE/DELETE) - Added title annotations for human-readable display This improves tool safety metadata for MCP clients like Claude Code, which can auto-approve read-only tools and prompt for confirmation on destructive operations. Co-Authored-By: Claude --- controller/llm.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/controller/llm.go b/controller/llm.go index 684bea4..6fe4ea0 100644 --- a/controller/llm.go +++ b/controller/llm.go @@ -671,7 +671,11 @@ func Mcp(cmd *cobra.Command, args []string) error { s := server.NewMCPServer("Anyquery", "0.1.0") // Create the MCP server - tool := mcp.NewTool("listTables", mcp.WithDescription("Lists all the tables available. When the user requests data, or wants an action (insert/update/delete), call this endpoint to check if a table corresponds to the user's request.")) + tool := mcp.NewTool("listTables", + mcp.WithDescription("Lists all the tables available. When the user requests data, or wants an action (insert/update/delete), call this endpoint to check if a table corresponds to the user's request."), + mcp.WithTitleAnnotation("List Tables"), + mcp.WithReadOnlyHintAnnotation(true), + ) s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { if authEnabled { @@ -697,7 +701,10 @@ func Mcp(cmd *cobra.Command, args []string) error { tool = mcp.NewTool("describeTable", mcp.WithDescription("Describes a table. It returns the columns of the table, the supported operations, and the SQL examples. Before calling executeQuery, you must call this endpoint for each table you want to interact with."), - mcp.WithString("tableName", mcp.Required(), mcp.Description("The name of the table to describe"))) + mcp.WithTitleAnnotation("Describe Table"), + mcp.WithReadOnlyHintAnnotation(true), + mcp.WithString("tableName", mcp.Required(), mcp.Description("The name of the table to describe")), + ) s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { if authEnabled { @@ -788,7 +795,10 @@ To install Anyquery, the user must follow the tutorial at https://anyquery.dev/d By default, Anyquery does not have any integrations. The user must visit https://anyquery.dev/integrations to find some integrations they might like and follow the instructions to add them. `), - mcp.WithString("query", mcp.Required(), mcp.Description("The SQL query to execute"))) + mcp.WithTitleAnnotation("Execute Query"), + mcp.WithDestructiveHintAnnotation(true), + mcp.WithString("query", mcp.Required(), mcp.Description("The SQL query to execute")), + ) s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { if authEnabled { suppliedToken := request.Header.Get("Authorization")