mcp-dbutils 0.7.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

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.
@@ -4,14 +4,14 @@ from psycopg2.pool import SimpleConnectionPool
4
4
  from typing import Optional, List
5
5
  import mcp.types as types
6
6
  from importlib.metadata import metadata
7
- from ..base import DatabaseServer
7
+ from ..base import ConnectionServer
8
8
  from ..log import create_logger
9
- from .config import PostgresConfig
9
+ from .config import PostgreSQLConfig
10
10
 
11
11
  # 获取包信息用于日志命名
12
12
  pkg_meta = metadata("mcp-dbutils")
13
- class PostgresServer(DatabaseServer):
14
- def __init__(self, config: PostgresConfig, config_path: Optional[str] = None):
13
+ class PostgreSQLServer(ConnectionServer):
14
+ def __init__(self, config: PostgreSQLConfig, config_path: Optional[str] = None):
15
15
  """初始化PostgreSQL服务器
16
16
  Args:
17
17
  config: 数据库配置
@@ -32,9 +32,9 @@ class PostgresServer(DatabaseServer):
32
32
  self.log("info", "测试连接成功")
33
33
  # 创建连接池
34
34
  self.pool = SimpleConnectionPool(1, 5, **conn_params)
35
- self.log("info", "数据库连接池创建成功")
35
+ self.log("info", "连接池创建成功")
36
36
  except psycopg2.Error as e:
37
- self.log("error", f"数据库连接失败: [Code: {e.pgcode}] {e.pgerror or str(e)}")
37
+ self.log("error", f"连接失败: [Code: {e.pgcode}] {e.pgerror or str(e)}")
38
38
  raise
39
39
  async def list_resources(self) -> list[types.Resource]:
40
40
  """列出所有表资源"""
@@ -124,9 +124,9 @@ class PostgresServer(DatabaseServer):
124
124
  inputSchema={
125
125
  "type": "object",
126
126
  "properties": {
127
- "database": {
127
+ "connection": {
128
128
  "type": "string",
129
- "description": "数据库配置名称(可选)"
129
+ "description": "数据库连接名称(可选)"
130
130
  },
131
131
  "sql": {
132
132
  "type": "string",
@@ -147,16 +147,16 @@ class PostgresServer(DatabaseServer):
147
147
  # 仅允许SELECT语句
148
148
  if not sql.lower().startswith("select"):
149
149
  raise ValueError("仅支持SELECT查询")
150
- database = arguments.get("database")
150
+ connection = arguments.get("connection")
151
151
  use_pool = True
152
152
  conn = None
153
153
  try:
154
- if database and self.config_path:
155
- # 使用指定的数据库配置
156
- config = PostgresConfig.from_yaml(self.config_path, database)
154
+ if connection and self.config_path:
155
+ # 使用指定的数据库连接
156
+ config = PostgreSQLConfig.from_yaml(self.config_path, connection)
157
157
  conn_params = config.get_connection_params()
158
158
  masked_params = config.get_masked_connection_info()
159
- self.log("info", f"使用配置 {database} 连接数据库: {masked_params}")
159
+ self.log("info", f"使用配置 {connection} 连接数据库: {masked_params}")
160
160
  conn = psycopg2.connect(**conn_params)
161
161
  use_pool = False
162
162
  else:
@@ -173,7 +173,7 @@ class PostgresServer(DatabaseServer):
173
173
  formatted_results = [dict(zip(columns, row)) for row in results]
174
174
  result_text = str({
175
175
  'type': 'postgres',
176
- 'config_name': database or 'default',
176
+ 'config_name': connection or 'default',
177
177
  'query_result': {
178
178
  'columns': columns,
179
179
  'rows': formatted_results,
@@ -191,7 +191,7 @@ class PostgresServer(DatabaseServer):
191
191
  error = f"查询执行失败: {str(e)}"
192
192
  error_msg = str({
193
193
  'type': 'postgres',
194
- 'config_name': database or 'default',
194
+ 'config_name': connection or 'default',
195
195
  'error': error
196
196
  })
197
197
  self.log("error", error_msg)
@@ -205,5 +205,5 @@ class PostgresServer(DatabaseServer):
205
205
  async def cleanup(self):
206
206
  """清理资源"""
207
207
  if hasattr(self, 'pool'):
208
- self.log("info", "关闭数据库连接池")
208
+ self.log("info", "关闭连接池")
209
209
  self.pool.closeall()
@@ -1,6 +1,6 @@
1
1
  """SQLite module"""
2
2
 
3
- from .handler import SqliteHandler
4
- from .config import SqliteConfig
3
+ from .handler import SQLiteHandler
4
+ from .config import SQLiteConfig
5
5
 
6
- __all__ = ['SqliteHandler', 'SqliteConfig']
6
+ __all__ = ['SQLiteHandler', 'SQLiteConfig']
@@ -4,13 +4,13 @@ from dataclasses import dataclass
4
4
  from pathlib import Path
5
5
  from typing import Dict, Any, Optional, Literal
6
6
  from urllib.parse import urlparse, parse_qs
7
- from ..config import DatabaseConfig
7
+ from ..config import ConnectionConfig
8
8
 
9
9
  def parse_jdbc_url(jdbc_url: str) -> Dict[str, str]:
10
10
  """Parse JDBC URL into connection parameters
