universal-db-mcp 0.1.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.
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Redis 数据库适配器
3
+ * 使用 ioredis 驱动实现 DbAdapter 接口
4
+ *
5
+ * 注意:Redis 是 NoSQL 键值存储,没有传统的表结构
6
+ * 本适配器提供基本的键值操作和信息查询功能
7
+ */
8
+ import { Redis } from 'ioredis';
9
+ export class RedisAdapter {
10
+ client = null;
11
+ config;
12
+ constructor(config) {
13
+ this.config = config;
14
+ }
15
+ /**
16
+ * 连接到 Redis 数据库
17
+ */
18
+ async connect() {
19
+ try {
20
+ this.client = new Redis({
21
+ host: this.config.host,
22
+ port: this.config.port,
23
+ password: this.config.password,
24
+ db: this.config.database ? parseInt(this.config.database) : 0,
25
+ retryStrategy: (times) => {
26
+ if (times > 3) {
27
+ return null; // 停止重试
28
+ }
29
+ return Math.min(times * 100, 2000);
30
+ },
31
+ });
32
+ // 测试连接
33
+ await this.client.ping();
34
+ }
35
+ catch (error) {
36
+ throw new Error(`Redis 连接失败: ${error instanceof Error ? error.message : String(error)}`);
37
+ }
38
+ }
39
+ /**
40
+ * 断开数据库连接
41
+ */
42
+ async disconnect() {
43
+ if (this.client) {
44
+ await this.client.quit();
45
+ this.client = null;
46
+ }
47
+ }
48
+ /**
49
+ * 执行 Redis 命令
50
+ *
51
+ * 支持的命令格式示例:
52
+ * - "GET mykey"
53
+ * - "SET mykey myvalue"
54
+ * - "HGETALL myhash"
55
+ * - "KEYS pattern*"
56
+ */
57
+ async executeQuery(query, params) {
58
+ if (!this.client) {
59
+ throw new Error('数据库未连接');
60
+ }
61
+ const startTime = Date.now();
62
+ try {
63
+ // 解析命令和参数
64
+ const parts = query.trim().split(/\s+/);
65
+ const command = parts[0].toLowerCase();
66
+ const args = parts.slice(1);
67
+ // 如果提供了额外参数,追加到参数列表
68
+ if (params && params.length > 0) {
69
+ args.push(...params.map(p => String(p)));
70
+ }
71
+ // 执行 Redis 命令
72
+ const result = await this.client.call(command, ...args);
73
+ const executionTime = Date.now() - startTime;
74
+ // 格式化结果
75
+ const formattedResult = this.formatRedisResult(command, result);
76
+ return {
77
+ rows: formattedResult,
78
+ executionTime,
79
+ metadata: {
80
+ command: command.toUpperCase(),
81
+ rawResult: result,
82
+ },
83
+ };
84
+ }
85
+ catch (error) {
86
+ throw new Error(`Redis 命令执行失败: ${error instanceof Error ? error.message : String(error)}`);
87
+ }
88
+ }
89
+ /**
90
+ * 格式化 Redis 命令结果为统一的行格式
91
+ */
92
+ formatRedisResult(command, result) {
93
+ // 处理 null/undefined
94
+ if (result === null || result === undefined) {
95
+ return [{ result: null }];
96
+ }
97
+ // 处理数组结果(如 KEYS, MGET 等)
98
+ if (Array.isArray(result)) {
99
+ // 如果是 HGETALL 返回的数组,转换为键值对
100
+ if (command === 'hgetall' && result.length % 2 === 0) {
101
+ const obj = {};
102
+ for (let i = 0; i < result.length; i += 2) {
103
+ obj[result[i]] = result[i + 1];
104
+ }
105
+ return [obj];
106
+ }
107
+ // 其他数组结果,每个元素作为一行
108
+ return result.map((item, index) => ({
109
+ index,
110
+ value: item,
111
+ }));
112
+ }
113
+ // 处理简单值
114
+ return [{ result }];
115
+ }
116
+ /**
117
+ * 获取 Redis 数据库信息
118
+ *
119
+ * Redis 没有传统的表结构,这里返回数据库统计信息
120
+ */
121
+ async getSchema() {
122
+ if (!this.client) {
123
+ throw new Error('数据库未连接');
124
+ }
125
+ try {
126
+ // 获取 Redis 服务器信息
127
+ const info = await this.client.info();
128
+ const lines = info.split('\r\n');
129
+ let version = 'unknown';
130
+ for (const line of lines) {
131
+ if (line.startsWith('redis_version:')) {
132
+ version = line.split(':')[1];
133
+ }
134
+ }
135
+ // 获取当前数据库编号
136
+ const dbIndex = this.config.database || '0';
137
+ // 获取键的样本(最多 100 个)
138
+ const keys = await this.client.keys('*');
139
+ const sampleKeys = keys.slice(0, 100);
140
+ // 分析键的类型分布
141
+ const typeMap = new Map();
142
+ for (const key of sampleKeys) {
143
+ const type = await this.client.type(key);
144
+ if (!typeMap.has(type)) {
145
+ typeMap.set(type, []);
146
+ }
147
+ typeMap.get(type).push(key);
148
+ }
149
+ // 为每种类型创建一个"虚拟表"
150
+ const tables = [];
151
+ // 添加概览表
152
+ tables.push({
153
+ name: '_overview',
154
+ columns: [
155
+ { name: 'metric', type: 'string', nullable: false },
156
+ { name: 'value', type: 'string', nullable: false },
157
+ ],
158
+ primaryKeys: [],
159
+ estimatedRows: 5,
160
+ });
161
+ // 为每种数据类型添加表
162
+ for (const [type, keyList] of typeMap.entries()) {
163
+ const columns = [
164
+ { name: 'key', type: 'string', nullable: false },
165
+ { name: 'type', type: 'string', nullable: false },
166
+ ];
167
+ // 根据类型添加特定列
168
+ switch (type) {
169
+ case 'string':
170
+ columns.push({ name: 'value', type: 'string', nullable: true });
171
+ break;
172
+ case 'list':
173
+ columns.push({ name: 'length', type: 'number', nullable: false });
174
+ break;
175
+ case 'set':
176
+ columns.push({ name: 'cardinality', type: 'number', nullable: false });
177
+ break;
178
+ case 'zset':
179
+ columns.push({ name: 'cardinality', type: 'number', nullable: false });
180
+ break;
181
+ case 'hash':
182
+ columns.push({ name: 'field_count', type: 'number', nullable: false });
183
+ break;
184
+ }
185
+ tables.push({
186
+ name: `keys_${type}`,
187
+ columns,
188
+ primaryKeys: ['key'],
189
+ estimatedRows: keyList.length,
190
+ });
191
+ }
192
+ return {
193
+ databaseType: 'redis',
194
+ databaseName: `db${dbIndex}`,
195
+ tables,
196
+ version,
197
+ };
198
+ }
199
+ catch (error) {
200
+ throw new Error(`获取 Redis 信息失败: ${error instanceof Error ? error.message : String(error)}`);
201
+ }
202
+ }
203
+ /**
204
+ * 检查是否为写操作
205
+ *
206
+ * Redis 写操作包括:SET, DEL, FLUSHDB, FLUSHALL 等
207
+ */
208
+ isWriteOperation(query) {
209
+ const upperQuery = query.trim().toUpperCase();
210
+ const writeCommands = [
211
+ 'SET', 'SETEX', 'SETNX', 'MSET', 'MSETNX',
212
+ 'DEL', 'UNLINK',
213
+ 'FLUSHDB', 'FLUSHALL',
214
+ 'LPUSH', 'RPUSH', 'LPOP', 'RPOP', 'LSET', 'LREM',
215
+ 'SADD', 'SREM', 'SPOP',
216
+ 'ZADD', 'ZREM', 'ZPOPMIN', 'ZPOPMAX',
217
+ 'HSET', 'HMSET', 'HDEL',
218
+ 'INCR', 'DECR', 'INCRBY', 'DECRBY',
219
+ 'APPEND', 'SETRANGE',
220
+ 'EXPIRE', 'EXPIREAT', 'PERSIST',
221
+ 'RENAME', 'RENAMENX',
222
+ ];
223
+ const command = upperQuery.split(/\s+/)[0];
224
+ return writeCommands.includes(command);
225
+ }
226
+ }
227
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/adapters/redis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP 数据库万能连接器 - 入口文件
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;GAEG"}
package/dist/index.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP 数据库万能连接器 - 入口文件
4
+ */
5
+ import { Command } from 'commander';
6
+ import { DatabaseMCPServer } from './server.js';
7
+ import { MySQLAdapter } from './adapters/mysql.js';
8
+ import { PostgreSQLAdapter } from './adapters/postgres.js';
9
+ import { RedisAdapter } from './adapters/redis.js';
10
+ const program = new Command();
11
+ program
12
+ .name('universal-db-mcp')
13
+ .description('MCP 数据库万能连接器 - 让 Claude Desktop 直接连接你的数据库')
14
+ .version('0.1.0')
15
+ .requiredOption('--type <type>', '数据库类型 (mysql|postgres|redis)')
16
+ .requiredOption('--host <host>', '数据库主机地址')
17
+ .requiredOption('--port <port>', '数据库端口', parseInt)
18
+ .option('--user <user>', '用户名')
19
+ .option('--password <password>', '密码')
20
+ .option('--database <database>', '数据库名称')
21
+ .option('--danger-allow-write', '启用写入模式(危险!默认为只读模式)', false)
22
+ .action(async (options) => {
23
+ try {
24
+ // 验证数据库类型
25
+ if (!['mysql', 'postgres', 'redis'].includes(options.type)) {
26
+ console.error('❌ 错误: 不支持的数据库类型。支持的类型: mysql, postgres, redis');
27
+ process.exit(1);
28
+ }
29
+ // 构建配置
30
+ const config = {
31
+ type: options.type,
32
+ host: options.host,
33
+ port: options.port,
34
+ user: options.user,
35
+ password: options.password,
36
+ database: options.database,
37
+ allowWrite: options.dangerAllowWrite,
38
+ };
39
+ console.error('🔧 配置信息:');
40
+ console.error(` 数据库类型: ${config.type}`);
41
+ console.error(` 主机地址: ${config.host}:${config.port}`);
42
+ console.error(` 数据库名: ${config.database || '(默认)'}`);
43
+ console.error(` 安全模式: ${config.allowWrite ? '❌ 写入已启用' : '✅ 只读模式'}`);
44
+ console.error('');
45
+ // 创建服务器
46
+ const server = new DatabaseMCPServer(config);
47
+ // 根据数据库类型创建适配器
48
+ let adapter;
49
+ switch (config.type) {
50
+ case 'mysql':
51
+ adapter = new MySQLAdapter({
52
+ host: config.host,
53
+ port: config.port,
54
+ user: config.user,
55
+ password: config.password,
56
+ database: config.database,
57
+ });
58
+ break;
59
+ case 'postgres':
60
+ adapter = new PostgreSQLAdapter({
61
+ host: config.host,
62
+ port: config.port,
63
+ user: config.user,
64
+ password: config.password,
65
+ database: config.database,
66
+ });
67
+ break;
68
+ case 'redis':
69
+ adapter = new RedisAdapter({
70
+ host: config.host,
71
+ port: config.port,
72
+ password: config.password,
73
+ database: config.database,
74
+ });
75
+ break;
76
+ default:
77
+ throw new Error(`不支持的数据库类型: ${config.type}`);
78
+ }
79
+ // 设置适配器并启动服务器
80
+ server.setAdapter(adapter);
81
+ await server.start();
82
+ // 优雅退出处理
83
+ process.on('SIGINT', async () => {
84
+ console.error('\n⏹️ 收到退出信号,正在关闭服务器...');
85
+ await server.stop();
86
+ process.exit(0);
87
+ });
88
+ process.on('SIGTERM', async () => {
89
+ console.error('\n⏹️ 收到终止信号,正在关闭服务器...');
90
+ await server.stop();
91
+ process.exit(0);
92
+ });
93
+ }
94
+ catch (error) {
95
+ console.error('❌ 启动失败:', error instanceof Error ? error.message : String(error));
96
+ process.exit(1);
97
+ }
98
+ });
99
+ program.parse();
100
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP 数据库万能连接器 - 主服务器
4
+ * 通过 Model Context Protocol 让 Claude Desktop 连接数据库
5
+ */
6
+ import type { DbAdapter, DbConfig } from './types/adapter.js';
7
+ /**
8
+ * 数据库 MCP 服务器类
9
+ */
10
+ export declare class DatabaseMCPServer {
11
+ private server;
12
+ private adapter;
13
+ private config;
14
+ constructor(config: DbConfig);
15
+ /**
16
+ * 设置 MCP 协议处理器
17
+ */
18
+ private setupHandlers;
19
+ /**
20
+ * 设置数据库适配器
21
+ */
22
+ setAdapter(adapter: DbAdapter): void;
23
+ /**
24
+ * 启动服务器
25
+ */
26
+ start(): Promise<void>;
27
+ /**
28
+ * 停止服务器
29
+ */
30
+ stop(): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAQH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9D;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,MAAM,CAAW;gBAEb,MAAM,EAAE,QAAQ;IAiB5B;;OAEG;IACH,OAAO,CAAC,aAAa;IA4IrB;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAIpC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAM5B"}
package/dist/server.js ADDED
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP 数据库万能连接器 - 主服务器
4
+ * 通过 Model Context Protocol 让 Claude Desktop 连接数据库
5
+ */
6
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
9
+ import { validateQuery } from './utils/safety.js';
10
+ /**
11
+ * 数据库 MCP 服务器类
12
+ */
13
+ export class DatabaseMCPServer {
14
+ server;
15
+ adapter = null;
16
+ config;
17
+ constructor(config) {
18
+ this.config = config;
19
+ this.server = new Server({
20
+ name: 'universal-db-mcp',
21
+ version: '0.1.0',
22
+ }, {
23
+ capabilities: {
24
+ tools: {},
25
+ },
26
+ });
27
+ this.setupHandlers();
28
+ }
29
+ /**
30
+ * 设置 MCP 协议处理器
31
+ */
32
+ setupHandlers() {
33
+ // 列出可用工具
34
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
35
+ return {
36
+ tools: [
37
+ {
38
+ name: 'execute_query',
39
+ description: '执行 SQL 查询或数据库命令。支持 SELECT、JOIN、聚合等查询操作。如果启用了写入模式,也可以执行 INSERT、UPDATE、DELETE 等操作。',
40
+ inputSchema: {
41
+ type: 'object',
42
+ properties: {
43
+ query: {
44
+ type: 'string',
45
+ description: '要执行的 SQL 语句或数据库命令',
46
+ },
47
+ params: {
48
+ type: 'array',
49
+ description: '查询参数(可选,用于参数化查询防止 SQL 注入)',
50
+ items: {
51
+ type: 'string',
52
+ },
53
+ },
54
+ },
55
+ required: ['query'],
56
+ },
57
+ },
58
+ {
59
+ name: 'get_schema',
60
+ description: '获取数据库结构信息,包括所有表名、列名、数据类型、主键、索引等元数据。在执行查询前调用此工具可以帮助理解数据库结构。',
61
+ inputSchema: {
62
+ type: 'object',
63
+ properties: {},
64
+ },
65
+ },
66
+ {
67
+ name: 'get_table_info',
68
+ description: '获取指定表的详细信息,包括列定义、索引、预估行数等。用于深入了解某个表的结构。',
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ tableName: {
73
+ type: 'string',
74
+ description: '表名',
75
+ },
76
+ },
77
+ required: ['tableName'],
78
+ },
79
+ },
80
+ ],
81
+ };
82
+ });
83
+ // 处理工具调用
84
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
85
+ const { name, arguments: args } = request.params;
86
+ try {
87
+ // 确保适配器已连接
88
+ if (!this.adapter) {
89
+ throw new Error('数据库未连接。请检查配置并重启服务。');
90
+ }
91
+ switch (name) {
92
+ case 'execute_query': {
93
+ const { query, params } = args;
94
+ // 安全检查
95
+ validateQuery(query, this.config.allowWrite ?? false);
96
+ console.error(`📊 执行查询: ${query.substring(0, 100)}...`);
97
+ const result = await this.adapter.executeQuery(query, params);
98
+ return {
99
+ content: [
100
+ {
101
+ type: 'text',
102
+ text: JSON.stringify(result, null, 2),
103
+ },
104
+ ],
105
+ };
106
+ }
107
+ case 'get_schema': {
108
+ console.error('📋 获取数据库结构...');
109
+ const schema = await this.adapter.getSchema();
110
+ return {
111
+ content: [
112
+ {
113
+ type: 'text',
114
+ text: JSON.stringify(schema, null, 2),
115
+ },
116
+ ],
117
+ };
118
+ }
119
+ case 'get_table_info': {
120
+ const { tableName } = args;
121
+ console.error(`📄 获取表信息: ${tableName}`);
122
+ const schema = await this.adapter.getSchema();
123
+ const table = schema.tables.find(t => t.name === tableName);
124
+ if (!table) {
125
+ throw new Error(`表 "${tableName}" 不存在`);
126
+ }
127
+ return {
128
+ content: [
129
+ {
130
+ type: 'text',
131
+ text: JSON.stringify(table, null, 2),
132
+ },
133
+ ],
134
+ };
135
+ }
136
+ default:
137
+ throw new Error(`未知工具: ${name}`);
138
+ }
139
+ }
140
+ catch (error) {
141
+ const errorMessage = error instanceof Error ? error.message : String(error);
142
+ console.error(`❌ 错误: ${errorMessage}`);
143
+ return {
144
+ content: [
145
+ {
146
+ type: 'text',
147
+ text: `执行失败: ${errorMessage}`,
148
+ },
149
+ ],
150
+ isError: true,
151
+ };
152
+ }
153
+ });
154
+ }
155
+ /**
156
+ * 设置数据库适配器
157
+ */
158
+ setAdapter(adapter) {
159
+ this.adapter = adapter;
160
+ }
161
+ /**
162
+ * 启动服务器
163
+ */
164
+ async start() {
165
+ if (!this.adapter) {
166
+ throw new Error('必须先设置数据库适配器才能启动服务器');
167
+ }
168
+ // 连接数据库
169
+ console.error('🔌 正在连接数据库...');
170
+ await this.adapter.connect();
171
+ console.error('✅ 数据库连接成功');
172
+ // 显示安全模式状态
173
+ if (this.config.allowWrite) {
174
+ console.error('⚠️ 警告: 写入模式已启用,请谨慎操作!');
175
+ }
176
+ else {
177
+ console.error('🛡️ 安全模式: 只读模式(推荐)');
178
+ }
179
+ // 启动 MCP 服务器
180
+ const transport = new StdioServerTransport();
181
+ await this.server.connect(transport);
182
+ console.error('🚀 MCP 服务器已启动,等待 Claude Desktop 连接...');
183
+ }
184
+ /**
185
+ * 停止服务器
186
+ */
187
+ async stop() {
188
+ if (this.adapter) {
189
+ await this.adapter.disconnect();
190
+ console.error('👋 数据库连接已关闭');
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}