mcp-dbutils 0.17.0__py3-none-any.whl → 0.19.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.
@@ -98,7 +98,7 @@ class SQLiteHandler(ConnectionHandler):
98
98
  end_time = time.time()
99
99
  elapsed_ms = (end_time - start_time) * 1000
100
100
  self.log("debug", f"Query executed in {elapsed_ms:.2f}ms")
101
-
101
+
102
102
  if is_select:
103
103
  # Get column names
104
104
  columns = [description[0] for description in cur.description]
@@ -110,7 +110,7 @@ class SQLiteHandler(ConnectionHandler):
110
110
  for i, col_name in enumerate(columns):
111
111
  row_dict[col_name] = row[i]
112
112
  results.append(row_dict)
113
-
113
+
114
114
  return str({
115
115
  "columns": columns,
116
116
  "rows": results
@@ -136,13 +136,13 @@ class SQLiteHandler(ConnectionHandler):
136
136
  # 获取表信息
137
137
  cur.execute(f"PRAGMA table_info({table_name})")
138
138
  columns = cur.fetchall()
139
-
139
+
140
140
  # SQLite不支持表级注释,但我们可以获取表的详细信息
141
141
  description = [
142
142
  f"Table: {table_name}\n",
143
143
  COLUMNS_HEADER
144
144
  ]
145
-
145
+
146
146
  for col in columns:
147
147
  col_info = [
148
148
  f" {col[1]} ({col[2]})",
@@ -152,9 +152,9 @@ class SQLiteHandler(ConnectionHandler):
152
152
  ]
153
153
  description.extend(col_info)
154
154
  description.append("") # Empty line between columns
155
-
155
+
156
156
  return "\n".join(description)
157
-
157
+
158
158
  except sqlite3.Error as e:
159
159
  error_msg = f"Failed to get table description: {str(e)}"
160
160
  self.stats.record_error(e.__class__.__name__)
@@ -168,25 +168,25 @@ class SQLiteHandler(ConnectionHandler):
168
168
  # SQLite provides the complete CREATE statement
169
169
  cur.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
170
170
  result = cur.fetchone()
171
-
171
+
172
172
  if not result:
173
173
  return f"Table {table_name} not found"
174
-
174
+
175
175
  ddl = result[0]
176
-
176
+
177
177
  # Get indexes
178
178
  cur.execute("SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name=?", (table_name,))
179
179
  indexes = cur.fetchall()
180
-
180
+
181
181
  # Add index definitions
182
182
  if indexes:
183
183
  ddl = ddl + "\n\n-- Indexes:"
184
184
  for idx in indexes:
185
185
  if idx[0]: # Some internal indexes might have NULL sql
186
186
  ddl = ddl + "\n" + idx[0] + ";"
187
-
187
+
188
188
  return ddl
189
-
189
+
190
190
  except sqlite3.Error as e:
191
191
  error_msg = f"Failed to get table DDL: {str(e)}"
192
192
  self.stats.record_error(e.__class__.__name__)
@@ -197,49 +197,49 @@ class SQLiteHandler(ConnectionHandler):
197
197
  try:
198
198
  with sqlite3.connect(self.config.path) as conn:
199
199
  cur = conn.cursor()
200
-
200
+
201
201
  # Check if table exists
202
202
  cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
203
203
  if not cur.fetchone():
204
204
  raise ConnectionHandlerError(f"Table '{table_name}' doesn't exist")
205
-
205
+
206
206
  # 获取索引列表
207
207
  cur.execute(f"PRAGMA index_list({table_name})")
208
208
  indexes = cur.fetchall()
209
-
209
+
210
210
  if not indexes:
211
211
  return f"No indexes found on table {table_name}"
212
-
212
+
213
213
  formatted_indexes = [f"Indexes for {table_name}:"]
214
-
214
+
215
215
  for idx in indexes:
216
216
  # 获取索引详细信息
217
217
  cur.execute(f"PRAGMA index_info({idx[1]})")
218
218
  index_info = cur.fetchall()
219
-
219
+
220
220
  # 获取索引的SQL定义
221
221
  cur.execute("SELECT sql FROM sqlite_master WHERE type='index' AND name=?", (idx[1],))
222
222
  sql = cur.fetchone()
223
-
223
+
224
224
  index_details = [
225
225
  f"\nIndex: {idx[1]}",
226
226
  f"Type: {'UNIQUE' if idx[2] else 'INDEX'}",
227
227
  COLUMNS_HEADER
228
228
  ]
229
-
229
+
230
230
  for col in index_info:
231
231
  index_details.append(f" - {col[2]}")
232
-
232
+
233
233
  if sql and sql[0]:
234
234
  index_details.extend([
235
235
  "Definition:",
236
236
  f" {sql[0]}"
237
237
  ])
238
-
238
+
239
239
  formatted_indexes.extend(index_details)
240
-
240
+
241
241
  return "\n".join(formatted_indexes)
242
-
242
+
243
243
  except sqlite3.Error as e:
244
244
  error_msg = f"Failed to get index information: {str(e)}"
245
245
  self.stats.record_error(e.__class__.__name__)
@@ -250,33 +250,33 @@ class SQLiteHandler(ConnectionHandler):
250
250
  try:
251
251
  with sqlite3.connect(self.config.path) as conn:
252
252
  cur = conn.cursor()
253
-
253
+
254
254
  # Check if table exists
255
255
  cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table_name,))
