@cmd233/mcp-database-server 1.1.5 → 1.1.7
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/dist/src/db/adapter.js +1 -1
- package/dist/src/db/index.js +7 -7
- package/dist/src/db/mysql-adapter.js +15 -15
- package/dist/src/db/postgresql-adapter.js +7 -7
- package/dist/src/db/sqlite-adapter.js +3 -3
- package/dist/src/db/sqlserver-adapter.js +2 -2
- package/dist/src/handlers/resourceHandlers.js +5 -4
- package/dist/src/handlers/toolHandlers.js +11 -11
- package/dist/src/index.js +18 -18
- package/dist/src/tools/insightTools.js +4 -4
- package/dist/src/tools/queryTools.js +8 -8
- package/dist/src/tools/schemaTools.js +20 -19
- package/package.json +1 -1
package/dist/src/db/adapter.js
CHANGED
package/dist/src/db/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function initDatabase(connectionInfo, dbType = 'sqlite') {
|
|
|
18
18
|
await dbAdapter.init();
|
|
19
19
|
}
|
|
20
20
|
catch (error) {
|
|
21
|
-
throw new Error(
|
|
21
|
+
throw new Error(`数据库初始化失败: ${error.message}`);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
@@ -29,7 +29,7 @@ export async function initDatabase(connectionInfo, dbType = 'sqlite') {
|
|
|
29
29
|
*/
|
|
30
30
|
export function dbAll(query, params = []) {
|
|
31
31
|
if (!dbAdapter) {
|
|
32
|
-
throw new Error("
|
|
32
|
+
throw new Error("数据库未初始化");
|
|
33
33
|
}
|
|
34
34
|
return dbAdapter.all(query, params);
|
|
35
35
|
}
|
|
@@ -41,7 +41,7 @@ export function dbAll(query, params = []) {
|
|
|
41
41
|
*/
|
|
42
42
|
export function dbRun(query, params = []) {
|
|
43
43
|
if (!dbAdapter) {
|
|
44
|
-
throw new Error("
|
|
44
|
+
throw new Error("数据库未初始化");
|
|
45
45
|
}
|
|
46
46
|
return dbAdapter.run(query, params);
|
|
47
47
|
}
|
|
@@ -52,7 +52,7 @@ export function dbRun(query, params = []) {
|
|
|
52
52
|
*/
|
|
53
53
|
export function dbExec(query) {
|
|
54
54
|
if (!dbAdapter) {
|
|
55
|
-
throw new Error("
|
|
55
|
+
throw new Error("数据库未初始化");
|
|
56
56
|
}
|
|
57
57
|
return dbAdapter.exec(query);
|
|
58
58
|
}
|
|
@@ -70,7 +70,7 @@ export function closeDatabase() {
|
|
|
70
70
|
*/
|
|
71
71
|
export function getDatabaseMetadata() {
|
|
72
72
|
if (!dbAdapter) {
|
|
73
|
-
throw new Error("
|
|
73
|
+
throw new Error("数据库未初始化");
|
|
74
74
|
}
|
|
75
75
|
return dbAdapter.getMetadata();
|
|
76
76
|
}
|
|
@@ -79,7 +79,7 @@ export function getDatabaseMetadata() {
|
|
|
79
79
|
*/
|
|
80
80
|
export function getListTablesQuery() {
|
|
81
81
|
if (!dbAdapter) {
|
|
82
|
-
throw new Error("
|
|
82
|
+
throw new Error("数据库未初始化");
|
|
83
83
|
}
|
|
84
84
|
return dbAdapter.getListTablesQuery();
|
|
85
85
|
}
|
|
@@ -89,7 +89,7 @@ export function getListTablesQuery() {
|
|
|
89
89
|
*/
|
|
90
90
|
export function getDescribeTableQuery(tableName) {
|
|
91
91
|
if (!dbAdapter) {
|
|
92
|
-
throw new Error("
|
|
92
|
+
throw new Error("数据库未初始化");
|
|
93
93
|
}
|
|
94
94
|
return dbAdapter.getDescribeTableQuery(tableName);
|
|
95
95
|
}
|
|
@@ -37,7 +37,7 @@ export class MysqlAdapter {
|
|
|
37
37
|
if (connectionInfo.port && typeof connectionInfo.port !== 'number') {
|
|
38
38
|
const parsedPort = parseInt(connectionInfo.port, 10);
|
|
39
39
|
if (isNaN(parsedPort)) {
|
|
40
|
-
throw new Error(
|
|
40
|
+
throw new Error(`无效的 MySQL 端口号: ${connectionInfo.port}`);
|
|
41
41
|
}
|
|
42
42
|
this.config.port = parsedPort;
|
|
43
43
|
}
|
|
@@ -49,10 +49,10 @@ export class MysqlAdapter {
|
|
|
49
49
|
*/
|
|
50
50
|
async generateAwsAuthToken() {
|
|
51
51
|
if (!this.awsRegion) {
|
|
52
|
-
throw new Error("AWS
|
|
52
|
+
throw new Error("AWS IAM 认证需要 AWS 区域参数");
|
|
53
53
|
}
|
|
54
54
|
if (!this.config.user) {
|
|
55
|
-
throw new Error("AWS
|
|
55
|
+
throw new Error("AWS IAM 认证需要 AWS 用户名参数");
|
|
56
56
|
}
|
|
57
57
|
try {
|
|
58
58
|
console.info(`[INFO] Generating AWS auth token for region: ${this.awsRegion}, host: ${this.host}, user: ${this.config.user}`);
|
|
@@ -67,8 +67,8 @@ export class MysqlAdapter {
|
|
|
67
67
|
return token;
|
|
68
68
|
}
|
|
69
69
|
catch (err) {
|
|
70
|
-
console.error(`[ERROR]
|
|
71
|
-
throw new Error(`AWS IAM
|
|
70
|
+
console.error(`[ERROR] 生成 AWS 认证令牌失败: ${err.message}`);
|
|
71
|
+
throw new Error(`AWS IAM 认证失败: ${err.message}。请检查您的 AWS 凭据和 IAM 权限。`);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
@@ -90,8 +90,8 @@ export class MysqlAdapter {
|
|
|
90
90
|
this.connection = await mysql.createConnection(awsConfig);
|
|
91
91
|
}
|
|
92
92
|
catch (err) {
|
|
93
|
-
console.error(`[ERROR] AWS IAM
|
|
94
|
-
throw new Error(`AWS IAM
|
|
93
|
+
console.error(`[ERROR] AWS IAM 认证失败: ${err.message}`);
|
|
94
|
+
throw new Error(`AWS IAM 认证失败: ${err.message}`);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
@@ -102,10 +102,10 @@ export class MysqlAdapter {
|
|
|
102
102
|
catch (err) {
|
|
103
103
|
console.error(`[ERROR] MySQL connection error: ${err.message}`);
|
|
104
104
|
if (this.awsIamAuth) {
|
|
105
|
-
throw new Error(
|
|
105
|
+
throw new Error(`使用 AWS IAM 认证连接 MySQL 失败: ${err.message}。请验证您的 AWS 凭据、IAM 权限和 RDS 配置。`);
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
|
-
throw new Error(
|
|
108
|
+
throw new Error(`连接 MySQL 失败: ${err.message}`);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
}
|
|
@@ -114,14 +114,14 @@ export class MysqlAdapter {
|
|
|
114
114
|
*/
|
|
115
115
|
async all(query, params = []) {
|
|
116
116
|
if (!this.connection) {
|
|
117
|
-
throw new Error("
|
|
117
|
+
throw new Error("数据库未初始化");
|
|
118
118
|
}
|
|
119
119
|
try {
|
|
120
120
|
const [rows] = await this.connection.execute(query, params);
|
|
121
121
|
return Array.isArray(rows) ? rows : [];
|
|
122
122
|
}
|
|
123
123
|
catch (err) {
|
|
124
|
-
throw new Error(`MySQL
|
|
124
|
+
throw new Error(`MySQL 查询错误: ${err.message}`);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
@@ -129,7 +129,7 @@ export class MysqlAdapter {
|
|
|
129
129
|
*/
|
|
130
130
|
async run(query, params = []) {
|
|
131
131
|
if (!this.connection) {
|
|
132
|
-
throw new Error("
|
|
132
|
+
throw new Error("数据库未初始化");
|
|
133
133
|
}
|
|
134
134
|
try {
|
|
135
135
|
const [result] = await this.connection.execute(query, params);
|
|
@@ -138,7 +138,7 @@ export class MysqlAdapter {
|
|
|
138
138
|
return { changes, lastID };
|
|
139
139
|
}
|
|
140
140
|
catch (err) {
|
|
141
|
-
throw new Error(`MySQL
|
|
141
|
+
throw new Error(`MySQL 查询错误: ${err.message}`);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
/**
|
|
@@ -146,13 +146,13 @@ export class MysqlAdapter {
|
|
|
146
146
|
*/
|
|
147
147
|
async exec(query) {
|
|
148
148
|
if (!this.connection) {
|
|
149
|
-
throw new Error("
|
|
149
|
+
throw new Error("数据库未初始化");
|
|
150
150
|
}
|
|
151
151
|
try {
|
|
152
152
|
await this.connection.query(query);
|
|
153
153
|
}
|
|
154
154
|
catch (err) {
|
|
155
|
-
throw new Error(`MySQL
|
|
155
|
+
throw new Error(`MySQL 批处理错误: ${err.message}`);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
@@ -39,7 +39,7 @@ export class PostgresqlAdapter {
|
|
|
39
39
|
}
|
|
40
40
|
catch (err) {
|
|
41
41
|
console.error(`[ERROR] PostgreSQL connection error: ${err.message}`);
|
|
42
|
-
throw new Error(
|
|
42
|
+
throw new Error(`连接 PostgreSQL 失败: ${err.message}`);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
@@ -50,7 +50,7 @@ export class PostgresqlAdapter {
|
|
|
50
50
|
*/
|
|
51
51
|
async all(query, params = []) {
|
|
52
52
|
if (!this.client) {
|
|
53
|
-
throw new Error("
|
|
53
|
+
throw new Error("数据库未初始化");
|
|
54
54
|
}
|
|
55
55
|
try {
|
|
56
56
|
// PostgreSQL 使用 $1, $2 等作为参数化查询的占位符
|
|
@@ -59,7 +59,7 @@ export class PostgresqlAdapter {
|
|
|
59
59
|
return result.rows;
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
62
|
-
throw new Error(`PostgreSQL
|
|
62
|
+
throw new Error(`PostgreSQL 查询错误: ${err.message}`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
@@ -70,7 +70,7 @@ export class PostgresqlAdapter {
|
|
|
70
70
|
*/
|
|
71
71
|
async run(query, params = []) {
|
|
72
72
|
if (!this.client) {
|
|
73
|
-
throw new Error("
|
|
73
|
+
throw new Error("数据库未初始化");
|
|
74
74
|
}
|
|
75
75
|
try {
|
|
76
76
|
// 将 ? 替换为编号参数
|
|
@@ -94,7 +94,7 @@ export class PostgresqlAdapter {
|
|
|
94
94
|
return { changes, lastID };
|
|
95
95
|
}
|
|
96
96
|
catch (err) {
|
|
97
|
-
throw new Error(`PostgreSQL
|
|
97
|
+
throw new Error(`PostgreSQL 查询错误: ${err.message}`);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
@@ -104,13 +104,13 @@ export class PostgresqlAdapter {
|
|
|
104
104
|
*/
|
|
105
105
|
async exec(query) {
|
|
106
106
|
if (!this.client) {
|
|
107
|
-
throw new Error("
|
|
107
|
+
throw new Error("数据库未初始化");
|
|
108
108
|
}
|
|
109
109
|
try {
|
|
110
110
|
await this.client.query(query);
|
|
111
111
|
}
|
|
112
112
|
catch (err) {
|
|
113
|
-
throw new Error(`PostgreSQL
|
|
113
|
+
throw new Error(`PostgreSQL 批处理错误: ${err.message}`);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
@@ -34,7 +34,7 @@ export class SqliteAdapter {
|
|
|
34
34
|
*/
|
|
35
35
|
async all(query, params = []) {
|
|
36
36
|
if (!this.db) {
|
|
37
|
-
throw new Error("
|
|
37
|
+
throw new Error("数据库未初始化");
|
|
38
38
|
}
|
|
39
39
|
return new Promise((resolve, reject) => {
|
|
40
40
|
this.db.all(query, params, (err, rows) => {
|
|
@@ -55,7 +55,7 @@ export class SqliteAdapter {
|
|
|
55
55
|
*/
|
|
56
56
|
async run(query, params = []) {
|
|
57
57
|
if (!this.db) {
|
|
58
|
-
throw new Error("
|
|
58
|
+
throw new Error("数据库未初始化");
|
|
59
59
|
}
|
|
60
60
|
return new Promise((resolve, reject) => {
|
|
61
61
|
this.db.run(query, params, function (err) {
|
|
@@ -75,7 +75,7 @@ export class SqliteAdapter {
|
|
|
75
75
|
*/
|
|
76
76
|
async exec(query) {
|
|
77
77
|
if (!this.db) {
|
|
78
|
-
throw new Error("
|
|
78
|
+
throw new Error("数据库未初始化");
|
|
79
79
|
}
|
|
80
80
|
return new Promise((resolve, reject) => {
|
|
81
81
|
this.db.exec(query, (err) => {
|
|
@@ -89,7 +89,7 @@ export class SqlServerAdapter {
|
|
|
89
89
|
catch (err) {
|
|
90
90
|
this.pool = null;
|
|
91
91
|
console.error(`[ERROR] SQL Server connection error: ${err.message}`);
|
|
92
|
-
throw new Error(
|
|
92
|
+
throw new Error(`连接 SQL Server 失败: ${err.message}`);
|
|
93
93
|
}
|
|
94
94
|
finally {
|
|
95
95
|
this.isConnecting = false;
|
|
@@ -109,7 +109,7 @@ export class SqlServerAdapter {
|
|
|
109
109
|
// 如果超时,重置状态并抛出错误
|
|
110
110
|
if (this.isConnecting) {
|
|
111
111
|
this.isConnecting = false;
|
|
112
|
-
throw new Error('
|
|
112
|
+
throw new Error('连接超时');
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
@@ -31,7 +31,7 @@ export async function handleListResources() {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
|
-
throw new Error(
|
|
34
|
+
throw new Error(`列出资源失败: ${error.message}`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -47,7 +47,7 @@ export async function handleReadResource(uri) {
|
|
|
47
47
|
const schema = pathComponents.pop();
|
|
48
48
|
const tableName = pathComponents.pop();
|
|
49
49
|
if (schema !== SCHEMA_PATH) {
|
|
50
|
-
throw new Error("
|
|
50
|
+
throw new Error("无效的资源 URI");
|
|
51
51
|
}
|
|
52
52
|
// 使用适配器特定的查询来描述表结构
|
|
53
53
|
const query = getDescribeTableQuery(tableName);
|
|
@@ -59,13 +59,14 @@ export async function handleReadResource(uri) {
|
|
|
59
59
|
mimeType: "application/json",
|
|
60
60
|
text: JSON.stringify(result.map((column) => ({
|
|
61
61
|
column_name: column.name,
|
|
62
|
-
data_type: column.type
|
|
62
|
+
data_type: column.type,
|
|
63
|
+
comment: column.comment || null
|
|
63
64
|
})), null, 2),
|
|
64
65
|
},
|
|
65
66
|
],
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
catch (error) {
|
|
69
|
-
throw new Error(
|
|
70
|
+
throw new Error(`读取资源失败: ${error.message}`);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
@@ -12,7 +12,7 @@ export function handleListTools() {
|
|
|
12
12
|
tools: [
|
|
13
13
|
{
|
|
14
14
|
name: "read_query",
|
|
15
|
-
description: "
|
|
15
|
+
description: "执行 SELECT 查询以从数据库读取数据",
|
|
16
16
|
inputSchema: {
|
|
17
17
|
type: "object",
|
|
18
18
|
properties: {
|
|
@@ -23,7 +23,7 @@ export function handleListTools() {
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
name: "write_query",
|
|
26
|
-
description: "
|
|
26
|
+
description: "执行 INSERT、UPDATE 或 DELETE 查询",
|
|
27
27
|
inputSchema: {
|
|
28
28
|
type: "object",
|
|
29
29
|
properties: {
|
|
@@ -34,7 +34,7 @@ export function handleListTools() {
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
name: "create_table",
|
|
37
|
-
description: "
|
|
37
|
+
description: "在数据库中创建新表",
|
|
38
38
|
inputSchema: {
|
|
39
39
|
type: "object",
|
|
40
40
|
properties: {
|
|
@@ -45,7 +45,7 @@ export function handleListTools() {
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
name: "alter_table",
|
|
48
|
-
description: "
|
|
48
|
+
description: "修改现有表结构(添加列、重命名表等)",
|
|
49
49
|
inputSchema: {
|
|
50
50
|
type: "object",
|
|
51
51
|
properties: {
|
|
@@ -56,7 +56,7 @@ export function handleListTools() {
|
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
name: "drop_table",
|
|
59
|
-
description: "
|
|
59
|
+
description: "从数据库中删除表(需要安全确认)",
|
|
60
60
|
inputSchema: {
|
|
61
61
|
type: "object",
|
|
62
62
|
properties: {
|
|
@@ -68,7 +68,7 @@ export function handleListTools() {
|
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
70
|
name: "export_query",
|
|
71
|
-
description: "
|
|
71
|
+
description: "将查询结果导出为各种格式(CSV、JSON)",
|
|
72
72
|
inputSchema: {
|
|
73
73
|
type: "object",
|
|
74
74
|
properties: {
|
|
@@ -80,7 +80,7 @@ export function handleListTools() {
|
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
name: "list_tables",
|
|
83
|
-
description: "
|
|
83
|
+
description: "获取数据库中所有表的列表",
|
|
84
84
|
inputSchema: {
|
|
85
85
|
type: "object",
|
|
86
86
|
properties: {},
|
|
@@ -88,7 +88,7 @@ export function handleListTools() {
|
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
name: "describe_table",
|
|
91
|
-
description: "
|
|
91
|
+
description: "查看特定表的结构信息",
|
|
92
92
|
inputSchema: {
|
|
93
93
|
type: "object",
|
|
94
94
|
properties: {
|
|
@@ -99,7 +99,7 @@ export function handleListTools() {
|
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
name: "append_insight",
|
|
102
|
-
description: "
|
|
102
|
+
description: "添加业务洞察到备忘录",
|
|
103
103
|
inputSchema: {
|
|
104
104
|
type: "object",
|
|
105
105
|
properties: {
|
|
@@ -110,7 +110,7 @@ export function handleListTools() {
|
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
112
|
name: "list_insights",
|
|
113
|
-
description: "
|
|
113
|
+
description: "列出备忘录中的所有业务洞察",
|
|
114
114
|
inputSchema: {
|
|
115
115
|
type: "object",
|
|
116
116
|
properties: {},
|
|
@@ -149,7 +149,7 @@ export async function handleToolCall(name, args) {
|
|
|
149
149
|
case "list_insights":
|
|
150
150
|
return await listInsights();
|
|
151
151
|
default:
|
|
152
|
-
throw new Error(
|
|
152
|
+
throw new Error(`未知的工具: ${name}`);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
catch (error) {
|
package/dist/src/index.js
CHANGED
|
@@ -27,12 +27,12 @@ const server = new Server({
|
|
|
27
27
|
// 解析命令行参数
|
|
28
28
|
const args = process.argv.slice(2);
|
|
29
29
|
if (args.length === 0) {
|
|
30
|
-
logger.error("
|
|
31
|
-
logger.error("
|
|
32
|
-
logger.error("
|
|
33
|
-
logger.error("
|
|
34
|
-
logger.error("
|
|
35
|
-
logger.error("
|
|
30
|
+
logger.error("请提供数据库连接信息");
|
|
31
|
+
logger.error("SQLite 用法: node index.js <database_file_path>");
|
|
32
|
+
logger.error("SQL Server 用法: node index.js --sqlserver --server <server> --database <database> [--user <user> --password <password>]");
|
|
33
|
+
logger.error("PostgreSQL 用法: node index.js --postgresql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
|
|
34
|
+
logger.error("MySQL 用法: node index.js --mysql --host <host> --database <database> [--user <user> --password <password> --port <port>]");
|
|
35
|
+
logger.error("MySQL with AWS IAM 用法: node index.js --mysql --aws-iam-auth --host <rds-endpoint> --database <database> --user <aws-username> --aws-region <region>");
|
|
36
36
|
process.exit(1);
|
|
37
37
|
}
|
|
38
38
|
// 解析参数以确定数据库类型和连接信息
|
|
@@ -67,7 +67,7 @@ if (args.includes('--sqlserver')) {
|
|
|
67
67
|
}
|
|
68
68
|
// 验证 SQL Server 连接信息
|
|
69
69
|
if (!connectionInfo.server || !connectionInfo.database) {
|
|
70
|
-
logger.error("
|
|
70
|
+
logger.error("错误: SQL Server 需要 --server 和 --database 参数");
|
|
71
71
|
process.exit(1);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -109,7 +109,7 @@ else if (args.includes('--postgresql') || args.includes('--postgres')) {
|
|
|
109
109
|
}
|
|
110
110
|
// 验证 PostgreSQL 连接信息
|
|
111
111
|
if (!connectionInfo.host || !connectionInfo.database) {
|
|
112
|
-
logger.error("
|
|
112
|
+
logger.error("错误: PostgreSQL 需要 --host 和 --database 参数");
|
|
113
113
|
process.exit(1);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
@@ -165,22 +165,22 @@ else if (args.includes('--mysql')) {
|
|
|
165
165
|
}
|
|
166
166
|
// 验证 MySQL 连接信息
|
|
167
167
|
if (!connectionInfo.host || !connectionInfo.database) {
|
|
168
|
-
logger.error("
|
|
168
|
+
logger.error("错误: MySQL 需要 --host 和 --database 参数");
|
|
169
169
|
process.exit(1);
|
|
170
170
|
}
|
|
171
171
|
// AWS IAM 认证的额外验证
|
|
172
172
|
if (connectionInfo.awsIamAuth) {
|
|
173
173
|
if (!connectionInfo.user) {
|
|
174
|
-
logger.error("
|
|
174
|
+
logger.error("错误: AWS IAM 认证需要 --user 参数");
|
|
175
175
|
process.exit(1);
|
|
176
176
|
}
|
|
177
177
|
if (!connectionInfo.awsRegion) {
|
|
178
|
-
logger.error("
|
|
178
|
+
logger.error("错误: AWS IAM 认证需要 --aws-region 参数");
|
|
179
179
|
process.exit(1);
|
|
180
180
|
}
|
|
181
181
|
// 为 AWS IAM 认证自动启用 SSL (必需)
|
|
182
182
|
connectionInfo.ssl = true;
|
|
183
|
-
logger.info("AWS IAM
|
|
183
|
+
logger.info("AWS IAM 认证已启用 - SSL 已自动配置");
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
else {
|
|
@@ -204,21 +204,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
204
204
|
});
|
|
205
205
|
// 优雅处理关闭信号
|
|
206
206
|
process.on('SIGINT', async () => {
|
|
207
|
-
logger.info('
|
|
207
|
+
logger.info('正在优雅关闭...');
|
|
208
208
|
await closeDatabase();
|
|
209
209
|
process.exit(0);
|
|
210
210
|
});
|
|
211
211
|
process.on('SIGTERM', async () => {
|
|
212
|
-
logger.info('
|
|
212
|
+
logger.info('正在优雅关闭...');
|
|
213
213
|
await closeDatabase();
|
|
214
214
|
process.exit(0);
|
|
215
215
|
});
|
|
216
216
|
// 添加全局错误处理器
|
|
217
217
|
process.on('uncaughtException', (error) => {
|
|
218
|
-
logger.error('
|
|
218
|
+
logger.error('未捕获的异常:', error);
|
|
219
219
|
});
|
|
220
220
|
process.on('unhandledRejection', (reason, promise) => {
|
|
221
|
-
logger.error('
|
|
221
|
+
logger.error('未处理的 Promise 拒绝:', promise, '原因:', reason);
|
|
222
222
|
});
|
|
223
223
|
/**
|
|
224
224
|
* 启动服务器
|
|
@@ -248,12 +248,12 @@ async function runServer() {
|
|
|
248
248
|
logger.info('Server running. Press Ctrl+C to exit.');
|
|
249
249
|
}
|
|
250
250
|
catch (error) {
|
|
251
|
-
logger.error("
|
|
251
|
+
logger.error("初始化失败:", error);
|
|
252
252
|
process.exit(1);
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
// 启动服务器
|
|
256
256
|
runServer().catch(error => {
|
|
257
|
-
logger.error("
|
|
257
|
+
logger.error("服务器初始化失败:", error);
|
|
258
258
|
process.exit(1);
|
|
259
259
|
});
|
|
@@ -8,7 +8,7 @@ import { formatSuccessResponse } from '../utils/formatUtils.js';
|
|
|
8
8
|
export async function appendInsight(insight) {
|
|
9
9
|
try {
|
|
10
10
|
if (!insight) {
|
|
11
|
-
throw new Error("
|
|
11
|
+
throw new Error("洞察内容不能为空");
|
|
12
12
|
}
|
|
13
13
|
// 如果 insights 表不存在则创建
|
|
14
14
|
await dbExec(`
|
|
@@ -20,10 +20,10 @@ export async function appendInsight(insight) {
|
|
|
20
20
|
`);
|
|
21
21
|
// 插入洞察记录
|
|
22
22
|
await dbRun("INSERT INTO mcp_insights (insight) VALUES (?)", [insight]);
|
|
23
|
-
return formatSuccessResponse({ success: true, message: "
|
|
23
|
+
return formatSuccessResponse({ success: true, message: "洞察已添加" });
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
|
-
throw new Error(
|
|
26
|
+
throw new Error(`添加洞察失败: ${error.message}`);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -49,6 +49,6 @@ export async function listInsights() {
|
|
|
49
49
|
return formatSuccessResponse(insights);
|
|
50
50
|
}
|
|
51
51
|
catch (error) {
|
|
52
|
-
throw new Error(
|
|
52
|
+
throw new Error(`列出洞察失败: ${error.message}`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -8,13 +8,13 @@ import { formatSuccessResponse, convertToCSV } from '../utils/formatUtils.js';
|
|
|
8
8
|
export async function readQuery(query) {
|
|
9
9
|
try {
|
|
10
10
|
if (!query.trim().toLowerCase().startsWith("select")) {
|
|
11
|
-
throw new Error("
|
|
11
|
+
throw new Error("read_query 只允许执行 SELECT 查询");
|
|
12
12
|
}
|
|
13
13
|
const result = await dbAll(query);
|
|
14
14
|
return formatSuccessResponse(result);
|
|
15
15
|
}
|
|
16
16
|
catch (error) {
|
|
17
|
-
throw new Error(`SQL
|
|
17
|
+
throw new Error(`SQL 错误: ${error.message}`);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -26,16 +26,16 @@ export async function writeQuery(query) {
|
|
|
26
26
|
try {
|
|
27
27
|
const lowerQuery = query.trim().toLowerCase();
|
|
28
28
|
if (lowerQuery.startsWith("select")) {
|
|
29
|
-
throw new Error("
|
|
29
|
+
throw new Error("SELECT 操作请使用 read_query");
|
|
30
30
|
}
|
|
31
31
|
if (!(lowerQuery.startsWith("insert") || lowerQuery.startsWith("update") || lowerQuery.startsWith("delete"))) {
|
|
32
|
-
throw new Error("
|
|
32
|
+
throw new Error("write_query 只允许执行 INSERT、UPDATE 或 DELETE 操作");
|
|
33
33
|
}
|
|
34
34
|
const result = await dbRun(query);
|
|
35
35
|
return formatSuccessResponse({ affected_rows: result.changes });
|
|
36
36
|
}
|
|
37
37
|
catch (error) {
|
|
38
|
-
throw new Error(`SQL
|
|
38
|
+
throw new Error(`SQL 错误: ${error.message}`);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -47,7 +47,7 @@ export async function writeQuery(query) {
|
|
|
47
47
|
export async function exportQuery(query, format) {
|
|
48
48
|
try {
|
|
49
49
|
if (!query.trim().toLowerCase().startsWith("select")) {
|
|
50
|
-
throw new Error("
|
|
50
|
+
throw new Error("export_query 只允许执行 SELECT 查询");
|
|
51
51
|
}
|
|
52
52
|
const result = await dbAll(query);
|
|
53
53
|
if (format === "csv") {
|
|
@@ -64,10 +64,10 @@ export async function exportQuery(query, format) {
|
|
|
64
64
|
return formatSuccessResponse(result);
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
67
|
-
throw new Error("
|
|
67
|
+
throw new Error("不支持的导出格式。请使用 'csv' 或 'json'");
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
catch (error) {
|
|
71
|
-
throw new Error(
|
|
71
|
+
throw new Error(`导出错误: ${error.message}`);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -8,13 +8,13 @@ import { formatSuccessResponse } from '../utils/formatUtils.js';
|
|
|
8
8
|
export async function createTable(query) {
|
|
9
9
|
try {
|
|
10
10
|
if (!query.trim().toLowerCase().startsWith("create table")) {
|
|
11
|
-
throw new Error("
|
|
11
|
+
throw new Error("只允许执行 CREATE TABLE 语句");
|
|
12
12
|
}
|
|
13
13
|
await dbExec(query);
|
|
14
|
-
return formatSuccessResponse({ success: true, message: "
|
|
14
|
+
return formatSuccessResponse({ success: true, message: "表创建成功" });
|
|
15
15
|
}
|
|
16
16
|
catch (error) {
|
|
17
|
-
throw new Error(`SQL
|
|
17
|
+
throw new Error(`SQL 错误: ${error.message}`);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -25,13 +25,13 @@ export async function createTable(query) {
|
|
|
25
25
|
export async function alterTable(query) {
|
|
26
26
|
try {
|
|
27
27
|
if (!query.trim().toLowerCase().startsWith("alter table")) {
|
|
28
|
-
throw new Error("
|
|
28
|
+
throw new Error("只允许执行 ALTER TABLE 语句");
|
|
29
29
|
}
|
|
30
30
|
await dbExec(query);
|
|
31
|
-
return formatSuccessResponse({ success: true, message: "
|
|
31
|
+
return formatSuccessResponse({ success: true, message: "表结构修改成功" });
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
|
-
throw new Error(`SQL
|
|
34
|
+
throw new Error(`SQL 错误: ${error.message}`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
@@ -43,12 +43,12 @@ export async function alterTable(query) {
|
|
|
43
43
|
export async function dropTable(tableName, confirm) {
|
|
44
44
|
try {
|
|
45
45
|
if (!tableName) {
|
|
46
|
-
throw new Error("
|
|
46
|
+
throw new Error("表名不能为空");
|
|
47
47
|
}
|
|
48
48
|
if (!confirm) {
|
|
49
49
|
return formatSuccessResponse({
|
|
50
50
|
success: false,
|
|
51
|
-
message: "
|
|
51
|
+
message: "需要安全确认。设置 confirm=true 以继续删除表。"
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
// First check if table exists by directly querying for tables
|
|
@@ -56,17 +56,17 @@ export async function dropTable(tableName, confirm) {
|
|
|
56
56
|
const tables = await dbAll(query);
|
|
57
57
|
const tableNames = tables.map(t => t.name);
|
|
58
58
|
if (!tableNames.includes(tableName)) {
|
|
59
|
-
throw new Error(
|
|
59
|
+
throw new Error(`表 '${tableName}' 不存在`);
|
|
60
60
|
}
|
|
61
|
-
//
|
|
61
|
+
// 删除表
|
|
62
62
|
await dbExec(`DROP TABLE "${tableName}"`);
|
|
63
63
|
return formatSuccessResponse({
|
|
64
64
|
success: true,
|
|
65
|
-
message:
|
|
65
|
+
message: `表 '${tableName}' 删除成功`
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
catch (error) {
|
|
69
|
-
throw new Error(
|
|
69
|
+
throw new Error(`删除表失败: ${error.message}`);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
@@ -75,13 +75,13 @@ export async function dropTable(tableName, confirm) {
|
|
|
75
75
|
*/
|
|
76
76
|
export async function listTables() {
|
|
77
77
|
try {
|
|
78
|
-
//
|
|
78
|
+
// 使用适配器特定的查询来列出表
|
|
79
79
|
const query = getListTablesQuery();
|
|
80
80
|
const tables = await dbAll(query);
|
|
81
81
|
return formatSuccessResponse(tables.map((t) => t.name));
|
|
82
82
|
}
|
|
83
83
|
catch (error) {
|
|
84
|
-
throw new Error(
|
|
84
|
+
throw new Error(`列出表失败: ${error.message}`);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
@@ -92,16 +92,16 @@ export async function listTables() {
|
|
|
92
92
|
export async function describeTable(tableName) {
|
|
93
93
|
try {
|
|
94
94
|
if (!tableName) {
|
|
95
|
-
throw new Error("
|
|
95
|
+
throw new Error("表名不能为空");
|
|
96
96
|
}
|
|
97
|
-
//
|
|
97
|
+
// 首先通过直接查询来检查表是否存在
|
|
98
98
|
const query = getListTablesQuery();
|
|
99
99
|
const tables = await dbAll(query);
|
|
100
100
|
const tableNames = tables.map(t => t.name);
|
|
101
101
|
if (!tableNames.includes(tableName)) {
|
|
102
102
|
throw new Error(`Table '${tableName}' does not exist`);
|
|
103
103
|
}
|
|
104
|
-
//
|
|
104
|
+
// 使用适配器特定的查询来描述表结构
|
|
105
105
|
const descQuery = getDescribeTableQuery(tableName);
|
|
106
106
|
const columns = await dbAll(descQuery);
|
|
107
107
|
return formatSuccessResponse(columns.map((col) => ({
|
|
@@ -109,10 +109,11 @@ export async function describeTable(tableName) {
|
|
|
109
109
|
type: col.type,
|
|
110
110
|
notnull: !!col.notnull,
|
|
111
111
|
default_value: col.dflt_value,
|
|
112
|
-
primary_key: !!col.pk
|
|
112
|
+
primary_key: !!col.pk,
|
|
113
|
+
comment: col.comment || null
|
|
113
114
|
})));
|
|
114
115
|
}
|
|
115
116
|
catch (error) {
|
|
116
|
-
throw new Error(
|
|
117
|
+
throw new Error(`描述表结构失败: ${error.message}`);
|
|
117
118
|
}
|
|
118
119
|
}
|
package/package.json
CHANGED