amirkiarafiei commited on
Commit
6e75e8f
·
1 Parent(s): 6c01c87

fix: improve some tools' parameters

Browse files
Files changed (2) hide show
  1. chat_history.json +1 -1
  2. 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 = %s
356
- AND tc.table_name = %s
357
  ORDER BY tc.constraint_name, kcu.ordinal_position
358
  """
359
- return execute_query(sql)
 
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 = $1 AND table_name = $2
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 = %s
496
- AND tc.table_name = %s
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 = %s
506
- AND table_name = %s
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 = %s
542
- AND t.table_name != %s -- Exclude self-references
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,