diff --git a/CHANGES.md b/CHANGES.md index 9d7bd1d..6829df2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/cratedb_mcp/core.py b/cratedb_mcp/core.py index 9c0caa3..f71a6db 100644 --- a/cratedb_mcp/core.py +++ b/cratedb_mcp/core.py @@ -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"}, ) ) @@ -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"}, ) ) @@ -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"}, ) ) diff --git a/cratedb_mcp/prompt/instructions.md b/cratedb_mcp/prompt/instructions.md index 19d6562..3b7bc1b 100644 --- a/cratedb_mcp/prompt/instructions.md +++ b/cratedb_mcp/prompt/instructions.md @@ -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. diff --git a/cratedb_mcp/tool.py b/cratedb_mcp/tool.py index e88b4cd..cd2be8d 100644 --- a/cratedb_mcp/tool.py +++ b/cratedb_mcp/tool.py @@ -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("/") @@ -18,6 +18,11 @@ 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) @@ -25,6 +30,7 @@ def query_sql(query: str) -> dict: 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, @@ -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 @@ -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) diff --git a/tests/test_knowledge.py b/tests/test_knowledge.py index 5e36e17..c51953e 100644 --- a/tests/test_knowledge.py +++ b/tests/test_knowledge.py @@ -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