# Directory Structure
```
├── .DS_Store
├── .gitignore
├── Dockerfile
├── git-upload.sh
├── issue-template.md
├── LICENSE
├── llms-install.md
├── logo-instructions.txt
├── mysql-mcp-logo.png
├── package-lock.json
├── package.json
├── README.md
├── src
│ └── index.ts
├── submission-checklist.md
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | node_modules/
2 | build/
3 | *.log
4 | .env*
5 | .DS_Store
6 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | # MySQL MCP Server
2 |
3 | A powerful MCP server that provides direct access to MySQL databases. This server enables AI agents to interact with MySQL databases, execute SQL queries, and manage database content through a simple interface.
4 |
5 | ## Features
6 |
7 | ### Resources
8 | - Access notes stored in the database via `note:///{id}` URIs
9 | - Each note has a title and content
10 | - Plain text mime type for simple content access
11 |
12 | ### Tools
13 | - `create_note` - Create new text notes in the database
14 | - Takes title and content as required parameters
15 | - Stores note in the MySQL database
16 | - `list_tables` - List all tables in the connected database
17 | - `count_tables` - Get the total number of tables in the database
18 | - `search_tables` - Search for tables using LIKE pattern
19 | - `describe_table` - Get the structure of a specific table
20 | - `execute_sql` - Execute custom SQL queries
21 |
22 | ## Prerequisites
23 |
24 | - Node.js 18 or higher
25 | - MySQL server installed and running
26 | - A database with appropriate permissions
27 |
28 | ## Setup
29 |
30 | 1. Clone this repository:
31 | ```bash
32 | git clone [email protected]:LeonMelamud/mysql-mcp.git
33 | cd mysql-mcp
34 | ```
35 |
36 | 2. Install dependencies:
37 | ```bash
38 | npm install
39 | ```
40 |
41 | 3. Create a `.env` file in the root directory with your MySQL connection details:
42 | ```
43 | MYSQL_HOST=localhost
44 | MYSQL_USER=your_username
45 | MYSQL_PASSWORD=your_password
46 | MYSQL_DATABASE=your_database
47 | ```
48 |
49 | 4. Build the server:
50 | ```bash
51 | npm run build
52 | ```
53 |
54 | ## Installation
55 |
56 | ### For Claude Desktop
57 |
58 | Add the server config to your Claude Desktop configuration file:
59 |
60 | On MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
61 | On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
62 |
63 | ```json
64 | {
65 | "mcpServers": {
66 | "mysql": {
67 | "command": "node",
68 | "args": ["/path/to/mysql-server/build/index.js"],
69 | "env": {
70 | "MYSQL_HOST": "localhost",
71 | "MYSQL_USER": "your_username",
72 | "MYSQL_PASSWORD": "your_password",
73 | "MYSQL_DATABASE": "your_database"
74 | }
75 | }
76 | }
77 | }
78 | ```
79 |
80 | ### For Cline
81 |
82 | Add the server config to your Cline MCP settings file:
83 |
84 | On MacOS: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
85 | On Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
86 |
87 | ```json
88 | {
89 | "mcpServers": {
90 | "mysql": {
91 | "command": "node",
92 | "args": ["/path/to/mysql-server/build/index.js"],
93 | "env": {
94 | "MYSQL_HOST": "localhost",
95 | "MYSQL_USER": "your_username",
96 | "MYSQL_PASSWORD": "your_password",
97 | "MYSQL_DATABASE": "your_database"
98 | },
99 | "disabled": false,
100 | "autoApprove": []
101 | }
102 | }
103 | }
104 | ```
105 |
106 | ## Usage Examples
107 |
108 | Once installed, you can use the MySQL MCP server in your conversations with Claude:
109 |
110 | ### List all tables in the database
111 | ```
112 | Please list all the tables in my MySQL database.
113 | ```
114 |
115 | ### Execute a SQL query
116 | ```
117 | Run this SQL query: SELECT * FROM users LIMIT 5
118 | ```
119 |
120 | ### Create a note
121 | ```
122 | Create a note titled "Meeting Notes" with the content "Discussed project timeline and assigned tasks."
123 | ```
124 |
125 | ## Development
126 |
127 | For development with auto-rebuild:
128 | ```bash
129 | npm run watch
130 | ```
131 |
132 | ### Debugging
133 |
134 | Use the MCP Inspector to debug the server:
135 | ```bash
136 | npm run inspector
137 | ```
138 |
139 | The Inspector will provide a URL to access debugging tools in your browser.
140 |
141 | ## License
142 |
143 | MIT
144 |
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "Node16",
5 | "moduleResolution": "Node16",
6 | "outDir": "./build",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true
12 | },
13 | "include": ["src/**/*"],
14 | "exclude": ["node_modules"]
15 | }
16 |
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
1 | FROM node:20-slim
2 |
3 | # Install MySQL client for connectivity testing
4 | RUN apt-get update && apt-get install -y default-mysql-client && rm -rf /var/lib/apt/lists/*
5 |
6 | WORKDIR /app
7 |
8 | # Copy package files
9 | COPY package*.json ./
10 |
11 | # Install dependencies
12 | RUN npm install
13 |
14 | # Copy source code
15 | COPY . .
16 |
17 | # Build TypeScript code
18 | RUN npm run build
19 |
20 | # Expose the default MCP port
21 | EXPOSE 3308
22 |
23 | # Set environment variables
24 | ENV NODE_ENV=production
25 |
26 | # Run the MCP server
27 | CMD ["node", "build/index.js"]
28 |
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
1 | {
2 | "name": "mysql-server",
3 | "version": "0.1.0",
4 | "description": "local mysql 3308",
5 | "private": true,
6 | "license": "MIT",
7 | "type": "module",
8 | "bin": {
9 | "mysql-server": "./build/index.js"
10 | },
11 | "files": [
12 | "build"
13 | ],
14 | "scripts": {
15 | "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
16 | "prepare": "npm run build",
17 | "watch": "tsc --watch",
18 | "inspector": "npx @modelcontextprotocol/inspector build/index.js"
19 | },
20 | "dependencies": {
21 | "@modelcontextprotocol/sdk": "0.6.0",
22 | "dotenv": "^16.4.7",
23 | "mysql2": "^3.11.5"
24 | },
25 | "devDependencies": {
26 | "@types/node": "^20.11.24",
27 | "typescript": "^5.3.3"
28 | }
29 | }
30 |
```
--------------------------------------------------------------------------------
/git-upload.sh:
--------------------------------------------------------------------------------
```bash
1 | #!/bin/bash
2 |
3 | # Initialize Git repository (if not already done)
4 | if [ ! -d .git ]; then
5 | echo "Initializing Git repository..."
6 | git init
7 | else
8 | echo "Git repository already initialized."
9 | fi
10 |
11 | # Add all files to the repository
12 | echo "Adding files to Git repository..."
13 | git add .
14 |
15 | # Commit the changes
16 | echo "Committing changes..."
17 | git commit -m "Initial commit of MySQL MCP server"
18 |
19 | # Set the remote origin to the GitHub repository
20 | echo "Setting remote origin..."
21 | git remote add origin [email protected]:LeonMelamud/mysql-mcp.git
22 |
23 | # Get the current branch name
24 | BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "main")
25 | if [ "$BRANCH" = "" ]; then
26 | BRANCH="main"
27 | fi
28 |
29 | # Push the changes to GitHub
30 | echo "Pushing to GitHub on branch $BRANCH..."
31 | git push -u origin $BRANCH
32 |
33 | echo "Done! Repository uploaded to GitHub."
34 |
```
--------------------------------------------------------------------------------
/logo-instructions.txt:
--------------------------------------------------------------------------------
```
1 | # MySQL MCP Server Logo Instructions
2 |
3 | To complete the submission to the MCP marketplace, you'll need to create a 400x400 PNG logo for your MySQL MCP server.
4 |
5 | ## Logo Requirements
6 | - Size: 400x400 pixels
7 | - Format: PNG with transparency
8 | - Content: A visual representation of MySQL and MCP integration
9 |
10 | ## Suggested Design
11 | 1. Use the MySQL dolphin logo as inspiration
12 | 2. Combine it with the MCP logo or a database icon
13 | 3. Use blue colors to match MySQL's branding
14 | 4. Keep the design simple and recognizable at smaller sizes
15 |
16 | ## Tools for Creating the Logo
17 | - Adobe Illustrator or Photoshop
18 | - Figma
19 | - Canva
20 | - GIMP (free alternative)
21 |
22 | ## File Naming and Location
23 | Save the completed logo as `mysql-mcp-logo.png` in the root directory of the MySQL MCP server project.
24 |
25 | ## Example Logo Description
26 | A blue MySQL dolphin icon with a database symbol, surrounded by a circular MCP-style connector icon, all on a transparent background.
27 |
```
--------------------------------------------------------------------------------
/issue-template.md:
--------------------------------------------------------------------------------
```markdown
1 | # MySQL MCP Server Submission
2 |
3 | I'd like to submit the MySQL MCP server to be included in Cline's MCP Marketplace.
4 |
5 | ## GitHub Repo URL
6 |
7 | [https://github.com/LeonMelamud/mysql-mcp](https://github.com/LeonMelamud/mysql-mcp)
8 |
9 | ## Logo Image
10 |
11 | 
12 |
13 | ## Reason for Addition
14 |
15 | The MySQL MCP server provides a powerful interface for AI agents like Cline to interact directly with MySQL databases. This enables users to:
16 |
17 | 1. **Query databases directly**: Users can ask Cline to retrieve information from their databases without writing SQL queries themselves.
18 |
19 | 2. **Manage database content**: The server allows creating, reading, updating, and deleting database records through natural language commands.
20 |
21 | 3. **Explore database structure**: Users can easily explore their database schema, list tables, and understand table structures.
22 |
23 | 4. **Execute custom SQL**: For advanced users, the server supports executing custom SQL queries while maintaining the security of parameterized queries.
24 |
25 | This MCP server bridges the gap between natural language interfaces and database operations, making database interactions more accessible to users without SQL expertise while still providing powerful capabilities for advanced users.
26 |
27 | ## Testing Confirmation
28 |
29 | - [x] Verified all functions work correctly
30 | - [x] list_tables
31 | - [x] count_tables
32 | - [x] search_tables
33 | - [x] describe_table
34 | - [x] execute_sql
35 | - [x] create_note
36 | - [x] Resource access (note:///{id})
37 |
38 | ## Additional Notes
39 |
40 | The server includes comprehensive error handling and security measures to prevent SQL injection. It's designed to be easily configurable through environment variables, making it adaptable to different MySQL server configurations.
41 |
```
--------------------------------------------------------------------------------
/submission-checklist.md:
--------------------------------------------------------------------------------
```markdown
1 | # MCP Marketplace Submission Checklist
2 |
3 | Use this checklist to ensure your MySQL MCP server is ready for submission to the MCP marketplace.
4 |
5 | ## Required Items
6 |
7 | - [x] Verified all functions work correctly
8 | - [x] list_tables
9 | - [x] count_tables
10 | - [x] search_tables
11 | - [x] describe_table
12 | - [x] execute_sql
13 | - [x] create_note
14 | - [x] Resource access (note:///{id})
15 |
16 | - [x] Updated README.md with clear installation instructions
17 | - [x] Features section
18 | - [x] Prerequisites section
19 | - [x] Setup instructions
20 | - [x] Installation instructions for Claude Desktop and Cline
21 | - [x] Usage examples
22 | - [x] Development and debugging information
23 |
24 | - [x] Created llms-install.md with additional guidance for AI agents
25 | - [x] Detailed installation steps
26 | - [x] Troubleshooting section
27 | - [x] Testing instructions
28 |
29 | - [X] Created a 400x400 PNG logo
30 | - [X] Logo represents MySQL and MCP integration
31 | - [X] Logo is visually appealing and recognizable
32 | - [X] Logo is saved as mysql-mcp-logo.png in the root directory
33 |
34 | ## Submission Process
35 |
36 | 1. [ ] Create a new issue in the [MCP Marketplace repository](https://github.com/cline/mcp-marketplace)
37 | 2. [ ] Include the following information in the issue:
38 | - [ ] GitHub Repo URL: Link to your MySQL MCP server repository (https://github.com/LeonMelamud/mysql-mcp)
39 | - [ ] Logo Image: Attach the 400x400 PNG logo
40 | - [ ] Reason for Addition: Explain why your MySQL MCP server is awesome and how it benefits Cline users
41 | 3. [ ] Confirm that you have tested giving Cline just your README.md and/or llms-install.md and watched it successfully setup the server
42 |
43 | ## Final Checks
44 |
45 | - [ ] Code is well-documented and follows best practices
46 | - [ ] All dependencies are properly listed in package.json
47 | - [ ] Server handles errors gracefully
48 | - [ ] Environment variables are properly documented
49 | - [ ] No sensitive information is included in the repository
50 |
```
--------------------------------------------------------------------------------
/llms-install.md:
--------------------------------------------------------------------------------
```markdown
1 | # MySQL MCP Server Installation Guide for AI Agents
2 |
3 | This guide provides specific instructions for AI agents like Cline to help users install and configure the MySQL MCP server.
4 |
5 | ## Prerequisites
6 |
7 | Before installing this MCP server, ensure the user has:
8 |
9 | 1. Node.js 18 or higher installed
10 | 2. A MySQL server installed and running
11 | 3. A database with appropriate permissions
12 | 4. The necessary database credentials (host, username, password, database name)
13 |
14 | ## Installation Steps
15 |
16 | 1. First, check if the user has a MySQL server running:
17 | ```bash
18 | mysql --version
19 | ```
20 |
21 | 2. If MySQL is not installed, guide the user to install it based on their operating system.
22 |
23 | 3. Clone the repository:
24 | ```bash
25 | git clone [email protected]:LeonMelamud/mysql-mcp.git
26 | cd mysql-mcp
27 | ```
28 |
29 | 4. Install dependencies:
30 | ```bash
31 | npm install
32 | ```
33 |
34 | 5. Create a `.env` file with the MySQL connection details:
35 | ```
36 | MYSQL_HOST=localhost
37 | MYSQL_USER=username
38 | MYSQL_PASSWORD=password
39 | MYSQL_DATABASE=database_name
40 | ```
41 |
42 | 6. Build the server:
43 | ```bash
44 | npm run build
45 | ```
46 |
47 | 7. Add the server configuration to the appropriate config file:
48 |
49 | For Claude Desktop:
50 | ```json
51 | {
52 | "mcpServers": {
53 | "mysql": {
54 | "command": "node",
55 | "args": ["/absolute/path/to/mysql-mcp/build/index.js"],
56 | "env": {
57 | "MYSQL_HOST": "localhost",
58 | "MYSQL_USER": "username",
59 | "MYSQL_PASSWORD": "password",
60 | "MYSQL_DATABASE": "database_name"
61 | }
62 | }
63 | }
64 | }
65 | ```
66 |
67 | For Cline:
68 | ```json
69 | {
70 | "mcpServers": {
71 | "mysql": {
72 | "command": "node",
73 | "args": ["/absolute/path/to/mysql-mcp/build/index.js"],
74 | "env": {
75 | "MYSQL_HOST": "localhost",
76 | "MYSQL_USER": "username",
77 | "MYSQL_PASSWORD": "password",
78 | "MYSQL_DATABASE": "database_name"
79 | },
80 | "disabled": false,
81 | "autoApprove": []
82 | }
83 | }
84 | }
85 | ```
86 |
87 | ## Troubleshooting
88 |
89 | If the user encounters issues:
90 |
91 | 1. Verify MySQL is running:
92 | ```bash
93 | sudo systemctl status mysql # For Linux
94 | brew services list # For macOS
95 | ```
96 |
97 | 2. Test the MySQL connection:
98 | ```bash
99 | mysql -u username -p -h localhost database_name
100 | ```
101 |
102 | 3. Check the .env file has the correct credentials
103 |
104 | 4. Ensure the build directory exists and contains the compiled JavaScript files:
105 | ```bash
106 | ls -la build/
107 | ```
108 |
109 | 5. Try running the server directly to see any error messages:
110 | ```bash
111 | node build/index.js
112 | ```
113 |
114 | ## Testing the Installation
115 |
116 | Once installed, you can verify the installation by asking the user to:
117 |
118 | 1. Restart Cline or Claude Desktop
119 | 2. Ask you to list all tables in their database
120 | 3. Create a test note
121 | 4. Access the created note
122 |
123 | Example commands to test:
124 | ```
125 | Please list all tables in my MySQL database.
126 | Create a note titled "Test Note" with content "This is a test note."
127 | Show me the note I just created.
128 | ```
129 |
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
1 | #!/usr/bin/env node
2 |
3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5 | import {
6 | CallToolRequestSchema,
7 | ListResourcesRequestSchema,
8 | ListToolsRequestSchema,
9 | ReadResourceRequestSchema,
10 | } from "@modelcontextprotocol/sdk/types.js";
11 | import mysql from 'mysql2/promise';
12 | import dotenv from 'dotenv';
13 |
14 | // Load environment variables from .env file
15 | dotenv.config();
16 |
17 | type Note = { title: string, content: string };
18 |
19 | // Create MySQL connection pool
20 | const pool = mysql.createPool({
21 | host: process.env.MYSQL_HOST,
22 | user: process.env.MYSQL_USER,
23 | password: process.env.MYSQL_PASSWORD,
24 | database: process.env.MYSQL_DATABASE,
25 | });
26 |
27 | // Initialize database table
28 | async function initDatabase() {
29 | try {
30 | const connection = await pool.getConnection();
31 | await connection.execute(`
32 | CREATE TABLE IF NOT EXISTS notes (
33 | id INT AUTO_INCREMENT PRIMARY KEY,
34 | title VARCHAR(255) NOT NULL,
35 | content TEXT NOT NULL
36 | )
37 | `);
38 | connection.release();
39 | } catch (error) {
40 | console.error('Failed to initialize database:', error);
41 | process.exit(1);
42 | }
43 | }
44 |
45 | const server = new Server(
46 | {
47 | name: "mysql-server",
48 | version: "0.1.0",
49 | },
50 | {
51 | capabilities: {
52 | resources: {},
53 | tools: {},
54 | },
55 | }
56 | );
57 |
58 | server.setRequestHandler(ListResourcesRequestSchema, async () => {
59 | const [rows] = await pool.execute('SELECT id, title FROM notes');
60 | return {
61 | resources: (rows as any[]).map(note => ({
62 | uri: `note:///${note.id}`,
63 | mimeType: "text/plain",
64 | name: note.title,
65 | description: `A text note: ${note.title}`
66 | }))
67 | };
68 | });
69 |
70 | server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
71 | const url = new URL(request.params.uri);
72 | const id = url.pathname.replace(/^\//, '');
73 |
74 | const [rows] = await pool.execute('SELECT * FROM notes WHERE id = ?', [id]);
75 | const notes = rows as any[];
76 |
77 | if (notes.length === 0) {
78 | throw new Error(`Note ${id} not found`);
79 | }
80 |
81 | return {
82 | contents: [{
83 | uri: request.params.uri,
84 | mimeType: "text/plain",
85 | text: notes[0].content
86 | }]
87 | };
88 | });
89 |
90 | server.setRequestHandler(ListToolsRequestSchema, async () => {
91 | return {
92 | tools: [
93 | {
94 | name: "create_note",
95 | description: "Create a new note",
96 | inputSchema: {
97 | type: "object",
98 | properties: {
99 | title: {
100 | type: "string",
101 | description: "Title of the note"
102 | },
103 | content: {
104 | type: "string",
105 | description: "Text content of the note"
106 | }
107 | },
108 | required: ["title", "content"]
109 | }
110 | },
111 | {
112 | name: "list_tables",
113 | description: "List all tables in the database",
114 | inputSchema: {
115 | type: "object",
116 | properties: {},
117 | required: []
118 | }
119 | },
120 | {
121 | name: "count_tables",
122 | description: "Get the total number of tables in the database",
123 | inputSchema: {
124 | type: "object",
125 | properties: {},
126 | required: []
127 | }
128 | },
129 | {
130 | name: "search_tables",
131 | description: "Search for tables using LIKE pattern",
132 | inputSchema: {
133 | type: "object",
134 | properties: {
135 | pattern: {
136 | type: "string",
137 | description: "LIKE pattern to search for (e.g. '%bill%')"
138 | }
139 | },
140 | required: ["pattern"]
141 | }
142 | },
143 | {
144 | name: "describe_table",
145 | description: "Get the structure of a table",
146 | inputSchema: {
147 | type: "object",
148 | properties: {
149 | table: {
150 | type: "string",
151 | description: "Name of the table to describe"
152 | }
153 | },
154 | required: ["table"]
155 | }
156 | },
157 | {
158 | name: "execute_sql",
159 | description: "Execute a SQL query",
160 | inputSchema: {
161 | type: "object",
162 | properties: {
163 | query: {
164 | type: "string",
165 | description: "SQL query to execute"
166 | },
167 | params: {
168 | type: "array",
169 | description: "Query parameters (optional)",
170 | items: {
171 | type: "string"
172 | }
173 | }
174 | },
175 | required: ["query"]
176 | }
177 | }
178 | ]
179 | };
180 | });
181 |
182 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
183 | switch (request.params.name) {
184 | case "create_note": {
185 | const title = String(request.params.arguments?.title);
186 | const content = String(request.params.arguments?.content);
187 | if (!title || !content) {
188 | throw new Error("Title and content are required");
189 | }
190 |
191 | const [result] = await pool.execute(
192 | 'INSERT INTO notes (title, content) VALUES (?, ?)',
193 | [title, content]
194 | );
195 | const id = (result as any).insertId;
196 |
197 | return {
198 | content: [{
199 | type: "text",
200 | text: `Created note ${id}: ${title}`
201 | }]
202 | };
203 | }
204 |
205 | case "list_tables": {
206 | const [rows] = await pool.execute('SHOW TABLES');
207 | const tables = (rows as any[]).map(row => Object.values(row)[0]);
208 |
209 | return {
210 | content: [{
211 | type: "text",
212 | text: `Tables in database:\n${tables.join('\n')}`
213 | }]
214 | };
215 | }
216 |
217 | case "count_tables": {
218 | try {
219 | const [rows] = await pool.execute('SHOW TABLES');
220 | const count = (rows as any[]).length;
221 |
222 | return {
223 | content: [{
224 | type: "text",
225 | text: `Total number of tables: ${count}`
226 | }]
227 | };
228 | } catch (error: any) {
229 | const errorMessage = error?.message || 'Unknown error occurred';
230 | throw new Error(`Failed to count tables: ${errorMessage}`);
231 | }
232 | }
233 |
234 | case "search_tables": {
235 | const pattern = String(request.params.arguments?.pattern);
236 | if (!pattern) {
237 | throw new Error("Search pattern is required");
238 | }
239 |
240 | const [rows] = await pool.execute('SHOW TABLES WHERE Tables_in_' + process.env.MYSQL_DATABASE + ' LIKE ?', [pattern]);
241 | const tables = (rows as any[]).map(row => Object.values(row)[0]);
242 |
243 | return {
244 | content: [{
245 | type: "text",
246 | text: `Tables matching pattern '${pattern}':\n${tables.join('\n')}`
247 | }]
248 | };
249 | }
250 |
251 | case "describe_table": {
252 | const table = String(request.params.arguments?.table);
253 | if (!table) {
254 | throw new Error("Table name is required");
255 | }
256 |
257 | // First verify the table exists
258 | const [tables] = await pool.execute('SHOW TABLES');
259 | const tableExists = (tables as any[]).some(row => Object.values(row)[0] === table);
260 |
261 | if (!tableExists) {
262 | throw new Error(`Table '${table}' does not exist`);
263 | }
264 |
265 | // Get table structure
266 | const [rows] = await pool.execute(`DESCRIBE ${table}`);
267 |
268 | return {
269 | content: [{
270 | type: "text",
271 | text: JSON.stringify(rows, null, 2)
272 | }]
273 | };
274 | }
275 |
276 | case "execute_sql": {
277 | const query = String(request.params.arguments?.query);
278 | const params = request.params.arguments?.params || [];
279 |
280 | if (!query) {
281 | throw new Error("SQL query is required");
282 | }
283 |
284 | try {
285 | // Execute the query with optional parameters
286 | const [result] = await pool.execute(query, params);
287 |
288 | return {
289 | content: [{
290 | type: "text",
291 | text: JSON.stringify(result, null, 2)
292 | }]
293 | };
294 | } catch (error: any) {
295 | const errorMessage = error?.message || 'Unknown error occurred';
296 | throw new Error(`Failed to execute SQL: ${errorMessage}`);
297 | }
298 | }
299 |
300 | default:
301 | throw new Error("Unknown tool");
302 | }
303 | });
304 |
305 | async function main() {
306 | try {
307 | await initDatabase();
308 | const transport = new StdioServerTransport();
309 | await server.connect(transport);
310 | console.error('MySQL MCP server running on stdio');
311 | } catch (error) {
312 | console.error("Server error:", error);
313 | process.exit(1);
314 | }
315 | }
316 |
317 | main().catch((error) => {
318 | console.error("Server error:", error);
319 | process.exit(1);
320 | });
321 |
```