mcp-server-sqlseed 0.2.4__tar.gz → 0.2.5__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_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/PKG-INFO +16 -9
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/README.md +14 -7
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/README.zh-CN.md +11 -7
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/pyproject.toml +1 -1
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/src/mcp_server_sqlseed/server.py +23 -9
- mcp_server_sqlseed-0.2.5/tests/test_default_provider.py +114 -0
- mcp_server_sqlseed-0.2.5/tests/test_error_redaction.py +24 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_yaml_execution_validation.py +32 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/.gitignore +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/LICENSE +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/src/mcp_server_sqlseed/__init__.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/src/mcp_server_sqlseed/__main__.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/src/mcp_server_sqlseed/config.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/.pylintrc +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/__init__.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/conftest.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_config.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_server.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_stdio_progress.py +0 -0
- {mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_validate_db_path.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcp-server-sqlseed
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Offline MCP tools for sqlseed rule-driven YAML configuration and test data generation
|
|
5
5
|
Project-URL: Documentation, https://sunbos.github.io/sqlseed/guide/
|
|
6
6
|
Project-URL: Homepage, https://github.com/sunbos/sqlseed
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Requires-Python: >=3.10
|
|
19
19
|
Requires-Dist: mcp<2,>=1.0
|
|
20
|
-
Requires-Dist: sqlseed<0.3,>=0.2.
|
|
20
|
+
Requires-Dist: sqlseed<0.3,>=0.2.5.dev0
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
|
|
23
23
|
# mcp-server-sqlseed
|
|
@@ -31,13 +31,15 @@ schema, then generate test data. Both tools use offline Core rules and require n
|
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
These instructions target version 0.2.5. Check [Releases](https://github.com/sunbos/sqlseed/releases)
|
|
35
|
+
for publication status; use the source installation below to test an unpublished candidate.
|
|
36
|
+
Use a Python 3.10+ virtual environment:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
python -m pip install "mcp-server-sqlseed==0.2.
|
|
39
|
+
python -m pip install "mcp-server-sqlseed==0.2.5"
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
Core 0.2.
|
|
42
|
+
Core 0.2.4 and older lack the shared diagnostic interfaces required by this version.
|
|
41
43
|
For development, install Core and the required local plugins together from the
|
|
42
44
|
repository root:
|
|
43
45
|
|
|
@@ -72,13 +74,15 @@ path. The server runs over stdio. `python -m mcp_server_sqlseed` is also support
|
|
|
72
74
|
The `db_path` argument accepts an existing SQLite `.db`/`.sqlite`/`.sqlite3` file or a
|
|
73
75
|
database URL. For PostgreSQL, install the Core `postgres` extra. Tables must already
|
|
74
76
|
exist. The schema mapper chooses generators deterministically; no model request is
|
|
75
|
-
made by either tool.
|
|
77
|
+
made by either tool. Both tools use the required Faker provider with the `en_US`
|
|
78
|
+
locale, matching the generated template; Mimesis is not required.
|
|
76
79
|
|
|
77
80
|
When `yaml_config` is supplied, it must be a YAML mapping containing the requested
|
|
78
81
|
table. Empty documents, unknown tables, and configurations for a different table fail
|
|
79
82
|
before generation. The UTF-8 size limit is 256 KiB. Tool arguments select the database,
|
|
80
83
|
table, row count, and enrichment; YAML contributes only the matching table's column
|
|
81
|
-
rules, seed, and `clear_before` setting.
|
|
84
|
+
rules, seed, and `clear_before` setting. Top-level YAML `provider` and `locale`
|
|
85
|
+
settings do not change this server's engine or locale.
|
|
82
86
|
|
|
83
87
|
A typical client workflow is:
|
|
84
88
|
|
|
@@ -97,7 +101,7 @@ schema-inspection tool are not provided. For LLM analysis, install the separate
|
|
|
97
101
|
AI MCP extra:
|
|
98
102
|
|
|
99
103
|
```bash
|
|
100
|
-
python -m pip install "sqlseed-ai[mcp]==0.2.
|
|
104
|
+
python -m pip install "sqlseed-ai[mcp]==0.2.5"
|
|
101
105
|
mcp-server-sqlseed-ai
|
|
102
106
|
```
|
|
103
107
|
|
|
@@ -108,8 +112,11 @@ Its YAML tool is
|
|
|
108
112
|
|
|
109
113
|
## Requirements
|
|
110
114
|
|
|
115
|
+
These metadata requirements apply to version 0.2.5 and its source candidates.
|
|
116
|
+
Use local Core and plugins together when developing from source.
|
|
117
|
+
|
|
111
118
|
- Python `>=3.10`
|
|
112
|
-
- `sqlseed>=0.2.
|
|
119
|
+
- `sqlseed>=0.2.5.dev0,<0.3`
|
|
113
120
|
- `mcp>=1.0,<2`
|
|
114
121
|
|
|
115
122
|
See the [user guide](https://sunbos.github.io/sqlseed/guide/),
|
|
@@ -9,13 +9,15 @@ schema, then generate test data. Both tools use offline Core rules and require n
|
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
These instructions target version 0.2.5. Check [Releases](https://github.com/sunbos/sqlseed/releases)
|
|
13
|
+
for publication status; use the source installation below to test an unpublished candidate.
|
|
14
|
+
Use a Python 3.10+ virtual environment:
|
|
13
15
|
|
|
14
16
|
```bash
|
|
15
|
-
python -m pip install "mcp-server-sqlseed==0.2.
|
|
17
|
+
python -m pip install "mcp-server-sqlseed==0.2.5"
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
Core 0.2.
|
|
20
|
+
Core 0.2.4 and older lack the shared diagnostic interfaces required by this version.
|
|
19
21
|
For development, install Core and the required local plugins together from the
|
|
20
22
|
repository root:
|
|
21
23
|
|
|
@@ -50,13 +52,15 @@ path. The server runs over stdio. `python -m mcp_server_sqlseed` is also support
|
|
|
50
52
|
The `db_path` argument accepts an existing SQLite `.db`/`.sqlite`/`.sqlite3` file or a
|
|
51
53
|
database URL. For PostgreSQL, install the Core `postgres` extra. Tables must already
|
|
52
54
|
exist. The schema mapper chooses generators deterministically; no model request is
|
|
53
|
-
made by either tool.
|
|
55
|
+
made by either tool. Both tools use the required Faker provider with the `en_US`
|
|
56
|
+
locale, matching the generated template; Mimesis is not required.
|
|
54
57
|
|
|
55
58
|
When `yaml_config` is supplied, it must be a YAML mapping containing the requested
|
|
56
59
|
table. Empty documents, unknown tables, and configurations for a different table fail
|
|
57
60
|
before generation. The UTF-8 size limit is 256 KiB. Tool arguments select the database,
|
|
58
61
|
table, row count, and enrichment; YAML contributes only the matching table's column
|
|
59
|
-
rules, seed, and `clear_before` setting.
|
|
62
|
+
rules, seed, and `clear_before` setting. Top-level YAML `provider` and `locale`
|
|
63
|
+
settings do not change this server's engine or locale.
|
|
60
64
|
|
|
61
65
|
A typical client workflow is:
|
|
62
66
|
|
|
@@ -75,7 +79,7 @@ schema-inspection tool are not provided. For LLM analysis, install the separate
|
|
|
75
79
|
AI MCP extra:
|
|
76
80
|
|
|
77
81
|
```bash
|
|
78
|
-
python -m pip install "sqlseed-ai[mcp]==0.2.
|
|
82
|
+
python -m pip install "sqlseed-ai[mcp]==0.2.5"
|
|
79
83
|
mcp-server-sqlseed-ai
|
|
80
84
|
```
|
|
81
85
|
|
|
@@ -86,8 +90,11 @@ Its YAML tool is
|
|
|
86
90
|
|
|
87
91
|
## Requirements
|
|
88
92
|
|
|
93
|
+
These metadata requirements apply to version 0.2.5 and its source candidates.
|
|
94
|
+
Use local Core and plugins together when developing from source.
|
|
95
|
+
|
|
89
96
|
- Python `>=3.10`
|
|
90
|
-
- `sqlseed>=0.2.
|
|
97
|
+
- `sqlseed>=0.2.5.dev0,<0.3`
|
|
91
98
|
- `mcp>=1.0,<2`
|
|
92
99
|
|
|
93
100
|
See the [user guide](https://sunbos.github.io/sqlseed/guide/),
|
|
@@ -9,13 +9,13 @@ YAML 配置,再生成测试数据。两个工具均使用离线 Core 规则,
|
|
|
9
9
|
|
|
10
10
|
## 安装
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
本文安装说明对应 0.2.5 版本;发布状态以 [Releases](https://github.com/sunbos/sqlseed/releases) 为准。测试尚未发布的候选版本时,使用下方的源码安装方式。请先创建并激活 Python 3.10+ 虚拟环境:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
python -m pip install "mcp-server-sqlseed==0.2.
|
|
15
|
+
python -m pip install "mcp-server-sqlseed==0.2.5"
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Core 0.2.
|
|
18
|
+
Core 0.2.4 及更早版本缺少本版本使用的共享诊断接口。
|
|
19
19
|
开发源码时,从仓库根一次安装本地 Core 与 MCP:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
@@ -48,12 +48,14 @@ python -m pip install -e . -e ./plugins/mcp-server-sqlseed
|
|
|
48
48
|
|
|
49
49
|
`db_path` 接受已存在的 SQLite `.db`、`.sqlite`、`.sqlite3` 文件或数据库 URL。
|
|
50
50
|
使用 PostgreSQL 时需在同一环境安装 Core 的 `postgres` extra。目标表必须已存在。
|
|
51
|
-
列映射由 Core
|
|
51
|
+
列映射由 Core 规则确定,两个工具都不会向模型发送请求。两者均使用 Core 必需依赖
|
|
52
|
+
Faker 和 `en_US` locale,与生成的模板一致;无需安装 Mimesis。
|
|
52
53
|
|
|
53
54
|
提供 `yaml_config` 时,其内容必须为 YAML mapping,并包含所请求的表。
|
|
54
55
|
空文档、未知目标表或不包含目标表的配置会在生成前失败;UTF-8 编码后上限为 256 KiB。
|
|
55
56
|
工具参数决定数据库、表、生成行数和 enrich;YAML 仅提供匹配表的列规则、seed 与
|
|
56
|
-
`clear_before`,不覆盖工具参数指定的范围。
|
|
57
|
+
`clear_before`,不覆盖工具参数指定的范围。YAML 顶层的 `provider` 和 `locale`
|
|
58
|
+
不会改变此服务器使用的引擎或语言地区。
|
|
57
59
|
|
|
58
60
|
## 使用示例与失败结果
|
|
59
61
|
|
|
@@ -77,7 +79,7 @@ MCP 传输成功不等于配置或填充成功,需要检查返回内容。
|
|
|
77
79
|
LLM 分析属于另一个 AI MCP 进程,安装 AI extra 后启动:
|
|
78
80
|
|
|
79
81
|
```bash
|
|
80
|
-
python -m pip install "sqlseed-ai[mcp]==0.2.
|
|
82
|
+
python -m pip install "sqlseed-ai[mcp]==0.2.5"
|
|
81
83
|
mcp-server-sqlseed-ai
|
|
82
84
|
```
|
|
83
85
|
|
|
@@ -89,8 +91,10 @@ AI YAML 工具名为 `sqlseed_ai_generate_yaml`,命令入口为 `mcp-server-sq
|
|
|
89
91
|
|
|
90
92
|
## 依赖
|
|
91
93
|
|
|
94
|
+
以下为 0.2.5 版本及其源码候选的依赖要求。源码开发时请在同一次解析中安装本地 Core 和插件。
|
|
95
|
+
|
|
92
96
|
- Python `>=3.10`
|
|
93
|
-
- `sqlseed>=0.2.
|
|
97
|
+
- `sqlseed>=0.2.5.dev0,<0.3`
|
|
94
98
|
- `mcp>=1.0,<2`
|
|
95
99
|
|
|
96
100
|
更多信息见[用户指南](https://sunbos.github.io/sqlseed/guide/)、
|
|
@@ -19,8 +19,10 @@ from sqlseed._utils.logger import get_logger
|
|
|
19
19
|
from sqlseed._utils.paths import validate_db_target as _validate_db_target
|
|
20
20
|
from sqlseed._utils.paths import validate_table_name as _validate_table_name
|
|
21
21
|
from sqlseed._utils.progress import NullProgressBackend
|
|
22
|
+
from sqlseed._utils.redaction import redact_url_credentials
|
|
22
23
|
from sqlseed.config.models import GeneratorConfig
|
|
23
24
|
from sqlseed.core.orchestrator import DataOrchestrator
|
|
25
|
+
from sqlseed.generators import ConfigurationError
|
|
24
26
|
|
|
25
27
|
logger = get_logger(__name__)
|
|
26
28
|
|
|
@@ -56,7 +58,7 @@ def sqlseed_generate_yaml(db_path: str, table_name: str) -> str:
|
|
|
56
58
|
"""
|
|
57
59
|
try:
|
|
58
60
|
db_path = _validate_db_target(db_path)
|
|
59
|
-
with DataOrchestrator(db_path) as orch:
|
|
61
|
+
with DataOrchestrator(db_path, provider_name="faker", locale="en_US") as orch:
|
|
60
62
|
_validate_table_name(table_name, orch.get_table_names())
|
|
61
63
|
specs = orch.get_column_mapping(table_name)
|
|
62
64
|
|
|
@@ -69,9 +71,15 @@ def sqlseed_generate_yaml(db_path: str, table_name: str) -> str:
|
|
|
69
71
|
}
|
|
70
72
|
logger.info("Rule-driven YAML generated", table_name=table_name, columns=len(columns))
|
|
71
73
|
return str(yaml.dump(output, allow_unicode=True, sort_keys=False, default_flow_style=False))
|
|
72
|
-
except (ValueError, RuntimeError, OSError) as e:
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
except (ValueError, RuntimeError, OSError, ConfigurationError) as e:
|
|
75
|
+
message = redact_url_credentials(str(e))
|
|
76
|
+
logger.error(
|
|
77
|
+
"Failed to generate YAML",
|
|
78
|
+
db_path=redact_url_credentials(db_path),
|
|
79
|
+
table_name=table_name,
|
|
80
|
+
error=message,
|
|
81
|
+
)
|
|
82
|
+
return f"# Error: {message}"
|
|
75
83
|
|
|
76
84
|
|
|
77
85
|
@mcp.tool()
|
|
@@ -89,7 +97,7 @@ def sqlseed_execute_fill(
|
|
|
89
97
|
if yaml_config is not None and len(yaml_config.encode("utf-8")) > _MAX_YAML_CONFIG_SIZE:
|
|
90
98
|
raise ValueError(f"yaml_config exceeds maximum allowed size of {_MAX_YAML_CONFIG_SIZE} bytes")
|
|
91
99
|
|
|
92
|
-
with DataOrchestrator(db_path) as orch:
|
|
100
|
+
with DataOrchestrator(db_path, provider_name="faker", locale="en_US") as orch:
|
|
93
101
|
_validate_table_name(table_name, orch.get_table_names())
|
|
94
102
|
column_configs = None
|
|
95
103
|
clear_before = False
|
|
@@ -133,8 +141,14 @@ def sqlseed_execute_fill(
|
|
|
133
141
|
"table_name": result.table_name,
|
|
134
142
|
"count": result.count,
|
|
135
143
|
"elapsed": result.elapsed,
|
|
136
|
-
"errors": result.errors,
|
|
144
|
+
"errors": [redact_url_credentials(error) for error in result.errors],
|
|
137
145
|
}
|
|
138
|
-
except (ValueError, RuntimeError, OSError, yaml.YAMLError) as e:
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
except (ValueError, RuntimeError, OSError, ConfigurationError, yaml.YAMLError) as e:
|
|
147
|
+
message = redact_url_credentials(str(e))
|
|
148
|
+
logger.error(
|
|
149
|
+
"Failed to execute fill",
|
|
150
|
+
db_path=redact_url_credentials(db_path),
|
|
151
|
+
table_name=table_name,
|
|
152
|
+
error=message,
|
|
153
|
+
)
|
|
154
|
+
return {"error": message}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import textwrap
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_mcp_uses_faker_en_us_without_mimesis(tmp_path: Path) -> None:
|
|
14
|
+
"""Compare real SQLite values with upstream Faker, including default mapping."""
|
|
15
|
+
program = textwrap.dedent(
|
|
16
|
+
"""
|
|
17
|
+
import importlib.abc
|
|
18
|
+
import json
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
class MissingMimesis(importlib.abc.MetaPathFinder):
|
|
22
|
+
def find_spec(self, fullname, path=None, target=None):
|
|
23
|
+
if fullname == 'mimesis' or fullname.startswith('mimesis.'):
|
|
24
|
+
raise ModuleNotFoundError('Unavailable test dependency: ' + fullname)
|
|
25
|
+
sys.meta_path.insert(0, MissingMimesis())
|
|
26
|
+
|
|
27
|
+
from faker import Faker
|
|
28
|
+
from structlog.testing import capture_logs
|
|
29
|
+
import yaml
|
|
30
|
+
|
|
31
|
+
with capture_logs() as events:
|
|
32
|
+
from mcp_server_sqlseed.server import sqlseed_execute_fill, sqlseed_generate_yaml
|
|
33
|
+
from sqlseed.core.orchestrator import DataOrchestrator
|
|
34
|
+
from sqlseed.generators import registry
|
|
35
|
+
from tests.sqlite_helpers import sqlite_connection
|
|
36
|
+
|
|
37
|
+
database = sys.argv[1]
|
|
38
|
+
seed = 31415
|
|
39
|
+
count = 5
|
|
40
|
+
with sqlite_connection(database) as connection:
|
|
41
|
+
connection.execute('CREATE TABLE people (first_name TEXT NOT NULL)')
|
|
42
|
+
|
|
43
|
+
template = yaml.safe_load(sqlseed_generate_yaml(database, 'people'))
|
|
44
|
+
template_defaults = {key: template[key] for key in ('provider', 'locale')}
|
|
45
|
+
expected_faker = Faker('en_US')
|
|
46
|
+
expected_faker.seed_instance(seed)
|
|
47
|
+
expected = [expected_faker.first_name() for _ in range(count)]
|
|
48
|
+
|
|
49
|
+
def read_names():
|
|
50
|
+
with sqlite_connection(database) as connection:
|
|
51
|
+
return [row[0] for row in connection.execute(
|
|
52
|
+
'SELECT first_name FROM people ORDER BY rowid'
|
|
53
|
+
)]
|
|
54
|
+
|
|
55
|
+
# No YAML: use the upstream seed API, without replacing the provider.
|
|
56
|
+
Faker.seed(seed)
|
|
57
|
+
default_result = sqlseed_execute_fill(database, 'people', count=count)
|
|
58
|
+
default_names = read_names()
|
|
59
|
+
|
|
60
|
+
table = template['tables'][0]
|
|
61
|
+
table['seed'] = seed
|
|
62
|
+
table['clear_before'] = True
|
|
63
|
+
generated_result = sqlseed_execute_fill(
|
|
64
|
+
database, 'people', count=count, yaml_config=yaml.safe_dump(template)
|
|
65
|
+
)
|
|
66
|
+
generated_names = read_names()
|
|
67
|
+
|
|
68
|
+
# Top-level engine/locale settings remain outside the tool's YAML scope.
|
|
69
|
+
template['provider'] = 'mimesis'
|
|
70
|
+
template['locale'] = 'zh_CN'
|
|
71
|
+
overridden_result = sqlseed_execute_fill(
|
|
72
|
+
database, 'people', count=count, yaml_config=yaml.safe_dump(template)
|
|
73
|
+
)
|
|
74
|
+
overridden_names = read_names()
|
|
75
|
+
tool_warnings = [event for event in events if event['log_level'] == 'warning']
|
|
76
|
+
|
|
77
|
+
# Positive control: the explicit unavailable Core provider still warns.
|
|
78
|
+
events.clear()
|
|
79
|
+
with DataOrchestrator(database, provider_name='mimesis') as orchestrator:
|
|
80
|
+
tables = orchestrator.get_table_names()
|
|
81
|
+
fallback_warnings = [event for event in events if event['log_level'] == 'warning']
|
|
82
|
+
|
|
83
|
+
print(json.dumps({
|
|
84
|
+
'mimesis_available': registry.HAS_MIMESIS,
|
|
85
|
+
'template_defaults': template_defaults,
|
|
86
|
+
'expected': expected,
|
|
87
|
+
'names': [default_names, generated_names, overridden_names],
|
|
88
|
+
'results': [default_result, generated_result, overridden_result],
|
|
89
|
+
'tool_warnings': tool_warnings,
|
|
90
|
+
'fallback_warnings': fallback_warnings,
|
|
91
|
+
'tables': tables,
|
|
92
|
+
}))
|
|
93
|
+
"""
|
|
94
|
+
)
|
|
95
|
+
result = subprocess.run(
|
|
96
|
+
[sys.executable, "-c", program, str(tmp_path / "faker-default.db")],
|
|
97
|
+
capture_output=True,
|
|
98
|
+
text=True,
|
|
99
|
+
check=True,
|
|
100
|
+
timeout=60,
|
|
101
|
+
)
|
|
102
|
+
status = json.loads(result.stdout)
|
|
103
|
+
assert status["mimesis_available"] is False
|
|
104
|
+
assert status["template_defaults"] == {"provider": "faker", "locale": "en_US"}
|
|
105
|
+
assert status["names"] == [status["expected"]] * 3
|
|
106
|
+
for fill_result in status["results"]:
|
|
107
|
+
assert fill_result["count"] == 5
|
|
108
|
+
assert fill_result["errors"] == []
|
|
109
|
+
assert status["tool_warnings"] == []
|
|
110
|
+
assert status["tables"] == ["people"]
|
|
111
|
+
assert any(
|
|
112
|
+
event["event"] == "Provider not available, falling back to 'base'" and event["provider_name"] == "mimesis"
|
|
113
|
+
for event in status["fallback_warnings"]
|
|
114
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Both core MCP error shapes and their stderr diagnostics hide URL credentials."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_core_mcp_malformed_url_is_redacted_in_results_and_logs() -> None:
|
|
10
|
+
script = """
|
|
11
|
+
from mcp_server_sqlseed.server import sqlseed_generate_yaml, sqlseed_execute_fill
|
|
12
|
+
target='sqlite://audit-user:synthetic-userinfo@host/db?password=synthetic-query'
|
|
13
|
+
for fn in (sqlseed_generate_yaml, sqlseed_execute_fill):
|
|
14
|
+
result=fn(target, 'items')
|
|
15
|
+
message=result if isinstance(result,str) else result['error']
|
|
16
|
+
assert 'Invalid database URL' in message
|
|
17
|
+
assert 'synthetic-userinfo' not in message and 'synthetic-query' not in message
|
|
18
|
+
print(message)
|
|
19
|
+
"""
|
|
20
|
+
result = subprocess.run([sys.executable, "-c", script], capture_output=True, text=True, timeout=30, check=True)
|
|
21
|
+
assert "Failed to generate YAML" in result.stderr
|
|
22
|
+
assert "Failed to execute fill" in result.stderr
|
|
23
|
+
assert "synthetic-userinfo" not in result.stdout + result.stderr
|
|
24
|
+
assert "synthetic-query" not in result.stdout + result.stderr
|
{mcp_server_sqlseed-0.2.4 → mcp_server_sqlseed-0.2.5}/tests/test_yaml_execution_validation.py
RENAMED
|
@@ -97,3 +97,35 @@ def test_valid_yaml_keeps_tool_target_count_and_matching_column_rules(tmp_path:
|
|
|
97
97
|
with closing(sqlite3.connect(database)) as connection:
|
|
98
98
|
assert connection.execute("SELECT value FROM users ORDER BY rowid").fetchall() == [(91,), (17,), (17,)]
|
|
99
99
|
assert connection.execute("SELECT value FROM orders").fetchall() == [(92,)]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_invalid_date_range_returns_tool_error_without_appending(tmp_path: Path) -> None:
|
|
103
|
+
database = tmp_path / "invalid-date.db"
|
|
104
|
+
with closing(sqlite3.connect(database)) as connection:
|
|
105
|
+
connection.executescript(
|
|
106
|
+
"CREATE TABLE events (created_at DATE NOT NULL); INSERT INTO events VALUES ('2020-01-01');"
|
|
107
|
+
)
|
|
108
|
+
document = yaml.safe_dump(
|
|
109
|
+
{
|
|
110
|
+
"db_path": str(database),
|
|
111
|
+
"tables": [
|
|
112
|
+
{
|
|
113
|
+
"name": "events",
|
|
114
|
+
"count": 5,
|
|
115
|
+
"columns": [
|
|
116
|
+
{
|
|
117
|
+
"name": "created_at",
|
|
118
|
+
"generator": "date",
|
|
119
|
+
"params": {"start_date": "2026-09-26", "end_date": "2026-09-26", "weekdays": "workdays"},
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
result = sqlseed_execute_fill(str(database), "events", count=5, yaml_config=document)
|
|
127
|
+
assert set(result) == {"error"}
|
|
128
|
+
assert "created_at" in result["error"]
|
|
129
|
+
assert "date" in result["error"]
|
|
130
|
+
with closing(sqlite3.connect(database)) as connection:
|
|
131
|
+
assert connection.execute("SELECT * FROM events").fetchall() == [("2020-01-01",)]
|
|
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
|
|
File without changes
|