Commit
·
6e75e8f
1
Parent(s):
6c01c87
fix: improve some tools' parameters
Browse files- chat_history.json +1 -1
- postgre_mcp_server.py +20 -14
chat_history.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
[{"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my previous request ?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "# Result\nlist all tables\n# Explanation\nThe user's previous request was to list all the tables in the database. This was determined by reviewing the previous turn in the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "count tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\n4\n# Explanation\nThe user requested the number of tables. The previous response listed the tables, and counting them gives the answer.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my last message ?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\ncount tables\n# Explanation\nThe user's last message was \"count tables\". This was determined by reviewing the previous turn in the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my very first message in this conversation?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nlist all tables\n# Explanation\nThe user's very first message in this conversation was \"list all tables\". This was determined by reviewing the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "total number of sales in 2024", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nThe tables in the database are:\n* dim_agreement\n* dim_customer\n* dim_product\n* dim_product_order_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "hi there. show me the largest table name", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am sorry, I cannot directly determine the \"largest table name\" based on the available tools. I can list the tables and show their schemas, but I do not have a tool to determine table sizes. I would need a tool to get table sizes to fulfill this request. However, I can list the tables for you.\n\n```markdown\n# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "you are free to execute any sql query and get the size of each table and return me the count of largest one", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am sorry, I cannot directly determine the \"largest table\" based on the available tools. I can list the tables and show their schemas, but I do not have a tool to determine table sizes. I would need a tool to get table sizes to fulfill this request. I can list the tables for you, but I cannot provide the count of the largest one.", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}]
|
|
|
|
| 1 |
+
[{"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my previous request ?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "# Result\nlist all tables\n# Explanation\nThe user's previous request was to list all the tables in the database. This was determined by reviewing the previous turn in the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "count tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\n4\n# Explanation\nThe user requested the number of tables. The previous response listed the tables, and counting them gives the answer.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my last message ?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\ncount tables\n# Explanation\nThe user's last message was \"count tables\". This was determined by reviewing the previous turn in the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "what was my very first message in this conversation?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nlist all tables\n# Explanation\nThe user's very first message in this conversation was \"list all tables\". This was determined by reviewing the conversation history.\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "total number of sales in 2024", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "list all tables", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "```markdown\n# Result\nThe tables in the database are:\n* dim_agreement\n* dim_customer\n* dim_product\n* dim_product_order_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "hi there. show me the largest table name", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am sorry, I cannot directly determine the \"largest table name\" based on the available tools. I can list the tables and show their schemas, but I do not have a tool to determine table sizes. I would need a tool to get table sizes to fulfill this request. However, I can list the tables for you.\n\n```markdown\n# Result\nThe tables in the database are:\n* dim\\_agreement\n* dim\\_customer\n* dim\\_product\n* dim\\_product\\_order\\_item\n\n# Explanation\nThe `list_tables` tool was called to retrieve a list of all available tables in the database schema. The result shows the names of these tables.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "you are free to execute any sql query and get the size of each table and return me the count of largest one", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am sorry, I cannot directly determine the \"largest table\" based on the available tools. I can list the tables and show their schemas, but I do not have a tool to determine table sizes. I would need a tool to get table sizes to fulfill this request. I can list the tables for you, but I cannot provide the count of the largest one.", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "can you find the foreign keys and relationships ?", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am unable to retrieve the foreign keys using the `get_foreign_keys` tool. It seems there's an issue with the tool's execution. However, based on the table schemas provided, I can infer the relationships.\n\n# Result\n\n* **dim\\_agreement**: Related to `dim_customer` via `customer_id`.\n* **dim\\_customer**: Likely related to `dim_product`, `dim_product_order_item`, and potentially other tables through their respective `customer_id` columns.\n* **dim\\_product**: Related to `dim_customer` via `customer_id`, `dim_agreement` via `agreement_id`, and likely other tables through foreign key relationships.\n* **dim\\_product\\_order\\_item**: Related to `dim_customer` via `customer_id`, `dim_agreement` via `agreement_id`, and likely related to a product order table via a `product_order_id`.\n\n# Explanation\n\nThe `get_foreign_keys` tool did not return the foreign key relationships. Therefore, I am relying on the schema descriptions to determine the relationships between the tables. The tables are connected through foreign keys, as described in the table descriptions.\n\n# Query\n\nN/A", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}, {"type": "human", "data": {"content": "get all the foreign keys and summarize them", "additional_kwargs": {}, "response_metadata": {}, "type": "human", "name": null, "id": null, "example": false}}, {"type": "ai", "data": {"content": "I am sorry, I cannot directly retrieve and summarize all foreign keys using the available tools. The `get_foreign_keys` tool did not work in a previous turn. However, I can describe the relationships between the tables based on the schema descriptions.\n\n# Result\n\n* **dim\\_agreement**: Related to `dim_customer` via `customer_id`.\n* **dim\\_customer**: Likely related to `dim_product` and `dim_product_order_item` through their respective `customer_id` columns.\n* **dim\\_product**: Related to `dim_customer` via `customer_id`, `dim_agreement` via `agreement_id`, and likely other tables through foreign key relationships.\n* **dim\\_product\\_order\\_item**: Related to `dim_customer` via `customer_id`, `dim_agreement` via `agreement_id`, and likely related to a product order table via a `product_order_id`.\n\n# Explanation\n\nThe `get_foreign_keys` tool did not return the foreign key relationships. Therefore, I am relying on the schema descriptions to determine the relationships between the tables. The tables are connected through foreign keys, as described in the table descriptions.\n\n# Query\n```sql\nN/A\n```", "additional_kwargs": {}, "response_metadata": {}, "type": "ai", "name": null, "id": null, "example": false, "tool_calls": [], "invalid_tool_calls": [], "usage_metadata": null}}]
|
postgre_mcp_server.py
CHANGED
|
@@ -352,11 +352,12 @@ def get_foreign_keys(table_name: str) -> str:
|
|
| 352 |
JOIN information_schema.constraint_column_usage ccu
|
| 353 |
ON rc.unique_constraint_name = ccu.constraint_name
|
| 354 |
WHERE tc.constraint_type = 'FOREIGN KEY'
|
| 355 |
-
AND tc.table_schema =
|
| 356 |
-
AND tc.table_name =
|
| 357 |
ORDER BY tc.constraint_name, kcu.ordinal_position
|
| 358 |
"""
|
| 359 |
-
|
|
|
|
| 360 |
|
| 361 |
|
| 362 |
@mcp.tool(description="Fetches and formats the schema details for all tables in the configured database schema.")
|
|
@@ -428,15 +429,20 @@ async def generate_select_query(table_name: str) -> list[PromptMessage]:
|
|
| 428 |
|
| 429 |
@mcp.prompt(description="Generates a prompt message to assist in writing analytical queries for a given table.")
|
| 430 |
async def generate_analytical_query(table_name: str) -> list[PromptMessage]:
|
| 431 |
-
"""Generate analytical queries for a table
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
try:
|
| 433 |
async with db_lifespan(mcp) as db_ctx:
|
| 434 |
pool = db_ctx.pool
|
| 435 |
async with pool.acquire() as conn:
|
| 436 |
-
columns = await conn.fetch("""
|
| 437 |
SELECT column_name, data_type
|
| 438 |
FROM information_schema.columns
|
| 439 |
-
WHERE table_schema =
|
| 440 |
ORDER BY ordinal_position
|
| 441 |
""", db_ctx.schema, table_name)
|
| 442 |
|
|
@@ -477,7 +483,7 @@ def find_relationships(table_name: str, schema: str = 'public') -> str:
|
|
| 477 |
"""
|
| 478 |
try:
|
| 479 |
# First get explicit foreign key relationships
|
| 480 |
-
fk_sql = """
|
| 481 |
SELECT
|
| 482 |
kcu.column_name,
|
| 483 |
ccu.table_name as foreign_table,
|
|
@@ -492,18 +498,18 @@ def find_relationships(table_name: str, schema: str = 'public') -> str:
|
|
| 492 |
ON ccu.constraint_name = tc.constraint_name
|
| 493 |
AND ccu.table_schema = tc.table_schema
|
| 494 |
WHERE tc.constraint_type = 'FOREIGN KEY'
|
| 495 |
-
AND tc.table_schema =
|
| 496 |
-
AND tc.table_name =
|
| 497 |
"""
|
| 498 |
|
| 499 |
# Then look for implied relationships based on common patterns
|
| 500 |
-
implied_sql = """
|
| 501 |
WITH source_columns AS (
|
| 502 |
-- Get all ID-like columns from our table
|
| 503 |
SELECT column_name, data_type
|
| 504 |
FROM information_schema.columns
|
| 505 |
-
WHERE table_schema =
|
| 506 |
-
AND table_name =
|
| 507 |
AND (
|
| 508 |
column_name LIKE '%%id'
|
| 509 |
OR column_name LIKE '%%_id'
|
|
@@ -538,8 +544,8 @@ def find_relationships(table_name: str, schema: str = 'public') -> str:
|
|
| 538 |
ON c.table_schema = t.table_schema
|
| 539 |
AND c.table_name = t.table_name
|
| 540 |
AND (c.column_name = 'id' OR c.column_name = sc.column_name)
|
| 541 |
-
WHERE t.table_schema =
|
| 542 |
-
AND t.table_name !=
|
| 543 |
)
|
| 544 |
SELECT
|
| 545 |
source_column as column_name,
|
|
|
|
| 352 |
JOIN information_schema.constraint_column_usage ccu
|
| 353 |
ON rc.unique_constraint_name = ccu.constraint_name
|
| 354 |
WHERE tc.constraint_type = 'FOREIGN KEY'
|
| 355 |
+
AND tc.table_schema = {schema}
|
| 356 |
+
AND tc.table_name = {table_name}
|
| 357 |
ORDER BY tc.constraint_name, kcu.ordinal_position
|
| 358 |
"""
|
| 359 |
+
|
| 360 |
+
return execute_query(sql, (schema, table_name))
|
| 361 |
|
| 362 |
|
| 363 |
@mcp.tool(description="Fetches and formats the schema details for all tables in the configured database schema.")
|
|
|
|
| 429 |
|
| 430 |
@mcp.prompt(description="Generates a prompt message to assist in writing analytical queries for a given table.")
|
| 431 |
async def generate_analytical_query(table_name: str) -> list[PromptMessage]:
|
| 432 |
+
""" Generate analytical queries for a table
|
| 433 |
+
Args:
|
| 434 |
+
table_name: The name of the table to generate analytical queries for
|
| 435 |
+
"""
|
| 436 |
+
load_dotenv()
|
| 437 |
+
schema = os.getenv("DB_SCHEMA")
|
| 438 |
try:
|
| 439 |
async with db_lifespan(mcp) as db_ctx:
|
| 440 |
pool = db_ctx.pool
|
| 441 |
async with pool.acquire() as conn:
|
| 442 |
+
columns = await conn.fetch(f"""
|
| 443 |
SELECT column_name, data_type
|
| 444 |
FROM information_schema.columns
|
| 445 |
+
WHERE table_schema = {schema} AND table_name = {table_name}
|
| 446 |
ORDER BY ordinal_position
|
| 447 |
""", db_ctx.schema, table_name)
|
| 448 |
|
|
|
|
| 483 |
"""
|
| 484 |
try:
|
| 485 |
# First get explicit foreign key relationships
|
| 486 |
+
fk_sql = f"""
|
| 487 |
SELECT
|
| 488 |
kcu.column_name,
|
| 489 |
ccu.table_name as foreign_table,
|
|
|
|
| 498 |
ON ccu.constraint_name = tc.constraint_name
|
| 499 |
AND ccu.table_schema = tc.table_schema
|
| 500 |
WHERE tc.constraint_type = 'FOREIGN KEY'
|
| 501 |
+
AND tc.table_schema = {schema}
|
| 502 |
+
AND tc.table_name = {table_name}
|
| 503 |
"""
|
| 504 |
|
| 505 |
# Then look for implied relationships based on common patterns
|
| 506 |
+
implied_sql = f"""
|
| 507 |
WITH source_columns AS (
|
| 508 |
-- Get all ID-like columns from our table
|
| 509 |
SELECT column_name, data_type
|
| 510 |
FROM information_schema.columns
|
| 511 |
+
WHERE table_schema = {schema}
|
| 512 |
+
AND table_name = {table_name}
|
| 513 |
AND (
|
| 514 |
column_name LIKE '%%id'
|
| 515 |
OR column_name LIKE '%%_id'
|
|
|
|
| 544 |
ON c.table_schema = t.table_schema
|
| 545 |
AND c.table_name = t.table_name
|
| 546 |
AND (c.column_name = 'id' OR c.column_name = sc.column_name)
|
| 547 |
+
WHERE t.table_schema = {schema}
|
| 548 |
+
AND t.table_name != {table_name} -- Exclude self-references
|
| 549 |
)
|
| 550 |
SELECT
|
| 551 |
source_column as column_name,
|