Skip to main content
Glama
RathodDarshil

PostgreSQL Query MCP Server

query-postgres

Execute SQL queries on PostgreSQL databases to retrieve data through natural language interaction, enabling direct database access for information retrieval.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes

Implementation Reference

  • The inline handler function for the "query-postgres" tool. Validates the query is a read-only SELECT, executes it using the Postgres pool with a 10-second timeout, formats results as JSON (rows, rowCount, fields), or returns an error message.
    server.tool("query-postgres", { query: z.string() }, async ({ query }) => { try { // Validate that the query is read-only if (!isReadOnlyQuery(query)) { return { content: [ { type: "text", text: "Error: Only SELECT queries are allowed. INSERT, UPDATE, DELETE, and other write operations are not permitted.", }, ], isError: true, }; } // Create a promise that will be rejected after 10 seconds const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new Error("Query execution timed out after 10 seconds. Pls modify the query and try again.")); }, 10000); // 10 seconds in milliseconds }); // Execute the query with a timeout const result = (await Promise.race([pool.query(query), timeoutPromise])) as any; // Using 'any' here to handle the type after the race return { content: [ { type: "text", text: JSON.stringify( { rows: result.rows, rowCount: result.rowCount, fields: result.fields.map((f: any) => ({ name: f.name, dataType: f.dataTypeID, })), }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error executing query: ${(error as Error).message}`, }, ], isError: true, }; } });
  • Input schema for the tool using Zod, requiring a single 'query' parameter of type string.
    server.tool("query-postgres", { query: z.string() }, async ({ query }) => {
  • src/index.ts:79-79 (registration)
    Registration of the "query-postgres" tool on the MCP server instance.
    server.tool("query-postgres", { query: z.string() }, async ({ query }) => {
  • Helper function to validate that the SQL query is read-only (starts with SELECT, excludes common write operations like INSERT, UPDATE, etc.). Called within the tool handler.
    function isReadOnlyQuery(query: string): boolean { // Normalize the query by removing comments, extra whitespace, and converting to lowercase const normalizedQuery = query .replace(/--.*$/gm, "") // Remove single-line comments .replace(/\/\*[\s\S]*?\*\//g, "") // Remove multi-line comments .replace(/\s+/g, " ") .trim() .toLowerCase(); // Check if the query starts with SELECT if (normalizedQuery.startsWith("select")) { return true; } // Check for other write operations const writeOperations = [ "insert", "update", "delete", "drop", "create", "alter", "truncate", "grant", "revoke", "copy", // COPY can write data ]; for (const op of writeOperations) { if (normalizedQuery.startsWith(op) || normalizedQuery.includes(" " + op + " ")) { return false; } } return true; }
  • Postgres connection pool initialized from DATABASE_URL or command-line argument, used by the query-postgres tool handler.
    const pool = new Pool({ connectionString, ssl: { rejectUnauthorized: false, // Use this if you're getting SSL certificate errors }, });

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RathodDarshil/mcp-postgres-query-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server