Skip to content

Commit 68c2817

Browse files
committed
README: Add recommendations to use a read-only database user
... to prevent agents from modifying the database content.
1 parent 0829bec commit 68c2817

File tree

6 files changed

+34
-15
lines changed

6 files changed

+34
-15
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
introducing powerful client capabilities, server proxying & composition,
1010
OpenAPI/FastAPI integration, and more advanced features.
1111
See [FastMCP 2.0 and the Official MCP SDK].
12+
- README: Added recommendations to use a read-only database user
13+
to prevent agents from modifying the database content
1214

1315
[FastMCP 2.0 and the Official MCP SDK]: https://gofastmcp.com/getting-started/welcome#fastmcp-2-0-and-the-official-mcp-sdk
1416

README.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,6 @@ Relevant information is pulled from <https://cratedb.com/docs>, curated per
181181
<br>
182182
Tool names are: `get_cratedb_documentation_index`, `fetch_cratedb_docs`
183183

184-
### Security considerations
185-
186-
**By default, the application will access the database in read-only mode.**
187-
188-
We do not recommend letting LLM-based agents insert or modify data by itself.
189-
As such, only `SELECT` statements are permitted and forwarded to the database.
190-
All other operations will raise a `ValueError` exception, unless the
191-
`CRATEDB_MCP_PERMIT_ALL_STATEMENTS` environment variable is set to a
192-
truthy value. This is **not** recommended.
193-
194184
### Install
195185

196186
The configuration snippets for AI assistants are using the `uvx` launcher
@@ -233,6 +223,23 @@ in seconds.
233223
The `CRATEDB_MCP_DOCS_CACHE_TTL` environment variable (default: 3600) defines
234224
the cache lifetime for documentation resources in seconds.
235225

226+
### Security considerations
227+
228+
If you want to prevent agents from modifying data, i.e., permit `SELECT` statements
229+
only, it is recommended to [create a read-only database user by using "GRANT DQL"].
230+
```sql
231+
CREATE USER "read-only" WITH (password = 'YOUR_PASSWORD');
232+
GRANT DQL TO "read-only";
233+
```
234+
Then, include relevant access credentials in the cluster URL.
235+
```shell
236+
export CRATEDB_CLUSTER_URL="https://read-only:[email protected]:4200"
237+
```
238+
The MCP Server also prohibits non-SELECT statements on the application level.
239+
All other operations will raise a `PermissionError` exception, unless the
240+
`CRATEDB_MCP_PERMIT_ALL_STATEMENTS` environment variable is set to a
241+
truthy value.
242+
236243
### Operate
237244

238245
Start MCP server with `stdio` transport (default).
@@ -289,6 +296,7 @@ Version pinning is strongly recommended, especially if you use it as a library.
289296
[CrateDB]: https://cratedb.com/database
290297
[cratedb-about]: https://pypi.org/project/cratedb-about/
291298
[cratedb-outline.yaml]: https://github.com/crate/about/blob/v0.0.4/src/cratedb_about/outline/cratedb-outline.yaml
299+
[create a read-only database user by using "GRANT DQL"]: https://community.cratedb.com/t/create-read-only-database-user-by-using-grant-dql/2031
292300
[development documentation]: https://github.com/crate/cratedb-mcp/blob/main/DEVELOP.md
293301
[example questions]: https://github.com/crate/about/blob/v0.0.4/src/cratedb_about/query/model.py#L17-L44
294302
[examples folder]: https://github.com/crate/cratedb-mcp/tree/main/examples

cratedb_mcp/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def query_cratedb(query: str) -> list[dict]:
2727
)
2828
def query_sql(query: str):
2929
if not sql_is_permitted(query):
30-
raise ValueError("Only queries that have a SELECT statement are allowed.")
30+
raise PermissionError("Only queries that have a SELECT statement are allowed.")
3131
return query_cratedb(query)
3232

3333

examples/mcptools.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@ set -euo pipefail
1414
# brew tap f/mcptools
1515
# brew install mcp uv
1616

17+
if ! command -v mcptools >/dev/null 2>&1; then
18+
echo mcptools not installed, skipping.
19+
echo "Skipped."
20+
exit 0
21+
fi
22+
1723
# Some systems do not provide the `mcpt` alias.
1824
alias mcpt=mcptools
1925

26+
# Display available MCP tools.
27+
mcpt tools uvx cratedb-mcp serve
28+
2029
# Explore the Text-to-SQL tools.
2130
mcpt call query_sql --params '{"query":"SELECT * FROM sys.summits LIMIT 3"}' uvx cratedb-mcp serve
2231
mcpt call get_table_metadata uvx cratedb-mcp serve

tests/test_examples.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# ruff: noqa: S603, S607
22
import subprocess
3-
from shutil import which
43

54
import pytest
65

76

8-
@pytest.mark.skipif(not which("mcptools"), reason="requires mcptools")
97
def test_mcptools():
108
proc = subprocess.run(["examples/mcptools.sh"], capture_output=True, timeout=15, check=True)
119
assert proc.returncode == 0
10+
if b"Skipped." in proc.stdout:
11+
raise pytest.skip("mcptools not installed")
1212
assert b"Ready." in proc.stdout

tests/test_mcp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ def test_query_sql_permitted():
3838

3939

4040
def test_query_sql_forbidden_easy():
41-
with pytest.raises(ValueError) as ex:
41+
with pytest.raises(PermissionError) as ex:
4242
assert "RelationUnknown" in str(
4343
query_sql("INSERT INTO foobar (id) VALUES (42) RETURNING id")
4444
)
4545
assert ex.match("Only queries that have a SELECT statement are allowed")
4646

4747

4848
def test_query_sql_forbidden_sneak_value():
49-
with pytest.raises(ValueError) as ex:
49+
with pytest.raises(PermissionError) as ex:
5050
query_sql("INSERT INTO foobar (operation) VALUES ('select')")
5151
assert ex.match("Only queries that have a SELECT statement are allowed")
5252

0 commit comments

Comments
 (0)