All posts

Least-privilege access for MCP servers on Postgres

How can you give an MCP server just enough rights to query Postgres while enforcing least-privilege access? Enforcing least-privilege access means granting the minimum permissions needed for the server to function. Most teams hand an MCP server a static database user that has read‑write privileges on every schema. The credential lives in a configuration file or secret store, and any compromise of the server instantly grants an attacker unrestricted access. Auditing is an after‑thought; the serv

Free White Paper

Least Privilege Principle + On-Call Engineer Privileges: The Complete Guide

Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.

Free. No spam. Unsubscribe anytime.

How can you give an MCP server just enough rights to query Postgres while enforcing least-privilege access? Enforcing least-privilege access means granting the minimum permissions needed for the server to function.

Most teams hand an MCP server a static database user that has read‑write privileges on every schema. The credential lives in a configuration file or secret store, and any compromise of the server instantly grants an attacker unrestricted access. Auditing is an after‑thought; the server talks directly to the database, so no one sees which statements were run, whether a query returned sensitive columns, or if a dangerous command slipped through.

What you really need is a non‑human identity that is scoped to the exact tables and columns the MCP server requires, and a guard that can intervene before the query reaches the database. Even with that scoped identity, the request still travels straight to Postgres, leaving the connection point without any visibility, masking, or approval workflow.

Implementing least-privilege access for Postgres

The first step is to define a service account that represents the MCP server. In the identity provider you create a token that carries the server’s group membership. The token is short‑lived and can be refreshed on demand, ensuring that the server never holds long‑term credentials.

Next, you configure a Layer 7 gateway to sit between the token‑bearing server and the PostgreSQL instance. This gateway is the only place where the request can be examined, altered, or blocked. Because the gateway terminates the PostgreSQL wire protocol, it can inspect each SQL statement before it reaches the database engine.

hoop.dev acts as that gateway. It receives the server’s OIDC token, validates the claims, and then maps the identity to a narrowly scoped PostgreSQL user that has permission only on the required tables and columns. The gateway holds the actual database credential, so the MCP server does not have direct access to the password or IAM token.

When the server issues a query, hoop.dev records the exact statement, applies inline data masking to any columns marked as sensitive, and checks the statement against a set of guardrails. If the query tries to write to a disallowed table or selects a column that should be hidden, hoop.dev can block the command or route it for human approval before execution.

Continue reading? Get the full guide.

Least Privilege Principle + On-Call Engineer Privileges: Architecture Patterns & Best Practices

Free. No spam. Unsubscribe anytime.

Because the gateway is the sole data path, every enforcement outcome, audit logging, inline masking, just‑in‑time approval, and command‑level blocking, originates from hoop.dev. If you removed the gateway, none of those controls would exist; the MCP server would talk directly to Postgres with its scoped user, but you would lose visibility and the ability to mask or approve queries in real time.

Key architectural pieces

  • Setup: Configure OIDC/SAML in your identity provider, create a group for the MCP server, and issue short‑lived tokens. This determines who the request is and whether it may start.
  • Data path: Deploy the hoop.dev gateway near the PostgreSQL instance. All traffic from the MCP server must flow through this gateway.
  • Enforcement outcomes: hoop.dev records each query, masks sensitive fields, blocks prohibited statements, and can pause execution for an approval workflow. These outcomes are only possible because the gateway sits in the data path.

With this architecture you achieve true least‑privilege access: the MCP server holds only a token, the gateway enforces fine‑grained permissions, and every action is auditable.

Getting started

For a practical walkthrough, start with the getting‑started guide. It shows how to spin up the gateway with Docker Compose, connect it to a PostgreSQL instance, and bind OIDC authentication to your identity provider. The learn section dives deeper into masking policies, guardrail configuration, and approval workflows.

All of the configuration details, including how to define the scoped PostgreSQL user and set up inline masking for PII columns, are documented in the repository. You can explore the source code and contribution guidelines at the project’s GitHub page:

https://github.com/hoophq/hoop

FAQ

Do I still need to rotate database passwords?

No. The gateway stores the database credential and presents it on behalf of the MCP server. Password rotation is handled at the gateway level, not on the server.

Can I see which queries were blocked or approved?

Yes. hoop.dev logs every statement, including the outcome of guardrail checks and any approval steps. Those logs are available for replay and audit.

What happens if the gateway goes down?

The gateway is the single point of enforcement. If it becomes unavailable, the MCP server cannot reach PostgreSQL, which prevents any unguarded access. You can run the gateway in a highly available mode using the Kubernetes deployment guide.

Open source

Save the open-source gateway for agent data access

Hoop is MIT-licensed infrastructure for controlling how AI agents reach production data. Star hoophq/hoop so you can inspect it, deploy it, or share it when your team starts governing agent access.

Star and save the repo →More posts