256
256
  if not cur.fetchone():
257
257
  raise ConnectionHandlerError(f"Table '{table_name}' doesn't exist")
258
-
258
+
259
259
  # Get basic table information
260
260
  cur.execute(f"PRAGMA table_info({table_name})")
261
261
  columns = cur.fetchall()
262
-
262
+
263
263
  # Count rows
264
264
  cur.execute(f"SELECT COUNT(*) FROM {table_name}")
265
265
  row_count = cur.fetchone()[0]
266
-
266
+
267
267
  # Get index information
268
268
  cur.execute(f"PRAGMA index_list({table_name})")
269
269
  indexes = cur.fetchall()
270
-
270
+
271
271
  # Get page count and size
272
272
  cur.execute("PRAGMA page_count")
273
273
  page_count = cur.fetchone()[0]
274
274
  cur.execute("PRAGMA page_size")
275
275
  page_size = cur.fetchone()[0]
276
-
276
+
277
277
  # Calculate total size
278
278
  total_size = page_count * page_size
279
-
279
+
280
280
  # Format size in human readable format
281
281
  def format_size(size):
282
282
  for unit in ['B', 'KB', 'MB', 'GB']:
@@ -284,7 +284,7 @@ class SQLiteHandler(ConnectionHandler):
284
284
  return f"{size:.2f} {unit}"
285
285
  size /= 1024
286
286
  return f"{size:.2f} TB"
287
-
287
+
288
288
  # Get column statistics
289
289
  column_stats = []
290
290
  for col in columns:
@@ -295,7 +295,7 @@ class SQLiteHandler(ConnectionHandler):
295
295
  # Get distinct value count
296
296
  cur.execute(f"SELECT COUNT(DISTINCT {col_name}) FROM {table_name}")
297
297
  distinct_count = cur.fetchone()[0]
298
-
298
+
299
299
  column_stats.append({
300
300
  'name': col_name,
301
301
  'type': col[2],
@@ -303,7 +303,7 @@ class SQLiteHandler(ConnectionHandler):
303
303
  'null_percent': (null_count / row_count * 100) if row_count > 0 else 0,
304
304
  'distinct_count': distinct_count
305
305
  })
306
-
306
+
307
307
  # Format output
308
308
  output = [
309
309
  f"Table Statistics for {table_name}:",
@@ -314,7 +314,7 @@ class SQLiteHandler(ConnectionHandler):
314
314
  f" Index Count: {len(indexes)}\n",
315
315
  "Column Statistics:"
316
316
  ]
317
-
317
+
318
318
  for stat in column_stats:
319
319
  col_info = [
320
320
  f" {stat['name']} ({stat['type']}):",
@@ -323,7 +323,7 @@ class SQLiteHandler(ConnectionHandler):
323
323
  ]
