mcp-dbutils 0.14.0__tar.gz → 0.15.0__tar.gz

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.
Files changed (53) hide show
  1. mcp_dbutils-0.15.0/.github/workflows/code-style.yml +17 -0
  2. mcp_dbutils-0.15.0/.pre-commit-config.yaml +7 -0
  3. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/CHANGELOG.md +7 -0
  4. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/PKG-INFO +36 -1
  5. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/README.md +33 -0
  6. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/README_CN.md +65 -0
  7. mcp_dbutils-0.15.0/pyproject.toml +119 -0
  8. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/__init__.py +4 -3
  9. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/base.py +5 -6
  10. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/config.py +3 -4
  11. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/log.py +2 -1
  12. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/config.py +4 -2
  13. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/handler.py +2 -2
  14. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/server.py +6 -6
  15. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/config.py +4 -2
  16. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/handler.py +2 -2
  17. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/server.py +6 -6
  18. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/config.py +4 -2
  19. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/handler.py +2 -2
  20. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/server.py +5 -6
  21. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/stats.py +4 -3
  22. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/conftest.py +6 -6
  23. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/conftest.py +3 -6
  24. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/fixtures.py +8 -6
  25. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_logging.py +4 -7
  26. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring.py +5 -2
  27. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring_enhanced.py +6 -5
  28. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql.py +7 -2
  29. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql_config.py +5 -4
  30. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres.py +7 -2
  31. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres_config.py +4 -2
  32. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_prompts.py +4 -3
  33. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite.py +8 -3
  34. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite_config.py +4 -2
  35. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools.py +4 -3
  36. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools_advanced.py +4 -3
  37. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/unit/test_log.py +5 -2
  38. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/unit/test_stats.py +2 -1
  39. mcp_dbutils-0.14.0/pyproject.toml +0 -58
  40. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.coveragerc +0 -0
  41. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.github/workflows/quality-assurance.yml +0 -0
  42. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.github/workflows/release.yml +0 -0
  43. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.gitignore +0 -0
  44. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.releaserc.json +0 -0
  45. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/Dockerfile +0 -0
  46. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/LICENSE +0 -0
  47. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/config.yaml.example +0 -0
  48. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/smithery.yaml +0 -0
  49. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/sonar-project.properties +0 -0
  50. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/__init__.py +1 -1
  51. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/__init__.py +1 -1
  52. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/__init__.py +1 -1
  53. {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/__init__.py +0 -0
@@ -0,0 +1,17 @@
1
+ name: Code Style
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ ruff:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: astral-sh/ruff-action@v3.2.1
16
+ with:
17
+ version: latest
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.3.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -1,3 +1,10 @@
1
+ # [0.15.0](https://github.com/donghao1393/mcp-dbutils/compare/v0.14.0...v0.15.0) (2025-03-14)
2
+
3
+
4
+ ### Features
5
+
6
+ * integrate Ruff code style automation ([#35](https://github.com/donghao1393/mcp-dbutils/issues/35)) ([6b2bdd7](https://github.com/donghao1393/mcp-dbutils/commit/6b2bdd749cecf2ad9167867c6e41149d1a57746f)), closes [#34](https://github.com/donghao1393/mcp-dbutils/issues/34)
7
+
1
8
  # [0.14.0](https://github.com/donghao1393/mcp-dbutils/compare/v0.13.0...v0.14.0) (2025-03-14)
2
9
 
3
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-dbutils
3
- Version: 0.14.0
3
+ Version: 0.15.0
4
4
  Summary: MCP Database Utilities Service
5
5
  Author: Dong Hao
6
6
  License-Expression: MIT
@@ -14,10 +14,12 @@ Requires-Dist: pyyaml>=6.0.2
14
14
  Provides-Extra: test
15
15
  Requires-Dist: aiosqlite>=0.19.0; extra == 'test'
16
16
  Requires-Dist: docker>=7.0.0; extra == 'test'
17
+ Requires-Dist: pre-commit>=3.6.0; extra == 'test'
17
18
  Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
18
19
  Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
19
20
  Requires-Dist: pytest-docker>=2.0.0; extra == 'test'
20
21
  Requires-Dist: pytest>=7.0.0; extra == 'test'
22
+ Requires-Dist: ruff>=0.3.0; extra == 'test'
21
23
  Requires-Dist: testcontainers>=3.7.0; extra == 'test'
22
24
  Description-Content-Type: text/markdown
23
25
 
@@ -483,6 +485,19 @@ Our CI/CD pipeline automatically performs:
483
485
 
484
486
  Pull requests that don't meet these standards will be automatically blocked from merging.
485
487
 
488
+ ### Code Style
489
+ We use Ruff for code style checking and formatting:
490
+
491
+ [![Code Style](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
492
+
493
+ All code must follow our style guide:
494
+ - Line length: 88 characters
495
+ - Indentation: 4 spaces
496
+ - Quotes: Double quotes
497
+ - Naming: PEP8 conventions
498
+
499
+ For detailed guidelines, see [STYLE_GUIDE.md](docs/STYLE_GUIDE.md).
500
+
486
501
  ### Local Development
487
502
  To check code quality locally:
488
503
  1. Run tests with coverage:
@@ -491,6 +506,26 @@ To check code quality locally:
491
506
  ```
492
507
  2. Use SonarLint in your IDE to catch issues early
493
508
  3. Review SonarCloud analysis results in PR comments
509
+ 4. Run Ruff for code style checking:
510
+ ```bash
511
+ # Install Ruff
512
+ uv pip install ruff
513
+
514
+ # Check code style
515
+ ruff check .
516
+
517
+ # Format code
518
+ ruff format .
519
+ ```
520
+ 5. Use pre-commit hooks for automatic checks:
521
+ ```bash
522
+ # Install pre-commit
523
+ uv pip install pre-commit
524
+ pre-commit install
525
+
526
+ # Run all checks
527
+ pre-commit run --all-files
528
+ ```
494
529
 
495
530
  ## Contributing
496
531
  Contributions are welcome! Here's how you can help:
@@ -460,6 +460,19 @@ Our CI/CD pipeline automatically performs:
460
460
 
461
461
  Pull requests that don't meet these standards will be automatically blocked from merging.
462
462
 
463
+ ### Code Style
464
+ We use Ruff for code style checking and formatting:
465
+
466
+ [![Code Style](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
467
+
468
+ All code must follow our style guide:
469
+ - Line length: 88 characters
470
+ - Indentation: 4 spaces
471
+ - Quotes: Double quotes
472
+ - Naming: PEP8 conventions
473
+
474
+ For detailed guidelines, see [STYLE_GUIDE.md](docs/STYLE_GUIDE.md).
475
+
463
476
  ### Local Development
464
477
  To check code quality locally:
465
478
  1. Run tests with coverage:
@@ -468,6 +481,26 @@ To check code quality locally:
468
481
  ```
469
482
  2. Use SonarLint in your IDE to catch issues early
470
483
  3. Review SonarCloud analysis results in PR comments
484
+ 4. Run Ruff for code style checking:
485
+ ```bash
486
+ # Install Ruff
487
+ uv pip install ruff
488
+
489
+ # Check code style
490
+ ruff check .
491
+
492
+ # Format code
493
+ ruff format .
494
+ ```
495
+ 5. Use pre-commit hooks for automatic checks:
496
+ ```bash
497
+ # Install pre-commit
498
+ uv pip install pre-commit
499
+ pre-commit install
500
+
501
+ # Run all checks
502
+ pre-commit run --all-files
503
+ ```
471
504
 
472
505
  ## Contributing
473
506
  Contributions are welcome! Here's how you can help:
@@ -419,6 +419,71 @@ except Exception as e:
419
419
  - SSL/TLS安全连接
420
420
  - URL和标准连接方式
421
421
 
422
+ ## 代码质量
423
+
424
+ ### 质量门禁
425
+ 我们使用SonarCloud维持高代码质量标准。所有的Pull Request必须通过以下质量门禁:
426
+
427
+ - 代码覆盖率:≥ 80%
428
+ - 代码质量:
429
+ * 无阻塞级和严重级问题
430
+ * 主要问题数少于10个
431
+ * 代码重复率 < 3%
432
+ - 安全性:
433
+ * 无安全漏洞
434
+ * 无安全热点问题
435
+
436
+ ### 自动化检查
437
+ 我们的CI/CD流程自动执行:
438
+ 1. 完整测试套件运行
439
+ 2. 代码覆盖率分析
440
+ 3. SonarCloud静态代码分析
441
+ 4. 质量门禁验证
442
+
443
+ 不符合这些标准的Pull Request将被自动阻止合并。
444
+
445
+ ### 代码风格
446
+ 我们使用Ruff进行代码风格检查和格式化:
447
+
448
+ [![Code Style](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
449
+
450
+ 所有代码必须遵循我们的风格指南:
451
+ - 行长度:88个字符
452
+ - 缩进:4个空格
453
+ - 引号:双引号
454
+ - 命名:PEP8约定
455
+
456
+ 详细指南请参见[STYLE_GUIDE.md](docs/STYLE_GUIDE.md)。
457
+
458
+ ### 本地开发
459
+ 本地检查代码质量:
460
+ 1. 运行带覆盖率的测试:
461
+ ```bash
462
+ pytest --cov=src/mcp_dbutils --cov-report=xml:coverage.xml tests/
463
+ ```
464
+ 2. 在IDE中使用SonarLint及早发现问题
465
+ 3. 在PR评论中查看SonarCloud分析结果
466
+ 4. 运行Ruff进行代码风格检查:
467
+ ```bash
468
+ # 安装Ruff
469
+ uv pip install ruff
470
+
471
+ # 检查代码风格
472
+ ruff check .
473
+
474
+ # 格式化代码
475
+ ruff format .
476
+ ```
477
+ 5. 使用pre-commit钩子进行自动检查:
478
+ ```bash
479
+ # 安装pre-commit
480
+ uv pip install pre-commit
481
+ pre-commit install
482
+
483
+ # 运行所有检查
484
+ pre-commit run --all-files
485
+ ```
486
+
422
487
  ## 参与贡献
423
488
  欢迎贡献!以下是参与项目的方式:
424
489
 
@@ -0,0 +1,119 @@
1
+ [project]
2
+ name = "mcp-dbutils"
3
+ version = "0.15.0"
4
+ description = "MCP Database Utilities Service"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [
8
+ {name = "Dong Hao"}
9
+ ]
10
+ dependencies = [
11
+ "mcp>=1.2.1",
12
+ "psycopg2-binary>=2.9.10",
13
+ "python-dotenv>=1.0.1",
14
+ "pyyaml>=6.0.2",
15
+ "mysql-connector-python>=8.2.0",
16
+ ]
17
+ requires-python = ">=3.10"
18
+
19
+ [build-system]
20
+ requires = ["hatchling"]
21
+ build-backend = "hatchling.build"
22
+
23
+ [project.scripts]
24
+ mcp-dbutils = "mcp_dbutils:main"
25
+
26
+ [tool.semantic_release]
27
+ version_variables = [
28
+ "pyproject.toml:project.version"
29
+ ]
30
+ version_toml = [
31
+ "pyproject.toml:project.version"
32
+ ]
33
+ commit_parser = "conventional"
34
+ major_on_zero = false
35
+ branch = "main"
36
+ changelog_components = "semantic_release.changelog.changelog"
37
+ build_command = "uv build"
38
+
39
+ [project.optional-dependencies]
40
+ test = [
41
+ "pytest>=7.0.0",
42
+ "pytest-asyncio>=0.23.0",
43
+ "pytest-docker>=2.0.0",
44
+ "docker>=7.0.0",
45
+ "aiosqlite>=0.19.0",
46
+ "testcontainers>=3.7.0",
47
+ "pytest-cov>=4.1.0",
48
+ "ruff>=0.3.0",
49
+ "pre-commit>=3.6.0"
50
+ ]
51
+
52
+ [tool.pytest.ini_options]
53
+ asyncio_mode = "strict"
54
+ asyncio_default_fixture_loop_scope = "function"
55
+ markers = [
56
+ "no_collect: marks test classes that should not be collected as test cases"
57
+ ]
58
+ filterwarnings = [
59
+ "ignore::pytest.PytestCollectionWarning"
60
+ ]
61
+
62
+ # Ruff配置
63
+ [tool.ruff]
64
+ # 目标Python版本
65
+ target-version = "0.15.0"
66
+ # 行长度限制
67
+ line-length = 88
68
+ # 排除的文件和目录
69
+ exclude = [
70
+ ".git",
71
+ ".venv",
72
+ "__pycache__",
73
+ "build",
74
+ "dist",
75
+ ]
76
+
77
+ # Lint配置
78
+ [tool.ruff.lint]
79
+ # 选择的规则集
80
+ select = [
81
+ "E", # pycodestyle错误
82
+ "F", # pyflakes
83
+ "I", # isort
84
+ "N", # pep8-naming
85
+ "UP", # pyupgrade
86
+ "B", # flake8-bugbear
87
+ "C4", # flake8-comprehensions
88
+ "SIM", # flake8-simplify
89
+ "T20", # flake8-print
90
+ ]
91
+ # 忽略的规则 - 暂时忽略,后续PR中逐步修复
92
+ ignore = [
93
+ "E501", # 行太长
94
+ "B904", # 在except子句中使用raise ... from err
95
+ "UP035", # 使用新的typing语法
96
+ "UP006", # 使用新的类型注解语法
97
+ "UP007", # 使用X | Y替代Union
98
+ "F401", # 未使用的导入
99
+ "F541", # f-string没有占位符
100
+ "UP015", # 不必要的mode参数
101
+ "UP032", # 使用f-string替代format
102
+ "B905", # zip()没有strict参数
103
+ "SIM105", # 使用contextlib.suppress
104
+ "UP038", # 在isinstance调用中使用X | Y
105
+ "F821", # 未定义的名称
106
+ "F841", # 未使用的局部变量
107
+ "E402", # 模块级导入不在文件顶部
108
+ "T201", # print语句 - 在日志模块中是必要的
109
+ ]
110
+
111
+ # isort配置
112
+ [tool.ruff.lint.isort]
113
+ known-first-party = ["mcp_dbutils"]
114
+
115
+ # 格式化配置
116
+ [tool.ruff.format]
117
+ quote-style = "double"
118
+ indent-style = "space"
119
+ line-ending = "auto"
@@ -1,15 +1,16 @@
1
1
  """MCP Connection Utilities Service"""
2
2
 
3
- import asyncio
4
3
  import argparse
4
+ import asyncio
5
5
  import os
6
6
  import sys
7
+ from importlib.metadata import metadata
7
8
  from pathlib import Path
9
+
8
10
  import yaml
9
- from importlib.metadata import metadata
10
11
 
12
+ from .base import LOG_NAME, ConnectionServer
11
13
  from .log import create_logger
12
- from .base import ConnectionServer, LOG_NAME
13
14
 
14
15
  # 获取包信息
15
16
  pkg_meta = metadata("mcp-dbutils")
@@ -12,18 +12,17 @@ class ConnectionError(ConnectionHandlerError):
12
12
  """Connection related errors"""
13
13
  pass
14
14
 
15
+ import json
15
16
  from abc import ABC, abstractmethod
16
- from typing import Any, List, Optional, AsyncContextManager
17
17
  from contextlib import asynccontextmanager
18
- import json
19
- import yaml
20
- import time
21
18
  from datetime import datetime
22
19
  from importlib.metadata import metadata
23
- from mcp.server import Server, NotificationOptions
20
+ from typing import AsyncContextManager
21
+
24
22
  import mcp.server.stdio
25
23
  import mcp.types as types
26
- from mcp.shared.session import RequestResponder
24
+ import yaml
25
+ from mcp.server import Server
27
26
 
28
27
  from .log import create_logger
29
28
  from .stats import ResourceStats
@@ -1,11 +1,10 @@
1
1
  """Common configuration utilities"""
2
2
 
3
3
  import os
4
- import yaml
5
4
  from abc import ABC, abstractmethod
6
- from dataclasses import dataclass, field
7
- from typing import Optional, Dict, Any, Literal
8
- from pathlib import Path
5
+ from typing import Any, Dict, Literal
6
+
7
+ import yaml
9
8
 
10
9
  # Supported connection types
11
10
  ConnectionType = Literal['sqlite', 'postgres', 'mysql']
@@ -1,8 +1,9 @@
1
1
  """日志处理模块"""
2
2
 
3
3
  import sys
4
+ from collections.abc import Callable
4
5
  from datetime import datetime
5
- from typing import Callable
6
+
6
7
 
7
8
  def create_logger(name: str, is_debug: bool = False) -> Callable:
8
9
  """创建stderr日志函数,用于本地调试
@@ -1,9 +1,11 @@
1
1
  """MySQL configuration module"""
2
2
  from dataclasses import dataclass
3
- from typing import Optional, Dict, Any, Literal
4
- from urllib.parse import urlparse, parse_qs
3
+ from typing import Any, Dict, Literal, Optional
4
+ from urllib.parse import parse_qs, urlparse
5
+
5
6
  from ..config import ConnectionConfig
6
7
 
8
+
7
9
  @dataclass
8
10
  class SSLConfig:
9
11
  """SSL configuration for MySQL connection"""
@@ -1,12 +1,12 @@
1
1
  """MySQL connection handler implementation"""
2
2
 
3
- import mysql.connector
4
- from mysql.connector.pooling import MySQLConnectionPool
5
3
  import mcp.types as types
4
+ import mysql.connector
6
5
 
7
6
  from ..base import ConnectionHandler, ConnectionHandlerError
8
7
  from .config import MySQLConfig
9
8
 
9
+
10
10
  class MySQLHandler(ConnectionHandler):
11
11
  @property
12
12
  def db_type(self) -> str:
@@ -1,15 +1,15 @@
1
1
  """MySQL MCP server implementation"""
2
+ from typing import Optional
3
+
4
+ import mcp.types as types
2
5
  import mysql.connector
3
6
  from mysql.connector.pooling import MySQLConnectionPool, PooledMySQLConnection
4
- from typing import Optional, List
5
- import mcp.types as types
6
- from importlib.metadata import metadata
7
- from ..base import ConnectionServer
7
+
8
+ # 获取包信息用于日志命名
9
+ from ..base import LOG_NAME, ConnectionServer
8
10
  from ..log import create_logger
9
11
  from .config import MySQLConfig
10
12
 
11
- # 获取包信息用于日志命名
12
- from ..base import LOG_NAME
13
13
 
14
14
  class MySQLServer(ConnectionServer):
15
15
  def __init__(self, config: MySQLConfig, config_path: Optional[str] = None):
@@ -1,9 +1,11 @@
1
1
  """PostgreSQL configuration module"""
2
2
  from dataclasses import dataclass
3
- from typing import Optional, Dict, Any, Literal
4
- from urllib.parse import urlparse, parse_qs
3
+ from typing import Any, Dict, Literal, Optional
4
+ from urllib.parse import parse_qs, urlparse
5
+
5
6
  from ..config import ConnectionConfig
6
7
 
8
+
7
9
  @dataclass
8
10
  class SSLConfig:
9
11
  """SSL configuration for PostgreSQL connection"""
@@ -1,12 +1,12 @@
1
1
  """PostgreSQL connection handler implementation"""
2
2
 
3
- import psycopg2
4
- from psycopg2.pool import SimpleConnectionPool
5
3
  import mcp.types as types
4
+ import psycopg2
6
5
 
7
6
  from ..base import ConnectionHandler, ConnectionHandlerError
8
7
  from .config import PostgreSQLConfig
9
8
 
9
+
10
10
  class PostgreSQLHandler(ConnectionHandler):
11
11
  @property
12
12
  def db_type(self) -> str:
@@ -1,15 +1,15 @@
1
1
  """PostgreSQL MCP server implementation"""
2
+ from typing import Optional
3
+
4
+ import mcp.types as types
2
5
  import psycopg2
3
6
  from psycopg2.pool import SimpleConnectionPool
4
- from typing import Optional, List
5
- import mcp.types as types
6
- from importlib.metadata import metadata
7
- from ..base import ConnectionServer
7
+
8
+ # 获取包信息用于日志命名
9
+ from ..base import LOG_NAME, ConnectionServer
8
10
  from ..log import create_logger
9
11
  from .config import PostgreSQLConfig
10
12
 
11
- # 获取包信息用于日志命名
12
- from ..base import LOG_NAME
13
13
 
14
14
  class PostgreSQLServer(ConnectionServer):
15
15
  def __init__(self, config: PostgreSQLConfig, config_path: Optional[str] = None):
@@ -2,10 +2,12 @@
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from pathlib import Path
5
- from typing import Dict, Any, Optional, Literal
6
- from urllib.parse import urlparse, parse_qs
5
+ from typing import Any, Dict, Literal, Optional
6
+ from urllib.parse import parse_qs, urlparse
7
+
7
8
  from ..config import ConnectionConfig
8
9
 
10
+
9
11
  def parse_jdbc_url(jdbc_url: str) -> Dict[str, str]:
10
12
  """Parse JDBC URL into connection parameters
11
13
 
@@ -1,13 +1,13 @@
1
1
  """SQLite connection handler implementation"""
2
2
 
3
3
  import sqlite3
4
- import json
5
- from typing import Any
4
+
6
5
  import mcp.types as types
7
6
 
8
7
  from ..base import ConnectionHandler, ConnectionHandlerError
9
8
  from .config import SQLiteConfig
10
9
 
10
+
11
11
  class SQLiteHandler(ConnectionHandler):
12
12
  @property
13
13
  def db_type(self) -> str:
@@ -1,18 +1,17 @@
1
1
  """SQLite MCP server implementation"""
2
2
 
3
3
  import sqlite3
4
- from pathlib import Path
5
4
  from contextlib import closing
6
- from typing import Optional, List
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
7
8
  import mcp.types as types
8
- from importlib.metadata import metadata
9
9
 
10
- from ..base import ConnectionServer
10
+ # 获取包信息用于日志命名
11
+ from ..base import LOG_NAME, ConnectionServer
11
12
  from ..log import create_logger
12
13
  from .config import SQLiteConfig
13
14
 
14
- # 获取包信息用于日志命名
15
- from ..base import LOG_NAME
16
15
 
17
16
  class SQLiteServer(ConnectionServer):
18
17
  def __init__(self, config: SQLiteConfig, config_path: Optional[str] = None):
@@ -1,10 +1,11 @@
1
1
  """Resource monitoring statistics module"""
2
2
 
3
+ import statistics
4
+ import sys
3
5
  from dataclasses import dataclass
4
6
  from datetime import datetime
5
- from typing import Optional, List, Tuple
6
- import sys
7
- import statistics
7
+ from typing import List, Optional, Tuple
8
+
8
9
 
9
10
  @dataclass
10
11
  class ResourceStats:
@@ -1,14 +1,14 @@
1
- import os
2
- import pytest
3
- from pytest_asyncio import fixture
4
- import asyncio
5
1
  import tempfile
2
+ from collections.abc import AsyncGenerator
6
3
  from pathlib import Path
4
+ from typing import Dict
5
+ from urllib.parse import urlparse
6
+
7
7
  import aiosqlite
8
8
  import psycopg2
9
+ import pytest
10
+ from pytest_asyncio import fixture
9
11
  from testcontainers.postgres import PostgresContainer
10
- from typing import AsyncGenerator, Generator, Dict
11
- from urllib.parse import urlparse
12
12
 
13
13
  # Enable pytest-asyncio for testing
14
14
  pytest.register_assert_rewrite("tests")
@@ -1,12 +1,9 @@
1
1
  """Test fixtures and utility functions for pytest"""
2
2
 
3
- import pytest
4
- from .fixtures import (
5
- TestConnectionHandler,
6
- mysql_db,
7
- mcp_config
8
- )
3
+
4
+ from .fixtures import TestConnectionHandler, mcp_config, mysql_db
9
5
 
10
6
  # Register fixtures
11
7
  mysql_db = mysql_db
12
8
  mcp_config = mcp_config
9
+ TestConnectionHandler = TestConnectionHandler
@@ -1,18 +1,20 @@
1
1
  """Test fixtures and helper classes for integration tests"""
2
2
 
3
- import pytest
4
3
  import tempfile
5
- import asyncio
4
+ from collections.abc import AsyncGenerator
6
5
  from pathlib import Path
6
+ from typing import Dict
7
+ from unittest.mock import MagicMock
8
+ from urllib.parse import urlparse
9
+
7
10
  import aiosqlite
8
11
  import psycopg2
9
- from unittest.mock import MagicMock
12
+ import pytest
10
13
  from testcontainers.mysql import MySqlContainer
11
14
  from testcontainers.postgres import PostgresContainer
12
- from testcontainers.core.waiting_utils import wait_for_logs
15
+
13
16
  from mcp_dbutils.base import ConnectionHandler
14
- from typing import AsyncGenerator, Dict
15
- from urllib.parse import urlparse
17
+
16
18
 
17
19
  class _TestConnectionHandler(ConnectionHandler):
18
20
  """Test implementation of ConnectionHandler"""
@@ -1,14 +1,11 @@
1
1
  """Test MCP logging functionality"""
2
2
 
3
+ from unittest.mock import MagicMock, patch
4
+
3
5
  import pytest
4
- import asyncio
5
- import logging
6
- from unittest.mock import MagicMock, patch, call
7
- from mcp.server import Server
8
- from mcp.types import LoggingMessageNotification
9
6
 
10
- from mcp_dbutils.base import ConnectionHandler, ConnectionServer
11
- from mcp_dbutils.log import create_logger
7
+ from mcp_dbutils.base import ConnectionServer
8
+
12
9
  from . import conftest
13
10
 
14
11
  TestConnectionHandler = conftest.TestConnectionHandler
@@ -1,9 +1,12 @@
1
1
  """Integration tests for resource monitoring"""
2
2
 
3
- import pytest
4
3
  import tempfile
4
+
5
+ import pytest
5
6
  import yaml
6
- from mcp_dbutils.base import ConnectionServer, ConnectionHandlerError
7
+
8
+ from mcp_dbutils.base import ConnectionHandlerError, ConnectionServer
9
+
7
10
 
8
11
  @pytest.mark.asyncio
9
12
  async def test_sqlite_monitoring(sqlite_db, mcp_config):
@@ -1,14 +1,15 @@
1
1
  """Integration tests for enhanced monitoring features"""
2
2
 
3
- import pytest
4
3
  import tempfile
5
- import yaml
6
- import time
7
- import json
8
4
  from datetime import datetime
9
- from mcp_dbutils.base import ConnectionServer, ConnectionHandlerError
5
+
6
+ import pytest
7
+ import yaml
8
+
9
+ from mcp_dbutils.base import ConnectionHandlerError, ConnectionServer
10
10
  from mcp_dbutils.stats import ResourceStats
11
11
 
12
+
12
13
  @pytest.mark.asyncio
13
14
  async def test_resource_stats_performance_tracking(sqlite_db, mcp_config):
14
15
  """Test performance tracking in ResourceStats"""
@@ -1,9 +1,14 @@
1
1
  """Test MySQL integration"""
2
2
 
3
- import pytest
4
3
  import tempfile
4
+
5
+ import pytest
5
6
  import yaml
6
- from mcp_dbutils.base import ConnectionServer, ConfigurationError, ConnectionHandlerError
7
+
8
+ from mcp_dbutils.base import (
9
+ ConnectionHandlerError,
10
+ ConnectionServer,
11
+ )
7
12
  from mcp_dbutils.log import create_logger
8
13
 
9
14
  # 创建测试用的 logger
@@ -1,11 +1,12 @@
1
1
  """Test MySQL configuration parsing"""
2
2
 
3
- import pytest
4
- import os
5
3
  import tempfile
4
+
5
+ import pytest
6
6
  import yaml
7
- from mcp_dbutils.mysql.config import MySQLConfig, SSLConfig
8
- from mcp_dbutils.base import ConfigurationError
7
+
8
+ from mcp_dbutils.mysql.config import MySQLConfig
9
+
9
10
 
10
11
  def test_basic_config():
11
12
  """Test basic MySQL configuration parsing"""
@@ -1,7 +1,12 @@
1
- import pytest
2
1
  import tempfile
2
+
3
+ import pytest
3
4
  import yaml
4
- from mcp_dbutils.base import ConnectionServer, ConfigurationError, ConnectionHandlerError
5
+
6
+ from mcp_dbutils.base import (
7
+ ConnectionHandlerError,
8
+ ConnectionServer,
9
+ )
5
10
  from mcp_dbutils.log import create_logger
6
11
 
7
12
  # 创建测试用的 logger
@@ -1,8 +1,10 @@
1
1
  """Test PostgreSQL configuration functionality"""
2
+
2
3
  import pytest
3
- import tempfile
4
4
  import yaml
5
- from mcp_dbutils.postgres.config import PostgreSQLConfig, parse_url, SSLConfig
5
+
6
+ from mcp_dbutils.postgres.config import PostgreSQLConfig, SSLConfig, parse_url
7
+
6
8
 
7
9
  def test_parse_url():
8
10
  """Test URL parsing"""
@@ -1,13 +1,14 @@
1
1
  """Integration tests for prompts functionality"""
2
2
 
3
3
  import asyncio
4
- import pytest
5
4
  import tempfile
6
- import yaml
5
+
7
6
  import anyio
8
7
  import mcp.types as types
8
+ import pytest
9
+ import yaml
9
10
  from mcp import ClientSession
10
- import mcp.server.stdio
11
+
11
12
  from mcp_dbutils.base import ConnectionServer
12
13
  from mcp_dbutils.log import create_logger
13
14
 
@@ -1,8 +1,13 @@
1
- import pytest
2
1
  import tempfile
2
+
3
+ import pytest
3
4
  import yaml
4
- from pathlib import Path
5
- from mcp_dbutils.base import ConnectionServer, ConfigurationError, ConnectionHandlerError
5
+
6
+ from mcp_dbutils.base import (
7
+ ConnectionHandlerError,
8
+ ConnectionServer,
9
+ )
10
+
6
11
 
7
12
  @pytest.mark.asyncio
8
13
  async def test_list_tables(sqlite_db, mcp_config):
@@ -1,10 +1,12 @@
1
1
  """Test SQLite configuration functionality"""
2
+ from pathlib import Path
3
+
2
4
  import pytest
3
- import tempfile
4
5
  import yaml
5
- from pathlib import Path
6
+
6
7
  from mcp_dbutils.sqlite.config import SQLiteConfig, parse_jdbc_url
7
8
 
9
+
8
10
  def test_parse_jdbc_url():
9
11
  """Test JDBC URL parsing"""
10
12
  # Test basic URL
@@ -1,11 +1,12 @@
1
1
  import asyncio
2
- import pytest
3
2
  import tempfile
4
- import yaml
3
+
5
4
  import anyio
6
5
  import mcp.types as types
6
+ import pytest
7
+ import yaml
7
8
  from mcp import ClientSession
8
- from mcp.shared.exceptions import McpError
9
+
9
10
  from mcp_dbutils.base import ConnectionServer
10
11
  from mcp_dbutils.log import create_logger
11
12
 
@@ -1,13 +1,14 @@
1
1
  """Integration tests for advanced database tools"""
2
2
 
3
3
  import asyncio
4
- import pytest
5
4
  import tempfile
6
- import yaml
5
+
7
6
  import anyio
8
7
  import mcp.types as types
8
+ import pytest
9
+ import yaml
9
10
  from mcp import ClientSession
10
- from mcp.shared.exceptions import McpError
11
+
11
12
  from mcp_dbutils.base import ConnectionServer
12
13
  from mcp_dbutils.log import create_logger
13
14
 
@@ -1,11 +1,14 @@
1
1
  """Test logging module"""
2
2
 
3
- import sys
4
3
  import io
5
- import pytest
4
+ import sys
6
5
  from datetime import datetime
6
+
7
+ import pytest
8
+
7
9
  from mcp_dbutils.log import create_logger
8
10
 
11
+
9
12
  def test_log_basic_output():
10
13
  """Test basic log output functionality"""
11
14
  # 捕获stderr输出
@@ -1,9 +1,10 @@
1
1
  """Unit tests for resource monitoring functionality"""
2
2
 
3
- import pytest
4
3
  from datetime import datetime
4
+
5
5
  from mcp_dbutils.stats import ResourceStats
6
6
 
7
+
7
8
  def test_connection_tracking():
8
9
  """Test connection tracking functionality"""
9
10
  stats = ResourceStats()
@@ -1,58 +0,0 @@
1
- [project]
2
- name = "mcp-dbutils"
3
- version = "0.14.0"
4
- description = "MCP Database Utilities Service"
5
- readme = "README.md"
6
- license = "MIT"
7
- authors = [
8
- {name = "Dong Hao"}
9
- ]
10
- dependencies = [
11
- "mcp>=1.2.1",
12
- "psycopg2-binary>=2.9.10",
13
- "python-dotenv>=1.0.1",
14
- "pyyaml>=6.0.2",
15
- "mysql-connector-python>=8.2.0",
16
- ]
17
- requires-python = ">=3.10"
18
-
19
- [build-system]
20
- requires = ["hatchling"]
21
- build-backend = "hatchling.build"
22
-
23
- [project.scripts]
24
- mcp-dbutils = "mcp_dbutils:main"
25
-
26
- [tool.semantic_release]
27
- version_variables = [
28
- "pyproject.toml:project.version"
29
- ]
30
- version_toml = [
31
- "pyproject.toml:project.version"
32
- ]
33
- commit_parser = "conventional"
34
- major_on_zero = false
35
- branch = "main"
36
- changelog_components = "semantic_release.changelog.changelog"
37
- build_command = "uv build"
38
-
39
- [project.optional-dependencies]
40
- test = [
41
- "pytest>=7.0.0",
42
- "pytest-asyncio>=0.23.0",
43
- "pytest-docker>=2.0.0",
44
- "docker>=7.0.0",
45
- "aiosqlite>=0.19.0",
46
- "testcontainers>=3.7.0",
47
- "pytest-cov>=4.1.0"
48
- ]
49
-
50
- [tool.pytest.ini_options]
51
- asyncio_mode = "strict"
52
- asyncio_default_fixture_loop_scope = "function"
53
- markers = [
54
- "no_collect: marks test classes that should not be collected as test cases"
55
- ]
56
- filterwarnings = [
57
- "ignore::pytest.PytestCollectionWarning"
58
- ]
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
1
  """MySQL module"""
2
2
 
3
- from .handler import MySQLHandler
4
3
  from .config import MySQLConfig
4
+ from .handler import MySQLHandler
5
5
 
6
6
  __all__ = ['MySQLHandler', 'MySQLConfig']
@@ -1,6 +1,6 @@
1
1
  """PostgreSQL module"""
2
2
 
3
- from .handler import PostgreSQLHandler
4
3
  from .config import PostgreSQLConfig
4
+ from .handler import PostgreSQLHandler
5
5
 
6
6
  __all__ = ['PostgreSQLHandler', 'PostgreSQLConfig']
@@ -1,6 +1,6 @@
1
1
  """SQLite module"""
2
2
 
3
- from .handler import SQLiteHandler
4
3
  from .config import SQLiteConfig
4
+ from .handler import SQLiteHandler
5
5
 
6
6
  __all__ = ['SQLiteHandler', 'SQLiteConfig']