You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/scripts/mcp
Rene Cannao 28742554b5
Use relative catalog path instead of absolute path
1 month ago
..
README.md Use relative catalog path instead of absolute path 1 month ago
configure_mcp.sh Use relative catalog path instead of absolute path 1 month ago
init_testdb.sql Fix argument parsing and documentation in setup_test_db.sh 1 month ago
setup_test_db.sh Fix argument parsing and documentation in setup_test_db.sh 1 month ago
stress_test.sh Add comprehensive MCP testing suite in scripts/mcp/ 1 month ago
test_catalog.sh Add comprehensive MCP testing suite in scripts/mcp/ 1 month ago
test_mcp_tools.sh Add comprehensive MCP testing suite in scripts/mcp/ 1 month ago

README.md

MCP Module Testing Suite

This directory contains scripts to test the ProxySQL MCP (Model Context Protocol) module with MySQL connection pool and exploration tools.

Table of Contents

  1. Architecture Overview
  2. Components
  3. Testing Flow
  4. Quick Start (Copy/Paste)
  5. Detailed Documentation
  6. Troubleshooting

Architecture Overview

What is MCP?

MCP (Model Context Protocol) is a JSON-RPC 2.0 protocol that allows AI/LLM applications to:

  • Discover database schemas (list tables, describe columns, view relationships)
  • Explore data safely (sample rows, run read-only queries with guardrails)
  • Remember discoveries in an external catalog (SQLite-based memory for LLM)

Component Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                         ProxySQL MCP Module                        │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │         ProxySQL Admin Interface (Port 6032)                 │   │
│  │   Configure: mcp-enabled, mcp-mysql_hosts, mcp-port, etc.    │   │
│  └──────────────────────────┬──────────────────────────────────┘   │
│                             │                                       │
│  ┌──────────────────────────▼──────────────────────────────────┐   │
│  │         MCP HTTPS Server (Port 6071)                       │   │
│  │                                                              │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │   │
│  │  │   /config   │  │   /query    │  │    /admin   │       │   │
│  │  │   endpoint  │  │   endpoint  │  │   endpoint  │       │   │
│  │  └──────┬──────┘  └──────┬──────┘  └─────────────┘       │   │
│  └─────────┼─────────────────┼─────────────────────────────────┘   │
│            │                 │                                       │
│  ┌─────────▼─────────────────▼─────────────────────────────────┐   │
│  │              MySQL_Tool_Handler                               │   │
│  │   ┌─────────────────────────────────────────────────────┐   │   │
│  │   │         MySQL Connection Pool                         │   │   │
│  │   │   ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐                   │   │   │
│  │   │   │Conn1│ │Conn2│ │Conn3│ │ ... │ (to MySQL)         │   │   │
│  │   │   └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘                   │   │   │
│  │   │      └──────┴──────┴──────┴──────┘                    │   │   │
│  │   └─────────────────────────────────────────────────────┘   │   │
│  │                                                              │   │
│  │   Tool Methods:                                             │   │
│  │   • list_schemas, list_tables, describe_table              │   │
│  │   • sample_rows, sample_distinct, run_sql_readonly         │   │
│  │   • catalog_upsert, catalog_get, catalog_search            │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │              MySQL_Catalog (SQLite Memory)                  │   │
│  │   • LLM discoveries catalog (FTS searchable)                │   │
│  │   • Tables: catalog_entries, catalog_links                 │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    MySQL Server (Port 3306)                          │
│                    • Test Database: testdb                          │
│                    • Tables: customers, orders, products, etc.       │
└──────────────────────────────────────────────────────────────────────┘

MCP Tools Available

Category Tools Purpose
Inventory list_schemas, list_tables Discover available databases and tables
Structure describe_table, get_constraints Get schema details (columns, keys, indexes)
Sampling sample_rows, sample_distinct Sample data safely with row limits
Query run_sql_readonly, explain_sql Execute SELECT queries with guardrails
Catalog catalog_upsert, catalog_get, catalog_search Store/retrieve LLM discoveries

