# MySQL MCP Server Pro Complete Call Flow
## π Table of Contents
1. [Server Startup Flow](#server-startup-flow)
2. [AI Client Connection Flow](#ai-client-connection-flow)
3. [Complete Call Flow Example](#complete-call-flow-example)
4. [Code Execution Path](#code-execution-path)
---
## Server Startup Flow
### 1. Server Initialization Phase
```
Server startup (server.py)
β
Load environment variable configuration (.env)
β
Create database connection pool (ExecuteSqlUtil.create_mysql_pool)
β
Import handles module (handles/__init__.py)
β
Automatically register all tool classes
```
### 2. Automatic Tool Registration Mechanism
**Code Location: `src/mysql_mcp_server_pro/handles/base.py`**
```python
# When importing GetTableName class
from .get_table_name import GetTableName # handles/__init__.py
# BaseHandler.__init_subclass__ automatically executed
class BaseHandler:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if cls.name: # If class defines name attribute
ToolRegistry.register(cls) # Automatically register to tool registry
β
# ToolRegistry.register() execution:
tool = tool_class() # Create tool instance
cls._tools[tool.name] = tool # Store in dictionary
# _tools = {
# "get_table_name": GetTableName instance,
# "execute_sql": ExecuteSQL instance,
# "get_table_desc": GetTableDesc instance,
# ...
# }
```
**Execution Timing:**
- β
Automatically executed when importing modules
- β
No manual invocation required
- β
All classes inheriting `BaseHandler` are automatically registered
---
## AI Client Connection Flow
### Step 1: Client Connects to Server
```
AI Client (Cursor/Claude Desktop, etc.)
β
Connect to server via MCP protocol
β
Establish communication channel (STDIO/SSE/StreamableHttp)
```
### Step 2: Client Requests Tool List
```
AI client sends request: list_tools()
β
Server receives request: server.py @app.list_tools()
β
Call: ToolRegistry.get_all_tools()
β
Iterate through all registered tool instances
β
Call tool.get_tool_description() for each tool
```
**Detailed Execution Path:**
```python
# server.py lines 67-72
@app.list_tools()
async def list_tools() -> list[Tool]:
return ToolRegistry.get_all_tools()
β
# base.py lines 41-48
@classmethod
def get_all_tools(cls) -> list[Tool]:
return [tool.get_tool_description() for tool in cls._tools.values()]
β
# For get_table_name tool:
# get_table_name.py lines 20-34
def get_tool_description(self) -> Tool:
return Tool(
name="get_table_name",
description="Search for table names in the database based on Chinese table names or table descriptions",
inputSchema={
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Chinese table name or table description to search, single query only"
}
},
"required": ["text"]
}
)
```
### Step 3: Client Receives Tool List
```
Server returns tool list (JSON format)
β
AI client parses tool information
β
AI client now knows:
- What tools are available
- Each tool's name and description
- What parameters each tool requires
```
**Returned Data Example:**
```json
[
{
"name": "get_table_name",
"description": "Search for table names in the database based on Chinese table names or table descriptions",
"inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Chinese table name or table description to search, single query only"
}
},
"required": ["text"]
}
},
{
"name": "execute_sql",
"description": "Execute SQL on MySQL database",
...
},
...
]
```
---
## Complete Call Flow Example
### Scenario: User queries "data of Zhang San in user info table"
#### Phase 1: User Input
```
User inputs natural language: "Query data of Zhang San in user info table"
β
AI client (e.g., Cursor) receives user input
```
#### Phase 2: AI Analysis and Decision
```
AI analyzes user intent
β
Determines need for:
1. First find the actual table name corresponding to "user info table"
2. Get table structure
3. Generate SQL query
4. Execute query
β
AI decides to call tool: get_table_name
```
#### Phase 3: Call get_table_name Tool
```
AI client sends request via MCP protocol:
call_tool(
name="get_table_name",
arguments={"text": "user info table"}
)
β
Server receives request: server.py @app.call_tool()
β
Code execution path:
```
**Detailed Code Execution:**
```python
# ========== Server-side Execution ==========
# 1. server.py lines 74-90
@app.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]):
tool = ToolRegistry.get_tool(name) # name = "get_table_name"
β
# 2. base.py lines 24-39
@classmethod
def get_tool(cls, name: str) -> 'BaseHandler':
if name not in cls._tools: # Check if tool exists
raise ValueError(f"Unknown tool: {name}")
return cls._tools[name] # Return GetTableName instance
β
# 3. Call tool's run_tool method
return await tool.run_tool(arguments) # arguments = {"text": "user info table"}
β
# 4. get_table_name.py lines 36-58
async def run_tool(self, arguments: Dict[str, Any]):
# 4.1 Validate parameters
if "text" not in arguments:
raise ValueError("Missing query statement")
text = arguments["text"] # text = "user info table"
# 4.2 Get database configuration
config = get_db_config() # Get database connection information
# 4.3 Create ExecuteSQL instance
execute_sql = ExecuteSQL()
# 4.4 Build SQL statement (hardcoded metadata query SQL)
sql = "SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COMMENT "
sql += f"FROM information_schema.TABLES "
sql += f"WHERE TABLE_SCHEMA = '{config['database']}' "
sql += f"AND TABLE_COMMENT LIKE '%{text}%';"
# Final SQL:
# SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COMMENT
# FROM information_schema.TABLES
# WHERE TABLE_SCHEMA = 'your_database'
# AND TABLE_COMMENT LIKE '%user info table%';
# 4.5 Call execute_sql tool to execute SQL
return await execute_sql.run_tool({"query": sql})
β
# 5. execute_sql.py lines 37-64
async def run_tool(self, arguments: Dict[str, Any]):
query = arguments["query"] # Get SQL statement
# 5.1 Create ExecuteSqlUtil instance
exe = ExecuteSqlUtil()
# 5.2 Execute SQL (may contain multiple statements, separated by semicolons)
sql_results = exe.execute_multiple_statements(query)
β
# 5.3 execute_sql_util.py execution
# - Check permissions
# - Get database connection (from connection pool)
# - Execute SQL
# - Return results
# 5.4 Format results
results = []
for result in sql_results:
formatted_result = exe.format_result(result)
results.append(formatted_result)
# 5.5 Return formatted results
return [TextContent(type="text", text="\n---\n".join(results))]
```
#### Phase 4: Return Results to AI
```
Server returns query results:
TextContent(
type="text",
text="TABLE_SCHEMA,TABLE_NAME,TABLE_COMMENT\n
your_database,user_info,user info table"
)
β
AI client receives results
β
AI parses results, learns:
- Table name is "user_info"
- Database is "your_database"
```
#### Phase 5: AI Continues Calling Other Tools
```
AI decides to continue calling: get_table_desc
β
call_tool(
name="get_table_desc",
arguments={"text": "user_info"}
)
β
Get table structure:
- id (int)
- name (varchar)
- age (int)
- email (varchar)
β
AI generates business SQL:
SELECT * FROM user_info WHERE name = 'Zhang San';
β
AI calls: execute_sql
β
call_tool(
name="execute_sql",
arguments={"query": "SELECT * FROM user_info WHERE name = 'Zhang San';"}
)
β
Execute SQL, return query results
β
AI returns results to user
```
---
## Code Execution Path
### Complete Call Chain Diagram
```
User input
β
AI Client
β
MCP protocol communication
β
βββββββββββββββββββββββββββββββββββββββ
β Server-side (MySQL MCP Server Pro) β
βββββββββββββββββββββββββββββββββββββββ€
β β
β 1. app.call_tool β
β β β
β 2. Returns tool instance β
β β β
β 3. tool.run_tool(arguments) β
β (Specific tool class method) β
β β β
β 4. Tool internal logic: β
β - Build SQL (e.g., get_table_name) β
β - Call other tools (e.g., execute_sql) β
β β β
β 5. ExecuteSqlUtil β
β - Permission check β
β - Get connection from pool β
β - Execute SQL β
β - Return results β
β β
βββββββββββββββββββββββββββββββββββββββ
β
Return results to AI client
β
AI processes results, may continue calling other tools
β
Final results returned to user
```
### Key Code Location Reference Table
| Step | File Path | Line Number | Function |
|------|-----------|-------------|----------|
| Server startup entry | `server.py` | 202-244 | `main()` function |
| Tool registration | `handles/base.py` | 56-60 | `BaseHandler.__init_subclass__()` |
| Tool registry | `handles/base.py` | 6-48 | `ToolRegistry` class |
| List all tools | `server.py` | 67-72 | `@app.list_tools()` |
| Call tool entry | `server.py` | 74-90 | `@app.call_tool()` |
| Get tool instance | `handles/base.py` | 24-39 | `ToolRegistry.get_tool()` |
| get_table_name implementation | `handles/get_table_name.py` | 36-58 | `run_tool()` method |
| execute_sql implementation | `handles/execute_sql.py` | 37-64 | `run_tool()` method |
| SQL execution utility class | `utils/execute_sql_util.py` | 129-319 | `ExecuteSqlUtil` class |
---
## Sequence Diagram
```
User AI Client Server Tool Registry Tool Instance Database
β β β β β β
β Input query β β β β β
ββββββββββββββ>β β β β β
β β β β β β
β β list_tools() β β β β
β ββββββββββββββββ>β β β β
β β β get_all_tools() β β β
β β βββββββββββββββββ>β β β
β β β β get_description() β
β β β ββββββββββββββββ>β β
β β β β β β
β β β β<ββββββββββββββββ€ β
β β β<βββββββββββββββββ€ β β
β β<ββββββββββββββββ€ β β β
β β β β β β
β β call_tool() β β β β
β β ("get_table_ β β β β
β β name", {...}) β β β β
β ββββββββββββββββ>β β β β
β β β get_tool() β β β
β β βββββββββββββββββ>β β β
β β β β β β
β β β β return instanceβ β
β β β<βββββββββββββββββ€ β β
β β β β β β
β β β run_tool() β β β
β β ββββββββββββββββββββββββββββββββββ>β β
β β β β β β
β β β β β Build SQL β
β β β β β β
β β β β β call execute β
β β β β β_sql β
β β β β ββββββββββββββββ>β
β β β β β β
β β β β β Execute SQL β
β β β β β β
β β β β β<ββββββββββββββββ€
β β β β β β
β β β β β return result β
β β β<ββββββββββββββββββββββββββββββββββ€ β
β β<ββββββββββββββββ€ β β β
β β β β β β
β β (Continue calling other tools...)β β β
β β β β β β
β β Return final result β β β
β<βββββββββββββββ€ β β β β
β β β β β β
```
---
## Key Points Summary
### 1. Automatic Registration Mechanism
- β
All classes inheriting `BaseHandler` are automatically registered when imported
- β
No manual tool registration required
- β
Just import in `handles/__init__.py`
### 2. Role of Tool Description
- β
AI client learns tool functionality through `get_tool_description()`
- β
AI decides when to call which tool based on descriptions
- β
`inputSchema` in description tells AI what parameters are needed
### 3. Tool Call Flow
1. AI client sends `call_tool(name, arguments)`
2. Server gets tool instance via `ToolRegistry.get_tool(name)`
3. Call tool's `run_tool(arguments)` method
4. Tool executes internal logic (may call other tools)
5. Return results to AI client
### 4. Inter-Tool Calls
- β
Tools can call other tools (e.g., `get_table_name` calls `execute_sql`)
- β
By creating tool instances and calling `run_tool()` method
- β
Tool chaining forms complex workflows
---
Hope this flow diagram helps you understand the entire call mechanism! π