feat: add stats endpoint for SQL object and update README with Docker AI usage

This commit is contained in:
Marcelo Ochoa
2025-03-19 11:17:35 -03:00
parent 70023ae03e
commit eccea564dd
3 changed files with 143 additions and 1 deletions

View File

@@ -65,7 +65,11 @@ To use this server with the Claude Desktop app, add the following configuration
"-y",
"@modelcontextprotocol/server-oracle",
"host.docker.internal:1521/freepdb1"
]
],
"env": {
"ORACLE_USER": "scott",
"ORACLE_PASSWORD": "tiger"
}
}
}
}
@@ -93,6 +97,60 @@ See in action using Claude Desktop App
![Oracle MCP Server demo](./demo-prompts.gif)
### Using Docker AI
[Ask Gordon](https://docs.docker.com/desktop/features/gordon/) is an AI assistant designed to streamline your Docker workflow by providing contextual assistance tailored to your local environment. Currently in Beta and available in Docker Desktop version 4.38.0 or later, Ask Gordon offers intelligent support for various Docker-related tasks.
```sh
% cd src/oracle
% docker ai 'stats for table countries'
• Calling stats ✔️
Here are the statistics for the COUNTRIES table:
### Table Statistics:
• Owner: HR
• Table Name: COUNTRIES
• Number of Rows: 25
• Average Row Length: 16 bytes
• Last Analyzed: 2025-03-10 22:00:38
### Index Statistics:
• Index Name: COUNTRY_C_ID_PK
• B-Level: 0
• Leaf Blocks: 1
• Distinct Keys: 25
• Number of Rows: 25
• Clustering Factor: 0
• Last Analyzed: 2025-03-10 22:00:38
### Column Statistics:
1. COUNTRY_ID:
• Number of Distinct Values: 25
• Density: 0.04
• Histogram: NONE
• Last Analyzed: 2025-03-10 22:00:38
2. COUNTRY_NAME:
• Number of Distinct Values: 25
• Density: 0.04
• Histogram: NONE
• Last Analyzed: 2025-03-10 22:00:38
3. REGION_ID:
• Number of Distinct Values: 5
• Density: 0.02
• Histogram: FREQUENCY
• Last Analyzed: 2025-03-10 22:00:38
```
## Building
Docker:

View File

@@ -0,0 +1,9 @@
services:
time:
image: mcp/time
oracle:
image: mcp/oracle
command: ["host.docker.internal:1521/freepdb1"]
environment:
- ORACLE_USER=hr
- ORACLE_PASSWORD=hr_2025

View File

@@ -179,6 +179,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
},
},
},
{
name: "stats",
description: "Stats for SQL object",
inputSchema: {
type: "object",
properties: {
name: { type: "string" },
},
},
},
],
};
});
@@ -236,6 +246,71 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}
}
}
if (request.params.name === "stats") {
const tableName = request.params.arguments?.name as string;
let connection;
try {
connection = await pool.getConnection();
const result = await connection.execute<{ STATS_JSON: string }>(`SELECT JSON_OBJECT(
'table_stats' VALUE (
SELECT JSON_OBJECT(
'owner' VALUE owner,
'table_name' VALUE table_name,
'num_rows' VALUE num_rows,
'blocks' VALUE blocks,
'empty_blocks' VALUE empty_blocks,
'avg_row_len' VALUE avg_row_len,
'last_analyzed' VALUE TO_CHAR(last_analyzed, 'YYYY-MM-DD HH24:MI:SS')
)
FROM dba_tab_statistics
WHERE owner = UPPER(USER) AND table_name = UPPER(:tableName)
),
'index_stats' VALUE (
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'index_name' VALUE index_name,
'blevel' VALUE blevel,
'leaf_blocks' VALUE leaf_blocks,
'distinct_keys' VALUE distinct_keys,
'num_rows' VALUE num_rows,
'clustering_factor' VALUE clustering_factor,
'last_analyzed' VALUE TO_CHAR(last_analyzed, 'YYYY-MM-DD HH24:MI:SS')
)
)
FROM dba_ind_statistics
WHERE table_owner = UPPER(USER) AND table_name = UPPER(:tableName)
),
'column_stats' VALUE (
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'column_name' VALUE column_name,
'num_distinct' VALUE num_distinct,
'density' VALUE density,
'histogram' VALUE histogram,
'last_analyzed' VALUE TO_CHAR(last_analyzed, 'YYYY-MM-DD HH24:MI:SS')
)
)
FROM dba_tab_col_statistics
WHERE owner = UPPER(USER) AND table_name = UPPER(:tableName)
)
) AS stats_json
FROM dual`, [tableName,tableName,tableName], { outFormat: oracledb.OUT_FORMAT_OBJECT });
return {
content: [{ type: "text", text: result.rows?.[0]?.STATS_JSON }],
isError: false,
};
} catch (error) {
throw error;
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.warn("Could not close connection:", err);
}
}
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
});