Components

1. ProxySQL MCP Module

Location: Built into ProxySQL (lib/MCP_*.cpp)

Purpose: Exposes HTTPS endpoints that implement JSON-RPC 2.0 protocol for LLM integration.

Key Configuration Variables:

Variable Default Description
mcp-enabled false Enable/disable MCP server
mcp-port 6071 HTTPS port for MCP endpoints
mcp-mysql_hosts 127.0.0.1 MySQL server(s) for tool execution
mcp-mysql_ports 3306 MySQL port(s)
mcp-mysql_user (empty) MySQL username for connections
mcp-mysql_password (empty) MySQL password
mcp-mysql_schema (empty) Default schema for queries
mcp-catalog_path mcp_catalog.db SQLite catalog database path (relative to datadir)

Endpoints:

  • POST https://localhost:6071/config - Initialize, ping, tools/list
  • POST https://localhost:6071/query - Execute tools (tools/call)

2. MySQL Connection Pool

Location: lib/MySQL_Tool_Handler.cpp

Purpose: Manages reusable connections to backend MySQL servers for tool execution.

Features:

  • Thread-safe connection pooling with pthread_mutex_t
  • One connection per configured host:port pair
  • Automatic connection on first use
  • 5-second timeouts for connect/read/write operations

3. MySQL Catalog (LLM Memory)

Location: lib/MySQL_Catalog.cpp

Purpose: External memory for LLM to store discoveries with full-text search.

Features:

  • SQLite-based storage (mcp_catalog.db)
  • Full-text search (FTS) on document content
  • Link tracking between related entries
  • Entry kinds: table, domain, column, relationship, pattern

4. Test Scripts

Script Purpose What it Does
setup_test_db.sh Database setup Creates test MySQL database with sample data (customers, orders, products)
configure_mcp.sh ProxySQL configuration Sets MCP variables and loads to runtime
test_mcp_tools.sh Tool testing Tests all 15 MCP tools via JSON-RPC
test_catalog.sh Catalog testing Tests catalog CRUD and FTS search
stress_test.sh Load testing Concurrent connection stress test

Testing Flow

┌─────────────────────────────────────────────────────────────────────┐
│ Step 1: Setup Test Database                                        │
│ ─────────────────────────────────────────────────────────────────  │
│ ./setup_test_db.sh start --mode native                             │
│                                                                      │
│ → Creates 'testdb' database on your MySQL server                    │
│ → Creates tables: customers, orders, products, order_items          │
│ → Inserts sample data (5 customers, 5 products, 5 orders)           │
│ → Creates view: customer_orders                                     │
│ → Creates stored procedure: get_customer_stats                      │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Step 2: Configure ProxySQL MCP Module                               │
│ ─────────────────────────────────────────────────────────────────  │
│ ./configure_mcp.sh --host 127.0.0.1 --port 3306 --user root \       │
│   --password your_password --enable                                 │
│                                                                      │
│ → Sets mcp-mysql_hosts=127.0.0.1                                    │
│ → Sets mcp-mysql_ports=3306                                          │
│ → Sets mcp-mysql_user=root                                           │
│ → Sets mcp-mysql_password=your_password                              │
│ → Sets mcp-mysql_schema=testdb                                        │
│ → Sets mcp-enabled=true                                              │
│ → Loads MCP VARIABLES TO RUNTIME                                    │
│                                                                      │
│ Result:                                                              │
│ → MySQL_Tool_Handler initializes connection pool                      │
│ → Connection established to MySQL server                             │
│ → HTTPS server starts on port 6071                                  │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Step 3: Test MCP Tools                                               │
│ ─────────────────────────────────────────────────────────────────  │
│ ./test_mcp_tools.sh                                                  │
│                                                                      │
│ → Sends JSON-RPC requests to https://localhost:6071/query           │
│ → Tests tools: list_schemas, list_tables, describe_table, etc.     │
│ → Verifies responses are valid JSON with expected data               │
│                                                                      │
│ Example Request:                                                     │
│ POST /query                                                          │
│ {                                                                   │
│   "jsonrpc": "2.0",                                                 │
│   "method": "tools/call",                                           │
│   "params": {                                                       │
│     "name": "list_tables",                                          │
│     "arguments": {"schema": "testdb"}                               │
│   },                                                                │
│   "id": 1                                                           │
│ }                                                                   │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Step 4: Verify Connection Pool                                      │
│ ─────────────────────────────────────────────────────────────────  │
│ grep "MySQL_Tool_Handler" /path/to/proxysql.log                     │
│                                                                      │
│ Expected logs:                                                       │
│ MySQL_Tool_Handler: Connected to 127.0.0.1:3306                     │
│ MySQL_Tool_Handler: Connection pool initialized with 1 connection(s)│
│ MySQL Tool Handler initialized for schema 'testdb'                  │
└─────────────────────────────────────────────────────────────────────┘

