Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions packages/mcp-server-mysql/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Dependencies
node_modules/

# Build output
dist/
*.tsbuildinfo

# IDE
.vscode/
.idea/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Environment files
.env
.env.local
.env.*.local

# OS files
.DS_Store
Thumbs.db

# Test coverage
coverage/
.nyc_output/
168 changes: 168 additions & 0 deletions packages/mcp-server-mysql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# MySQL MCP Server

A Model Context Protocol (MCP) server that provides MySQL database operations.

## Features

- Execute SELECT queries safely
- Execute INSERT, UPDATE, DELETE, and DDL operations
- List databases and tables
- Describe table structures
- Test database connections
- Connection pooling for efficient resource usage

## Installation

```bash
npm install @roo-code/mcp-server-mysql
```

## Configuration

The MySQL MCP server requires the following environment variables:

- `MYSQL_HOST` - MySQL server host (default: `localhost`)
- `MYSQL_PORT` - MySQL server port (default: `3306`)
- `MYSQL_USER` - MySQL username (default: `root`)
- `MYSQL_PASSWORD` - MySQL password (default: empty string)
- `MYSQL_DATABASE` - Default database to use (optional)

## Available Tools

### `query`

Execute SELECT queries on the MySQL database.

**Parameters:**

- `query` (string, required): The SELECT query to execute
- `database` (string, optional): Database to use (overrides default)

**Example:**

```json
{
"query": "SELECT * FROM users WHERE active = 1",
"database": "myapp"
}
```

### `execute`

Execute non-SELECT queries (INSERT, UPDATE, DELETE, CREATE, etc.).

**Parameters:**

- `query` (string, required): The SQL query to execute
- `database` (string, optional): Database to use (overrides default)

**Example:**

```json
{
"query": "INSERT INTO users (name, email) VALUES ('John Doe', '[email protected]')",
"database": "myapp"
}
```

### `list_databases`

List all databases in the MySQL server.

**No parameters required.**

### `list_tables`

List all tables in a specific database.

**Parameters:**

- `database` (string, required): The database name

**Example:**

```json
{
"database": "myapp"
}
```

### `describe_table`

Get the structure of a table.

**Parameters:**

- `table` (string, required): The table name
- `database` (string, optional): The database name (uses default if not specified)

**Example:**

```json
{
"table": "users",
"database": "myapp"
}
```

### `test_connection`

Test the MySQL connection and get server information.

**No parameters required.**

## Usage with Roo Code

To use this MCP server with Roo Code, add it to your MCP settings configuration:

```json
{
"mcpServers": {
"mysql": {
"command": "node",
"args": ["path/to/@roo-code/mcp-server-mysql/dist/index.js"],
"env": {
"MYSQL_HOST": "localhost",
"MYSQL_PORT": "3306",
"MYSQL_USER": "your_username",
"MYSQL_PASSWORD": "your_password",
"MYSQL_DATABASE": "your_default_db"
}
}
}
}
```

## Security Considerations

- The `query` tool only allows SELECT, SHOW, and DESCRIBE queries
- The `execute` tool is for all other operations (INSERT, UPDATE, DELETE, etc.)
- Always use parameterized queries when building dynamic SQL
- Ensure proper access controls are in place at the MySQL server level
- Store credentials securely and never commit them to version control

## Development

```bash
# Install dependencies
npm install

# Build the project
npm run build

# Run in development mode
npm run dev

# Run tests
npm test

# Type checking
npm run typecheck

# Linting
npm run lint
```

## License

MIT
4 changes: 4 additions & 0 deletions packages/mcp-server-mysql/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { config } from "@roo-code/config-eslint/base"

/** @type {import("eslint").Linter.Config} */
export default [...config]
43 changes: 43 additions & 0 deletions packages/mcp-server-mysql/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@roo-code/mcp-server-mysql",
"version": "0.1.0",
"description": "MySQL MCP server for Roo Code",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsx src/index.ts",
"start": "node dist/index.js",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint src --ext .ts",
"typecheck": "tsc --noEmit"
},
"keywords": [
"mcp",
"mysql",
"database",
"model-context-protocol"
],
"author": "Roo Code Inc",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.9.0",
"mysql2": "^3.11.5",
"zod": "^3.24.1"
},
"devDependencies": {
"@roo-code/config-eslint": "workspace:*",
"@types/node": "^22.10.5",
"@typescript-eslint/eslint-plugin": "^8.20.0",
"@typescript-eslint/parser": "^8.20.0",
"eslint": "^9.18.0",
"tsx": "^4.19.2",
"typescript": "^5.7.3",
"vitest": "^2.1.8"
},
"engines": {
"node": ">=18"
}
}
43 changes: 43 additions & 0 deletions packages/mcp-server-mysql/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, it, expect, beforeAll, afterAll, vi } from "vitest"
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"

// Mock the mysql2/promise module
vi.mock("mysql2/promise", () => ({
default: {
createPool: vi.fn(() => ({
getConnection: vi.fn(() => ({
execute: vi.fn(() => [[{ Database: "test_db" }], [{ name: "Database" }]]),
ping: vi.fn(),
changeUser: vi.fn(),
release: vi.fn(),
})),
})),
},
}))

describe("MySQL MCP Server", () => {
it("should create server instance", () => {
const server = new McpServer({
name: "mysql-server",
version: "0.1.0",
description: "MySQL database operations via MCP",
})

expect(server).toBeDefined()
})

it("should have required tools", async () => {
const { server } = await import("./index.js")

// Check if tools are registered
const tools = server.getTools()
const toolNames = tools.map((tool) => tool.name)

expect(toolNames).toContain("query")
expect(toolNames).toContain("execute")
expect(toolNames).toContain("list_databases")
expect(toolNames).toContain("list_tables")
expect(toolNames).toContain("describe_table")
expect(toolNames).toContain("test_connection")
})
})
Loading
Loading