324
324
  output.extend(col_info)
325
325
  output.append("") # Empty line between columns
326
-
326
+
327
327
  return "\n".join(output)
328
328
 
329
329
  except sqlite3.Error as e:
@@ -336,21 +336,21 @@ class SQLiteHandler(ConnectionHandler):
336
336
  try:
337
337
  with sqlite3.connect(self.config.path) as conn:
338
338
  cur = conn.cursor()
339
-
339
+
340
340
  # Get table info (includes PRIMARY KEY)
341
341
  cur.execute(f"PRAGMA table_info({table_name})")
342
342
  columns = cur.fetchall()
343
-
343
+
344
344
  # Get foreign keys
345
345
  cur.execute(f"PRAGMA foreign_key_list({table_name})")
346
346
  foreign_keys = cur.fetchall()
347
-
347
+
348
348
  # Get indexes (for UNIQUE constraints)
349
349
  cur.execute(f"PRAGMA index_list({table_name})")
350
350
  indexes = cur.fetchall()
351
-
351
+
352
352
  output = [f"Constraints for {table_name}:"]
353
-
353
+
354
354
  # Primary Key constraints
355
355
  pk_columns = [col[1] for col in columns if col[5]] # col[5] is pk flag
356
356
  if pk_columns:
@@ -358,13 +358,13 @@ class SQLiteHandler(ConnectionHandler):
358
358
  "\nPrimary Key Constraints:",
359
359
  f" PRIMARY KEY ({', '.join(pk_columns)})"
360
360
  ])
361
-
361
+
362
362
  # Foreign Key constraints
363
363
  if foreign_keys:
364
364
  output.append("\nForeign Key Constraints:")
365
365
  current_fk = None
366
366
  fk_columns = []
367
-
367
+
368
368
  for fk in foreign_keys:
369
369
  # SQLite foreign_key_list format:
370
370
  # id, seq, table, from, to, on_update, on_delete, match
@@ -380,10 +380,10 @@ class SQLiteHandler(ConnectionHandler):
380
380
  output.append(f" ON UPDATE: {fk[5]}")
381
381
  if fk[6]: # on_delete
382
382
  output.append(f" ON DELETE: {fk[6]}")
383
-
383
+
384
384
  if fk_columns:
385
385
  output.append(f" ({', '.join(fk_columns)})")
386
-
386
+
387
387
  # Unique constraints (from indexes)
388
388
  unique_indexes = [idx for idx in indexes if idx[2]] # idx[2] is unique flag
389
389
  if unique_indexes:
@@ -394,7 +394,7 @@ class SQLiteHandler(ConnectionHandler):
394
394
  index_info = cur.fetchall()
395
395
  columns = [info[2] for info in index_info] # info[2] is column name
396
396
  output.append(f" UNIQUE ({', '.join(columns)})")
397
-
397
+
398
398
  # Check constraints
399
399
  # Note: SQLite doesn't provide direct access to CHECK constraints through PRAGMA
400
400
  # We need to parse the table creation SQL
@@ -403,7 +403,7 @@ class SQLiteHandler(ConnectionHandler):
403
403
  if "CHECK" in create_sql.upper():
404
404
  output.append("\nCheck Constraints:")
405
405
  output.append(" See table DDL for CHECK constraints")
406
-
406
+
407
407
  return "\n".join(output)
408
408
 
409
409
  except sqlite3.Error as e:
@@ -416,18 +416,18 @@ class SQLiteHandler(ConnectionHandler):
416
416
  try:
417
417
  with sqlite3.connect(self.config.path) as conn:
418
418
  cur = conn.cursor()
419
-
419
+
420
420
  # Check if the query is valid by preparing it
421
421
  try:
422
422
  # Use prepare to validate the query without executing it
423
423
  conn.execute(f"EXPLAIN {sql}")
424
424
  except sqlite3.Error as e:
425
425
  raise ConnectionHandlerError(f"Failed to explain query: {str(e)}")
426
-
426
+
427
427
  # Get EXPLAIN output
428
428
  cur.execute(f"EXPLAIN QUERY PLAN {sql}")
