@bytebase/dbhub 0.0.8 → 0.1.1
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 +34 -33
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1489 -13
- package/dist/resources/employee-sqlite/employee.sql +117 -0
- package/dist/resources/employee-sqlite/load_department.sql +10 -0
- package/dist/resources/employee-sqlite/load_dept_emp.sql +1103 -0
- package/dist/resources/employee-sqlite/load_dept_manager.sql +17 -0
- package/dist/resources/employee-sqlite/load_employee.sql +1000 -0
- package/dist/resources/employee-sqlite/load_salary1.sql +9488 -0
- package/dist/resources/employee-sqlite/load_title.sql +1470 -0
- package/dist/resources/employee-sqlite/object.sql +74 -0
- package/dist/resources/employee-sqlite/show_elapsed.sql +4 -0
- package/dist/resources/employee-sqlite/test_employee_md5.sql +119 -0
- package/package.json +5 -4
- package/dist/config/demo-loader.js +0 -45
- package/dist/config/env.js +0 -146
- package/dist/connectors/interface.js +0 -55
- package/dist/connectors/manager.js +0 -91
- package/dist/connectors/mysql/index.js +0 -169
- package/dist/connectors/postgres/index.js +0 -172
- package/dist/connectors/sqlite/index.js +0 -208
- package/dist/connectors/sqlserver/index.js +0 -186
- package/dist/prompts/db-explainer.js +0 -201
- package/dist/prompts/index.js +0 -11
- package/dist/prompts/sql-generator.js +0 -114
- package/dist/resources/index.js +0 -12
- package/dist/resources/schema.js +0 -36
- package/dist/resources/tables.js +0 -17
- package/dist/server.js +0 -140
- package/dist/tools/index.js +0 -11
- package/dist/tools/list-connectors.js +0 -23
- package/dist/tools/run-query.js +0 -32
- package/dist/utils/response-formatter.js +0 -109
package/dist/server.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
3
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import express from 'express';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { readFileSync } from 'fs';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
8
|
-
import { ConnectorManager } from './connectors/manager.js';
|
|
9
|
-
import { ConnectorRegistry } from './connectors/interface.js';
|
|
10
|
-
import { resolveDSN, resolveTransport, resolvePort } from './config/env.js';
|
|
11
|
-
import { getSqliteInMemorySetupSql } from './config/demo-loader.js';
|
|
12
|
-
import { registerResources } from './resources/index.js';
|
|
13
|
-
import { registerTools } from './tools/index.js';
|
|
14
|
-
import { registerPrompts } from './prompts/index.js';
|
|
15
|
-
// Create __dirname equivalent for ES modules
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = path.dirname(__filename);
|
|
18
|
-
// Load package.json to get version
|
|
19
|
-
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
20
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
21
|
-
// Server info
|
|
22
|
-
export const SERVER_NAME = "DBHub MCP Server";
|
|
23
|
-
export const SERVER_VERSION = packageJson.version;
|
|
24
|
-
/**
|
|
25
|
-
* Generate ASCII art banner with version information
|
|
26
|
-
*/
|
|
27
|
-
export function generateBanner(version, isDemo = false) {
|
|
28
|
-
const demoText = isDemo ? " [DEMO MODE]" : "";
|
|
29
|
-
return `
|
|
30
|
-
_____ ____ _ _ _
|
|
31
|
-
| __ \\| _ \\| | | | | |
|
|
32
|
-
| | | | |_) | |_| |_ _| |__
|
|
33
|
-
| | | | _ <| _ | | | | '_ \\
|
|
34
|
-
| |__| | |_) | | | | |_| | |_) |
|
|
35
|
-
|_____/|____/|_| |_|\\__,_|_.__/
|
|
36
|
-
|
|
37
|
-
v${version}${demoText} - Universal Database MCP Server
|
|
38
|
-
`;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Initialize and start the DBHub server
|
|
42
|
-
*/
|
|
43
|
-
export async function main() {
|
|
44
|
-
try {
|
|
45
|
-
// Resolve DSN from command line args, environment variables, or .env files
|
|
46
|
-
const dsnData = resolveDSN();
|
|
47
|
-
if (!dsnData) {
|
|
48
|
-
const samples = ConnectorRegistry.getAllSampleDSNs();
|
|
49
|
-
const sampleFormats = Object.entries(samples)
|
|
50
|
-
.map(([id, dsn]) => ` - ${id}: ${dsn}`)
|
|
51
|
-
.join('\n');
|
|
52
|
-
console.error(`
|
|
53
|
-
ERROR: Database connection string (DSN) is required.
|
|
54
|
-
Please provide the DSN in one of these ways (in order of priority):
|
|
55
|
-
|
|
56
|
-
1. Use demo mode: --demo (uses in-memory SQLite with sample employee database)
|
|
57
|
-
2. Command line argument: --dsn="your-connection-string"
|
|
58
|
-
3. Environment variable: export DSN="your-connection-string"
|
|
59
|
-
4. .env file: DSN=your-connection-string
|
|
60
|
-
|
|
61
|
-
Example formats:
|
|
62
|
-
${sampleFormats}
|
|
63
|
-
|
|
64
|
-
See documentation for more details on configuring database connections.
|
|
65
|
-
`);
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
// Create MCP server
|
|
69
|
-
const server = new McpServer({
|
|
70
|
-
name: SERVER_NAME,
|
|
71
|
-
version: SERVER_VERSION
|
|
72
|
-
});
|
|
73
|
-
// Register resources, tools, and prompts
|
|
74
|
-
registerResources(server);
|
|
75
|
-
registerTools(server);
|
|
76
|
-
registerPrompts(server);
|
|
77
|
-
// Create connector manager and connect to database
|
|
78
|
-
const connectorManager = new ConnectorManager();
|
|
79
|
-
console.error(`Connecting with DSN: ${dsnData.dsn}`);
|
|
80
|
-
console.error(`DSN source: ${dsnData.source}`);
|
|
81
|
-
// If in demo mode, load the employee database
|
|
82
|
-
if (dsnData.isDemo) {
|
|
83
|
-
console.error('Running in demo mode with sample employee database');
|
|
84
|
-
const initScript = getSqliteInMemorySetupSql();
|
|
85
|
-
await connectorManager.connectWithDSN(dsnData.dsn, initScript);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
await connectorManager.connectWithDSN(dsnData.dsn);
|
|
89
|
-
}
|
|
90
|
-
// Resolve transport type
|
|
91
|
-
const transportData = resolveTransport();
|
|
92
|
-
console.error(`Using transport: ${transportData.type}`);
|
|
93
|
-
console.error(`Transport source: ${transportData.source}`);
|
|
94
|
-
// Print ASCII art banner with version and slogan
|
|
95
|
-
console.error(generateBanner(SERVER_VERSION, dsnData.isDemo));
|
|
96
|
-
// Set up transport based on type
|
|
97
|
-
if (transportData.type === 'sse') {
|
|
98
|
-
// Set up Express server for SSE transport
|
|
99
|
-
const app = express();
|
|
100
|
-
let transport;
|
|
101
|
-
app.get("/sse", async (req, res) => {
|
|
102
|
-
transport = new SSEServerTransport("/message", res);
|
|
103
|
-
console.error("Client connected", transport?.['_sessionId']);
|
|
104
|
-
await server.connect(transport);
|
|
105
|
-
// Listen for connection close
|
|
106
|
-
res.on('close', () => {
|
|
107
|
-
console.error("Client Disconnected", transport?.['_sessionId']);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
app.post("/message", async (req, res) => {
|
|
111
|
-
console.error("Client Message", transport?.['_sessionId']);
|
|
112
|
-
await transport.handlePostMessage(req, res, req.body);
|
|
113
|
-
});
|
|
114
|
-
// Start the HTTP server (port is only relevant for SSE transport)
|
|
115
|
-
const portData = resolvePort();
|
|
116
|
-
const port = portData.port;
|
|
117
|
-
console.error(`Port source: ${portData.source}`);
|
|
118
|
-
app.listen(port, () => {
|
|
119
|
-
console.error(`DBHub server listening at http://localhost:${port}`);
|
|
120
|
-
console.error(`Connect to MCP server at http://localhost:${port}/sse`);
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
// Set up STDIO transport
|
|
125
|
-
const transport = new StdioServerTransport();
|
|
126
|
-
console.error("Starting with STDIO transport");
|
|
127
|
-
await server.connect(transport);
|
|
128
|
-
// Listen for SIGINT to gracefully shut down
|
|
129
|
-
process.on('SIGINT', async () => {
|
|
130
|
-
console.error('Shutting down...');
|
|
131
|
-
await transport.close();
|
|
132
|
-
process.exit(0);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
catch (err) {
|
|
137
|
-
console.error("Fatal error:", err);
|
|
138
|
-
process.exit(1);
|
|
139
|
-
}
|
|
140
|
-
}
|
package/dist/tools/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { runQueryToolHandler, runQuerySchema } from './run-query.js';
|
|
2
|
-
import { listConnectorsToolHandler } from './list-connectors.js';
|
|
3
|
-
/**
|
|
4
|
-
* Register all tool handlers with the MCP server
|
|
5
|
-
*/
|
|
6
|
-
export function registerTools(server) {
|
|
7
|
-
// Tool to run a SQL query (read-only for safety)
|
|
8
|
-
server.tool("run_query", runQuerySchema, runQueryToolHandler);
|
|
9
|
-
// Tool to list available database connectors
|
|
10
|
-
server.tool("list_connectors", {}, listConnectorsToolHandler);
|
|
11
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ConnectorManager } from '../connectors/manager.js';
|
|
2
|
-
import { ConnectorRegistry } from '../connectors/interface.js';
|
|
3
|
-
import { createToolSuccessResponse } from '../utils/response-formatter.js';
|
|
4
|
-
/**
|
|
5
|
-
* list_connectors tool handler
|
|
6
|
-
* Lists all available database connectors and their sample DSNs
|
|
7
|
-
*/
|
|
8
|
-
export async function listConnectorsToolHandler(_args, _extra) {
|
|
9
|
-
const connectors = ConnectorManager.getAvailableConnectors();
|
|
10
|
-
const samples = ConnectorRegistry.getAllSampleDSNs();
|
|
11
|
-
// Convert to a more structured format
|
|
12
|
-
const sampleObjects = Object.entries(samples).map(([id, dsn]) => ({
|
|
13
|
-
id,
|
|
14
|
-
dsn
|
|
15
|
-
}));
|
|
16
|
-
// Prepare response data
|
|
17
|
-
const responseData = {
|
|
18
|
-
connectors: sampleObjects,
|
|
19
|
-
count: sampleObjects.length
|
|
20
|
-
};
|
|
21
|
-
// Use the utility to create a standardized response
|
|
22
|
-
return createToolSuccessResponse(responseData);
|
|
23
|
-
}
|
package/dist/tools/run-query.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { ConnectorManager } from '../connectors/manager.js';
|
|
3
|
-
import { createToolSuccessResponse, createToolErrorResponse } from '../utils/response-formatter.js';
|
|
4
|
-
// Schema for run_query tool
|
|
5
|
-
export const runQuerySchema = {
|
|
6
|
-
query: z.string().describe("SQL query to execute (SELECT only)")
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* run_query tool handler
|
|
10
|
-
* Executes a SQL query and returns the results
|
|
11
|
-
*/
|
|
12
|
-
export async function runQueryToolHandler({ query }, _extra) {
|
|
13
|
-
const connector = ConnectorManager.getCurrentConnector();
|
|
14
|
-
try {
|
|
15
|
-
// Validate the query before execution
|
|
16
|
-
const validationResult = connector.validateQuery(query);
|
|
17
|
-
if (!validationResult.isValid) {
|
|
18
|
-
return createToolErrorResponse(validationResult.message ?? "Unknown validation error", "VALIDATION_ERROR");
|
|
19
|
-
}
|
|
20
|
-
// Execute the query if validation passed
|
|
21
|
-
const result = await connector.executeQuery(query);
|
|
22
|
-
// Build response data
|
|
23
|
-
const responseData = {
|
|
24
|
-
rows: result.rows,
|
|
25
|
-
count: result.rows.length
|
|
26
|
-
};
|
|
27
|
-
return createToolSuccessResponse(responseData);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
return createToolErrorResponse(error.message, "EXECUTION_ERROR");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Response formatter utility for consistent API responses
|
|
3
|
-
* Provides formatting for resources, tools, and prompts
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Create a success response with the given data
|
|
7
|
-
*/
|
|
8
|
-
export function formatSuccessResponse(data, meta = {}) {
|
|
9
|
-
return {
|
|
10
|
-
success: true,
|
|
11
|
-
data,
|
|
12
|
-
...(Object.keys(meta).length > 0 ? { meta } : {})
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Create an error response with the given message and code
|
|
17
|
-
*/
|
|
18
|
-
export function formatErrorResponse(error, code = 'ERROR', details) {
|
|
19
|
-
return {
|
|
20
|
-
success: false,
|
|
21
|
-
error,
|
|
22
|
-
code,
|
|
23
|
-
...(details ? { details } : {})
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Create a tool error response object
|
|
28
|
-
*/
|
|
29
|
-
export function createToolErrorResponse(error, code = 'ERROR', details) {
|
|
30
|
-
return {
|
|
31
|
-
content: [{
|
|
32
|
-
type: "text",
|
|
33
|
-
text: JSON.stringify(formatErrorResponse(error, code, details), null, 2),
|
|
34
|
-
mimeType: "application/json"
|
|
35
|
-
}],
|
|
36
|
-
isError: true
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Create a tool success response object
|
|
41
|
-
*/
|
|
42
|
-
export function createToolSuccessResponse(data, meta = {}) {
|
|
43
|
-
return {
|
|
44
|
-
content: [{
|
|
45
|
-
type: "text",
|
|
46
|
-
text: JSON.stringify(formatSuccessResponse(data, meta), null, 2),
|
|
47
|
-
mimeType: "application/json"
|
|
48
|
-
}]
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Create a resource error response object
|
|
53
|
-
*/
|
|
54
|
-
export function createResourceErrorResponse(uri, error, code = 'ERROR', details) {
|
|
55
|
-
return {
|
|
56
|
-
contents: [{
|
|
57
|
-
uri,
|
|
58
|
-
text: JSON.stringify(formatErrorResponse(error, code, details), null, 2),
|
|
59
|
-
mimeType: "application/json"
|
|
60
|
-
}]
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Create a resource success response object
|
|
65
|
-
*/
|
|
66
|
-
export function createResourceSuccessResponse(uri, data, meta = {}) {
|
|
67
|
-
return {
|
|
68
|
-
contents: [{
|
|
69
|
-
uri,
|
|
70
|
-
text: JSON.stringify(formatSuccessResponse(data, meta), null, 2),
|
|
71
|
-
mimeType: "application/json"
|
|
72
|
-
}]
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Format a successful prompt response in the MCP format
|
|
77
|
-
*/
|
|
78
|
-
export function formatPromptSuccessResponse(text, references = []) {
|
|
79
|
-
return {
|
|
80
|
-
messages: [
|
|
81
|
-
{
|
|
82
|
-
role: 'assistant',
|
|
83
|
-
content: {
|
|
84
|
-
type: 'text',
|
|
85
|
-
text
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
...(references.length > 0 ? { references } : {})
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Format an error prompt response in the MCP format
|
|
94
|
-
*/
|
|
95
|
-
export function formatPromptErrorResponse(error, code = 'ERROR') {
|
|
96
|
-
return {
|
|
97
|
-
messages: [
|
|
98
|
-
{
|
|
99
|
-
role: 'assistant',
|
|
100
|
-
content: {
|
|
101
|
-
type: 'text',
|
|
102
|
-
text: `Error: ${error}`
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
],
|
|
106
|
-
error,
|
|
107
|
-
code
|
|
108
|
-
};
|
|
109
|
-
}
|