Skip to content

Commit 386df86

Browse files
authored
Merge pull request #2 from griffithsbs/allow-read-only-queries-that-do-not-start-with-select-keyword
Allow read-only queries that do not start with SELECT keyword
2 parents 6af6532 + 53fc506 commit 386df86

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

mcp_server_snowflake/main.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from mcp.server.models import InitializationOptions
2323
from mcp.server.lowlevel import NotificationOptions
2424
from dotenv import load_dotenv
25+
import sqlglot
26+
from sqlglot.errors import ParseError
2527

2628
from mcp_server_snowflake.utils.snowflake_conn import (
2729
SnowflakeConfig,
@@ -346,9 +348,16 @@ async def handle_execute_query(
346348
)
347349
]
348350

349-
# Validate that the query is read-only (SELECT statement)
350-
query = query.strip()
351-
if not query.upper().startswith("SELECT "):
351+
# Validate that the query is read-only
352+
try:
353+
parsed_statements = sqlglot.parse(query, dialect="snowflake")
354+
read_only_types = {'select', 'show', 'describe', 'explain', 'with'}
355+
356+
for stmt in parsed_statements:
357+
if stmt.key.lower() not in read_only_types:
358+
raise ParseError(f"Error: Only read-only queries are allowed. Found statement type: {stmt.key}")
359+
360+
except ParseError:
352361
return [
353362
mcp_types.TextContent(
354363
type="text",

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies = [
1616
"cryptography>=41.0.0",
1717
"mcp",
1818
"anyio>=3.7.1",
19+
"sqlglot>=11.5.5"
1920
]
2021

2122
[project.scripts]

uv.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)