Skip to content

Commit 6f98c85

Browse files
committed
feat: add local databend mode
1 parent b3b5fb6 commit 6f98c85

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

mcp_databend/env.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ def safe_mode(self) -> bool:
3333
@property
3434
def local_mode(self) -> bool:
3535
"""Get the local mode setting."""
36-
return os.environ.get("LOCAL_MODE", "false").lower() in ("true", "1", "yes", "on")
36+
return os.environ.get("LOCAL_MODE", "false").lower() in (
37+
"true",
38+
"1",
39+
"yes",
40+
"on",
41+
)
3742

3843

3944
# Global instance placeholder for the singleton pattern

mcp_databend/server.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
# Global Databend client singleton
3636
_databend_client = None
3737

38+
3839
def get_global_databend_client():
3940
"""Get global Databend client instance (deprecated, use create_databend_client)."""
4041
global _databend_client
@@ -57,12 +58,12 @@ def is_sql_safe(sql: str) -> tuple[bool, str]:
5758

5859
# List of dangerous operations to block in safe mode
5960
dangerous_patterns = [
60-
(r'\bDROP\s+', "DROP operations are not allowed in MCP safe mode"),
61-
(r'\bDELETE\s+', "DELETE operations are not allowed in MCP safe mode"),
62-
(r'\bTRUNCATE\s+', "TRUNCATE operations are not allowed in MCP safe mode"),
63-
(r'\bALTER\s+', "ALTER operations are not allowed in MCP safe mode"),
64-
(r'\bUPDATE\s+', "UPDATE operations are not allowed in MCP safe mode"),
65-
(r'\bREVOKE\s+', "REVOKE operations are not allowed in MCP safe mode"),
61+
(r"\bDROP\s+", "DROP operations are not allowed in MCP safe mode"),
62+
(r"\bDELETE\s+", "DELETE operations are not allowed in MCP safe mode"),
63+
(r"\bTRUNCATE\s+", "TRUNCATE operations are not allowed in MCP safe mode"),
64+
(r"\bALTER\s+", "ALTER operations are not allowed in MCP safe mode"),
65+
(r"\bUPDATE\s+", "UPDATE operations are not allowed in MCP safe mode"),
66+
(r"\bREVOKE\s+", "REVOKE operations are not allowed in MCP safe mode"),
6667
]
6768

6869
# Check each dangerous pattern
@@ -80,10 +81,12 @@ def create_databend_client():
8081
if config.local_mode:
8182
# Use local in-memory Databend
8283
import databend
84+
8385
return databend.SessionContext()
8486
else:
8587
# Use remote Databend server
8688
from databend_driver import BlockingDatabendClient
89+
8790
return BlockingDatabendClient(config.dsn)
8891

8992

@@ -105,7 +108,7 @@ def execute_databend_query(sql: str) -> list[dict] | dict:
105108
# Handle local in-memory Databend
106109
result = client.sql(sql)
107110
df = result.to_pandas()
108-
return df.to_dict('records')
111+
return df.to_dict("records")
109112
else:
110113
# Handle remote Databend server
111114
conn = client.get_conn()
@@ -165,6 +168,7 @@ def _execute_sql(sql: str) -> dict:
165168
logger.error(error_msg)
166169
return {"status": "error", "message": error_msg}
167170

171+
168172
@mcp.tool()
169173
async def execute_sql(sql: str) -> dict:
170174
"""
@@ -246,7 +250,7 @@ async def list_stage_files(stage_name: str, path: Optional[str] = None):
246250
Returns:
247251
Dictionary containing either query results or error information
248252
"""
249-
if not stage_name.startswith('@'):
253+
if not stage_name.startswith("@"):
250254
stage_name = f"@{stage_name}"
251255

252256
if path:
@@ -267,7 +271,9 @@ async def show_connections():
267271

268272

269273
@mcp.tool()
270-
async def create_stage(name: str, url: str, connection_name: Optional[str] = None, **kwargs) -> dict:
274+
async def create_stage(
275+
name: str, url: str, connection_name: Optional[str] = None, **kwargs
276+
) -> dict:
271277
"""
272278
Create a Databend stage with connection
273279
Args:
@@ -288,7 +294,7 @@ async def create_stage(name: str, url: str, connection_name: Optional[str] = Non
288294

289295
# Add any additional options from kwargs
290296
for key, value in kwargs.items():
291-
if key not in ['name', 'url', 'connection_name']:
297+
if key not in ["name", "url", "connection_name"]:
292298
sql_parts.append(f"{key.upper()} = '{value}'")
293299

294300
sql = " ".join(sql_parts)

0 commit comments

Comments
 (0)