Quick Start (Copy/Paste)

Prerequisites - Set Environment Variables

# Add to ~/.bashrc or run before testing
export PROXYSQL_ADMIN_PASSWORD=admin        # Your ProxySQL admin password
export MYSQL_PASSWORD=your_mysql_password   # Your MySQL root password
cd /home/rene/proxysql-vec/scripts/mcp

# 1. Setup test database on your MySQL server
./setup_test_db.sh start --mode native

# 2. Configure and enable ProxySQL MCP module
./configure_mcp.sh --host 127.0.0.1 --port 3306 --user root --enable

# 3. Run all MCP tool tests
./test_mcp_tools.sh

# 4. Run catalog tests
./test_catalog.sh

# 5. Run stress test (10 concurrent requests)
./stress_test.sh -n 10

# 6. Clean up (drop test database when done)
./setup_test_db.sh reset --mode native

Option B: Using Docker

cd /home/rene/proxysql-vec/scripts/mcp

# 1. Start test MySQL container
./setup_test_db.sh start --mode docker

# 2. Configure and enable ProxySQL MCP module
./configure_mcp.sh --host 127.0.0.1 --port 3307 --user root --password test123 --enable

# 3. Run all MCP tool tests
./test_mcp_tools.sh

# 4. Stop test MySQL container when done
./setup_test_db.sh stop --mode docker

Detailed Documentation

setup_test_db.sh - Database Setup

Purpose: Creates a test MySQL database with sample schema and data for MCP testing.

What it does:

  • Creates testdb database with 4 tables: customers, orders, products, order_items
  • Inserts sample data (5 customers, 5 products, 5 orders with items)
  • Creates a view (customer_orders) and stored procedure (get_customer_stats)
  • Generates init_testdb.sql for reproducibility

Commands:

./setup_test_db.sh start [--mode native|docker]    # Create test database
./setup_test_db.sh status [--mode native|docker]   # Check database status
./setup_test_db.sh connect [--mode native|docker]  # Connect to MySQL shell
./setup_test_db.sh reset [--mode native|docker]    # Drop/recreate database
./setup_test_db.sh --help                           # Show help

Native Mode (your MySQL server):

# With defaults (127.0.0.1:3306, root user)
./setup_test_db.sh start --mode native

# With custom credentials
./setup_test_db.sh start --mode native --host localhost --port 3307 \
  --user myuser --password mypass

Docker Mode (isolated container):

./setup_test_db.sh start --mode docker
# Container port: 3307, root user, password: test123

configure_mcp.sh - ProxySQL Configuration

Purpose: Configures ProxySQL MCP module variables via admin interface.

What it does:

  1. Connects to ProxySQL admin interface (default: 127.0.0.1:6032)
  2. Sets MCP configuration variables:
    • mcp-mysql_hosts - Where to find MySQL server
    • mcp-mysql_ports - MySQL port
    • mcp-mysql_user - MySQL username
    • mcp-mysql_password - MySQL password
    • mcp-mysql_schema - Default database
    • mcp-enabled - Enable/disable MCP server
  3. Loads variables to RUNTIME (activates the configuration)
  4. Optionally tests MCP server connectivity