429
429
  plan = cur.fetchall()
430
-
430
+
431
431
  # Format the output
432
432
  output = [
433
433
  "Query Execution Plan:",
@@ -435,20 +435,20 @@ class SQLiteHandler(ConnectionHandler):
435
435
  "Details:",
436
436
  "--------"
437
437
  ]
438
-
438
+
439
439
  for step in plan:
440
440
  # EXPLAIN QUERY PLAN format:
441
441
  # id | parent | notused | detail
442
442
  indent = " " * (step[0] - step[1] if step[1] >= 0 else step[0])
443
443
  output.append(f"{indent}{step[3]}")
444
-
444
+
445
445
  # Add query statistics
446
446
  output.extend([
447
447
  "\nNote: SQLite's EXPLAIN QUERY PLAN provides a high-level overview.",
448
448
  "For detailed execution statistics, consider using EXPLAIN (not QUERY PLAN)",
449
449
  "which shows the virtual machine instructions."
450
450
  ])
451
-
451
+
452
452
  return "\n".join(output)
453
453
 
454
454
  except sqlite3.Error as e:
@@ -456,6 +456,21 @@ class SQLiteHandler(ConnectionHandler):
456
456
  self.stats.record_error(e.__class__.__name__)
457
457
  raise ConnectionHandlerError(error_msg)
458
458
 
459
+ async def test_connection(self) -> bool:
460
+ """Test database connection
461
+
462
+ Returns:
463
+ bool: True if connection is successful, False otherwise
464
+ """
465
+ try:
466
+ with sqlite3.connect(self.config.path) as conn:
467
+ cur = conn.cursor()
468
+ cur.execute("SELECT 1")
469
+ return True
470
+ except sqlite3.Error as e:
471
+ self.log("error", f"Connection test failed: {str(e)}")
472
+ return False
473
+
459
474
  async def cleanup(self):
460
475
  """Cleanup resources"""
