sql-builder-ai-mcp 1.0.1__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CSOAI-ORG / MEOK AI Labs
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,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: sql-builder-ai-mcp
3
+ Version: 1.0.1
4
+ Summary: Sql Builder Ai automation via MCP. Includes build select, build insert, explain query. By MEOK AI Labs.
5
+ Project-URL: Homepage, https://meok.ai
6
+ Project-URL: Repository, https://github.com/CSOAI-ORG/sql-builder-ai-mcp
7
+ Author-email: MEOK AI Labs <nicholas@meok.ai>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 CSOAI-ORG / MEOK AI Labs
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Keywords: ai,builder,mcp,meok,sql
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: OS Independent
33
+ Classifier: Programming Language :: Python :: 3
34
+ Classifier: Topic :: Software Development :: Libraries
35
+ Requires-Python: >=3.10
36
+ Requires-Dist: mcp>=1.0.0
37
+ Description-Content-Type: text/markdown
38
+
39
+ [![sql-builder-ai-mcp MCP server](https://glama.ai/mcp/servers/CSOAI-ORG/sql-builder-ai-mcp/badges/card.svg)](https://glama.ai/mcp/servers/CSOAI-ORG/sql-builder-ai-mcp)
40
+
41
+ # Sql Builder Ai
42
+
43
+ > By [MEOK AI Labs](https://meok.ai) — MEOK AI Labs MCP Server
44
+
45
+ SQL Builder AI MCP Server
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install sql-builder-ai-mcp
51
+ ```
52
+
53
+ ## Usage
54
+
55
+ ```bash
56
+ # Run standalone
57
+ python server.py
58
+
59
+ # Or via MCP
60
+ mcp install sql-builder-ai-mcp
61
+ ```
62
+
63
+ ## Tools
64
+
65
+ ### `build_select`
66
+ Build a SELECT SQL query from structured parameters.
67
+
68
+ **Parameters:**
69
+ - `table` (str)
70
+ - `columns` (str)
71
+ - `where` (str)
72
+ - `order_by` (str)
73
+ - `limit` (int)
74
+ - `joins` (str)
75
+
76
+ ### `build_insert`
77
+ Build an INSERT SQL query from a list of row dicts.
78
+
79
+ **Parameters:**
80
+ - `table` (str)
81
+ - `rows` (str)
82
+ - `on_conflict` (str)
83
+
84
+ ### `explain_query`
85
+ Analyze and explain a SQL query's structure and components.
86
+
87
+ **Parameters:**
88
+ - `sql` (str)
89
+
90
+ ### `optimize_query_hints`
91
+ Suggest optimizations for a SQL query.
92
+
93
+ **Parameters:**
94
+ - `sql` (str)
95
+
96
+
97
+ ## Authentication
98
+
99
+ Free tier: 15 calls/day. Upgrade at [meok.ai/pricing](https://meok.ai/pricing) for unlimited access.
100
+
101
+ ## Links
102
+
103
+ - **Website**: [meok.ai](https://meok.ai)
104
+ - **GitHub**: [CSOAI-ORG/sql-builder-ai-mcp](https://github.com/CSOAI-ORG/sql-builder-ai-mcp)
105
+ - **PyPI**: [pypi.org/project/sql-builder-ai-mcp](https://pypi.org/project/sql-builder-ai-mcp/)
106
+
107
+ ## License
108
+
109
+ MIT — MEOK AI Labs
110
+ <!-- mcp-name: io.github.CSOAI-ORG/sql-builder-ai-mcp -->
@@ -0,0 +1,72 @@
1
+ [![sql-builder-ai-mcp MCP server](https://glama.ai/mcp/servers/CSOAI-ORG/sql-builder-ai-mcp/badges/card.svg)](https://glama.ai/mcp/servers/CSOAI-ORG/sql-builder-ai-mcp)
2
+
3
+ # Sql Builder Ai
4
+
5
+ > By [MEOK AI Labs](https://meok.ai) — MEOK AI Labs MCP Server
6
+
7
+ SQL Builder AI MCP Server
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install sql-builder-ai-mcp
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ # Run standalone
19
+ python server.py
20
+
21
+ # Or via MCP
22
+ mcp install sql-builder-ai-mcp
23
+ ```
24
+
25
+ ## Tools
26
+
27
+ ### `build_select`
28
+ Build a SELECT SQL query from structured parameters.
29
+
30
+ **Parameters:**
31
+ - `table` (str)
32
+ - `columns` (str)
33
+ - `where` (str)
34
+ - `order_by` (str)
35
+ - `limit` (int)
36
+ - `joins` (str)
37
+
38
+ ### `build_insert`
39
+ Build an INSERT SQL query from a list of row dicts.
40
+
41
+ **Parameters:**
42
+ - `table` (str)
43
+ - `rows` (str)
44
+ - `on_conflict` (str)
45
+
46
+ ### `explain_query`
47
+ Analyze and explain a SQL query's structure and components.
48
+
49
+ **Parameters:**
50
+ - `sql` (str)
51
+
52
+ ### `optimize_query_hints`
53
+ Suggest optimizations for a SQL query.
54
+
55
+ **Parameters:**
56
+ - `sql` (str)
57
+
58
+
59
+ ## Authentication
60
+
61
+ Free tier: 15 calls/day. Upgrade at [meok.ai/pricing](https://meok.ai/pricing) for unlimited access.
62
+
63
+ ## Links
64
+
65
+ - **Website**: [meok.ai](https://meok.ai)
66
+ - **GitHub**: [CSOAI-ORG/sql-builder-ai-mcp](https://github.com/CSOAI-ORG/sql-builder-ai-mcp)
67
+ - **PyPI**: [pypi.org/project/sql-builder-ai-mcp](https://pypi.org/project/sql-builder-ai-mcp/)
68
+
69
+ ## License
70
+
71
+ MIT — MEOK AI Labs
72
+ <!-- mcp-name: io.github.CSOAI-ORG/sql-builder-ai-mcp -->
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+ [project]
5
+ name = "sql-builder-ai-mcp"
6
+ version = "1.0.1"
7
+ description = "Sql Builder Ai automation via MCP. Includes build select, build insert, explain query. By MEOK AI Labs."
8
+ readme = "README.md"
9
+ license = {file = "LICENSE"}
10
+ requires-python = ">=3.10"
11
+ authors = [{name = "MEOK AI Labs", email = "nicholas@meok.ai"}]
12
+ dependencies = ["mcp>=1.0.0"]
13
+ keywords = ["mcp", "ai", "meok", "sql", "builder"]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: OS Independent",
18
+ "Topic :: Software Development :: Libraries",
19
+ ]
20
+ [project.urls]
21
+ Homepage = "https://meok.ai"
22
+ Repository = "https://github.com/CSOAI-ORG/sql-builder-ai-mcp"
23
+ [tool.hatch.build.targets.wheel]
24
+ packages = ["."]
25
+ only-include = ["server.py"]
26
+
27
+ [project.scripts]
28
+ sql_builder_ai_mcp = "server:main"
@@ -0,0 +1,200 @@
1
+ """
2
+ SQL Builder AI MCP Server
3
+ SQL query building and analysis tools powered by MEOK AI Labs.
4
+ """
5
+
6
+
7
+ import sys, os
8
+ sys.path.insert(0, os.path.expanduser('~/clawd/meok-labs-engine/shared'))
9
+ from auth_middleware import check_access
10
+
11
+ import re
12
+ import time
13
+ from collections import defaultdict
14
+ from mcp.server.fastmcp import FastMCP
15
+
16
+ mcp = FastMCP("sql-builder-ai", instructions="MEOK AI Labs MCP Server")
17
+
18
+ _call_counts: dict[str, list[float]] = defaultdict(list)
19
+ FREE_TIER_LIMIT = 50
20
+ WINDOW = 86400
21
+
22
+
23
+ def _check_rate_limit(tool_name: str) -> None:
24
+ now = time.time()
25
+ _call_counts[tool_name] = [t for t in _call_counts[tool_name] if now - t < WINDOW]
26
+ if len(_call_counts[tool_name]) >= FREE_TIER_LIMIT:
27
+ raise ValueError(f"Rate limit exceeded for {tool_name}. Free tier: {FREE_TIER_LIMIT}/day. Upgrade at https://meok.ai/pricing")
28
+ _call_counts[tool_name].append(now)
29
+
30
+
31
+ def _quote_id(name: str) -> str:
32
+ return f'"{name}"' if not name.isidentifier() or name.upper() in SQL_KEYWORDS else name
33
+
34
+
35
+ SQL_KEYWORDS = {"SELECT", "FROM", "WHERE", "INSERT", "UPDATE", "DELETE", "JOIN", "ON",
36
+ "ORDER", "GROUP", "BY", "HAVING", "LIMIT", "OFFSET", "TABLE", "INDEX",
37
+ "CREATE", "DROP", "ALTER", "AND", "OR", "NOT", "IN", "BETWEEN", "LIKE", "AS"}
38
+
39
+
40
+ @mcp.tool()
41
+ def build_select(
42
+ table: str, columns: list[str] | None = None, where: dict | None = None,
43
+ order_by: str = "", limit: int = 0, joins: list[dict] | None = None
44
+ , api_key: str = "") -> dict:
45
+ """Build a SELECT SQL query from structured parameters.
46
+
47
+ Args:
48
+ table: Main table name
49
+ columns: List of column names (default: *)
50
+ where: Dict of column:value conditions (AND-joined)
51
+ order_by: Column to order by (prefix with - for DESC)
52
+ limit: LIMIT clause (0 = no limit)
53
+ joins: List of dicts with keys: table, on, type (LEFT/INNER/RIGHT)
54
+ """
55
+ allowed, msg, tier = check_access(api_key)
56
+ if not allowed:
57
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
58
+
59
+ _check_rate_limit("build_select")
60
+ cols = ", ".join(columns) if columns else "*"
61
+ sql = f"SELECT {cols}\nFROM {table}"
62
+ params = []
63
+ if joins:
64
+ for j in joins:
65
+ jtype = j.get("type", "LEFT").upper()
66
+ sql += f"\n{jtype} JOIN {j['table']} ON {j['on']}"
67
+ if where:
68
+ conditions = []
69
+ for col, val in where.items():
70
+ if val is None:
71
+ conditions.append(f"{col} IS NULL")
72
+ elif isinstance(val, list):
73
+ placeholders = ", ".join(["%s"] * len(val))
74
+ conditions.append(f"{col} IN ({placeholders})")
75
+ params.extend(val)
76
+ else:
77
+ conditions.append(f"{col} = %s")
78
+ params.append(val)
79
+ if conditions:
80
+ sql += "\nWHERE " + " AND ".join(conditions)
81
+ if order_by:
82
+ direction = "DESC" if order_by.startswith("-") else "ASC"
83
+ col = order_by.lstrip("-")
84
+ sql += f"\nORDER BY {col} {direction}"
85
+ if limit > 0:
86
+ sql += f"\nLIMIT {limit}"
87
+ return {"sql": sql + ";", "params": params, "type": "SELECT"}
88
+
89
+
90
+ @mcp.tool()
91
+ def build_insert(table: str, rows: list[dict], on_conflict: str = "", api_key: str = "") -> dict:
92
+ """Build an INSERT SQL query from a list of row dicts.
93
+
94
+ Args:
95
+ table: Target table name
96
+ rows: List of dicts (each dict is a row, keys are column names)
97
+ on_conflict: Conflict resolution: '' (none), 'ignore', 'update'
98
+ """
99
+ allowed, msg, tier = check_access(api_key)
100
+ if not allowed:
101
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
102
+
103
+ _check_rate_limit("build_insert")
104
+ if not rows:
105
+ return {"error": "No rows provided"}
106
+ columns = list(rows[0].keys())
107
+ placeholders = ", ".join(["%s"] * len(columns))
108
+ cols_str = ", ".join(columns)
109
+ sql = f"INSERT INTO {table} ({cols_str})\nVALUES"
110
+ all_params = []
111
+ value_rows = []
112
+ for row in rows:
113
+ vals = [row.get(c) for c in columns]
114
+ value_rows.append(f"({placeholders})")
115
+ all_params.extend(vals)
116
+ sql += "\n" + ",\n".join(value_rows)
117
+ if on_conflict == "ignore":
118
+ sql += "\nON CONFLICT DO NOTHING"
119
+ elif on_conflict == "update":
120
+ updates = ", ".join(f"{c} = EXCLUDED.{c}" for c in columns)
121
+ sql += f"\nON CONFLICT DO UPDATE SET {updates}"
122
+ return {"sql": sql + ";", "params": all_params, "type": "INSERT", "row_count": len(rows)}
123
+
124
+
125
+ @mcp.tool()
126
+ def explain_query(sql: str, api_key: str = "") -> dict:
127
+ """Analyze and explain a SQL query's structure and components.
128
+
129
+ Args:
130
+ sql: SQL query string to analyze
131
+ """
132
+ allowed, msg, tier = check_access(api_key)
133
+ if not allowed:
134
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
135
+
136
+ _check_rate_limit("explain_query")
137
+ sql_upper = sql.upper().strip()
138
+ query_type = "UNKNOWN"
139
+ for t in ("SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "ALTER"):
140
+ if sql_upper.startswith(t):
141
+ query_type = t
142
+ break
143
+ components = {"type": query_type}
144
+ tables = re.findall(r'\bFROM\s+(\w+)', sql, re.IGNORECASE)
145
+ tables += re.findall(r'\bJOIN\s+(\w+)', sql, re.IGNORECASE)
146
+ tables += re.findall(r'\bINTO\s+(\w+)', sql, re.IGNORECASE)
147
+ tables += re.findall(r'\bUPDATE\s+(\w+)', sql, re.IGNORECASE)
148
+ components["tables"] = list(set(tables))
149
+ if re.search(r'\bWHERE\b', sql, re.IGNORECASE):
150
+ where = re.search(r'\bWHERE\b(.+?)(?:\bORDER\b|\bGROUP\b|\bLIMIT\b|\bHAVING\b|;|$)', sql, re.IGNORECASE | re.DOTALL)
151
+ components["where_clause"] = where.group(1).strip() if where else ""
152
+ joins = re.findall(r'((?:LEFT|RIGHT|INNER|OUTER|CROSS|FULL)\s+)?JOIN\s+(\w+)\s+ON\s+([^)]+?)(?=\s+(?:LEFT|RIGHT|INNER|WHERE|ORDER|GROUP|LIMIT|$))', sql, re.IGNORECASE)
153
+ if joins:
154
+ components["joins"] = [{"type": j[0].strip() or "INNER", "table": j[1], "condition": j[2].strip()} for j in joins]
155
+ has_subquery = "(" in sql and "SELECT" in sql_upper.split("(", 1)[-1] if "(" in sql else False
156
+ components["has_subquery"] = has_subquery
157
+ components["complexity"] = "simple" if len(tables) <= 1 and not has_subquery else "moderate" if len(tables) <= 3 else "complex"
158
+ return components
159
+
160
+
161
+ @mcp.tool()
162
+ def optimize_query_hints(sql: str, api_key: str = "") -> dict:
163
+ """Suggest optimizations for a SQL query.
164
+
165
+ Args:
166
+ sql: SQL query string to analyze for optimizations
167
+ """
168
+ allowed, msg, tier = check_access(api_key)
169
+ if not allowed:
170
+ return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
171
+
172
+ _check_rate_limit("optimize_query_hints")
173
+ hints = []
174
+ sql_upper = sql.upper()
175
+ if "SELECT *" in sql_upper:
176
+ hints.append({"hint": "Avoid SELECT * - specify only needed columns", "severity": "warning", "category": "performance"})
177
+ if "WHERE" not in sql_upper and "SELECT" in sql_upper:
178
+ hints.append({"hint": "No WHERE clause - may scan entire table", "severity": "warning", "category": "performance"})
179
+ if re.search(r'WHERE.*\bLIKE\s+["\']%', sql, re.IGNORECASE):
180
+ hints.append({"hint": "Leading wildcard in LIKE prevents index usage", "severity": "warning", "category": "index"})
181
+ if re.search(r'WHERE.*\bOR\b', sql, re.IGNORECASE):
182
+ hints.append({"hint": "OR conditions may prevent index usage - consider UNION", "severity": "info", "category": "index"})
183
+ if "DISTINCT" in sql_upper:
184
+ hints.append({"hint": "DISTINCT can be expensive - ensure it's necessary", "severity": "info", "category": "performance"})
185
+ if "ORDER BY" in sql_upper and "LIMIT" not in sql_upper:
186
+ hints.append({"hint": "ORDER BY without LIMIT sorts all results", "severity": "info", "category": "performance"})
187
+ if sql_upper.count("SELECT") > 1:
188
+ hints.append({"hint": "Subquery detected - consider using JOINs or CTEs instead", "severity": "info", "category": "readability"})
189
+ if re.search(r'WHERE.*(?:FUNCTION|UPPER|LOWER|CAST|CONVERT)\s*\(', sql, re.IGNORECASE):
190
+ hints.append({"hint": "Function in WHERE clause prevents index usage", "severity": "warning", "category": "index"})
191
+ tables = re.findall(r'\bFROM\s+(\w+)', sql, re.IGNORECASE) + re.findall(r'\bJOIN\s+(\w+)', sql, re.IGNORECASE)
192
+ idx_suggestions = []
193
+ for col_match in re.finditer(r'WHERE\s+(\w+)\s*=', sql, re.IGNORECASE):
194
+ idx_suggestions.append(f"Consider index on {col_match.group(1)}")
195
+ return {"hints": hints, "hint_count": len(hints), "index_suggestions": idx_suggestions,
196
+ "tables_referenced": list(set(tables))}
197
+
198
+
199
+ if __name__ == "__main__":
200
+ mcp.run()