Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

free-postgres-mcp-server

MCP spec 2026-07-28 PostgreSQL 16.2 Transport: Streamable HTTP License: MIT

$ psql "postgresql://freebase@HOST:5432/bikeshare"
psql (16.2)
bikeshare=> SELECT version();
 PostgreSQL 16.2 on x86_64-pc-linux-gnu

That transcript is the whole point of this repository.

A freebase.cloud PostgreSQL instance answers on TCP 5432 speaking the PostgreSQL frontend/backend protocol v3. libpq connects. psql connects. Prisma, SQLAlchemy, pgx, ActiveRecord, Knex and DBeaver connect — unmodified, no shim, no proxy driver. The same database is simultaneously exposed to an LLM over MCP at a single HTTPS URL. Neither view is a simulation of the other; they are two front doors onto one Postgres 16.

This repo holds the connection recipes, a reference schema, and runnable examples.


Contents


The two access paths

Native wire protocol MCP
Endpoint postgresql://freebase@HOST:5432/DBNAME https://freebase.cloud/api/mcp/YOUR_TOKEN
Protocol PostgreSQL v3 frontend/backend JSON-RPC 2.0 over Streamable HTTP
Auth connection string credentials token embedded in the URL path
Consumers psql, pgAdmin, ORMs, migration tools Claude, ChatGPT, Cursor, VS Code, agents
Transactions full — BEGIN/SAVEPOINT/COMMIT per-call statements
Typical use migrations, app runtime, dumps exploration, reporting, agent writes

Use the wire protocol for anything your build pipeline does. Use MCP for anything a model does. Migrations belong in the first column; "summarise last week's trips" belongs in the second. Nothing stops you from using both against the same free instance.


Setup

1. Create the instance. Sign up for a free Postgres 16 instance, create a session, pick PostgreSQL. No credit card, no cluster sizing dialog.

2. Mint an MCP token. Settings → MCP → New Token, select the connection, copy the URL. It looks like:

https://freebase.cloud/api/mcp/YOUR_TOKEN

The token lives in the path. There is no Authorization header anywhere in this document — if a client config asks you for one, leave it blank.

3. Name the connection. MCP tool names are prefixed with the connection name you chose, not with the engine. Everything below assumes a connection named bikes. If you called yours app, read bikes_query as app_query.

4. Register with a client. See Client configuration.


Tool surface

Four tools ship with every connection:

Tool Purpose Notes
bikes_query SELECT / read SQL, returns rows full PostgreSQL 16 grammar
bikes_store INSERT / UPDATE / upsert use for agent writes
bikes_list_tables enumerate tables in the database cheap discovery call
bikes_annotate_table attach a prose description to a table improves model accuracy a lot

PostgreSQL connections additionally surface three helpers that do not exist on the other engines:

Helper Purpose
pg_dump logical export of the database as SQL
pg_restore load a previously produced dump
pg_tables Postgres-native catalogue listing, with schema/owner detail

pg_tables and bikes_list_tables overlap. Prefer pg_tables when you care about which schema an object lives in; prefer bikes_list_tables when you just want names.

On annotate_table

Models guess column semantics from names, and they guess badly on abbreviations. One annotation per table removes most of that guesswork:

bikes_annotate_table(
  table: "trips",
  description: "One row per completed rental. duration_s is seconds, not minutes.
                start_station_id/end_station_id join to stations.station_id.
                Rows with end_time IS NULL are rides still in progress."
)

Annotations are stored server-side and are visible to the model on subsequent calls. Do this once per table after your first migration; it is the highest-leverage minute you will spend.


Client configuration

Claude Code

claude mcp add --transport http bikes https://freebase.cloud/api/mcp/YOUR_TOKEN

Add --scope project to write a committable .mcp.json; --scope user registers it for every project on the machine. The generated file:

