Skip to content

Commit 0e92cfd

Browse files
committed
Adding MySQL Support/Tools (#15)
- **MySQL ML and AI Tools** - Similarity search and RAG on existing vector stores - Create vector store from objects in Object Store - Create vector store from objects in file system - **Additional Features** - OCI Object Store list buckets and objects - MySQL AI secure file system list Signed-off-by: Gregory Howe <[email protected]>
1 parent 064eb2f commit 0e92cfd

File tree

7 files changed

+3133
-0
lines changed

7 files changed

+3133
-0
lines changed

src/mysql-mcp-server/README.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# MySQL MCP Server (mysql_mcp_server.py)
2+
3+
A Python-based MCP (Model Context Protocol) server that provides a suite of tools for managing and interacting with MySQL AI and MySQL HeatWave database resources. This MCP server is not intended for production use but as a proof of concept for exploring models using MCP Servers.
4+
5+
## Overview
6+
7+
`mysql_mcp_server.py` is a FastMCP-based server that provides tools for managing MySQL connections, executing SQL, using MySQL AI ML/AI features, and working with OCI Object Storage.
8+
9+
## Features
10+
11+
- **Database Connection Management**
12+
- Load connection configs from JSON or environment variables
13+
- List all configured database connections
14+
- Validate connectivity and resolve provider mode (MySQL AI vs. OCI)
15+
16+
- **Database Operations**
17+
- Execute SQL queries
18+
19+
- **MySQL AI ML and AI Tools**
20+
- `ml_generate`: Text generation with MySQL AI GenAI
21+
- `ragify_column`: Create/populate vector columns for embeddings
22+
- `ask_ml_rag`: Retrieval-augmented generation from vector stores
23+
24+
- **Vector Store Management**
25+
- List files in `secure_file_priv` (local mode)
26+
- Load documents into vector stores from local file system
27+
- Load documents from OCI Object Storage into vector stores
28+
29+
- **OCI Object Store Tools**
30+
- List all compartments
31+
- Get compartment by name
32+
- List buckets in a compartment
33+
- List objects in a bucket
34+
35+
## Prerequisites
36+
37+
- Python 3.x
38+
- `fastmcp`
39+
- `oci` SDK
40+
- `mysql-connector-python` SDK
41+
- Valid database connection file. Resolution order:
42+
1) Path specified by environment variable `MYSQL_MCP_CONFIG` (absolute or relative to this module)
43+
2) `src/mysql-mcp-server/local_config.json` (default)
44+
- Valid OCI configuration file (`~/.oci/config`) or environment variables
45+
46+
## Installation
47+
48+
1. Clone this repository.
49+
2. Install required dependencies using pip:
50+
```
51+
pip install -r requirements.txt
52+
```
53+
This will install `oci`, `fastmcp`, `mysql-connector-python`, and all other dependencies.
54+
3. Set up your OCI config file at ~/.oci/config
55+
56+
## OCI Configuration
57+
58+
The server requires a valid OCI config file with proper credentials.
59+
The default location is ~/.oci/config. For instructions on setting up this file,
60+
see the [OCI SDK documentation](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm).
61+
62+
## Required Python Packages
63+
64+
- `oci`
65+
- `requests`
66+
- `fastmcp`
67+
- `mysql-connector-python`
68+
69+
## Supported Database Modes
70+
71+
- **MYSQL_AI** (local MySQL AI AI mode)
72+
- **OCI** (Oracle Cloud Infrastructure-managed databases)
73+
74+
## MCP Server Configuration
75+
76+
Installation is dependent on the MCP Client being used, it usually consists of adding the MCP Server invocation in a json config file, for example with Claude UI on windows it looks like this:
77+
```json
78+
{
79+
"mcpServers": {
80+
"mysqltools": {
81+
"command": "C:\\Python\\python.exe",
82+
"args": [
83+
"C:\\Users\\user1\\mysql-mcp-server\\mysql_mcp_server.py"
84+
]
85+
}
86+
}
87+
}
88+
```
89+
90+
91+
92+
Example with TENANCY_ID_OVERRIDE::
93+
```json
94+
{
95+
"mcpServers": {
96+
"mysqltools": {
97+
"command": "C:\\Python\\python.exe",
98+
"args": [
99+
"C:\\Users\\user1\\mysql-mcp-server\\mysql_mcp_server.py"
100+
],
101+
"env": {
102+
"TENANCY_ID_OVERRIDE": "ocid1.tenancy.oc1..deadbeef"
103+
}
104+
}
105+
}
106+
}
107+
```
108+
109+
## Environment Variables
110+
111+
The server supports the following environment variables:
112+
113+
- `PROFILE_NAME`: OCI configuration profile name (default: "DEFAULT")
114+
- `TENANCY_ID_OVERRIDE`: Overrides the tenancy ID from the config file
115+
116+
## Configuration (utils.fill_config_defaults and utils.load_mysql_config)
117+
118+
The server loads and validates connection configuration using two helpers in utils.py.
119+
120+
- utils.load_mysql_config:
121+
- Search order (first existing file wins):
122+
1) Path from env `MYSQL_MCP_CONFIG` (if set). If relative, also tries `<module_dir>/<value>`.
123+
2) `<module_dir>/local_config.json` (default when env not set)
124+
3) `<module_dir>/config.json`
125+
4) `<cwd>/config.json`
126+
- Returns a validated dict after passing the loaded JSON through fill_config_defaults.
127+
128+
- utils.fill_config_defaults:
129+
- Validates the schema and applies defaults for the optional bastion section.
130+
- Expected JSON shape:
131+
{
132+
"server_infos": {
133+
"<connection_id>": {
134+
"host": "<hostname or IP>",
135+
"user": "<username>",
136+
"password": "<password>",
137+
"database": "<default_schema>",
138+
"port": 3306
139+
}
140+
},
141+
"bastion": { // optional; for SSH tunneling
142+
"bastion_host": "<host>",
143+
"bastion_username": "<user>",
144+
"private_key_path": "<path to private key>",
145+
"db_host": "<remote DB host>",
146+
"db_port": 3306, // default 3306
147+
"bastion_port": 22, // default 22
148+
"local_bind_host": "127.0.0.1", // default 127.0.0.1
149+
"local_bind_port": 3306 // default 3306
150+
}
151+
}
152+
- Required server entry keys are exactly: {"host","user","password","database","port"}.
153+
- If a bastion block is present, only the allowed keys above are permitted; defaults are applied when omitted.
154+
155+
Example minimal config (local file):
156+
{
157+
"server_infos": {
158+
"local_server": {
159+
"host": "localhost",
160+
"user": "root",
161+
"password": "",
162+
"database": "mysql_mcp",
163+
"port": 3306
164+
}
165+
}
166+
}
167+
168+
Example with bastion:
169+
{
170+
"server_infos": {
171+
"remote_via_bastion": {
172+
"host": "127.0.0.1",
173+
"user": "dbuser",
174+
"password": "secret",
175+
"database": "appdb",
176+
"port": 3306
177+
}
178+
},
179+
"bastion": {
180+
"bastion_host": "bastion.example.com",
181+
"bastion_username": "ubuntu",
182+
"private_key_path": "/home/user/.ssh/id_rsa",
183+
"db_host": "mysql.internal",
184+
"db_port": 3306
185+
// optional keys (with defaults if omitted): bastion_port, local_bind_host, local_bind_port
186+
}
187+
}
188+
189+
Note:
190+
- Set `MYSQL_MCP_CONFIG` to point at a specific JSON file if you don't want to use `local_config.json`.
191+
- The defaults and schema enforcement are performed at startup; invalid or incomplete entries raise clear exceptions.
192+
193+
## Usage
194+
195+
The server runs using stdio transport and can be started by running:
196+
197+
```bash
198+
python mysql_mcp_server.py
199+
```
200+
201+
## API Tools
202+
203+
1. `list_all_connections()`: List configured database connections and modes
204+
2. `execute_sql_tool_by_connection_id(connection_id, sql, params)`: Execute SQL on a database connection
205+
3. `ml_generate(connection_id, question)`: Generate text via MySQL AI ML
206+
4. `ragify_column(connection_id, table, input_col, embedding_col)`: Embed text into a VECTOR column
207+
5. `list_vector_store_files_local(connection_id)`: List available files in `secure_file_priv`
208+
6. `load_vector_store_local(connection_id, file_path)`: Load documents from local filesystem
209+
7. `load_vector_store_oci(connection_id, namespace, bucket, prefix, schema, table)`: Load documents from OCI Object Storage
210+
8. `ask_ml_rag_vector_store(connection_id, question)`: RAG query on default vector store
211+
9. `ask_ml_rag_innodb(connection_id, question, segment_col, embedding_col)`: RAG query restricted to InnoDB tables
212+
10. `list_all_compartments()`: List OCI compartments
213+
11. `object_storage_list_buckets(compartment_name | compartment_id)`: List buckets in a compartment
214+
12. `object_storage_list_objects(namespace, bucket_name)`: List objects in a bucket
215+
216+
## Security
217+
218+
- Uses OCI’s config-based authentication
219+
- MySQL connection parameters may be stored in JSON config or environment variables
220+
221+
## Example Prompts
222+
223+
Here are example prompts you can use to interact with the MCP server, note that depending on the model being used you might need to be more specific, for example: "list all employees using myConnection1 mysql connection".
224+
225+
### 1. Database Operations
226+
227+
```
228+
"List all configured database connections"
229+
"Execute 'SELECT * FROM employees' on my connection"
230+
"Add embeddings for 'body' column into 'embedding' column in docs table"
231+
```
232+
233+
### 2. MySQL AI AI
234+
235+
```
236+
"Generate a summary of error logs using MySQL AI ML"
237+
"Ask ml_rag: Show me refund policy from the vector store"
238+
```
239+
240+
### 3. Object Storage
241+
242+
```
243+
"List all compartments in my tenancy"
244+
"Show all buckets in the development compartment"
245+
"List objects in my 'docs-bucket'"
246+
```
247+
248+
### 4. Vector Store
249+
250+
```
251+
"Load all documents with prefix 'manuals/' into schema hr, table product_docs"
252+
"List local files for vector store ingestion"
253+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"server_infos": {
3+
"example_local_server": {
4+
"host": "<local-db-hostname-or-ip>",
5+
"user": "<local-db-username>",
6+
"password": "<local-db-password>",
7+
"database": "<local-default-schema>",
8+
"port": 3306
9+
},
10+
"example_remote_server": {
11+
"host": "<remote-db-hostname-or-ip-or-tunnel-endpoint>",
12+
"user": "<remote-db-username>",
13+
"password": "<remote-db-password>",
14+
"database": "<remote-default-schema>",
15+
"port": 3306
16+
}
17+
},
18+
"bastion": {
19+
"bastion_host": "<bastion-hostname-or-ip>",
20+
"bastion_username": "<bastion-ssh-username>",
21+
"private_key_path": "<absolute-path-to-private-key>",
22+
"db_host": "<remote-db-hostname-or-ip>",
23+
"db_port": 3306,
24+
"bastion_port": 22,
25+
"local_bind_host": "127.0.0.1",
26+
"local_bind_port": 3306
27+
}
28+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"server_infos": {
3+
"local_server": {
4+
"host": "localhost",
5+
"user": "root",
6+
"password": "",
7+
"database": "mysql_mcp",
8+
"port": 3306
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)