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
3 changes: 3 additions & 0 deletions src/postgres/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

A Model Context Protocol server that provides read-only access to PostgreSQL databases. This server enables LLMs to inspect database schemas and execute read-only queries.

> [!CAUTION]
> This server provides database access to AI models. If you need to enforce read-only access for security, create a separate database user with only SELECT permissions instead of relying on this server's built-in restrictions.

## Components

### Tools
Expand Down
14 changes: 12 additions & 2 deletions src/postgres/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const client = await pool.connect();
try {
await client.query("BEGIN TRANSACTION READ ONLY");
const result = await client.query(sql);
// Use a prepared statement to isolate the query. This approach
// ensures that the SQL text is parsed as a single statement, preventing
// malicious injections like "SELECT 1; COMMIT; DROP TABLE users;" which
// could bypass the read-only transaction by committing it prematurely.
const result = await client.query({
name: "isolated-statement",
text: sql,
values: [],
});
return {
content: [{ type: "text", text: JSON.stringify(result.rows, null, 2) }],
isError: false,
Expand All @@ -129,7 +137,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
console.warn("Could not roll back transaction:", error),
);

client.release();
// Release the client with destroy=true to ensure complete cleanup of the
// database session, preventing any potential state leakage between queries.
client.release(true);
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
Expand Down