{ "mcpServers": { "bikes": { "type": "http", "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }

A url entry with no type is a hard error in Claude Code. streamable-http is accepted as an alias for http.

Claude Desktop / Claude web / Cowork — UI only. Settings (⌘, / Ctrl+,) → Connectors (Customize → Connectors in newer builds) → Add custom connector → paste the URL → Add — the Claude connection walkthrough has the same steps with screenshots. Enable it per conversation with the + button in the composer. Available on Free, Pro, Max, Team and Enterprise; the Free tier allows one custom connector. Note that claude_desktop_config.json has no support for remote HTTP servers — the UI is the path, or bridge through mcp-remote.

Cursor~/.cursor/mcp.json or .cursor/mcp.json:

{ "mcpServers": { "bikes": { "url": "https://freebase.cloud/api/mcp/YOUR_TOKEN" } } }

No type key here; the presence of url is what marks the server as remote.

VS Code / GitHub Copilot Chat.vscode/mcp.json, top-level key is servers, and the token can be prompted for rather than committed. See examples/vscode-mcp.json.

Gemini CLI

gemini mcp add --transport http bikes https://freebase.cloud/api/mcp/YOUR_TOKEN

If you hand-edit settings.json instead, the key for Streamable HTTP is httpUrl. A plain url key means SSE there, and SSE is the deprecated transport — this trips people up regularly.

ChatGPT — Settings → AppsAdvanced settings → developer mode → Apps → Create → paste the endpoint → Auth NoneScan ToolsCreate. Developer mode is documented for Pro, Plus, Business, Enterprise and Edu. Full write access is still rolling out to Business, Enterprise and Edu workspaces, so bikes_store may be unavailable on your plan even though bikes_query works.

Stdio-only clients — bridge with mcp-remote. Its own README describes it as experimental; treat it as a fallback, not the default.


Worked example: a bike-share dataset

examples/bikeshare_schema.sql creates three tables — stations, bicycles, trips — with a GiST-free, ordinary B-tree index layout, a JSONB column for station metadata, and a materialised daily rollup. Apply it over the wire:

psql "$FREEBASE_DSN" -f examples/bikeshare_schema.sql

Then ask a model, through MCP:

Which five stations had the worst net dock imbalance last Saturday?

The model reaches for bikes_query and writes something close to:

SELECT s.name,
       count(*) FILTER (WHERE t.end_station_id   = s.station_id) AS arrivals,
       count(*) FILTER (WHERE t.start_station_id = s.station_id) AS departures,
       count(*) FILTER (WHERE t.end_station_id   = s.station_id)
     - count(*) FILTER (WHERE t.start_station_id = s.station_id) AS net
FROM stations s
JOIN trips t ON s.station_id IN (t.start_station_id, t.end_station_id)
WHERE t.start_time >= date_trunc('week', now()) - INTERVAL '2 days'
GROUP BY s.name
ORDER BY abs(net) DESC
LIMIT 5;

FILTER, date_trunc, count(*) OVER () and every other Postgres 16 construct are available because this is real Postgres 16. Nothing in the MCP layer rewrites your SQL.

examples/trips_report.mjs does the same thing as a plain Node.js MCP client — useful when you want to see the raw JSON-RPC frames rather than a chat UI's rendering of them.


Backups: pg_dump over the wire and over MCP

Two routes, same output format:

# Route A — the standard tool, over TCP 5432
pg_dump "$FREEBASE_DSN" --no-owner --no-privileges -f backup.sql

# Route B — the MCP helper, no local Postgres install needed
#   tool: pg_dump   → returns SQL text

examples/dump_restore.sh wraps route A with a schema-only option and a restore path, because "can I get my data out" should be answerable in one command. Route B needs nothing installed locally beyond an MCP token. You own the data either way.


Known limits

  • The free tier targets development, prototyping and small production workloads. It is not positioned as a substitute for a provisioned production cluster, and no SLA, uptime figure, backup retention policy or storage quota is claimed here. Check the dashboard for current quota detail rather than trusting a number in a README.
  • MCP calls are not a transaction boundary. Each bikes_store call stands alone. If you need BEGIN … COMMIT semantics across several statements, do it over the wire protocol, or express it as a single statement with CTEs.
  • Token in the URL means URL = credential. Do not commit it, do not paste it into an issue, and rotate it in Settings → MCP if it leaks. The examples here all read it from FREEBASE_MCP_URL.
  • Free-tier Claude allows one custom connector. If you already have one registered, you will need to swap it.
  • Extensions: common ones — uuid-ossp, pgcrypto, hstore, citext — are enabled with CREATE EXTENSION in the usual way. Anything requiring a compiled module you supply yourself is a different conversation; check before you design around it.

FAQ

Is the MCP layer just wrapping a REST API over a hosted Postgres? It is an MCP server in front of a real Postgres 16.2 backend. The proof is that you can attach psql to the same database and see the rows the model wrote.

Do I need both paths? No. Plenty of people use only the connection string and never mint a token, and plenty of people never open psql. They coexist.

Which Postgres version, exactly? 16.2. Version-gated syntax — MERGE, SQL/JSON constructors, random_normal() — behaves as the 16 documentation says.

Can Prisma or SQLAlchemy talk to it? Yes; they see a standard connection string. Migration tooling (prisma migrate, alembic) works because DDL is unrestricted at the SQL level.

Does EXPLAIN ANALYZE work through MCP? Yes — it is just a statement, and bikes_query returns the plan rows as text. Handy for letting a model diagnose its own slow query.

Can the model drop my tables? It can run what its tool grants allow. Approve writes deliberately, and keep a dump if the data matters. Most clients let you require confirmation per tool call.


See also


freebase.cloud is an independent service and is not affiliated with the PostgreSQL Global Development Group, Anthropic, OpenAI, Google, Microsoft or Cursor.

About

Free PostgreSQL MCP server — connect Claude, ChatGPT, and Cursor to a free cloud Postgres database

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors