mcp-dbutils 0.13.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 (55) hide show
  1. mcp_dbutils-0.15.0/.github/workflows/code-style.yml +17 -0
  2. mcp_dbutils-0.15.0/.github/workflows/quality-assurance.yml +266 -0
  3. mcp_dbutils-0.15.0/.pre-commit-config.yaml +7 -0
  4. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/CHANGELOG.md +14 -0
  5. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/PKG-INFO +36 -1
  6. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/README.md +33 -0
  7. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/README_CN.md +65 -0
  8. mcp_dbutils-0.15.0/pyproject.toml +119 -0
  9. mcp_dbutils-0.15.0/sonar-project.properties +14 -0
  10. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/__init__.py +4 -3
  11. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/base.py +5 -6
  12. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/config.py +3 -4
  13. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/log.py +2 -1
  14. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/config.py +4 -2
  15. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/handler.py +2 -2
  16. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/server.py +6 -6
  17. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/config.py +4 -2
  18. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/handler.py +2 -2
  19. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/server.py +6 -6
  20. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/config.py +4 -2
  21. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/handler.py +2 -2
  22. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/server.py +5 -6
  23. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/stats.py +4 -3
  24. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/conftest.py +6 -6
  25. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/conftest.py +3 -6
  26. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/fixtures.py +8 -6
  27. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_logging.py +4 -7
  28. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring.py +5 -2
  29. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_monitoring_enhanced.py +6 -5
  30. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql.py +7 -2
  31. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_mysql_config.py +5 -4
  32. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres.py +7 -2
  33. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_postgres_config.py +4 -2
  34. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_prompts.py +4 -3
  35. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite.py +8 -3
  36. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_sqlite_config.py +4 -2
  37. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools.py +4 -3
  38. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/integration/test_tools_advanced.py +4 -3
  39. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/unit/test_log.py +5 -2
  40. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/tests/unit/test_stats.py +2 -1
  41. mcp_dbutils-0.13.0/.github/workflows/quality-assurance.yml +0 -110
  42. mcp_dbutils-0.13.0/pyproject.toml +0 -58
  43. mcp_dbutils-0.13.0/sonar-project.properties +0 -6
  44. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/.coveragerc +0 -0
  45. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/.github/workflows/release.yml +0 -0
  46. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/.gitignore +0 -0
  47. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/.releaserc.json +0 -0
  48. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/Dockerfile +0 -0
  49. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/LICENSE +0 -0
  50. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/config.yaml.example +0 -0
  51. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/smithery.yaml +0 -0
  52. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/mysql/__init__.py +1 -1
  53. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/postgres/__init__.py +1 -1
  54. {mcp_dbutils-0.13.0 → mcp_dbutils-0.15.0}/src/mcp_dbutils/sqlite/__init__.py +1 -1
  55. {mcp_dbutils-0.13.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,266 @@
1
+ name: Quality Assurance
2
+
3
+ # 添加明确的权限声明
4
+ permissions:
5
+ contents: read
6
+ pull-requests: write # 允许创建PR评论
7
+ issues: write # 允许创建issue评论
8
+ checks: write # 允许更新检查状态
9
+
10
+ on:
11
+ push:
12
+ branches: [ main ]
13
+ pull_request:
14
+ branches: [ main ]
15
+
16
+ jobs:
17
+ pytest:
18
+ runs-on: ubuntu-latest
19
+
20
+ services:
21
+ postgres:
22
+ image: postgres:15-alpine
23
+ env:
24
+ POSTGRES_PASSWORD: postgres
25
+ ports:
26
+ - 5432:5432
27
+ options: >-
28
+ --health-cmd pg_isready
29
+ --health-interval 10s
30
+ --health-timeout 5s
31
+ --health-retries 5
32
+
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v4
38
+
39
+ - name: Set up Python
40
+ run: uv python install
41
+
42
+ - name: Create and activate venv
43
+ run: |
44
+ uv venv
45
+ . .venv/bin/activate
46
+
47
+ - name: Install dependencies
48
+ run: uv pip install -e ".[test]"
49
+
50
+ - name: Run tests with coverage
51
+ id: tests
52
+ run: |
53
+ uv run pytest \
54
+ -v \
55
+ --cov=src/mcp_dbutils \
56
+ --cov-report=html \
57
+ --cov-report=term-missing \
58
+ --cov-report=json:coverage.json \
59
+ --cov-report=xml:coverage.xml \
60
+ tests/
61
+
62
+ - name: Upload coverage report
63
+ uses: actions/upload-artifact@v4
64
+ with:
65
+ name: coverage-report
66
+ path: coverage.xml
67
+
68
+ - name: Calculate coverage percentage
69
+ id: calc_coverage
70
+ run: |
71
+ COVERAGE=$(jq -r '.totals.percent_covered' coverage.json)
72
+ echo "Coverage: $COVERAGE"
73
+ echo "percentage=${COVERAGE%.*}" >> $GITHUB_OUTPUT
74
+ if (( $(echo "$COVERAGE >= 90" | bc -l) )); then
75
+ echo "color=green" >> $GITHUB_OUTPUT
76
+ elif (( $(echo "$COVERAGE >= 80" | bc -l) )); then
77
+ echo "color=yellow" >> $GITHUB_OUTPUT
78
+ else
79
+ echo "color=red" >> $GITHUB_OUTPUT
80
+ fi
81
+
82
+ - name: Create Coverage Badge
83
+ uses: schneegans/dynamic-badges-action@v1.7.0
84
+ with:
85
+ auth: ${{ secrets.GIST_SECRET }}
86
+ gistID: bdd0a63ec2a816539ff8c136ceb41e48
87
+ filename: coverage.json
88
+ label: "coverage"
89
+ message: "${{ steps.calc_coverage.outputs.percentage }}%"
90
+ color: "${{ steps.calc_coverage.outputs.color }}"
91
+ namedLogo: python
92
+
93
+ sonarcloud:
94
+ name: SonarCloud
95
+ needs: pytest
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+ with:
100
+ fetch-depth: 0
101
+ - name: Download coverage report
102
+ uses: actions/download-artifact@v4
103
+ with:
104
+ name: coverage-report
105
+ - name: SonarCloud Scan
106
+ uses: SonarSource/sonarqube-scan-action@v5.0.0
107
+ env:
108
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
110
+
111
+ - name: SonarQube Quality Gate Check
112
+ uses: sonarsource/sonarqube-quality-gate-action@master
113
+ timeout-minutes: 5
114
+ env:
115
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
116
+ with:
117
+ scanMetadataReportFile: .scannerwork/report-task.txt
118
+
119
+ - name: SonarCloud PR Comment
120
+ if: github.event_name == 'pull_request'
121
+ uses: actions/github-script@v6
122
+ env:
123
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
124
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
125
+ SONAR_PROJECT_KEY: 'donghao1393_mcp-dbutils'
126
+ with:
127
+ script: |
128
+ const fs = require('fs');
129
+
130
+ // 读取质量门禁结果
131
+ let qualityGateStatus = 'Unknown';
132
+ try {
133
+ const reportTaskContent = fs.readFileSync('.scannerwork/report-task.txt', 'utf8');
134
+ const ceTaskIdMatch = reportTaskContent.match(/ceTaskId=(.+)/);
135
+ if (ceTaskIdMatch && ceTaskIdMatch[1]) {
136
+ const ceTaskId = ceTaskIdMatch[1];
137
+
138
+ // 等待分析完成
139
+ let analysisComplete = false;
140
+ let retries = 0;
141
+ while (!analysisComplete && retries < 10) {
142
+ const ceTaskResponse = await fetch(
143
+ `https://sonarcloud.io/api/ce/task?id=${ceTaskId}`,
144
+ { headers: { Authorization: `Bearer ${process.env.SONAR_TOKEN}` } }
145
+ ).then(res => res.json());
146
+
147
+ if (ceTaskResponse.task && ceTaskResponse.task.status === 'SUCCESS') {
148
+ analysisComplete = true;
149
+ } else {
150
+ retries++;
151
+ await new Promise(resolve => setTimeout(resolve, 5000)); // 等待5秒
152
+ }
153
+ }
154
+ }
155
+ } catch (error) {
156
+ console.error('Error reading report task file:', error);
157
+ }
158
+
159
+ // 获取SonarCloud分析结果
160
+ const projectKey = process.env.SONAR_PROJECT_KEY;
161
+ const sonarResponse = await fetch(
162
+ `https://sonarcloud.io/api/measures/component?component=${projectKey}&metricKeys=bugs,vulnerabilities,code_smells,coverage,duplicated_lines_density`,
163
+ { headers: { Authorization: `Bearer ${process.env.SONAR_TOKEN}` } }
164
+ ).then(res => res.json());
165
+
166
+ // 解析结果
167
+ let coverage = 'N/A';
168
+ let bugs = 'N/A';
169
+ let vulnerabilities = 'N/A';
170
+ let codeSmells = 'N/A';
171
+ let duplication = 'N/A';
172
+
173
+ if (sonarResponse && sonarResponse.component && sonarResponse.component.measures) {
174
+ const measures = sonarResponse.component.measures;
175
+
176
+ for (const measure of measures) {
177
+ switch (measure.metric) {
178
+ case 'coverage':
179
+ coverage = `${parseFloat(measure.value).toFixed(2)}%`;
180
+ break;
181
+ case 'bugs':
182
+ bugs = measure.value;
183
+ break;
184
+ case 'vulnerabilities':
185
+ vulnerabilities = measure.value;
186
+ break;
187
+ case 'code_smells':
188
+ codeSmells = measure.value;
189
+ break;
190
+ case 'duplicated_lines_density':
191
+ duplication = `${parseFloat(measure.value).toFixed(2)}%`;
192
+ break;
193
+ }
194
+ }
195
+ }
196
+
197
+ // 获取质量门禁状态
198
+ const qualityGateResponse = await fetch(
199
+ `https://sonarcloud.io/api/qualitygates/project_status?projectKey=${projectKey}`,
200
+ { headers: { Authorization: `Bearer ${process.env.SONAR_TOKEN}` } }
201
+ ).then(res => res.json());
202
+
203
+ if (qualityGateResponse && qualityGateResponse.projectStatus) {
204
+ qualityGateStatus = qualityGateResponse.projectStatus.status === 'OK' ? '✅ Passed' : '❌ Failed';
205
+ }
206
+
207
+ // 计算总问题数
208
+ const totalIssues = parseInt(bugs || 0) + parseInt(vulnerabilities || 0) + parseInt(codeSmells || 0);
209
+
210
+ // 生成评论内容
211
+ let recommendations = [];
212
+ if (parseInt(bugs) > 0) recommendations.push('- Fix identified bugs to improve code reliability');
213
+ if (parseInt(vulnerabilities) > 0) recommendations.push('- Address security vulnerabilities to enhance application security');
214
+ if (parseInt(codeSmells) > 5) recommendations.push('- Refactor code to reduce code smells and improve maintainability');
215
+ if (parseFloat(coverage) < 80) recommendations.push('- Increase test coverage to meet the 80% minimum requirement');
216
+ if (parseFloat(duplication) > 3) recommendations.push('- Reduce code duplication to improve maintainability');
217
+
218
+ const comment = [
219
+ '## SonarCloud Analysis Results',
220
+ '',
221
+ '### Summary',
222
+ `- **Quality Gate**: ${qualityGateStatus}`,
223
+ `- **Coverage**: ${coverage}`,
224
+ `- **Total Issues**: ${totalIssues}`,
225
+ `- **Code Duplication**: ${duplication}`,
226
+ '',
227
+ '### Details',
228
+ `- **Code Smells**: ${codeSmells}`,
229
+ `- **Bugs**: ${bugs}`,
230
+ `- **Security Vulnerabilities**: ${vulnerabilities}`,
231
+ '',
232
+ '### Recommendations',
233
+ ...recommendations,
234
+ '',
235
+ `[View full report on SonarCloud](https://sonarcloud.io/dashboard?id=${projectKey})`
236
+ ].join('\n');
237
+
238
+ // 发布或更新PR评论
239
+ const { data: comments } = await github.rest.issues.listComments({
240
+ owner: context.repo.owner,
241
+ repo: context.repo.repo,
242
+ issue_number: context.issue.number,
243
+ });
244
+
245
+ const botComment = comments.find(comment =>
246
+ comment.user.login === 'github-actions[bot]' &&
247
+ comment.body.includes('SonarCloud Analysis Results')
248
+ );
249
+
250
+ if (botComment) {
251
+ await github.rest.issues.updateComment({
252
+ owner: context.repo.owner,
253
+ repo: context.repo.repo,
254
+ comment_id: botComment.id,
255
+ body: comment,
256
+ });
257
+ console.log('Updated existing SonarCloud comment');
258
+ } else {
259
+ await github.rest.issues.createComment({
260
+ owner: context.repo.owner,
261
+ repo: context.repo.repo,
262
+ issue_number: context.issue.number,
263
+ body: comment,
264
+ });
265
+ console.log('Created new SonarCloud comment');
266
+ }
@@ -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,17 @@
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
+
8
+ # [0.14.0](https://github.com/donghao1393/mcp-dbutils/compare/v0.13.0...v0.14.0) (2025-03-14)
9
+
10
+
11
+ ### Features
12
+
13
+ * implement SonarCloud PR auto-comment system ([#33](https://github.com/donghao1393/mcp-dbutils/issues/33)) ([4e83211](https://github.com/donghao1393/mcp-dbutils/commit/4e83211c4c7a289a6b794cdc5e03caac301d173c)), closes [#32](https://github.com/donghao1393/mcp-dbutils/issues/32)
14
+
1
15
  # [0.13.0](https://github.com/donghao1393/mcp-dbutils/compare/v0.12.0...v0.13.0) (2025-03-14)
2
16
 
3
17
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-dbutils
3
- Version: 0.13.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"
@@ -0,0 +1,14 @@
1
+ sonar.organization=donghao1393
2
+ sonar.projectKey=donghao1393_mcp-dbutils
3
+ sonar.sources=src/mcp_dbutils
4
+ sonar.tests=tests
5
+ sonar.python.coverage.reportPaths=coverage.xml
6
+ sonar.python.version=3.10
7
+
8
+ # PR Analysis Configuration
9
+ sonar.pullrequest.provider=github
10
+ sonar.pullrequest.github.repository=donghao1393/mcp-dbutils
11
+ sonar.pullrequest.github.endpoint=https://api.github.com/
12
+
13
+ # Quality Gate Settings
14
+ sonar.qualitygate.wait=true
@@ -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']