mirror of
https://github.com/executeautomation/mcp-database-server.git
synced 2025-12-09 21:12:57 +08:00
Add MySQL support to MCP Database Server
Updated package.json and package-lock.json to include MySQL dependencies. Enhanced README with MySQL usage instructions and configuration details. Modified index.ts to handle MySQL connection parameters and logging. Added MysqlAdapter for database interactions.
This commit is contained in:
100
package-lock.json
generated
100
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "1.9.0",
|
"@modelcontextprotocol/sdk": "1.9.0",
|
||||||
"mssql": "11.0.1",
|
"mssql": "11.0.1",
|
||||||
|
"mysql2": "^3.14.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"sqlite3": "5.1.7"
|
"sqlite3": "5.1.7"
|
||||||
},
|
},
|
||||||
@@ -639,6 +640,14 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/aws-ssl-profiles": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -1124,6 +1133,14 @@
|
|||||||
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@@ -1645,6 +1662,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
@@ -2032,6 +2057,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
|
||||||
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/is-property": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
|
},
|
||||||
"node_modules/is-stream": {
|
"node_modules/is-stream": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
@@ -2180,12 +2210,31 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/long": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "10.4.3",
|
"version": "10.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/lru.min": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
|
||||||
|
"engines": {
|
||||||
|
"bun": ">=1.0.0",
|
||||||
|
"deno": ">=1.30.0",
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/wellwelwel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/make-fetch-happen": {
|
"node_modules/make-fetch-happen": {
|
||||||
"version": "9.1.0",
|
"version": "9.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
|
||||||
@@ -2545,6 +2594,44 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mysql2": {
|
||||||
|
"version": "3.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==",
|
||||||
|
"dependencies": {
|
||||||
|
"aws-ssl-profiles": "^1.1.1",
|
||||||
|
"denque": "^2.1.0",
|
||||||
|
"generate-function": "^2.3.1",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"long": "^5.2.1",
|
||||||
|
"lru.min": "^1.0.0",
|
||||||
|
"named-placeholders": "^1.1.3",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^7.14.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||||
|
"version": "7.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/napi-build-utils": {
|
"node_modules/napi-build-utils": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
||||||
@@ -3413,6 +3500,11 @@
|
|||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
"node_modules/serve-static": {
|
"node_modules/serve-static": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
|
||||||
@@ -3688,6 +3780,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ssri": {
|
"node_modules/ssri": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "1.9.0",
|
"@modelcontextprotocol/sdk": "1.9.0",
|
||||||
"mssql": "11.0.1",
|
"mssql": "11.0.1",
|
||||||
|
"mysql2": "^3.14.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"sqlite3": "5.1.7"
|
"sqlite3": "5.1.7"
|
||||||
},
|
},
|
||||||
|
|||||||
44
readme.md
44
readme.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# MCP Database Server
|
# MCP Database Server
|
||||||
|
|
||||||
This MCP (Model Context Protocol) server provides database access capabilities to Claude, supporting SQLite, SQL Server, and PostgreSQL databases.
|
This MCP (Model Context Protocol) server provides database access capabilities to Claude, supporting SQLite, SQL Server, PostgreSQL, and MySQL databases.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -92,6 +92,25 @@ Optional parameters:
|
|||||||
- `--ssl`: Enable SSL connection (true/false)
|
- `--ssl`: Enable SSL connection (true/false)
|
||||||
- `--connection-timeout`: Connection timeout in milliseconds (default: 30000)
|
- `--connection-timeout`: Connection timeout in milliseconds (default: 30000)
|
||||||
|
|
||||||
|
### MySQL Database
|
||||||
|
|
||||||
|
To use with a MySQL database:
|
||||||
|
|
||||||
|
```
|
||||||
|
node dist/src/index.js --mysql --host <host-name> --database <database-name> [--user <username> --password <password>]
|
||||||
|
```
|
||||||
|
|
||||||
|
Required parameters:
|
||||||
|
- `--host`: MySQL host name or IP address
|
||||||
|
- `--database`: Name of the database
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
- `--user`: Username for MySQL authentication
|
||||||
|
- `--password`: Password for MySQL authentication
|
||||||
|
- `--port`: Port number (default: 3306)
|
||||||
|
- `--ssl`: Enable SSL connection (true/false or object)
|
||||||
|
- `--connection-timeout`: Connection timeout in milliseconds (default: 30000)
|
||||||
|
|
||||||
## Configuring Claude Desktop
|
## Configuring Claude Desktop
|
||||||
|
|
||||||
### Direct Usage Configuration
|
### Direct Usage Configuration
|
||||||
@@ -132,6 +151,18 @@ If you installed the package globally, configure Claude Desktop with:
|
|||||||
"--user", "your-username",
|
"--user", "your-username",
|
||||||
"--password", "your-password"
|
"--password", "your-password"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@executeautomation/database-server",
|
||||||
|
"--mysql",
|
||||||
|
"--host", "your-host-name",
|
||||||
|
"--database", "your-database-name",
|
||||||
|
"--user", "your-username",
|
||||||
|
"--password", "your-password"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,6 +203,17 @@ For local development, configure Claude Desktop to use your locally built versio
|
|||||||
"--user", "your-username",
|
"--user", "your-username",
|
||||||
"--password", "your-password"
|
"--password", "your-password"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"command": "node",
|
||||||
|
"args": [
|
||||||
|
"/absolute/path/to/mcp-database-server/dist/src/index.js",
|
||||||
|
"--mysql",
|
||||||
|
"--host", "your-host-name",
|
||||||
|
"--database", "your-database-name",
|
||||||
|
"--user", "your-username",
|
||||||
|
"--password", "your-password"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export interface DbAdapter {
|
|||||||
import { SqliteAdapter } from './sqlite-adapter.js';
|
import { SqliteAdapter } from './sqlite-adapter.js';
|
||||||
import { SqlServerAdapter } from './sqlserver-adapter.js';
|
import { SqlServerAdapter } from './sqlserver-adapter.js';
|
||||||
import { PostgresqlAdapter } from './postgresql-adapter.js';
|
import { PostgresqlAdapter } from './postgresql-adapter.js';
|
||||||
|
import { MysqlAdapter } from './mysql-adapter.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory function to create the appropriate database adapter
|
* Factory function to create the appropriate database adapter
|
||||||
@@ -72,6 +73,8 @@ export function createDbAdapter(type: string, connectionInfo: any): DbAdapter {
|
|||||||
case 'postgresql':
|
case 'postgresql':
|
||||||
case 'postgres':
|
case 'postgres':
|
||||||
return new PostgresqlAdapter(connectionInfo);
|
return new PostgresqlAdapter(connectionInfo);
|
||||||
|
case 'mysql':
|
||||||
|
return new MysqlAdapter(connectionInfo);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported database type: ${type}`);
|
throw new Error(`Unsupported database type: ${type}`);
|
||||||
}
|
}
|
||||||
|
|||||||
135
src/db/mysql-adapter.ts
Normal file
135
src/db/mysql-adapter.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import { DbAdapter } from "./adapter.js";
|
||||||
|
import mysql from "mysql2/promise";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL database adapter implementation
|
||||||
|
*/
|
||||||
|
export class MysqlAdapter implements DbAdapter {
|
||||||
|
private connection: mysql.Connection | null = null;
|
||||||
|
private config: mysql.ConnectionOptions;
|
||||||
|
private host: string;
|
||||||
|
private database: string;
|
||||||
|
|
||||||
|
constructor(connectionInfo: {
|
||||||
|
host: string;
|
||||||
|
database: string;
|
||||||
|
user?: string;
|
||||||
|
password?: string;
|
||||||
|
port?: number;
|
||||||
|
ssl?: boolean | object;
|
||||||
|
connectionTimeout?: number;
|
||||||
|
}) {
|
||||||
|
this.host = connectionInfo.host;
|
||||||
|
this.database = connectionInfo.database;
|
||||||
|
this.config = {
|
||||||
|
host: connectionInfo.host,
|
||||||
|
database: connectionInfo.database,
|
||||||
|
port: connectionInfo.port || 3306,
|
||||||
|
user: connectionInfo.user,
|
||||||
|
password: connectionInfo.password,
|
||||||
|
connectTimeout: connectionInfo.connectionTimeout || 30000,
|
||||||
|
multipleStatements: true,
|
||||||
|
};
|
||||||
|
if (typeof connectionInfo.ssl === 'object' || typeof connectionInfo.ssl === 'string') {
|
||||||
|
this.config.ssl = connectionInfo.ssl;
|
||||||
|
} else if (connectionInfo.ssl === true) {
|
||||||
|
this.config.ssl = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize MySQL connection
|
||||||
|
*/
|
||||||
|
async init(): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.error(`[INFO] Connecting to MySQL: ${this.host}, Database: ${this.database}`);
|
||||||
|
this.connection = await mysql.createConnection(this.config);
|
||||||
|
console.error(`[INFO] MySQL connection established successfully`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[ERROR] MySQL connection error: ${(err as Error).message}`);
|
||||||
|
throw new Error(`Failed to connect to MySQL: ${(err as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a SQL query and get all results
|
||||||
|
*/
|
||||||
|
async all(query: string, params: any[] = []): Promise<any[]> {
|
||||||
|
if (!this.connection) {
|
||||||
|
throw new Error("Database not initialized");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const [rows] = await this.connection.execute(query, params);
|
||||||
|
return Array.isArray(rows) ? rows : [];
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`MySQL query error: ${(err as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a SQL query that modifies data
|
||||||
|
*/
|
||||||
|
async run(query: string, params: any[] = []): Promise<{ changes: number, lastID: number }> {
|
||||||
|
if (!this.connection) {
|
||||||
|
throw new Error("Database not initialized");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const [result]: any = await this.connection.execute(query, params);
|
||||||
|
const changes = result.affectedRows || 0;
|
||||||
|
const lastID = result.insertId || 0;
|
||||||
|
return { changes, lastID };
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`MySQL query error: ${(err as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute multiple SQL statements
|
||||||
|
*/
|
||||||
|
async exec(query: string): Promise<void> {
|
||||||
|
if (!this.connection) {
|
||||||
|
throw new Error("Database not initialized");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.connection.query(query);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`MySQL batch error: ${(err as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the database connection
|
||||||
|
*/
|
||||||
|
async close(): Promise<void> {
|
||||||
|
if (this.connection) {
|
||||||
|
await this.connection.end();
|
||||||
|
this.connection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get database metadata
|
||||||
|
*/
|
||||||
|
getMetadata(): { name: string; type: string; server: string; database: string } {
|
||||||
|
return {
|
||||||
|
name: "MySQL",
|
||||||
|
type: "mysql",
|
||||||
|
server: this.host,
|
||||||
|
database: this.database,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get database-specific query for listing tables
|
||||||
|
*/
|
||||||
|
getListTablesQuery(): string {
|
||||||
|
return "SHOW TABLES";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get database-specific query for describing a table
|
||||||
|
*/
|
||||||
|
getDescribeTableQuery(tableName: string): string {
|
||||||
|
return `DESCRIBE \`${tableName}\``;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/index.ts
42
src/index.ts
@@ -45,6 +45,7 @@ if (args.length === 0) {
|
|||||||
logger.error("Usage for SQLite: node index.js <database_file_path>");
|
logger.error("Usage for SQLite: node index.js <database_file_path>");
|
||||||
logger.error("Usage for SQL Server: node index.js --sqlserver --server <server> --database <database> [--user <user> --password <password>]");
|
logger.error("Usage for SQL Server: node index.js --sqlserver --server <server> --database <database> [--user <user> --password <password>]");
|
||||||
logger.error("Usage for PostgreSQL: node index.js --postgresql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
|
logger.error("Usage for PostgreSQL: node index.js --postgresql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
|
||||||
|
logger.error("Usage for MySQL: node index.js --mysql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +121,45 @@ else if (args.includes('--postgresql') || args.includes('--postgres')) {
|
|||||||
logger.error("Error: PostgreSQL requires --host and --database parameters");
|
logger.error("Error: PostgreSQL requires --host and --database parameters");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// Check if using MySQL
|
||||||
|
else if (args.includes('--mysql')) {
|
||||||
|
dbType = 'mysql';
|
||||||
|
connectionInfo = {
|
||||||
|
host: '',
|
||||||
|
database: '',
|
||||||
|
user: undefined,
|
||||||
|
password: undefined,
|
||||||
|
port: undefined,
|
||||||
|
ssl: undefined,
|
||||||
|
connectionTimeout: undefined
|
||||||
|
};
|
||||||
|
// Parse MySQL connection parameters
|
||||||
|
for (let i = 0; i < args.length; i++) {
|
||||||
|
if (args[i] === '--host' && i + 1 < args.length) {
|
||||||
|
connectionInfo.host = args[i + 1];
|
||||||
|
} else if (args[i] === '--database' && i + 1 < args.length) {
|
||||||
|
connectionInfo.database = args[i + 1];
|
||||||
|
} else if (args[i] === '--user' && i + 1 < args.length) {
|
||||||
|
connectionInfo.user = args[i + 1];
|
||||||
|
} else if (args[i] === '--password' && i + 1 < args.length) {
|
||||||
|
connectionInfo.password = args[i + 1];
|
||||||
|
} else if (args[i] === '--port' && i + 1 < args.length) {
|
||||||
|
connectionInfo.port = parseInt(args[i + 1], 10);
|
||||||
|
} else if (args[i] === '--ssl' && i + 1 < args.length) {
|
||||||
|
const sslVal = args[i + 1];
|
||||||
|
if (sslVal === 'true') connectionInfo.ssl = true;
|
||||||
|
else if (sslVal === 'false') connectionInfo.ssl = false;
|
||||||
|
else connectionInfo.ssl = sslVal;
|
||||||
|
} else if (args[i] === '--connection-timeout' && i + 1 < args.length) {
|
||||||
|
connectionInfo.connectionTimeout = parseInt(args[i + 1], 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Validate MySQL connection info
|
||||||
|
if (!connectionInfo.host || !connectionInfo.database) {
|
||||||
|
logger.error("Error: MySQL requires --host and --database parameters");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// SQLite mode (default)
|
// SQLite mode (default)
|
||||||
dbType = 'sqlite';
|
dbType = 'sqlite';
|
||||||
@@ -178,6 +218,8 @@ async function runServer() {
|
|||||||
logger.info(`Server: ${connectionInfo.server}, Database: ${connectionInfo.database}`);
|
logger.info(`Server: ${connectionInfo.server}, Database: ${connectionInfo.database}`);
|
||||||
} else if (dbType === 'postgresql') {
|
} else if (dbType === 'postgresql') {
|
||||||
logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`);
|
logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`);
|
||||||
|
} else if (dbType === 'mysql') {
|
||||||
|
logger.info(`Host: ${connectionInfo.host}, Database: ${connectionInfo.database}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the database
|
// Initialize the database
|
||||||
|
|||||||
Reference in New Issue
Block a user