From 07dc887af2e509b6e1b453fd3a3eece339bafdc8 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Mon, 12 Jan 2026 09:29:09 +0000 Subject: [PATCH] Add MCP Tool Discovery Guide Comprehensive guide for discovering and using MCP Query endpoint tools: - Tool discovery via tools/list method - Complete list of all Query endpoint tools with parameters - cURL and Python examples for tool discovery and execution - Complete database exploration example - Test script usage guide --- doc/MCP/Tool_Discovery_Guide.md | 475 ++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 doc/MCP/Tool_Discovery_Guide.md diff --git a/doc/MCP/Tool_Discovery_Guide.md b/doc/MCP/Tool_Discovery_Guide.md new file mode 100644 index 000000000..aaa2f38ff --- /dev/null +++ b/doc/MCP/Tool_Discovery_Guide.md @@ -0,0 +1,475 @@ +# MCP Tool Discovery Guide + +This guide explains how to discover and interact with MCP tools available on the Query endpoint. + +## Overview + +The MCP (Model Context Protocol) Query endpoint provides dynamic tool discovery through the `tools/list` method. This allows clients to: + +1. Discover all available tools at runtime +2. Get detailed schemas for each tool (parameters, requirements, descriptions) +3. Dynamically adapt to new tools without code changes + +## Endpoint Information + +- **URL**: `https://127.0.0.1:6071/mcp/query` +- **Protocol**: JSON-RPC 2.0 over HTTPS +- **Authentication**: Bearer token (optional, if configured) + +## Getting the Tool List + +### Basic Request + +```bash +curl -k -X POST https://127.0.0.1:6071/mcp/query \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "tools/list", + "id": 1 + }' | jq +``` + +### With Authentication + +If authentication is configured: + +```bash +curl -k -X POST https://127.0.0.1:6071/mcp/query \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_TOKEN" \ + -d '{ + "jsonrpc": "2.0", + "method": "tools/list", + "id": 1 + }' | jq +``` + +### Using Query Parameter (Alternative) + +If header authentication is not available: + +```bash +curl -k -X POST "https://127.0.0.1:6071/mcp/query?token=YOUR_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "tools/list", + "id": 1 + }' | jq +``` + +## Response Format + +```json +{ + "id": "1", + "jsonrpc": "2.0", + "result": { + "tools": [ + { + "name": "tool_name", + "description": "Tool description", + "inputSchema": { + "type": "object", + "properties": { + "param_name": { + "type": "string|integer", + "description": "Parameter description" + } + }, + "required": ["param1", "param2"] + } + } + ] + } +} +``` + +## Available Query Endpoint Tools + +### Inventory Tools + +#### list_schemas +List all available schemas/databases. + +**Parameters:** +- `page_token` (string, optional) - Pagination token +- `page_size` (integer, optional) - Results per page (default: 50) + +#### list_tables +List tables in a schema. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `page_token` (string, optional) - Pagination token +- `page_size` (integer, optional) - Results per page (default: 50) +- `name_filter` (string, optional) - Filter table names by pattern + +### Structure Tools + +#### describe_table +Get detailed table schema including columns, types, keys, and indexes. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name + +#### get_constraints +Get constraints (foreign keys, unique constraints, etc.) for a table. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, optional) - Table name + +### Profiling Tools + +#### table_profile +Get table statistics including row count, size estimates, and data distribution. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name +- `mode` (string, optional) - Profile mode: "quick" or "full" (default: "quick") + +#### column_profile +Get column statistics including distinct values, null count, and top values. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name +- `column` (string, **required**) - Column name +- `max_top_values` (integer, optional) - Maximum top values to return (default: 20) + +### Sampling Tools + +#### sample_rows +Get sample rows from a table (with hard cap on rows returned). + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name +- `columns` (string, optional) - Comma-separated column names +- `where` (string, optional) - WHERE clause filter +- `order_by` (string, optional) - ORDER BY clause +- `limit` (integer, optional) - Maximum rows (default: 20) + +#### sample_distinct +Sample distinct values from a column. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name +- `column` (string, **required**) - Column name +- `where` (string, optional) - WHERE clause filter +- `limit` (integer, optional) - Maximum values (default: 50) + +### Query Tools + +#### run_sql_readonly +Execute a read-only SQL query with safety guardrails enforced. + +**Parameters:** +- `sql` (string, **required**) - SQL query to execute +- `max_rows` (integer, optional) - Maximum rows to return (default: 200) +- `timeout_sec` (integer, optional) - Query timeout (default: 2) + +**Safety rules:** +- Must start with SELECT +- No dangerous keywords (DROP, DELETE, INSERT, UPDATE, etc.) +- SELECT * requires LIMIT clause + +#### explain_sql +Explain a query execution plan using EXPLAIN or EXPLAIN ANALYZE. + +**Parameters:** +- `sql` (string, **required**) - SQL query to explain + +### Relationship Inference Tools + +#### suggest_joins +Suggest table joins based on heuristic analysis of column names and types. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table_a` (string, **required**) - First table +- `table_b` (string, optional) - Second table (if omitted, checks all) +- `max_candidates` (integer, optional) - Maximum join candidates (default: 5) + +#### find_reference_candidates +Find tables that might be referenced by a foreign key column. + +**Parameters:** +- `schema` (string, **required**) - Schema name +- `table` (string, **required**) - Table name +- `column` (string, **required**) - Column name +- `max_tables` (integer, optional) - Maximum tables to check (default: 50) + +### Catalog Tools (LLM Memory) + +#### catalog_upsert +Store or update an entry in the catalog (LLM external memory). + +**Parameters:** +- `kind` (string, **required**) - Entry kind (e.g., "table", "relationship", "insight") +- `key` (string, **required**) - Unique identifier +- `document` (string, **required**) - JSON document with data +- `tags` (string, optional) - Comma-separated tags +- `links` (string, optional) - Comma-separated related keys + +#### catalog_get +Retrieve an entry from the catalog. + +**Parameters:** +- `kind` (string, **required**) - Entry kind +- `key` (string, **required**) - Entry key + +#### catalog_search +Search the catalog for entries matching a query. + +**Parameters:** +- `query` (string, **required**) - Search query +- `kind` (string, optional) - Filter by kind +- `tags` (string, optional) - Filter by tags +- `limit` (integer, optional) - Maximum results (default: 20) +- `offset` (integer, optional) - Results offset (default: 0) + +#### catalog_list +List catalog entries by kind. + +**Parameters:** +- `kind` (string, optional) - Filter by kind +- `limit` (integer, optional) - Maximum results (default: 50) +- `offset` (integer, optional) - Results offset (default: 0) + +#### catalog_merge +Merge multiple catalog entries into a single consolidated entry. + +**Parameters:** +- `keys` (string, **required**) - Comma-separated keys to merge +- `target_key` (string, **required**) - Target key for merged entry +- `kind` (string, optional) - Entry kind (default: "domain") +- `instructions` (string, optional) - Merge instructions + +#### catalog_delete +Delete an entry from the catalog. + +**Parameters:** +- `kind` (string, **required**) - Entry kind +- `key` (string, **required**) - Entry key + +## Calling a Tool + +### Request Format + +```bash +curl -k -X POST https://127.0.0.1:6071/mcp/query \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "tools/call", + "params": { + "name": "list_tables", + "arguments": { + "schema": "testdb" + } + }, + "id": 2 + }' | jq +``` + +### Response Format + +```json +{ + "id": "2", + "jsonrpc": "2.0", + "result": { + "success": true, + "data": [...] + } +} +``` + +### Error Response + +```json +{ + "id": "2", + "jsonrpc": "2.0", + "result": { + "success": false, + "error": "Error message" + } +} +``` + +## Python Examples + +### Basic Tool Discovery + +```python +import requests +import json + +# Get tool list +response = requests.post( + "https://127.0.0.1:6071/mcp/query", + json={ + "jsonrpc": "2.0", + "method": "tools/list", + "id": 1 + }, + verify=False # For self-signed cert +) + +tools = response.json()["result"]["tools"] + +# Print all tools +for tool in tools: + print(f"\n{tool['name']}") + print(f" Description: {tool['description']}") + print(f" Required: {tool['inputSchema'].get('required', [])}") +``` + +### Calling a Tool + +```python +def call_tool(tool_name, arguments): + response = requests.post( + "https://127.0.0.1:6071/mcp/query", + json={ + "jsonrpc": "2.0", + "method": "tools/call", + "params": { + "name": tool_name, + "arguments": arguments + }, + "id": 2 + }, + verify=False + ) + return response.json()["result"] + +# List tables +result = call_tool("list_tables", {"schema": "testdb"}) +print(json.dumps(result, indent=2)) + +# Describe a table +result = call_tool("describe_table", { + "schema": "testdb", + "table": "customers" +}) +print(json.dumps(result, indent=2)) + +# Run a query +result = call_tool("run_sql_readonly", { + "sql": "SELECT * FROM customers LIMIT 10" +}) +print(json.dumps(result, indent=2)) +``` + +### Complete Example: Database Discovery + +```python +import requests +import json + +class MCPQueryClient: + def __init__(self, host="127.0.0.1", port=6071, token=None): + self.url = f"https://{host}:{port}/mcp/query" + self.headers = { + "Content-Type": "application/json", + **({"Authorization": f"Bearer {token}"} if token else {}) + } + + def list_tools(self): + response = requests.post( + self.url, + json={"jsonrpc": "2.0", "method": "tools/list", "id": 1}, + headers=self.headers, + verify=False + ) + return response.json()["result"]["tools"] + + def call_tool(self, name, arguments): + response = requests.post( + self.url, + json={ + "jsonrpc": "2.0", + "method": "tools/call", + "params": {"name": name, "arguments": arguments}, + "id": 2 + }, + headers=self.headers, + verify=False + ) + return response.json()["result"] + + def explore_schema(self, schema): + """Explore a schema: list tables and their structures""" + print(f"\n=== Exploring schema: {schema} ===\n") + + # List tables + tables = self.call_tool("list_tables", {"schema": schema}) + for table in tables.get("data", []): + table_name = table["name"] + print(f"\nTable: {table_name}") + print(f" Type: {table['type']}") + print(f" Rows: {table.get('row_count', 'unknown')}") + + # Describe table + schema_info = self.call_tool("describe_table", { + "schema": schema, + "table": table_name + }) + + if schema_info.get("success"): + print(f" Columns: {', '.join([c['name'] for c in schema_info['data']['columns']])}") + +# Usage +client = MCPQueryClient() +client.explore_schema("testdb") +``` + +## Using the Test Script + +The test script provides a convenient way to discover and test tools: + +```bash +# List all discovered tools (without testing) +./scripts/mcp/test_mcp_tools.sh --list-only + +# Test only query endpoint +./scripts/mcp/test_mcp_tools.sh --endpoint query + +# Test specific tool with verbose output +./scripts/mcp/test_mcp_tools.sh --endpoint query --tool list_tables -v + +# Test all endpoints +./scripts/mcp/test_mcp_tools.sh +``` + +## Other Endpoints + +The same discovery pattern works for all MCP endpoints: + +- **Config**: `/mcp/config` - Configuration management tools +- **Query**: `/mcp/query` - Database exploration and query tools +- **Admin**: `/mcp/admin` - Administrative operations +- **Cache**: `/mcp/cache` - Cache management tools +- **Observe**: `/mcp/observe` - Monitoring and metrics tools + +Simply change the endpoint URL: + +```bash +curl -k -X POST https://127.0.0.1:6071/mcp/config \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}' +``` + +## Related Documentation + +- [Architecture.md](Architecture.md) - Overall MCP architecture +- [Database_Discovery_Agent.md](Database_Discovery_Agent.md) - AI agent architecture +- [README.md](README.md) - Module overview