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.
- mcp_dbutils-0.15.0/.github/workflows/code-style.yml +17 -0
- mcp_dbutils-0.15.0/.pre-commit-config.yaml +7 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/CHANGELOG.md +7 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/PKG-INFO +36 -1
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/README.md +33 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/README_CN.md +65 -0
- mcp_dbutils-0.15.0/pyproject.toml +119 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/__init__.py +4 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/base.py +5 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/config.py +3 -4
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/log.py +2 -1
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/config.py +4 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/handler.py +2 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/server.py +6 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/config.py +4 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/handler.py +2 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/server.py +6 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/config.py +4 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/handler.py +2 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/server.py +5 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/stats.py +4 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/conftest.py +6 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/conftest.py +3 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/fixtures.py +8 -6
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_logging.py +4 -7
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring.py +5 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring_enhanced.py +6 -5
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql.py +7 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql_config.py +5 -4
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres.py +7 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres_config.py +4 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_prompts.py +4 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite.py +8 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite_config.py +4 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools.py +4 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools_advanced.py +4 -3
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/unit/test_log.py +5 -2
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/tests/unit/test_stats.py +2 -1
- mcp_dbutils-0.14.0/pyproject.toml +0 -58
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.coveragerc +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.github/workflows/quality-assurance.yml +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.github/workflows/release.yml +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.gitignore +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/.releaserc.json +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/Dockerfile +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/LICENSE +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/config.yaml.example +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/smithery.yaml +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/sonar-project.properties +0 -0
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/__init__.py +1 -1
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/__init__.py +1 -1
- {mcp_dbutils-0.14.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/__init__.py +1 -1
- {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
|
@@ -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.
|
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
|
+
[](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
|
+
[](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
|
+
[](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
|
20
|
+
from typing import AsyncContextManager
|
21
|
+
|
24
22
|
import mcp.server.stdio
|
25
23
|
import mcp.types as types
|
26
|
-
|
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
|
7
|
-
|
8
|
-
|
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,9 +1,11 @@
|
|
1
1
|
"""MySQL configuration module"""
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
4
|
-
from urllib.parse import
|
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
|
-
|
5
|
-
|
6
|
-
from
|
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
|
4
|
-
from urllib.parse import
|
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
|
-
|
5
|
-
|
6
|
-
from
|
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,
|
6
|
-
from urllib.parse import
|
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
|
-
|
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
|
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
|
-
|
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
|
6
|
-
|
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
|
-
|
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
|
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
|
-
|
12
|
+
import pytest
|
10
13
|
from testcontainers.mysql import MySqlContainer
|
11
14
|
from testcontainers.postgres import PostgresContainer
|
12
|
-
|
15
|
+
|
13
16
|
from mcp_dbutils.base import ConnectionHandler
|
14
|
-
|
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
|
11
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
8
|
-
from mcp_dbutils.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
5
|
-
from mcp_dbutils.base import
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|