@rog0x/mcp-database-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # mcp-database-tools
2
+
3
+ MCP server providing SQL and database tools for AI agents. All analysis is performed on SQL text — no actual database connection required.
4
+
5
+ ## Tools
6
+
7
+ ### sql_format
8
+ Format and prettify SQL queries with proper indentation, uppercased keywords, and aligned columns. Supports MySQL, PostgreSQL, and SQLite syntax.
9
+
10
+ ### sql_explain
11
+ Take a SQL query and explain what it does in plain English, step by step. Identifies query type, tables, columns, conditions, and provides optimization tips.
12
+
13
+ ### schema_analyze
14
+ Parse CREATE TABLE statements to extract tables, columns, types, constraints, foreign keys, and indexes. Generates an ER diagram in Mermaid format.
15
+
16
+ ### query_build
17
+ Build SQL queries from natural language descriptions. Supports common patterns like filtering by date, aggregation, joins, ordering, and pagination.
18
+
19
+ ### migration_generate
20
+ Compare two schemas (old vs new CREATE TABLE statements) and generate ALTER TABLE migration statements. Produces both up (forward) and down (rollback) migrations.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install
26
+ npm run build
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### With Claude Desktop
32
+
33
+ Add to your Claude Desktop config (`claude_desktop_config.json`):
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "database-tools": {
39
+ "command": "node",
40
+ "args": ["path/to/mcp-database-tools/dist/index.js"]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Standalone
47
+
48
+ ```bash
49
+ npm start
50
+ ```
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ npm run build # Compile TypeScript
56
+ npm start # Run the server
57
+ ```
58
+
59
+ ## License
60
+
61
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
7
+ const sql_formatter_js_1 = require("./tools/sql-formatter.js");
8
+ const sql_explainer_js_1 = require("./tools/sql-explainer.js");
9
+ const schema_analyzer_js_1 = require("./tools/schema-analyzer.js");
10
+ const query_builder_js_1 = require("./tools/query-builder.js");
11
+ const migration_generator_js_1 = require("./tools/migration-generator.js");
12
+ const server = new index_js_1.Server({
13
+ name: "mcp-database-tools",
14
+ version: "1.0.0",
15
+ }, {
16
+ capabilities: {
17
+ tools: {},
18
+ },
19
+ });
20
+ // List available tools
21
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
22
+ tools: [
23
+ {
24
+ name: "sql_format",
25
+ description: "Format and prettify SQL queries with proper indentation, uppercased keywords, and aligned columns. Supports MySQL, PostgreSQL, and SQLite syntax.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ sql: {
30
+ type: "string",
31
+ description: "The SQL query to format",
32
+ },
33
+ dialect: {
34
+ type: "string",
35
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
36
+ description: "SQL dialect (default: generic)",
37
+ },
38
+ indent_size: {
39
+ type: "number",
40
+ description: "Number of spaces for indentation (default: 2)",
41
+ },
42
+ uppercase: {
43
+ type: "boolean",
44
+ description: "Uppercase SQL keywords (default: true)",
45
+ },
46
+ align_columns: {
47
+ type: "boolean",
48
+ description: "Place each SELECT column on its own line (default: true)",
49
+ },
50
+ },
51
+ required: ["sql"],
52
+ },
53
+ },
54
+ {
55
+ name: "sql_explain",
56
+ description: "Take a SQL query and explain what it does in plain English, step by step. Identifies tables, columns, conditions, and provides optimization tips.",
57
+ inputSchema: {
58
+ type: "object",
59
+ properties: {
60
+ sql: {
61
+ type: "string",
62
+ description: "The SQL query to explain",
63
+ },
64
+ },
65
+ required: ["sql"],
66
+ },
67
+ },
68
+ {
69
+ name: "schema_analyze",
70
+ description: "Parse CREATE TABLE statements to extract tables, columns, types, constraints, foreign keys, and indexes. Generates an ER diagram in Mermaid format.",
71
+ inputSchema: {
72
+ type: "object",
73
+ properties: {
74
+ sql: {
75
+ type: "string",
76
+ description: "SQL containing CREATE TABLE statements (can include multiple tables)",
77
+ },
78
+ },
79
+ required: ["sql"],
80
+ },
81
+ },
82
+ {
83
+ name: "query_build",
84
+ description: 'Build SQL queries from natural language descriptions. Example: "get all users who signed up this month and have at least 3 orders" generates the corresponding SQL.',
85
+ inputSchema: {
86
+ type: "object",
87
+ properties: {
88
+ description: {
89
+ type: "string",
90
+ description: "Natural language description of the desired query",
91
+ },
92
+ dialect: {
93
+ type: "string",
94
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
95
+ description: "SQL dialect (default: postgresql)",
96
+ },
97
+ schema_hint: {
98
+ type: "string",
99
+ description: "Optional schema context (table/column names) to improve accuracy",
100
+ },
101
+ },
102
+ required: ["description"],
103
+ },
104
+ },
105
+ {
106
+ name: "migration_generate",
107
+ description: "Compare two schemas (old vs new CREATE TABLE statements) and generate ALTER TABLE migration statements with both up and down migrations.",
108
+ inputSchema: {
109
+ type: "object",
110
+ properties: {
111
+ old_schema: {
112
+ type: "string",
113
+ description: "The old/current schema (CREATE TABLE statements)",
114
+ },
115
+ new_schema: {
116
+ type: "string",
117
+ description: "The new/target schema (CREATE TABLE statements)",
118
+ },
119
+ dialect: {
120
+ type: "string",
121
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
122
+ description: "SQL dialect for migration syntax (default: postgresql)",
123
+ },
124
+ },
125
+ required: ["old_schema", "new_schema"],
126
+ },
127
+ },
128
+ ],
129
+ }));
130
+ // Handle tool calls
131
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
132
+ const { name, arguments: args } = request.params;
133
+ try {
134
+ switch (name) {
135
+ case "sql_format": {
136
+ const result = (0, sql_formatter_js_1.sqlFormatter)(args?.sql, args?.dialect, args?.indent_size, args?.uppercase, args?.align_columns);
137
+ return {
138
+ content: [{ type: "text", text: result }],
139
+ };
140
+ }
141
+ case "sql_explain": {
142
+ const result = (0, sql_explainer_js_1.sqlExplainer)(args?.sql);
143
+ return {
144
+ content: [
145
+ { type: "text", text: JSON.stringify(result, null, 2) },
146
+ ],
147
+ };
148
+ }
149
+ case "schema_analyze": {
150
+ const result = (0, schema_analyzer_js_1.schemaAnalyzer)(args?.sql);
151
+ return {
152
+ content: [
153
+ { type: "text", text: JSON.stringify(result, null, 2) },
154
+ ],
155
+ };
156
+ }
157
+ case "query_build": {
158
+ const result = (0, query_builder_js_1.queryBuilder)(args?.description, args?.dialect, args?.schema_hint);
159
+ return {
160
+ content: [
161
+ { type: "text", text: JSON.stringify(result, null, 2) },
162
+ ],
163
+ };
164
+ }
165
+ case "migration_generate": {
166
+ const result = (0, migration_generator_js_1.migrationGenerator)(args?.old_schema, args?.new_schema, args?.dialect);
167
+ return {
168
+ content: [
169
+ { type: "text", text: JSON.stringify(result, null, 2) },
170
+ ],
171
+ };
172
+ }
173
+ default:
174
+ throw new Error(`Unknown tool: ${name}`);
175
+ }
176
+ }
177
+ catch (error) {
178
+ return {
179
+ content: [{ type: "text", text: `Error: ${error.message}` }],
180
+ isError: true,
181
+ };
182
+ }
183
+ });
184
+ // Start server
185
+ async function main() {
186
+ const transport = new stdio_js_1.StdioServerTransport();
187
+ await server.connect(transport);
188
+ console.error("MCP Database Tools server running on stdio");
189
+ }
190
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@rog0x/mcp-database-tools",
3
+ "version": "1.0.0",
4
+ "description": "MCP server providing SQL and database tools for AI agents - format, explain, analyze, build, and migrate SQL without a DB connection",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "mcp-database-tools": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "dev": "ts-node src/index.ts"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "claude",
17
+ "ai",
18
+ "sql",
19
+ "database",
20
+ "formatter",
21
+ "migration",
22
+ "schema"
23
+ ],
24
+ "author": "rog0x",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/rog0x/mcp-database-tools"
29
+ },
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.0.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.0.0",
35
+ "typescript": "^5.4.0"
36
+ }
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,227 @@
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
+ ListToolsRequestSchema,
8
+ } from "@modelcontextprotocol/sdk/types.js";
9
+ import { sqlFormatter } from "./tools/sql-formatter.js";
10
+ import { sqlExplainer } from "./tools/sql-explainer.js";
11
+ import { schemaAnalyzer } from "./tools/schema-analyzer.js";
12
+ import { queryBuilder } from "./tools/query-builder.js";
13
+ import { migrationGenerator } from "./tools/migration-generator.js";
14
+
15
+ const server = new Server(
16
+ {
17
+ name: "mcp-database-tools",
18
+ version: "1.0.0",
19
+ },
20
+ {
21
+ capabilities: {
22
+ tools: {},
23
+ },
24
+ }
25
+ );
26
+
27
+ // List available tools
28
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
29
+ tools: [
30
+ {
31
+ name: "sql_format",
32
+ description:
33
+ "Format and prettify SQL queries with proper indentation, uppercased keywords, and aligned columns. Supports MySQL, PostgreSQL, and SQLite syntax.",
34
+ inputSchema: {
35
+ type: "object" as const,
36
+ properties: {
37
+ sql: {
38
+ type: "string",
39
+ description: "The SQL query to format",
40
+ },
41
+ dialect: {
42
+ type: "string",
43
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
44
+ description: "SQL dialect (default: generic)",
45
+ },
46
+ indent_size: {
47
+ type: "number",
48
+ description: "Number of spaces for indentation (default: 2)",
49
+ },
50
+ uppercase: {
51
+ type: "boolean",
52
+ description: "Uppercase SQL keywords (default: true)",
53
+ },
54
+ align_columns: {
55
+ type: "boolean",
56
+ description:
57
+ "Place each SELECT column on its own line (default: true)",
58
+ },
59
+ },
60
+ required: ["sql"],
61
+ },
62
+ },
63
+ {
64
+ name: "sql_explain",
65
+ description:
66
+ "Take a SQL query and explain what it does in plain English, step by step. Identifies tables, columns, conditions, and provides optimization tips.",
67
+ inputSchema: {
68
+ type: "object" as const,
69
+ properties: {
70
+ sql: {
71
+ type: "string",
72
+ description: "The SQL query to explain",
73
+ },
74
+ },
75
+ required: ["sql"],
76
+ },
77
+ },
78
+ {
79
+ name: "schema_analyze",
80
+ description:
81
+ "Parse CREATE TABLE statements to extract tables, columns, types, constraints, foreign keys, and indexes. Generates an ER diagram in Mermaid format.",
82
+ inputSchema: {
83
+ type: "object" as const,
84
+ properties: {
85
+ sql: {
86
+ type: "string",
87
+ description:
88
+ "SQL containing CREATE TABLE statements (can include multiple tables)",
89
+ },
90
+ },
91
+ required: ["sql"],
92
+ },
93
+ },
94
+ {
95
+ name: "query_build",
96
+ description:
97
+ 'Build SQL queries from natural language descriptions. Example: "get all users who signed up this month and have at least 3 orders" generates the corresponding SQL.',
98
+ inputSchema: {
99
+ type: "object" as const,
100
+ properties: {
101
+ description: {
102
+ type: "string",
103
+ description: "Natural language description of the desired query",
104
+ },
105
+ dialect: {
106
+ type: "string",
107
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
108
+ description: "SQL dialect (default: postgresql)",
109
+ },
110
+ schema_hint: {
111
+ type: "string",
112
+ description:
113
+ "Optional schema context (table/column names) to improve accuracy",
114
+ },
115
+ },
116
+ required: ["description"],
117
+ },
118
+ },
119
+ {
120
+ name: "migration_generate",
121
+ description:
122
+ "Compare two schemas (old vs new CREATE TABLE statements) and generate ALTER TABLE migration statements with both up and down migrations.",
123
+ inputSchema: {
124
+ type: "object" as const,
125
+ properties: {
126
+ old_schema: {
127
+ type: "string",
128
+ description: "The old/current schema (CREATE TABLE statements)",
129
+ },
130
+ new_schema: {
131
+ type: "string",
132
+ description: "The new/target schema (CREATE TABLE statements)",
133
+ },
134
+ dialect: {
135
+ type: "string",
136
+ enum: ["mysql", "postgresql", "sqlite", "generic"],
137
+ description: "SQL dialect for migration syntax (default: postgresql)",
138
+ },
139
+ },
140
+ required: ["old_schema", "new_schema"],
141
+ },
142
+ },
143
+ ],
144
+ }));
145
+
146
+ // Handle tool calls
147
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
148
+ const { name, arguments: args } = request.params;
149
+
150
+ try {
151
+ switch (name) {
152
+ case "sql_format": {
153
+ const result = sqlFormatter(
154
+ args?.sql as string,
155
+ args?.dialect as string | undefined,
156
+ args?.indent_size as number | undefined,
157
+ args?.uppercase as boolean | undefined,
158
+ args?.align_columns as boolean | undefined
159
+ );
160
+ return {
161
+ content: [{ type: "text", text: result }],
162
+ };
163
+ }
164
+
165
+ case "sql_explain": {
166
+ const result = sqlExplainer(args?.sql as string);
167
+ return {
168
+ content: [
169
+ { type: "text", text: JSON.stringify(result, null, 2) },
170
+ ],
171
+ };
172
+ }
173
+
174
+ case "schema_analyze": {
175
+ const result = schemaAnalyzer(args?.sql as string);
176
+ return {
177
+ content: [
178
+ { type: "text", text: JSON.stringify(result, null, 2) },
179
+ ],
180
+ };
181
+ }
182
+
183
+ case "query_build": {
184
+ const result = queryBuilder(
185
+ args?.description as string,
186
+ args?.dialect as string | undefined,
187
+ args?.schema_hint as string | undefined
188
+ );
189
+ return {
190
+ content: [
191
+ { type: "text", text: JSON.stringify(result, null, 2) },
192
+ ],
193
+ };
194
+ }
195
+
196
+ case "migration_generate": {
197
+ const result = migrationGenerator(
198
+ args?.old_schema as string,
199
+ args?.new_schema as string,
200
+ args?.dialect as string | undefined
201
+ );
202
+ return {
203
+ content: [
204
+ { type: "text", text: JSON.stringify(result, null, 2) },
205
+ ],
206
+ };
207
+ }
208
+
209
+ default:
210
+ throw new Error(`Unknown tool: ${name}`);
211
+ }
212
+ } catch (error: any) {
213
+ return {
214
+ content: [{ type: "text", text: `Error: ${error.message}` }],
215
+ isError: true,
216
+ };
217
+ }
218
+ });
219
+
220
+ // Start server
221
+ async function main() {
222
+ const transport = new StdioServerTransport();
223
+ await server.connect(transport);
224
+ console.error("MCP Database Tools server running on stdio");
225
+ }
226
+
227
+ main().catch(console.error);