Skip to main content
Glama
itsalfredakku

Postgres MCP Server

admin

Manage PostgreSQL database administration tasks including user permissions, database information, and maintenance operations through structured commands.

Instructions

Database administration: users, permissions, database info, maintenance operations

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYesAdmin operation to perform
usernameNoUsername (required for user operations)
passwordNoPassword (required for create_user)
permissionsNoPermissions to grant/revoke
tableNameNoTable name (for permission operations)
optionsNoOperation options

Implementation Reference

  • The primary handler function for the 'admin' tool. It parses the 'operation' parameter and executes corresponding SQL queries for database administration tasks such as getting database info, managing users, granting/revoking permissions, and maintenance operations like VACUUM, ANALYZE, and REINDEX.
    private async handleAdmin(args: any) {
      const { operation, username, password, permissions, tableName, options = {} } = args;
    
      switch (operation) {
        case 'database_info':
          const dbInfo = await this.queryClient.executeQuery(`
            SELECT 
              current_database() as database_name,
              current_user as current_user,
              session_user as session_user,
              current_setting('server_version') as postgres_version,
              current_setting('server_encoding') as encoding,
              current_setting('timezone') as timezone,
              pg_database_size(current_database()) as database_size_bytes,
              pg_size_pretty(pg_database_size(current_database())) as database_size,
              (SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()) as active_connections,
              current_setting('max_connections') as max_connections,
              current_setting('shared_buffers') as shared_buffers,
              current_setting('effective_cache_size') as effective_cache_size
          `);
          
          const tableCount = await this.queryClient.executeQuery(`
            SELECT count(*) as table_count
            FROM information_schema.tables 
            WHERE table_schema NOT IN ('information_schema', 'pg_catalog')
          `);
          
          const result = {
            ...dbInfo.rows[0],
            table_count: parseInt(tableCount.rows[0].table_count),
            uptime: await this.getDatabaseUptime()
          };
          
          return {
            content: [{
              type: 'text',
              text: JSON.stringify(result, null, 2)
            }]
          };
    
        case 'list_users':
          const users = await this.queryClient.executeQuery(`
            SELECT 
              usename as username,
              usesysid as user_id,
              usecreatedb as can_create_db,
              usesuper as is_superuser,
              userepl as can_replicate,
              usebypassrls as bypass_rls,
              valuntil as password_expires,
              (SELECT string_agg(datname, ', ') 
               FROM pg_database 
               WHERE has_database_privilege(usename, datname, 'CONNECT')) as accessible_databases
            FROM pg_user
            ORDER BY usename
          `);
          return {
            content: [{
              type: 'text',
              text: JSON.stringify(users.rows, null, 2)
            }]
          };
    
        case 'create_user':
          if (!username || !password) {
            throw new Error('Username and password are required for user creation');
          }
          await this.queryClient.executeQuery(`CREATE USER ${username} WITH PASSWORD '${password}'`);
          return {
            content: [{
              type: 'text',
              text: `User '${username}' created successfully`
            }]
          };
    
        case 'drop_user':
          if (!username) {
            throw new Error('Username is required for user deletion');
          }
          await this.queryClient.executeQuery(`DROP USER ${username}`);
          return {
            content: [{
              type: 'text',
              text: `User '${username}' dropped successfully`
            }]
          };
    
        case 'grant_permissions':
          if (!username || !permissions || permissions.length === 0) {
            throw new Error('Username and permissions are required');
          }
          
          const target = tableName ? `TABLE ${tableName}` : 'ALL TABLES IN SCHEMA public';
          const grantSQL = `GRANT ${permissions.join(', ')} ON ${target} TO ${username}`;
          await this.queryClient.executeQuery(grantSQL);
          
          return {
            content: [{
              type: 'text',
              text: `Permissions ${permissions.join(', ')} granted to '${username}' on ${target}`
            }]
          };
    
        case 'revoke_permissions':
          if (!username || !permissions || permissions.length === 0) {
            throw new Error('Username and permissions are required');
          }
          
          const revokeTarget = tableName ? `TABLE ${tableName}` : 'ALL TABLES IN SCHEMA public';
          const revokeSQL = `REVOKE ${permissions.join(', ')} ON ${revokeTarget} FROM ${username}`;
          await this.queryClient.executeQuery(revokeSQL);
          
          return {
            content: [{
              type: 'text',
              text: `Permissions ${permissions.join(', ')} revoked from '${username}' on ${revokeTarget}`
            }]
          };
    
        case 'vacuum':
          if (tableName) {
            const vacuumSQL = `VACUUM${options.full ? ' FULL' : ''} ${tableName}`;
            await this.queryClient.executeQuery(vacuumSQL);
            return {
              content: [{
                type: 'text',
                text: `Vacuum completed for table '${tableName}'`
              }]
            };
          } else {
            await this.queryClient.executeQuery('VACUUM');
            return {
              content: [{
                type: 'text',
                text: 'Database vacuum completed'
              }]
            };
          }
    
        case 'analyze':
          if (tableName) {
            await this.queryClient.executeQuery(`ANALYZE ${tableName}`);
            return {
              content: [{
                type: 'text',
                text: `Analyze completed for table '${tableName}'`
              }]
            };
          } else {
            await this.queryClient.executeQuery('ANALYZE');
            return {
              content: [{
                type: 'text',
                text: 'Database analyze completed'
              }]
            };
          }
    
        case 'reindex_database':
          await this.queryClient.executeQuery('REINDEX DATABASE CONCURRENTLY');
          return {
            content: [{
              type: 'text',
              text: 'Database reindex completed'
            }]
          };
    
        default:
          throw new Error(`Unknown admin operation: ${operation}`);
      }
    }
  • The input schema definition for the 'admin' tool, specifying parameters like operation, username, password, permissions, etc., and validating inputs before execution.
    {
      name: 'admin',
      description: 'Database administration: users, permissions, database info, maintenance operations',
      inputSchema: {
        type: 'object',
        properties: {
          operation: {
            type: 'string',
            enum: ['database_info', 'list_users', 'create_user', 'drop_user', 'grant_permissions', 'revoke_permissions', 'vacuum', 'analyze', 'reindex_database'],
            description: 'Admin operation to perform'
          },
          username: {
            type: 'string',
            description: 'Username (required for user operations)'
          },
          password: {
            type: 'string',
            description: 'Password (required for create_user)'
          },
          permissions: {
            type: 'array',
            items: { type: 'string' },
            description: 'Permissions to grant/revoke'
          },
          tableName: {
            type: 'string',
            description: 'Table name (for permission operations)'
          },
          options: {
            type: 'object',
            properties: {
              full: { type: 'boolean', default: false },
              verbose: { type: 'boolean', default: false },
              analyze: { type: 'boolean', default: false }
            },
            description: 'Operation options'
          }
        },
        required: ['operation']
      }
    },
  • src/index.ts:634-636 (registration)
    Registration of the 'admin' tool schema via the ListToolsRequestSchema handler, which returns all tool definitions including 'admin'.
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: toolDefinitions,
    }));
  • src/index.ts:661-661 (registration)
    Dispatch registration in the CallToolRequestSchema handler switch statement that routes 'admin' tool calls to the handleAdmin function.
    case 'admin':
  • Helper function to detect potentially dangerous administrative SQL operations, used by security validator for admin tool executions.
     * Check if operation is a dangerous admin operation
     */
    private isDangerousAdminOperation(sql: string): boolean {
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. While 'administration' implies mutation capabilities (e.g., create_user, drop_user), the description doesn't specify required permissions, whether operations are reversible, potential side effects, or error handling. For a tool with multiple destructive operations and no annotation coverage, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that lists key domains without unnecessary elaboration. It's appropriately sized for the tool's complexity and front-loads the core purpose. However, it could be slightly more structured by separating domains with clearer formatting or bullet points for better readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's high complexity (6 parameters, multiple destructive operations, no output schema, and no annotations), the description is insufficient. It doesn't address behavioral aspects like authentication needs, side effects, or return formats. For an administration tool with potentially irreversible operations, more context about safety and usage is required to be complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 6 parameters thoroughly. The description adds no parameter-specific information beyond the high-level domains listed. It doesn't explain parameter relationships or provide additional context beyond what's in the schema, resulting in the baseline score of 3 for adequate but non-compensatory coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs 'Database administration' and lists the specific domains (users, permissions, database info, maintenance operations). It uses the verb 'administration' with the resource 'database' and provides scope through the listed domains. However, it doesn't explicitly differentiate from sibling tools like 'permissions', 'security', or 'monitoring' that might overlap in functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It lists functional domains but doesn't indicate prerequisites, appropriate contexts, or exclusions. With sibling tools like 'permissions', 'security', and 'monitoring' that might handle similar operations, the lack of differentiation leaves the agent without clear selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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/itsalfredakku/postgres-mcp'

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