Commands:

./configure_mcp.sh --enable                 # Enable with defaults
./configure_mcp.sh --disable                # Disable MCP server
./configure_mcp.sh --status                 # Show current configuration
./configure_mcp.sh --help                   # Show help

Options:

--host HOST           MySQL host (default: 127.0.0.1)
--port PORT           MySQL port (default: 3307 for Docker, 3306 for native)
--user USER           MySQL user (default: root)
--password PASS       MySQL password
--database DB         Default database (default: testdb)
--mcp-port PORT       MCP HTTPS port (default: 6071)

Full Example:

./configure_mcp.sh \
  --host 127.0.0.1 \
  --port 3306 \
  --user root \
  --password your_password \
  --database testdb \
  --enable

What happens when you run --enable:

  1. Sets mcp-mysql_hosts='127.0.0.1' in ProxySQL
  2. Sets mcp-mysql_ports='3306' in ProxySQL
  3. Sets mcp-mysql_user='root' in ProxySQL
  4. Sets mcp-mysql_password='your_password' in ProxySQL
  5. Sets mcp-mysql_schema='testdb' in ProxySQL
  6. Sets mcp-enabled='true' in ProxySQL
  7. Runs LOAD MCP VARIABLES TO RUNTIME
  8. MySQL_Tool_Handler initializes connection pool to MySQL
  9. HTTPS server starts listening on port 6071

test_mcp_tools.sh - Tool Testing

Purpose: Tests all MCP tools via HTTPS/JSON-RPC to verify the connection pool and tools work.

What it does:

  • Sends JSON-RPC 2.0 requests to MCP /query endpoint
  • Tests 15 tools across 5 categories
  • Validates JSON responses
  • Reports pass/fail statistics

Tools Tested:

Category Tools What it Verifies
Inventory list_schemas, list_tables Connection works, can query information_schema
Structure describe_table, get_constraints, describe_view Can read schema details
Profiling table_profile, column_profile Aggregation queries work
Sampling sample_rows, sample_distinct Can sample data with limits
Query run_sql_readonly, explain_sql Query guardrails and execution
Catalog catalog_upsert, catalog_get, catalog_search Catalog CRUD works

Commands:

./test_mcp_tools.sh                           # Test all tools
./test_mcp_tools.sh --tool list_schemas        # Test single tool
./test_mcp_tools.sh --skip-tool catalog_*      # Skip catalog tests
./test_mcp_tools.sh -v                          # Verbose output

Example Test Flow:

$ ./test_mcp_tools.sh --tool list_tables

[TEST] Testing tool: list_tables
[INFO] ✓ list_tables

Test Summary
Total tests:   1
Passed:        1
Failed:        0

test_catalog.sh - Catalog Testing

Purpose: Tests the SQLite catalog (LLM memory) functionality.

What it does:

  • Tests catalog CRUD operations (Create, Read, Update, Delete)
  • Tests full-text search (FTS)
  • Tests entry linking between related discoveries

Tests:

  1. CAT001: Upsert table schema entry
  2. CAT002: Upsert domain knowledge entry
  3. CAT003: Get table entry
  4. CAT004: Get domain entry
  5. CAT005: Search catalog
  6. CAT006: List entries by kind
  7. CAT007: Update existing entry
  8. CAT008: Verify update
  9. CAT009: FTS search with wildcard
  10. CAT010: Delete entry
  11. CAT011: Verify deletion
  12. CAT012: Cleanup domain entry

stress_test.sh - Load Testing

Purpose: Tests concurrent connection handling by the connection pool.

What it does:

  • Launches N concurrent requests to MCP server
  • Measures response times
  • Reports success rate and requests/second

Commands:

./stress_test.sh -n 10                      # 10 concurrent requests
./stress_test.sh -n 50 -d 100               # 50 requests, 100ms delay
./stress_test.sh -t list_tables -v          # Test specific tool

Troubleshooting

MCP server not starting

Check ProxySQL logs:

tail -f /path/to/proxysql.log | grep -i mcp

Verify configuration:

mysql -h 127.0.0.1 -P 6032 -u admin -padmin
SHOW VARIABLES LIKE 'mcp-%';

Expected output:

Variable_name   Value
mcp-enabled     true
mcp-port        6071
mcp-mysql_hosts 127.0.0.1
mcp-mysql_ports 3306
...

Connection pool failing

Verify MySQL is accessible:

mysql -h 127.0.0.1 -P 3306 -u root -pyourpassword testdb -e "SELECT 1"

Check for connection pool errors in logs:

grep "MySQL_Tool_Handler" /path/to/proxysql.log

Expected logs on success:

MySQL_Tool_Handler: Connected to 127.0.0.1:3306
MySQL_Tool_Handler: Connection pool initialized with 1 connection(s)
MySQL Tool Handler initialized for schema 'testdb'

Test failures

Common causes:

  1. MySQL not accessible - Check credentials, host, port
  2. Database not created - Run ./setup_test_db.sh start first
  3. MCP not enabled - Run ./configure_mcp.sh --enable
  4. Wrong port - Docker uses 3307, native uses 3306
  5. Firewall - Ensure ports 6032, 6071, and MySQL port are open

Enable verbose output:

./test_mcp_tools.sh -v

Clean slate

To reset everything and start over:

# 1. Disable MCP
./configure_mcp.sh --disable

# 2. Drop test database
./setup_test_db.sh reset --mode native

# 3. Start fresh
./setup_test_db.sh start --mode native
./configure_mcp.sh --enable

Default Configuration Reference

Variable Default Description
mcp-enabled false Enable MCP server
mcp-port 6071 HTTPS port for MCP
mcp-config_endpoint_auth (empty) Auth token for /config endpoint
mcp-observe_endpoint_auth (empty) Auth token for /observe endpoint
mcp-query_endpoint_auth (empty) Auth token for /query endpoint
mcp-admin_endpoint_auth (empty) Auth token for /admin endpoint
mcp-cache_endpoint_auth (empty) Auth token for /cache endpoint
mcp-timeout_ms 30000 Query timeout in milliseconds
mcp-mysql_hosts 127.0.0.1 MySQL server host(s)
mcp-mysql_ports 3306 MySQL server port(s)
mcp-mysql_user (empty) MySQL username
mcp-mysql_password (empty) MySQL password
mcp-mysql_schema (empty) Default schema
mcp-catalog_path mcp_catalog.db Catalog database path (relative to datadir)

Environment Variables Reference

# ProxySQL Admin Configuration (for configure_mcp.sh)
export PROXYSQL_ADMIN_HOST=${PROXYSQL_ADMIN_HOST:-127.0.0.1}
export PROXYSQL_ADMIN_PORT=${PROXYSQL_ADMIN_PORT:-6032}
export PROXYSQL_ADMIN_USER=${PROXYSQL_ADMIN_USER:-admin}
export PROXYSQL_ADMIN_PASSWORD=${PROXYSQL_ADMIN_PASSWORD:-admin}

# MySQL Configuration (for setup_test_db.sh and configure_mcp.sh)
export MYSQL_HOST=${MYSQL_HOST:-127.0.0.1}
export MYSQL_PORT=${MYSQL_PORT:-3306}
export MYSQL_USER=${MYSQL_USER:-root}
export MYSQL_PASSWORD=${MYSQL_PASSWORD:-}
export TEST_DB_NAME=${TEST_DB_NAME:-testdb}

# MCP Server Configuration (for test scripts)
export MCP_HOST=${MCP_HOST:-127.0.0.1}
export MCP_PORT=${MCP_PORT:-6071}