wtinydb-mcp 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wtinydb_mcp/__init__.py +3 -0
- wtinydb_mcp/catalog.py +59 -0
- wtinydb_mcp/server.py +245 -0
- wtinydb_mcp/templates.py +86 -0
- wtinydb_mcp-0.1.0.dist-info/METADATA +69 -0
- wtinydb_mcp-0.1.0.dist-info/RECORD +10 -0
- wtinydb_mcp-0.1.0.dist-info/WHEEL +5 -0
- wtinydb_mcp-0.1.0.dist-info/entry_points.txt +2 -0
- wtinydb_mcp-0.1.0.dist-info/licenses/LICENSE +21 -0
- wtinydb_mcp-0.1.0.dist-info/top_level.txt +1 -0
wtinydb_mcp/__init__.py
ADDED
wtinydb_mcp/catalog.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""WTinyDB Architectural Patterns Catalog."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PatternsCatalog:
|
|
7
|
+
"""Catalog of production-ready patterns for WTinyDB document database architectures."""
|
|
8
|
+
|
|
9
|
+
PATTERNS = [
|
|
10
|
+
{
|
|
11
|
+
"id": "pydantic-crud",
|
|
12
|
+
"name": "Pydantic Document Repository",
|
|
13
|
+
"feature": "CRUD & Models",
|
|
14
|
+
"module": "wtinydb.core.database",
|
|
15
|
+
"description": "Standard repository pattern wrapping WTinyDB with Pydantic model validation.",
|
|
16
|
+
"origin": "wisrovi SUITE",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "async-wtinydb",
|
|
20
|
+
"name": "Async Document Operations",
|
|
21
|
+
"feature": "Async / FastAPI Integration",
|
|
22
|
+
"module": "wtinydb.core.async_db",
|
|
23
|
+
"description": "Non-blocking ThreadPoolExecutor wrapper for high-throughput async APIs.",
|
|
24
|
+
"origin": "wisrovi SUITE",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "fluent-query",
|
|
28
|
+
"name": "Fluent Query Builder",
|
|
29
|
+
"feature": "Queries & Filtering",
|
|
30
|
+
"module": "wtinydb.core.query",
|
|
31
|
+
"description": "Chainable query builder (Q) for NoSQL field matching, regex search, and list filters.",
|
|
32
|
+
"origin": "wisrovi SUITE",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "soft-delete-audit",
|
|
36
|
+
"name": "Soft Delete & Audit Trailing",
|
|
37
|
+
"feature": "Audit & Lifecycle",
|
|
38
|
+
"module": "wtinydb.models",
|
|
39
|
+
"description": "Mixins for automatic created_at, updated_at timestamps and logical deletion.",
|
|
40
|
+
"origin": "wisrovi SUITE",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "n-level-nested-crud",
|
|
44
|
+
"name": "N-Level Nested JSON CRUD",
|
|
45
|
+
"feature": "Nested Documents & Path Querying",
|
|
46
|
+
"module": "wtinydb.core.database",
|
|
47
|
+
"description": "Single-responsibility modular CRUD for N-level deep nested JSON objects with dotted path matching.",
|
|
48
|
+
"origin": "wisrovi SUITE",
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
def search(self, query: str) -> List[Dict[str, str]]:
|
|
53
|
+
"""Search patterns matching query string across name, feature, or description."""
|
|
54
|
+
q = query.lower()
|
|
55
|
+
results = []
|
|
56
|
+
for p in self.PATTERNS:
|
|
57
|
+
if q in p["name"].lower() or q in p["feature"].lower() or q in p["description"].lower():
|
|
58
|
+
results.append(p)
|
|
59
|
+
return results
|
wtinydb_mcp/server.py
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""wtinydb-mcp: Model Context Protocol server for WTinyDB architecting and code generation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import ast
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
import signal
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from functools import lru_cache
|
|
12
|
+
|
|
13
|
+
from mcp.server.fastmcp import FastMCP
|
|
14
|
+
|
|
15
|
+
from wtinydb_mcp.catalog import PatternsCatalog
|
|
16
|
+
from wtinydb_mcp.templates import TemplateGenerator
|
|
17
|
+
|
|
18
|
+
# Setup logging strictly to stderr to avoid breaking MCP protocol
|
|
19
|
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s", stream=sys.stderr)
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
PID_FILE = os.path.expanduser("~/.wtinydb_mcp.pid")
|
|
23
|
+
|
|
24
|
+
# Create primary FastMCP Server instance
|
|
25
|
+
mcp = FastMCP("wtinydb-mcp-server")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@lru_cache(maxsize=1)
|
|
29
|
+
def get_catalog() -> PatternsCatalog:
|
|
30
|
+
"""Return shared patterns catalog instance."""
|
|
31
|
+
return PatternsCatalog()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _is_pydantic_model(cls: ast.ClassDef) -> bool:
|
|
35
|
+
"""Return True if class inherits from BaseModel or Mixins."""
|
|
36
|
+
return any(
|
|
37
|
+
isinstance(b, ast.Name) and b.id in ("BaseModel", "TimestampMixin", "SoftDeleteMixin", "AuditMixin")
|
|
38
|
+
for b in cls.bases
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@mcp.tool()
|
|
43
|
+
def validate_model_schema(model_code: str) -> str:
|
|
44
|
+
"""Validate a Pydantic model definition for WTinyDB compatibility."""
|
|
45
|
+
try:
|
|
46
|
+
tree = ast.parse(model_code)
|
|
47
|
+
issues = []
|
|
48
|
+
warnings = []
|
|
49
|
+
|
|
50
|
+
classes = [n for n in ast.walk(tree) if isinstance(n, ast.ClassDef)]
|
|
51
|
+
model_classes = [c for c in classes if _is_pydantic_model(c)]
|
|
52
|
+
|
|
53
|
+
if not model_classes:
|
|
54
|
+
issues.append("No Pydantic BaseModel or WTinyDB Mixin subclass found.")
|
|
55
|
+
|
|
56
|
+
result = "Valid Model Validation Result:\n"
|
|
57
|
+
if issues:
|
|
58
|
+
result += "Issues:\n" + "\n".join(f" ❌ {i}" for i in issues) + "\n"
|
|
59
|
+
if warnings:
|
|
60
|
+
result += "Warnings:\n" + "\n".join(f" ⚠️ {w}" for w in warnings) + "\n"
|
|
61
|
+
if not issues and not warnings:
|
|
62
|
+
result += "✅ Model looks good for WTinyDB document storage!"
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
except SyntaxError as e:
|
|
66
|
+
return f"❌ Syntax Error in model code: {e}"
|
|
67
|
+
except Exception as e:
|
|
68
|
+
return f"❌ Validation Error: {type(e).__name__}: {e}"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@mcp.tool()
|
|
72
|
+
def search_wtinydb_pattern(query: str) -> str:
|
|
73
|
+
"""Search for production-ready WTinyDB architectural patterns."""
|
|
74
|
+
results = get_catalog().search(query)
|
|
75
|
+
if not results:
|
|
76
|
+
return f"No pattern matching '{query}' was found in WTinyDB catalog."
|
|
77
|
+
|
|
78
|
+
response = "Found production-ready architectural patterns in wisrovi SUITE:\n\n"
|
|
79
|
+
for p in results:
|
|
80
|
+
response += f"🚀 [{p['origin']}] {p['name']}\n"
|
|
81
|
+
response += f" - Feature: {p['feature']}\n"
|
|
82
|
+
response += f" - Module: {p['module']}\n"
|
|
83
|
+
response += f" - Description: {p['description']}\n\n"
|
|
84
|
+
return response
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@mcp.tool()
|
|
88
|
+
def deploy_wtinydb_scaffolding(
|
|
89
|
+
target_dir: str,
|
|
90
|
+
project_name: str = "wtinydb_project",
|
|
91
|
+
scaffold_type: str = "standard",
|
|
92
|
+
) -> str:
|
|
93
|
+
"""Deploys a professional WTinyDB project structure following wisrovi standards."""
|
|
94
|
+
try:
|
|
95
|
+
if not os.path.isabs(target_dir):
|
|
96
|
+
return "Error: target_dir must be an absolute path."
|
|
97
|
+
|
|
98
|
+
for folder in TemplateGenerator.get_folders(scaffold_type):
|
|
99
|
+
os.makedirs(os.path.join(target_dir, folder), exist_ok=True)
|
|
100
|
+
|
|
101
|
+
blueprints = TemplateGenerator.get_files_blueprint(scaffold_type, project_name)
|
|
102
|
+
for rel_path, content in blueprints.items():
|
|
103
|
+
full_path = os.path.join(target_dir, rel_path)
|
|
104
|
+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
105
|
+
with open(full_path, "w", encoding="utf-8") as f:
|
|
106
|
+
f.write(content)
|
|
107
|
+
|
|
108
|
+
return f"Success: WTinyDB architecture '{project_name}' deployed at {target_dir}"
|
|
109
|
+
except Exception as e:
|
|
110
|
+
return f"Error deploying scaffolding: {str(e)}"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@mcp.tool()
|
|
114
|
+
def get_wtinydb_architect_blueprints() -> str:
|
|
115
|
+
"""Complete reference with read/write/update examples for every WTinyDB feature."""
|
|
116
|
+
crud_code = (
|
|
117
|
+
"from pydantic import BaseModel, Field\n"
|
|
118
|
+
"from wtinydb import WTinyDB, SoftDeleteMixin\n\n"
|
|
119
|
+
"class Article(SoftDeleteMixin, BaseModel):\n"
|
|
120
|
+
" title: str\n"
|
|
121
|
+
" content: str\n"
|
|
122
|
+
" tags: list[str] = []\n\n"
|
|
123
|
+
"db = WTinyDB(Article, db_path='articles.json')\n"
|
|
124
|
+
"# WRITE\n"
|
|
125
|
+
"art = db.insert(Article(title='Intro', content='Hello World'))\n"
|
|
126
|
+
"# READ\n"
|
|
127
|
+
"all_articles = db.get_all()\n"
|
|
128
|
+
"art1 = db.get(1)\n"
|
|
129
|
+
"# UPDATE\n"
|
|
130
|
+
"db.update(1, {'title': 'Updated Title'})\n"
|
|
131
|
+
"# DELETE\n"
|
|
132
|
+
"db.delete(1, hard=False)\n"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
async_code = (
|
|
136
|
+
"import asyncio\n"
|
|
137
|
+
"from wtinydb import WTinyDB, AsyncWTinyDB\n\n"
|
|
138
|
+
"async def main():\n"
|
|
139
|
+
" sync_db = WTinyDB(Article, db_path='articles.json')\n"
|
|
140
|
+
" db = AsyncWTinyDB(sync_db)\n"
|
|
141
|
+
" art = await db.insert(Article(title='Async Title', content='Text'))\n"
|
|
142
|
+
" rows = await db.get_all()\n"
|
|
143
|
+
" await db.close()\n"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
query_code = (
|
|
147
|
+
"from wtinydb import WTinyDB, Q\n\n"
|
|
148
|
+
"db = WTinyDB(Article, in_memory=True)\n"
|
|
149
|
+
"# Query with operators\n"
|
|
150
|
+
"tech_articles = db.find(Q('tags').in_list('tags', ['tech', 'python']))\n"
|
|
151
|
+
"regex_matches = db.find(Q('title').matches('title', r'^Intro'))\n"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
nested_code = (
|
|
155
|
+
"from wtinydb import WTinyDB, Q\n\n"
|
|
156
|
+
"db = WTinyDB(Company, db_path='companies.json')\n"
|
|
157
|
+
"# N-Level Dotted Path Querying\n"
|
|
158
|
+
"results = db.find(Q('department.manager.contact.address.city').eq('San Francisco'))\n"
|
|
159
|
+
"# N-Level Deep Field Updating\n"
|
|
160
|
+
"db.update(target_company, {'department.budget': 7500000.00})\n"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
"WTINYDB EXPERT BLUEPRINTS (COMPLETE REFERENCE)\n\n"
|
|
165
|
+
"=== 1. MODEL & CRUD ===\n" + crud_code + "\n"
|
|
166
|
+
"=== 2. ASYNC OPERATIONS ===\n" + async_code + "\n"
|
|
167
|
+
"=== 3. FLUENT QUERY BUILDER ===\n" + query_code + "\n"
|
|
168
|
+
"=== 4. N-LEVEL NESTED JSON CRUD ===\n" + nested_code
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@mcp.tool()
|
|
173
|
+
def get_wtinydb_architect_manual() -> str:
|
|
174
|
+
"""Expert manual for building high-performance document database systems with WTinyDB."""
|
|
175
|
+
manual_text = (
|
|
176
|
+
"WTINYDB ARCHITECT MANUAL (ADVANCED)\n"
|
|
177
|
+
"--- PROJECT STRUCTURE RULES (MANDATORY) ---\n"
|
|
178
|
+
"1. CONFIG: All database settings MUST be centralized in `config/settings.py` as a `DatabaseSettings` dataclass.\n"
|
|
179
|
+
"2. MODELS: All Pydantic models MUST be placed inside `models/` directory.\n"
|
|
180
|
+
"3. REPOSITORIES: All data-access logic MUST live in `repositories/` wrapping `WTinyDB` or `AsyncWTinyDB`.\n"
|
|
181
|
+
"4. ORCHESTRATOR: Service entrypoint MUST be `main.py` at root level.\n\n"
|
|
182
|
+
"--- CORE RULES ---\n"
|
|
183
|
+
"1. Always use Pydantic models for schema definitions.\n"
|
|
184
|
+
"2. Use `SoftDeleteMixin` or `AuditMixin` for soft-deletion and automatic creation/update timestamps.\n"
|
|
185
|
+
"3. Use `Q` fluent query builder for complex filtering.\n"
|
|
186
|
+
"4. For FastAPI/async apps, wrap WTinyDB with `AsyncWTinyDB`.\n\n"
|
|
187
|
+
"Generated by WTinyDB MCP by wisrovi"
|
|
188
|
+
)
|
|
189
|
+
return manual_text
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@mcp.tool()
|
|
193
|
+
def generate_wtinydb_crud(model_code: str) -> str:
|
|
194
|
+
"""Generate repository CRUD wrapper code for a Pydantic model definition."""
|
|
195
|
+
try:
|
|
196
|
+
tree = ast.parse(model_code)
|
|
197
|
+
classes = [n.name for n in ast.walk(tree) if isinstance(n, ast.ClassDef) and _is_pydantic_model(n)]
|
|
198
|
+
if not classes:
|
|
199
|
+
return "# Error: No Pydantic model found in provided code."
|
|
200
|
+
|
|
201
|
+
model_name = classes[0]
|
|
202
|
+
repo_name = f"{model_name}Repository"
|
|
203
|
+
|
|
204
|
+
code = (
|
|
205
|
+
f"from typing import List, Optional\n"
|
|
206
|
+
f"from wtinydb import WTinyDB, Q\n"
|
|
207
|
+
f"# Import {model_name} from models module\n\n"
|
|
208
|
+
f"class {repo_name}:\n"
|
|
209
|
+
f" def __init__(self, db_path: str = '{model_name.lower()}.json', in_memory: bool = False):\n"
|
|
210
|
+
f" self.db = WTinyDB({model_name}, db_path=db_path, in_memory=in_memory)\n\n"
|
|
211
|
+
f" def create(self, item: {model_name}) -> {model_name}:\n"
|
|
212
|
+
f" return self.db.insert(item)\n\n"
|
|
213
|
+
f" def get_by_id(self, doc_id: int) -> {model_name}:\n"
|
|
214
|
+
f" return self.db.get(doc_id)\n\n"
|
|
215
|
+
f" def get_all(self) -> List[{model_name}]:\n"
|
|
216
|
+
f" return self.db.get_all()\n\n"
|
|
217
|
+
f" def update(self, doc_id: int, data: dict) -> {model_name}:\n"
|
|
218
|
+
f" return self.db.update(doc_id, data)\n\n"
|
|
219
|
+
f" def delete(self, doc_id: int, hard: bool = False) -> bool:\n"
|
|
220
|
+
f" return self.db.delete(doc_id, hard=hard)\n"
|
|
221
|
+
)
|
|
222
|
+
return code
|
|
223
|
+
except Exception as e:
|
|
224
|
+
return f"# Generation error: {e}"
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def run_stdio():
|
|
228
|
+
"""Run MCP server in stdio mode."""
|
|
229
|
+
mcp.run(transport="stdio")
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def main():
|
|
233
|
+
"""Main CLI entrypoint for wtinydb-mcp server."""
|
|
234
|
+
parser = argparse.ArgumentParser(description="wtinydb-mcp: WTinyDB Architect MCP Server")
|
|
235
|
+
parser.add_argument("command", nargs="?", default="run", choices=["run", "help"])
|
|
236
|
+
args = parser.parse_args()
|
|
237
|
+
|
|
238
|
+
if args.command == "run":
|
|
239
|
+
run_stdio()
|
|
240
|
+
else:
|
|
241
|
+
parser.print_help()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if __name__ == "__main__":
|
|
245
|
+
main()
|
wtinydb_mcp/templates.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""WTinyDB Scaffolding Code and Folder Generator."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TemplateGenerator:
|
|
7
|
+
"""Generates standard directory structures and starter files for WTinyDB projects."""
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
def get_folders(scaffold_type: str = "standard") -> List[str]:
|
|
11
|
+
"""Return list of directory relative paths to create."""
|
|
12
|
+
return [
|
|
13
|
+
"config",
|
|
14
|
+
"models",
|
|
15
|
+
"repositories",
|
|
16
|
+
"services",
|
|
17
|
+
"tests",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def get_files_blueprint(scaffold_type: str = "standard", project_name: str = "wtinydb_project") -> Dict[str, str]:
|
|
22
|
+
"""Return dictionary of relative file paths and their starter contents."""
|
|
23
|
+
settings_py = (
|
|
24
|
+
"from dataclasses import dataclass\n"
|
|
25
|
+
"import os\n\n"
|
|
26
|
+
"@dataclass\n"
|
|
27
|
+
"class DatabaseSettings:\n"
|
|
28
|
+
" db_path: str = os.getenv('TINYDB_PATH', 'app_data.json')\n"
|
|
29
|
+
" in_memory: bool = os.getenv('TINYDB_IN_MEMORY', 'False').lower() == 'true'\n"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
user_model_py = (
|
|
33
|
+
"from pydantic import BaseModel, Field\n"
|
|
34
|
+
"from wtinydb import AuditMixin\n\n"
|
|
35
|
+
"class User(AuditMixin, BaseModel):\n"
|
|
36
|
+
" name: str = Field(description='User name')\n"
|
|
37
|
+
" email: str = Field(description='User email')\n"
|
|
38
|
+
" role: str = Field(default='user', description='Role')\n"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
user_repo_py = (
|
|
42
|
+
"from wtinydb import WTinyDB, Q\n"
|
|
43
|
+
"from config.settings import DatabaseSettings\n"
|
|
44
|
+
"from models.user import User\n\n"
|
|
45
|
+
"class UserRepository:\n"
|
|
46
|
+
" def __init__(self, settings: DatabaseSettings = None):\n"
|
|
47
|
+
" settings = settings or DatabaseSettings()\n"
|
|
48
|
+
" self.db = WTinyDB(User, db_path=settings.db_path, in_memory=settings.in_memory)\n\n"
|
|
49
|
+
" def create_user(self, user: User) -> User:\n"
|
|
50
|
+
" return self.db.insert(user)\n\n"
|
|
51
|
+
" def get_by_email(self, email: str):\n"
|
|
52
|
+
" return self.db.get_by_field('email', email)\n"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
main_py = (
|
|
56
|
+
f"'''{project_name} Entrypoint'''\n"
|
|
57
|
+
"from models.user import User\n"
|
|
58
|
+
"from repositories.user_repo import UserRepository\n\n"
|
|
59
|
+
"def main():\n"
|
|
60
|
+
" repo = UserRepository()\n"
|
|
61
|
+
" user = repo.create_user(User(name='Alice', email='alice@example.com'))\n"
|
|
62
|
+
" print(f'User created: {user.name} (email: {user.email})')\n\n"
|
|
63
|
+
"if __name__ == '__main__':\n"
|
|
64
|
+
" main()\n"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
readme_md = (
|
|
68
|
+
f"# {project_name}\n\n"
|
|
69
|
+
"WTinyDB Document Store Application.\n\n"
|
|
70
|
+
"## Architecture\n"
|
|
71
|
+
"```mermaid\n"
|
|
72
|
+
"flowchart TD\n"
|
|
73
|
+
" Main[main.py] --> Repo[UserRepository]\n"
|
|
74
|
+
" Repo --> WTinyDB[WTinyDB Engine]\n"
|
|
75
|
+
" WTinyDB --> JSON[(TinyDB JSON Storage)]\n"
|
|
76
|
+
"```\n\n"
|
|
77
|
+
"*Generated by WTinyDB MCP by wisrovi*\n"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
"config/settings.py": settings_py,
|
|
82
|
+
"models/user.py": user_model_py,
|
|
83
|
+
"repositories/user_repo.py": user_repo_py,
|
|
84
|
+
"main.py": main_py,
|
|
85
|
+
"README.md": readme_md,
|
|
86
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wtinydb-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Model Context Protocol (MCP) server for WTinyDB architecture and code generation
|
|
5
|
+
Author-email: "WILLIAM R." <william@ecapturedtech.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: mcp,wtinydb,tinydb,ai-agent,fastmcp,architecture
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: mcp>=1.0.0
|
|
12
|
+
Requires-Dist: pydantic>=2.0.0
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# wtinydb-mcp: Model Context Protocol Server for WTinyDB
|
|
20
|
+
|
|
21
|
+
`wtinydb-mcp` is an official **Model Context Protocol (MCP)** server built on top of **FastMCP** that equips AI agents with tools to architect, validate, scaffold, and generate code for **WTinyDB** (TinyDB + Pydantic document database engine).
|
|
22
|
+
|
|
23
|
+
## Key Technologies & Libraries
|
|
24
|
+
|
|
25
|
+
- **[MCP Protocol](https://modelcontextprotocol.io/)**: Open standard connecting AI models to external tools and context.
|
|
26
|
+
- **[FastMCP](https://github.com/jlowin/fastmcp)**: Python framework for fast MCP server implementation.
|
|
27
|
+
- **[WTinyDB](file:///home/william.rodriguez/Documents/w_libraries/w_libraries/wtinydb_os/wtinydb)**: Pydantic-powered document database engine on top of TinyDB.
|
|
28
|
+
- **[Pydantic v2](https://docs.pydantic.dev/)**: Data schema validation and Python AST inspection.
|
|
29
|
+
- **[Pytest](https://docs.pytest.org/)**: Modern Python testing framework.
|
|
30
|
+
- **[Pytest-Cov](https://pytest-cov.readthedocs.io/)**: Code coverage measurement for pytest.
|
|
31
|
+
- **[Docker](https://www.docker.com/)**: Containerized test execution environment.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## MCP Tools Exposed
|
|
36
|
+
|
|
37
|
+
1. **`validate_model_schema(model_code: str)`**: Validates Pydantic document models for WTinyDB compatibility.
|
|
38
|
+
2. **`search_wtinydb_pattern(query: str)`**: Searches the official wisrovi SUITE catalog for WTinyDB architectural patterns.
|
|
39
|
+
3. **`deploy_wtinydb_scaffolding(target_dir: str, project_name: str, scaffold_type: str)`**: Deploys project scaffolding with repository, config, models, and tests.
|
|
40
|
+
4. **`get_wtinydb_architect_blueprints()`**: Returns code reference and blueprints for WTinyDB features.
|
|
41
|
+
5. **`get_wtinydb_architect_manual()`**: Returns the comprehensive WTinyDB architecting manual.
|
|
42
|
+
6. **`generate_wtinydb_crud(model_code: str)`**: Automatically generates repository CRUD class for Pydantic models.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Running Unit Tests & Coverage
|
|
47
|
+
|
|
48
|
+
### Local Pytest Execution
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Install editable package
|
|
52
|
+
pip install -e .
|
|
53
|
+
|
|
54
|
+
# Run pytest test suite
|
|
55
|
+
pytest tests/
|
|
56
|
+
|
|
57
|
+
# Calculate code coverage
|
|
58
|
+
./scripts/run_coverage.sh
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Docker Containerized Test Execution
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
./scripts/run_tests_docker.sh
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
*Part of the wisrovi SUITE ecosystem.*
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
wtinydb_mcp/__init__.py,sha256=wJsh9LgxlxtTqgixgHZJarLL-jkiSRFjb4W50_LMq4A,65
|
|
2
|
+
wtinydb_mcp/catalog.py,sha256=ExZDrKRvf9OjuJpasERa5axtaqy0yxjAznhiZt3zqnU,2372
|
|
3
|
+
wtinydb_mcp/server.py,sha256=saNB9Wr4VsA_5AI0d13b_avsEzt-NXMAix9bEbLq3rk,9362
|
|
4
|
+
wtinydb_mcp/templates.py,sha256=HAEyFuMQ6sY5uo7B56bTBP8fJq1u9aG3Y_eUbXJ-cC4,3386
|
|
5
|
+
wtinydb_mcp-0.1.0.dist-info/licenses/LICENSE,sha256=Oyqf3mzTxsLVAFwTwTpmcfEsdCeJnA4jMu5Dv-Jq_Ag,1074
|
|
6
|
+
wtinydb_mcp-0.1.0.dist-info/METADATA,sha256=0NJMeaRTuU61mvllo-wAY3Q5N8Hcph7djgWz8bkHeC4,2772
|
|
7
|
+
wtinydb_mcp-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
8
|
+
wtinydb_mcp-0.1.0.dist-info/entry_points.txt,sha256=d93l9KfgOZuIoTduDhtsTLYLquem42grZxwknIfNLao,56
|
|
9
|
+
wtinydb_mcp-0.1.0.dist-info/top_level.txt,sha256=-KDYh9p5VKwAAuEl4jL4_KHhl89ueOWZU07Bf1hfWgQ,12
|
|
10
|
+
wtinydb_mcp-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William Rodriguez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wtinydb_mcp
|