11
11
 
12
12
  Args:
13
- jdbc_url: JDBC URL (e.g. jdbc:sqlite:file:/path/to/database.db or jdbc:sqlite:/path/to/database.db)
13
+ jdbc_url: JDBC URL (e.g. jdbc:sqlite:file:/path/to/sqlite.db or jdbc:sqlite:/path/to/sqlite.db)
14
14
 
15
15
  Returns:
16
16
  Dictionary of connection parameters
@@ -40,7 +40,7 @@ def parse_jdbc_url(jdbc_url: str) -> Dict[str, str]:
40
40
  params[key] = values[0]
41
41
 
42
42
  if not path:
43
- raise ValueError("Database path must be specified in URL")
43
+ raise ValueError("SQLite file path must be specified in URL")
44
44
 
45
45
  return {
46
46
  'path': path,
@@ -48,22 +48,22 @@ def parse_jdbc_url(jdbc_url: str) -> Dict[str, str]:
48
48
  }
49
49
 
50
50
  @dataclass
51
- class SqliteConfig(DatabaseConfig):
51
+ class SQLiteConfig(ConnectionConfig):
52
52
  path: str
53
53
  password: Optional[str] = None
54
54
  uri: bool = True # Enable URI mode to support parameters like password
55
55
  type: Literal['sqlite'] = 'sqlite'
56
56
 
57
57
  @classmethod
58
- def from_jdbc_url(cls, jdbc_url: str, password: Optional[str] = None) -> 'SqliteConfig':
58
+ def from_jdbc_url(cls, jdbc_url: str, password: Optional[str] = None) -> 'SQLiteConfig':
59
59
  """Create configuration from JDBC URL
60
60
 
61
61
  Args:
62
- jdbc_url: JDBC URL (e.g. jdbc:sqlite:file:/path/to/database.db)
62
+ jdbc_url: JDBC URL (e.g. jdbc:sqlite:file:/path/to/sqlite.db)
63
63
  password: Optional password for database encryption
64
64
 
65
65
  Returns:
66
- SqliteConfig instance
66
+ SQLiteConfig instance
67
67
 
68
68
  Raises:
69
69
  ValueError: If URL format is invalid
@@ -80,7 +80,7 @@ class SqliteConfig(DatabaseConfig):
80
80
 
81
81
  @property
82
82
  def absolute_path(self) -> str:
83
- """Return absolute path to database file"""
83
+ """Return absolute path to SQLite database file"""
84
84
  return str(Path(self.path).expanduser().resolve())
85
85
 
86
86
  def get_connection_params(self) -> Dict[str, Any]:
@@ -109,23 +109,23 @@ class SqliteConfig(DatabaseConfig):
109
109
  return info
110
110
 
111
111
  @classmethod
112
- def from_yaml(cls, yaml_path: str, db_name: str, **kwargs) -> 'SqliteConfig':
112
+ def from_yaml(cls, yaml_path: str, db_name: str, **kwargs) -> 'SQLiteConfig':
113
113
  """Create SQLite configuration from YAML
114
114
 
115
115
  Args:
116
116
  yaml_path: Path to YAML configuration file
117
- db_name: Database configuration name
117
+ db_name: Connection configuration name
118
118
  """
119
119
  configs = cls.load_yaml_config(yaml_path)
120
120
 
121
121
  if db_name not in configs:
122
122
  available_dbs = list(configs.keys())
123
- raise ValueError(f"Database configuration not found: {db_name}. Available configurations: {available_dbs}")
123
+ raise ValueError(f"Connection configuration not found: {db_name}. Available configurations: {available_dbs}")
124
124
 
125
125
  db_config = configs[db_name]
126
126
 
127
127
  if 'type' not in db_config:
128
- raise ValueError("Database configuration must include 'type' field")
128
+ raise ValueError("Connection configuration must include 'type' field")
129
129
  if db_config['type'] != 'sqlite':
130
130
  raise ValueError(f"Configuration is not SQLite type: {db_config['type']}")
131
131