461
476
  # Log final stats
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-dbutils
3
+ Version: 0.19.0
4
+ Summary: MCP Database Utilities Service
5
+ Author: Dong Hao
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: mcp>=1.2.1
10
+ Requires-Dist: mysql-connector-python>=8.2.0
11
+ Requires-Dist: psycopg2-binary>=2.9.10
12
+ Requires-Dist: python-dotenv>=1.0.1
13
+ Requires-Dist: pyyaml>=6.0.2
14
+ Provides-Extra: test
15
+ Requires-Dist: aiosqlite>=0.19.0; extra == 'test'
16
+ Requires-Dist: docker>=7.0.0; extra == 'test'
17
+ Requires-Dist: pre-commit>=3.6.0; extra == 'test'
18
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
19
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
20
+ Requires-Dist: pytest-docker>=2.0.0; extra == 'test'
21
+ Requires-Dist: pytest>=7.0.0; extra == 'test'
22
+ Requires-Dist: ruff>=0.3.0; extra == 'test'
23
+ Requires-Dist: testcontainers>=3.7.0; extra == 'test'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # MCP 数据库工具
27
+
28
+ <!-- 项目状态徽章 -->
29
+ [![构建状态](https://img.shields.io/github/workflow/status/donghao1393/mcp-dbutils/Quality%20Assurance?label=tests)](https://github.com/donghao1393/mcp-dbutils/actions)
30
+ [![覆盖率](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/donghao1393/bdd0a63ec2a816539ff8c136ceb41e48/raw/coverage.json)](https://github.com/donghao1393/mcp-dbutils/actions)
31
+ [![质量门禁状态](https://sonarcloud.io/api/project_badges/measure?project=donghao1393_mcp-dbutils&metric=alert_status)](https://sonarcloud.io/dashboard?id=donghao1393_mcp-dbutils)
32
+
33
+ <!-- 版本和安装徽章 -->
34
+ [![PyPI 版本](https://img.shields.io/pypi/v/mcp-dbutils)](https://pypi.org/project/mcp-dbutils/)
35
+ [![PyPI 下载量](https://img.shields.io/pypi/dm/mcp-dbutils)](https://pypi.org/project/mcp-dbutils/)
36
+ [![Smithery](https://smithery.ai/badge/@donghao1393/mcp-dbutils)](https://smithery.ai/server/@donghao1393/mcp-dbutils)
37
+
38
+ <!-- 技术规格徽章 -->
39
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-blue)](https://www.python.org/)
40
+ [![许可证](https://img.shields.io/github/license/donghao1393/mcp-dbutils)](LICENSE)
41
+ [![GitHub 星标](https://img.shields.io/github/stars/donghao1393/mcp-dbutils?style=social)](https://github.com/donghao1393/mcp-dbutils/stargazers)
42
+
43
+ [English](README_EN.md) | [Français](README_FR.md) | [Español](README_ES.md) | [العربية](README_AR.md) | [Русский](README_RU.md) | [文档导航](#文档导航)
44
+
45
+ ![Image](https://github.com/user-attachments/assets/26c4f1a1-7b19-4bdd-b9fd-34ad198b0ce3)
46
+
47
+ ## 简介
48
+
49
+ MCP Database Utilities 是一个多功能的 MCP 服务,它使您的 AI 能够通过统一的连接配置安全地访问各种类型的数据库(SQLite、MySQL、PostgreSQL 等)进行数据分析。
50
+
51
+ 您可以将其视为 AI 系统和数据库之间的安全桥梁,允许 AI 在不直接访问数据库或冒数据修改风险的情况下读取和分析您的数据。
52
+
53
+ ### 核心特性
54
+
55
+ - **安全优先**:严格只读操作,无直接数据库访问,隔离连接,按需连接,自动超时
56
+ - **隐私保障**:本地处理,最小数据暴露,凭证保护,敏感数据屏蔽
57
+ - **多数据库支持**:使用相同的接口连接 SQLite、MySQL、PostgreSQL
58
+ - **简单配置**:所有数据库连接使用单个 YAML 文件
59
+ - **高级功能**:表格浏览、架构分析和查询执行
60
+
61
+ > 🔒 **安全说明**:MCP 数据库工具采用安全优先的架构设计,非常适合注重数据保护的企业、初创公司和个人用户。详细了解我们的[安全架构](docs/zh/technical/security.md)。
62
+
63
+ ## 快速入门
64
+
65
+ 我们提供了多种安装方式,包括 uvx、Docker 和 Smithery。详细的安装和配置步骤请参阅[安装指南](docs/zh/installation.md)。
66
+
67
+ ### 基本步骤
68
+
69
+ 1. **安装**:选择适合您的安装方式([详细说明](docs/zh/installation.md))
70
+ 2. **配置**:创建包含数据库连接信息的 YAML 文件([配置指南](docs/zh/configuration.md))
71
+ 3. **连接**:将配置添加到您的 AI 客户端
72
+ 4. **使用**:开始与您的数据库交互([使用指南](docs/zh/usage.md))
73
+
74
+ ### 示例交互
75
+
76
+ **您**:"能否列出我的数据库中的所有表?"
77
+
78
+ **AI**:"以下是您的数据库中的表:
79
+ - customers(客户)
80
+ - products(产品)
81
+ - orders(订单)
82
+ - inventory(库存)"
83
+
84
+ **您**:"customers 表的结构是什么样的?"
85
+
86
+ **AI**:"customers 表有以下结构:
87
+ - id(整数,主键)
88
+ - name(文本)
89
+ - email(文本)
90
+ - registration_date(日期)"
91
+
92
+ ## 文档导航
93
+
94
+ ### 入门指南
95
+ - [安装指南](docs/zh/installation.md) - 详细的安装步骤和配置说明
96
+ - [平台特定安装指南](docs/zh/installation-platform-specific.md) - 针对不同操作系统的安装说明
97
+ - [配置指南](docs/zh/configuration.md) - 数据库连接配置示例和最佳实践
98
+ - [使用指南](docs/zh/usage.md) - 基本操作流程和常见使用场景
99
+
100
+ ### 技术文档
101
+ - [架构设计](docs/zh/technical/architecture.md) - 系统架构和组件说明
102
+ - [安全架构](docs/zh/technical/security.md) - 安全特性和保护机制
103
+ - [开发指南](docs/zh/technical/development.md) - 代码质量和开发流程
104
+ - [测试指南](docs/zh/technical/testing.md) - 测试框架和最佳实践
105
+ - [SonarCloud 集成](docs/zh/technical/sonarcloud-integration.md) - SonarCloud 与 AI 集成指南
106
+
107
+ ### 示例文档
108
+ - [SQLite 示例](docs/zh/examples/sqlite-examples.md) - SQLite 数据库操作示例
109
+ - [PostgreSQL 示例](docs/zh/examples/postgresql-examples.md) - PostgreSQL 数据库操作示例
110
+ - [MySQL 示例](docs/zh/examples/mysql-examples.md) - MySQL 数据库操作示例
111
+ - [高级 LLM 交互示例](docs/zh/examples/advanced-llm-interactions.md) - 与各类 LLM 的高级交互示例
112
+
113
+ ### 多语言文档
114
+ - **英语** - [English Documentation](docs/en/)
115
+ - **法语** - [Documentation Française](docs/fr/)
116
+ - **西班牙语** - [Documentación en Español](docs/es/)
117
+ - **阿拉伯语** - [التوثيق باللغة العربية](docs/ar/)
118
+ - **俄语** - [Документация на русском](docs/ru/)
119
+
120
+ ### 支持与反馈
121
+ - [GitHub Issues](https://github.com/donghao1393/mcp-dbutils/issues) - 报告问题或请求功能
122
+ - [Smithery](https://smithery.ai/server/@donghao1393/mcp-dbutils) - 简化安装和更新
123
+
124
+ ## 可用工具
125
+
126
+ MCP 数据库工具提供了多种工具,使 AI 能够与您的数据库交互:
127
+
128
+ - **dbutils-list-connections**:列出配置中的所有可用数据库连接
129
+ - **dbutils-list-tables**:列出数据库中的所有表
130
+ - **dbutils-run-query**:执行 SQL 查询(仅 SELECT)
131
+ - **dbutils-get-stats**:获取表统计信息
132
+ - **dbutils-list-constraints**:列出表约束
133
+ - **dbutils-explain-query**:获取查询执行计划
134
+ - **dbutils-get-performance**:获取数据库性能指标
135
+ - **dbutils-analyze-query**:分析查询以进行优化
136
+
137
+ 有关这些工具的详细说明和使用示例,请参阅[使用指南](docs/zh/usage.md)。
138
+
139
+ ## 星标历史
140
+
141
+ [![星标历史图表](https://starchart.cc/donghao1393/mcp-dbutils.svg?variant=adaptive)](https://starchart.cc/donghao1393/mcp-dbutils)
142
+
143
+ ## 许可证
144
+
145
+ 本项目采用 MIT 许可证 - 有关详细信息,请参阅 [LICENSE](LICENSE) 文件。
@@ -1,22 +1,22 @@
1
1
  mcp_dbutils/__init__.py,sha256=6LLccQv7je2L4IpY_I3OzSJZcK32VUDJv2IY31y6eYg,1900
2
- mcp_dbutils/base.py,sha256=9UDhPFpw6YdkUMhAqgGyy6vuXA2C78LIGrWiW0zeB8s,30839
2
+ mcp_dbutils/base.py,sha256=ptQfJwzYKteGokOrrkIcG3QIlz-f1Afk_XxyEHYcFLI,35957
3
3
  mcp_dbutils/config.py,sha256=bmXpOd1fyYfoyUS75I035ChT6t3wP5AyEnJ06e2ZS2o,1848
4
4
  mcp_dbutils/log.py,sha256=mqxi6I_IL-MF1F_pxBtnYZQKOHbGBJ74gsvZHVelr1w,823
5
5
  mcp_dbutils/stats.py,sha256=wMqWPfGnEOg9v5YBtTsARV-1YsFUMM_pKdzitzSU9x4,7137
6
6
  mcp_dbutils/mysql/__init__.py,sha256=gNhoHaxK1qhvMAH5AVl1vfV1rUpcbV9KZWUQb41aaQk,129
7
7
  mcp_dbutils/mysql/config.py,sha256=BTPPFqlhoTp7EBFIeLJZh8x6bCn3q9NivHYz9yZHziw,9820
8
- mcp_dbutils/mysql/handler.py,sha256=fVmOq49ZDsB24NOkHCMu5e4WwMFEV8hBkElkNA8FFJo,21962
8
+ mcp_dbutils/mysql/handler.py,sha256=L2COmWts8WNQaI7wZSPtQ-BqKnpYL7DRnNk7Yw3UsxU,22285
9
9
  mcp_dbutils/mysql/server.py,sha256=1bWAu7qHYXVeTZu4wdEpS6gSVB0RoXKI3Smy_ix-y8A,8586
10
10
  mcp_dbutils/postgres/__init__.py,sha256=-2zYuEJEQ2AMvmGhH5Z_umerSvt7S4xOa_XV4wgvGfI,154
11
11
  mcp_dbutils/postgres/config.py,sha256=NyQOVhkXJ1S-JD0w-ePNjTKI1Ja-aZQkDUdHi6U7Vl4,7752
12
- mcp_dbutils/postgres/handler.py,sha256=ppltSKtSk-BlPpp3iEVJlmoyl4AmqKcQHx_0zHlz03Y,24403
12
+ mcp_dbutils/postgres/handler.py,sha256=JKnh3QsF5oQ4nS-OdhMC1nWtTp235PArFncFN4pmDZ8,24670
13
13
  mcp_dbutils/postgres/server.py,sha256=_CiJC9PitpI1NB99Q1Bcs5TYADNgDpYMwv88fRHQunE,8640
14
14
  mcp_dbutils/sqlite/__init__.py,sha256=fK_3-WylCBYpBAzwuopi8hlwoIGJm2TPAlwcPWG46I0,134
15
15
  mcp_dbutils/sqlite/config.py,sha256=j67TJ8mQJ2D886MthSa-zYMtvUUYyyxYLMlNxkYoqZE,4509
16
- mcp_dbutils/sqlite/handler.py,sha256=iojyVhr_cgNOATKESXdSFYV58mdZQhywwDQVd4jXtvM,19740
16
+ mcp_dbutils/sqlite/handler.py,sha256=nCgBeBp3zjpE2HNohMbh3Jpz5tNeMczt5K87JOhVWzY,19320
17
17
  mcp_dbutils/sqlite/server.py,sha256=jqpE8d9vJETMs5xYGB7P0tvNDPes6Yn5ZM_iCCF7Tv4,7181
18
- mcp_dbutils-0.17.0.dist-info/METADATA,sha256=ZuJS8qq9D-Ru7TpXq18fQeTCB83hif0qR6luEMaAi1M,12075
19
- mcp_dbutils-0.17.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- mcp_dbutils-0.17.0.dist-info/entry_points.txt,sha256=XTjt0QmYRgKOJQT6skR9bp1EMUfIrgpHeZJPZ3CJffs,49
21
- mcp_dbutils-0.17.0.dist-info/licenses/LICENSE,sha256=1A_CwpWVlbjrKdVEYO77vYfnXlW7oxcilZ8FpA_BzCI,1065
22
- mcp_dbutils-0.17.0.dist-info/RECORD,,
18
+ mcp_dbutils-0.19.0.dist-info/METADATA,sha256=xOY0fVqaZ6XzrOmt2fQghZfEncZ8dXB8QN8fXaTaKKc,7146
19
+ mcp_dbutils-0.19.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ mcp_dbutils-0.19.0.dist-info/entry_points.txt,sha256=XTjt0QmYRgKOJQT6skR9bp1EMUfIrgpHeZJPZ3CJffs,49
21
+ mcp_dbutils-0.19.0.dist-info/licenses/LICENSE,sha256=1A_CwpWVlbjrKdVEYO77vYfnXlW7oxcilZ8FpA_BzCI,1065
22
+ mcp_dbutils-0.19.0.dist-info/RECORD,,