Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased
- OCI: Added `curl` to image
- MCP: Started using MCP tool descriptions from Python docstrings
- Instructions: Copy-editing. Wording.

## v0.0.5 - 2025-07-22
- MCP: Fixed defunct `get_cratedb_documentation_index` tool
Expand Down
18 changes: 7 additions & 11 deletions cratedb_mcp/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,15 @@ def add_tools(self):
# ------------------------------------------
self.mcp.add_tool(
Tool.from_function(
fn=get_table_metadata,
description="Return column schema and metadata for all tables stored in CrateDB. "
"Use it to inquire entities you don't know about.",
fn=query_sql,
description=query_sql.__doc__,
tags={"text-to-sql"},
)
)
self.mcp.add_tool(
Tool.from_function(
fn=query_sql,
description="Send an SQL query to CrateDB and return results. "
"Only 'SELECT' queries are allowed.",
fn=get_table_metadata,
description=get_table_metadata.__doc__,
tags={"text-to-sql"},
)
)
Expand All @@ -62,16 +60,14 @@ def add_tools(self):
self.mcp.add_tool(
Tool.from_function(
fn=get_cratedb_documentation_index,
description="Get an index of CrateDB documentation links for fetching. "
"Should download docs before answering questions. "
"Has documentation title, description, and link.",
description=get_cratedb_documentation_index.__doc__,
tags={"documentation"},
)
)
self.mcp.add_tool(
Tool.from_function(
fn=fetch_cratedb_docs,
description="Download individual CrateDB documentation pages by link.",
description=fetch_cratedb_docs.__doc__,
tags={"documentation"},
)
)
Expand All @@ -82,7 +78,7 @@ def add_tools(self):
self.mcp.add_tool(
Tool.from_function(
fn=get_cluster_health,
description="Return the health of the CrateDB cluster.",
description=get_cluster_health.__doc__,
tags={"health", "monitoring", "status"},
)
)
Expand Down
23 changes: 7 additions & 16 deletions cratedb_mcp/prompt/instructions.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
## Tool instructions

Use all available tools from the CrateDB MCP server `cratedb-mcp` or derived
applications for gathering accurate information.
Use all available tools for gathering accurate information.

You have the following tools available:

1. `get_table_metadata`: Return table and column schema information for all tables stored in CrateDB. Use it when you need to discover entities and database metadata you are unfamiliar with.
2. `query_sql`: Execute an SQL query on CrateDB and return the results.
1. `get_table_metadata`: Return table metadata for all tables stored in CrateDB.
2. `query_sql`: Execute an SQL query on CrateDB and return the results. Select only the columns you need (avoid `SELECT *`) and, where appropriate, add a `LIMIT` clause to keep result sets concise.
3. `get_cratedb_documentation_index`: Return the table of contents for the curated CrateDB documentation index. Use it whenever you need to verify CrateDB-specific syntax.
4. `fetch_cratedb_docs`: Given a link returned by `get_cratedb_documentation_index`, fetch the full content of that documentation page.

Those rules are applicable when using the available tools:

- First use `get_table_metadata` to find out about tables stored in the database and their
column names and types. Next, use `query_sql` to execute a parameterised SQL query that
returns only the columns you need (avoid `SELECT *`) and, where appropriate, add a
`LIMIT` clause to keep result sets concise.
4. `fetch_cratedb_docs`: Given a `link` returned by `get_cratedb_documentation_index`, fetch the full content of that documentation page. Content can be quoted verbatim when answering questions about CrateDB.

- First use `get_cratedb_documentation_index` to find out about curated documentation resources
about CrateDB. Then, use `fetch_cratedb_docs` to retrieve individual pages that
can be quoted verbatim when answering questions about CrateDB.
Please follow those rules when using the available tools:
- First use `get_table_metadata` to find out about tables stored in the database and their metadata. Next, use `query_sql` to execute the SQL query.
- First use `get_cratedb_documentation_index` to get an overview about curated documentation resources about CrateDB. Then, use `fetch_cratedb_docs` to retrieve individual pages by `link`.

After fetching data, reason about the output and provide a concise interpretation before
formulating the final answer.
22 changes: 18 additions & 4 deletions cratedb_mcp/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# Text-to-SQL
# ------------------------------------------
def query_cratedb(query: str) -> dict:
"""Sends a `query` to the set `$CRATEDB_CLUSTER_URL`"""
"""Send the SQL `query` to the configured CrateDB server and return the result."""
url = HTTP_URL
if url.endswith("/"):
url = url.removesuffix("/")
Expand All @@ -18,13 +18,19 @@ def query_cratedb(query: str) -> dict:


def query_sql(query: str) -> dict:
"""
Execute an SQL query on CrateDB and return the results.
Select only the columns you need (avoid `SELECT *`) and,
where appropriate, add a `LIMIT` clause to keep result sets concise.
"""
if not sql_is_permitted(query):
raise PermissionError("Only queries that have a SELECT statement are allowed.")
return query_cratedb(query)


def get_table_metadata() -> dict:
"""
Return table metadata for all tables stored in CrateDB.
Return an aggregation of schema:tables, e.g.: {'doc': [{name:'mytable', ...}, ...]}

The tables have metadata datapoints like replicas, shards,
Expand All @@ -36,17 +42,25 @@ def get_table_metadata() -> dict:
# ------------------------------------------
# Documentation inquiry
# ------------------------------------------

# Load CrateDB documentation outline.
documentation_index = DocumentationIndex()


def get_cratedb_documentation_index() -> list:
"""Get curated CrateDB documentation index."""
"""
Return the table of contents for the curated CrateDB documentation index.
Use it whenever you need to verify CrateDB-specific details or syntax.
"""
return documentation_index.items()


def fetch_cratedb_docs(link: str) -> str:
"""Fetch a CrateDB documentation link."""
"""
Given a `link` returned by `get_cratedb_documentation_index`,
fetch the full content of that documentation page. Content
can be quoted verbatim when answering questions about CrateDB.
"""
if not documentation_index.url_permitted(link):
raise ValueError(f"Link is not permitted: {link}")
return documentation_index.client.get(link, timeout=Settings.http_timeout()).text
Expand All @@ -56,5 +70,5 @@ def fetch_cratedb_docs(link: str) -> str:
# Health / Status
# ------------------------------------------
def get_cluster_health() -> dict:
"""Query sys.health ordered by severity."""
"""Return the health of the CrateDB cluster by querying `sys.health` ordered by severity."""
return query_cratedb(Queries.HEALTH)
8 changes: 2 additions & 6 deletions tests/test_knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ def test_documentation_index():


def test_queries():
# Verify basic parts of the query.
assert "information_schema.tables" in Queries.TABLES_METADATA

# Verify other critical parts of the query.
assert "sys.health" in Queries.TABLES_METADATA
assert "WITH partitions_health" in Queries.TABLES_METADATA
assert "LEFT JOIN" in Queries.TABLES_METADATA
assert "partitions_health" in Queries.TABLES_METADATA
assert "sys.health" in Queries.HEALTH