FISTA Solutions does not load Google Analytics until you accept. Rejecting keeps optional analytics off. Read the Cookie Policy.

All field notes

Playbook · 5 minute read

How to Build an MCP Server for Postgres

Building an MCP server for Postgres means exposing task-shaped read tools over allowlisted schemas and views, executing under a read-only role with row-level security and statement timeouts, offering write tools only as explicit, validated, gated operations, and testing with contract, permission, and injection tests before publishing through a gateway and registry.

By FISTA Solutions· AI-Native Engineering Team·
How to Build an MCP Server for Postgres article cover

A database connection is the most powerful tool an agent can be given and the most dangerous. Agents that can query the warehouse or the application database deliver immediate value in analytics, support, and operations, and they expose every row the connection can see to whatever the agent reads. This playbook builds a Postgres MCP server that gives agents safe, permissioned tools instead of raw SQL. It applies how to build an MCP server and the principles in the data agents and text-to-SQL whitepaper.

Step 1: Which tasks and which allowlist?

Start with what agents need: look up a customer, list recent orders, check inventory for a product, fetch a support history, summarize usage for an account. Each task becomes a tool over a specific view or table. Then define the allowlist: the schemas, views, and columns the server may ever touch. Everything else is invisible to the server, not merely unused.

Agent taskToolSource
Customer lookupget_customer_by_id, find_customersagent.customer_v view without restricted columns
Order historylist_orders_for_customeragent.order_v with row limits
Inventoryget_inventory_for_skuagent.inventory_v
Usage summaryget_usage_summaryagent.usage_summary_v, pre-aggregated
Notesadd_customer_noteInsert via prepared statement

Views in a dedicated schema are the cleanest allowlist: they restrict columns, pre-join safely, and can be pre-aggregated so the agent never scans raw fact tables.

Step 2: Create the database roles

Create a dedicated read-only role with SELECT only on the allowlisted views, a statement_timeout set at the role level, and no access to other schemas. If writes are required, create a separate write role with INSERT or UPDATE on the specific tables the write tools need and nothing else. The server authenticates with credentials from a broker, rotated and short-lived where the platform supports it, per secrets management for AI agents.

Step 3: How do you carry user context and apply row-level security?

For user-scoped data, the server sets the requesting user's identity in a session variable at the start of each call and the database applies row-level security policies that filter rows by it. This makes Postgres enforce the boundary regardless of how a tool is called. Where data is not user-scoped, the agent's role still bounds what the server can see through the allowlist. The delegated-context model is described in the agent identity and access control whitepaper.

Step 4: Build the read tools

Each read tool maps to a parameterized query against a view, with:

  • Validated parameters (types, ranges, enumerations).
  • A hard row limit and a default sort.
  • Column selection fixed by the tool, never chosen by the model.
  • Results shaped for the model: compact, with free-text columns labeled as untrusted.

If a constrained query tool is unavoidable, restrict it to the allowlisted views, read-only execution, a validated grammar, row and time limits, and a cost estimate check that rejects expensive plans.

Step 5: Build write tools as explicit operations

Writes are tools with validated parameters mapped to prepared statements, executed under the write role. Classify them: inserting a note is reversible and can flow with sampling; updating a balance, changing a status that triggers downstream processes, or deleting records is consequential, lives in a separate tool, and is gated by human approval at the gateway. Idempotency keys prevent duplicate writes on retries.

Step 6: What cost and safety limits are needed?

ControlImplementation
Statement timeoutSet on the role; short for interactive tools
Row limitsEnforced in every read tool
Cost estimate checkReject plans above a threshold for any query tool
Rate limitsPer agent at the gateway
Step budgetsIn the agent runtime, so a loop cannot hammer the database
Connection poolingBounded pool per server; never one connection per agent step

Step 7: Log and redact

Log every call with agent identity, delegated user, tool, parameters, row count, duration, and a trace identifier. Do not log result contents by default; where debugging requires it, redact by data category and restrict access to those logs. Audit-trail design is covered in how to build an AI audit trail.

Step 8: Test in CI against a copy

  • Contract tests per tool.
  • Permission tests: the read role cannot see non-allowlisted schemas; row-level security filters correctly for different users.
  • Limit tests: row limits and timeouts trigger as designed.
  • Injection tests: a note field containing instructions does not lead to a consequential write without approval; parameters cannot escape prepared statements.
  • End-state tests for writes.

Use a seeded copy or a fixture database; never test against production. Keep the fixture in version control next to the server so schema changes and test data evolve together, and run the suite on every change to the server, the views, or the roles.

Step 9: Publish and operate

Register the server with its owner, tools, classifications, and permitted agents; route through the gateway; monitor query time per tool, error rate, and connection pool health; and assign an on-call owner in the data or application team. Review the allowlist whenever the schema changes, and treat schema migrations as events that require re-running the test suite.

What are the common mistakes?

  1. The application's superuser connection string in the server.
  2. Raw SQL over production tables.
  3. No row limits, so a broad query returns a million rows into a prompt.
  4. Sensitive columns reachable because the tool selects *.
  5. Writes as free-form statements.
  6. Result contents logged without redaction.

How does FISTA Solutions help?

FISTA Solutions is an official Anthropic partner and builds database MCP servers and the data agents that use them as part of its AI agents and AI enablement practices, with forward deployed engineers working with your data and security teams on allowlists, roles, and row-level security. FISTA has delivered 150+ projects for 50+ companies across 12+ countries.

To build a Postgres server with us, message FISTA on WhatsApp, or read how to build a text-to-SQL agent for the agent side.

Share-ready article cover

Download the generated social format.

Download cover

Clear answers

Questions raised by this field note.

Straightforward guidance for evaluating scope, fit, and the next step.

01Should an MCP server let agents run arbitrary SQL?

Not on production data. Arbitrary SQL cannot be permissioned, is easy to make expensive, and exposes every column the connection can see. Expose task-shaped tools and, if a query tool is needed, constrain it to allowlisted views, read-only execution, row and time limits, and a validated grammar, with results redacted by data category.

02How do you enforce user permissions on database access?

Execute under a dedicated database role with the minimum privileges, set the requesting user's identity as a session variable, and use row-level security policies that filter rows by that identity. Combine with column-level restriction through views so sensitive fields never reach the agent regardless of how a tool is called.

03How do you stop an agent from running expensive queries?

Set statement timeouts on the role, enforce row limits in every read tool, reject queries whose estimated cost exceeds a threshold, prefer indexed access paths in tool design, and rate-limit tool calls per agent at the gateway. Monitor query time per tool and alert on regressions.

04Can the server support writes?

Yes, as explicit tools with validated parameters mapped to prepared statements, never as free-form statements. Reversible writes such as inserting a note can flow with sampling; consequential writes such as updating balances or deleting records are separate tools gated by human approval and executed under a separate, narrowly scoped role.

Start with the hard problem

Need the outcome owned, not merely analyzed?

Tell us where delivery is constrained. We’ll map the fastest credible path from intent to verified production.

Start a project