1. Conduid
  2. Documentation
  3. Prest
MCP server · Documentation

Prest

Instant REST and MCP APIs for PostgreSQL and MySQL, on existing or new databases. CRUD, custom SQL routes, auth and ACL without writing a backend. Low-code, ⚡ realtime, high-performance. Native MySQL support since v2.5.

64Good

Scored 5 hours ago · breakdown

About Prest

Prest is an MCP server published by prest in the Documentation category: instant REST and MCP APIs for PostgreSQL and MySQL, on existing or new databases. CRUD, custom SQL routes, auth and ACL without writing a backend. Low-code, ⚡ realtime, high-performance. Native MySQL support since v2.5.

The repository has 4.6K stars and 325 forks, with the last commit 2 days ago. Recent commit activity is the strongest signal that reported issues will get attention.

Install

From source
git clone https://github.com/prest/prest

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Ask AI

✦

Ask AI about Prest

Powered by Claude · Grounded in docs

I know everything about Prest. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

Static checks derived from the repository 4 hours ago. Heuristics on the source, not an audit.

  • ✓README presentThe repository ships documentation.
  • ✓License declaredUsable under a stated license.
  • ✓Tests presentA test suite exists in the repository.
  • ✓Dependencies pinnedA lockfile pins dependency versions.
  • ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.

1 check has not been run yet.

Releases

v2.5.1v2.5.1 · 8 Oct 2026Changelog f6f5cd4fa777c6e2f138e9adb125218aba14c06c: Fix/mysql v2.5.0 bugs (#1056) (@arxdsilva)
v2.5.0v2.5.0 · 7 Oct 2026Highlights: native MySQL 8.0.19+ adapter. Set `engine = "mysql"` or use a `mysql://` URL. REST CRUD, filtering, `/_QUERIES` scripts and the same TOML ACL work on MySQL. See MySQL docs for known…
v2.4.2v2.4.2 · 11 Aug 2026Changelog d25fdd5d633f111fb06e01796a9f451d5f311bc5: build(deps): bump github.com/lestrrat-go/jwx/v3 from 3.1.1 to 3.2.0 (#1015) (@dependabot[bot]) c354461a9d6ab208cbf7489889e21130c1d42b79: build(deps): bump google.golang.org/grpc from…
v2.4.1v2.4.1 · 29 Jul 2026Changelog 3cf83bccc3364cd3b316c712745572d37377a117: feat: implement expose configuration for MCP endpoint and listing predicates (#1016) (@arxdsilva)
v2.4.0v2.4.0 · 27 Jul 2026Changelog 084348fa82701b098492fc520557ff290b7691e2: Fix: six SQL-injection-adjacent security gaps found via advisory review (#1014) (@arxdsilva) e8dca3b7d1a1bd771507703ed8032de239c716cf: chore: upgrade deps for pREST Studio (#1004)…

README

pRESTd

Unit tests Go Reference Go Report Card codecov Homebrew Discord

pREST (PostgreSQL REST) is a production-ready API that delivers instant REST and Model Context Protocol (MCP) APIs on your existing or new SQL database — CRUD, custom SQL routes, auth, ACL, and a read-only MCP endpoint — without hand-writing a backend.

PostgreSQL 9.5+ is the default engine. MySQL 8.0.19+ is a separate native dialect from v2.5.0. Read-only MCP on MySQL is v2.5.1. Set engine = "mysql" to select it. An unset engine stays PostgreSQL. MariaDB, TiDB, and Aurora MySQL stay on the roadmap.

PostgreSQL 9.5+ (default). MySQL 8.0.19+ with engine = "mysql".

Contributor License Agreement — CLA assistant

Documentation

Full documentation lives at docs.prestd.com.

Topic Link
Get pREST (Docker, Homebrew, Go) Get pREST
Configuration Configuring pREST
API reference API Reference
MCP over HTTP MCP over HTTP
Multi-database Multi-database
Databases & roadmap Databases · Roadmap
MySQL 8 MySQL · v2.5.1
AI clients (Cursor, Claude, …) AI and MCP

Quick start

Install and run options (Docker, Homebrew, or Go) are documented in Get pREST. Point pREST at Postgres (PREST_PG_URL or pg.* / DATABASE_URL), then call:

GET /{database}/{schema}/{table}

MySQL 8.0.19+ uses the same path. {schema} is the MySQL database. Set the engine and a mysql:// URL. The port defaults to 3306 when unset. PREST_DB_* is read first, then the legacy PREST_PG_* names:

engine = "mysql"

[pg]
url = "mysql://user:pass@localhost:3306/mydb"
export PREST_ENGINE=mysql
export PREST_DB_URL='mysql://user:pass@localhost:3306/mydb'

A missing user or database fails startup. Postgres defaults (user postgres, database prest, port 5432) are not copied onto a MySQL engine. Guide: MySQL.

See Configuring pREST for auth, ACL, custom queries, and MCP.

Serving several databases

pREST can serve multiple databases in two modes:

Registry mode

Define a [[databases]] registry in prest.toml or use environment variables (DATABASE_ALIAS_<n> / DATABASE_URL_<n>). Aliases may differ from database names, and entries can be on the same host or different hosts:

[[databases]]
alias = "main"
url = "postgres://user:pass@localhost:5432/prest_main?sslmode=disable"

[[databases]]
alias = "tenant-1"
url = "postgres://user:pass@localhost:5432/tenant_1?sslmode=disable"

[[databases]]
alias = "reporting"
url = "mysql://user:pass@127.0.0.1:3306/reports?tls=false"

Or via environment:

DATABASE_ALIAS_1=main
DATABASE_URL_1="postgres://user:pass@localhost:5432/prest_main?sslmode=disable"
DATABASE_ALIAS_2=tenant-1
DATABASE_URL_2="postgres://user:pass@localhost:5432/tenant_1?sslmode=disable"

An entry that is unreachable at start-up is logged and answers 503 ("database unavailable") until it comes up; start-up fails only when every entry is unreachable or the configuration is invalid.

No-registry mode

Use pg.database plus pg.allowed_databases on the [pg] host with the [pg] credentials. Both Postgres and MySQL are supported. On MySQL, {schema} must equal {database}:

[pg]
database = "prest"
allowed_databases = ["secondary-db"]

Or via environment (comma-separated for allowed databases):

PREST_PG_DATABASE=prest
PREST_PG_ALLOWED_DATABASES=secondary-db,another-db
# or for MySQL:
PREST_DB_DATABASE=mydb
PREST_DB_ALLOWED_DATABASES=other-db

Catalog and MCP

The /databases endpoint and MCP prest.list_databases show only the served databases. In registry mode, that is the configured aliases. Without a registry, that is pg.database plus pg.allowed_databases.

Postgres supports up to 64 open pools. MySQL creates one pool per served database.

Migrating from pg.single

The pg.single configuration key has been removed and is ignored with a warning. Behavior changes:

  • Allow-listed names are always served. Previously, pg.single = true (the default) required requests to be for the main pg.database; allow-listed names were ignored. Now they are served whether the deprecated key is set or not.
  • A registry is no longer limited to pg.database. Previously, with both a registry and pg.single = true, every request was restricted to the main database. Now a registry serves its configured aliases freely.
  • /databases and MCP list only served databases. Requests for unlisted databases return 400 "database not registered".
  • On MySQL without a registry, /{database}/{other-schema}/… returns 404. On MySQL a schema is a database, so {schema} must equal {database}. Previously any database the MySQL user had grants on was reachable through pg.database.

Passing values to query scripts

Values a _QUERIES script template interpolates become part of the SQL text, so pREST screens them: anything carrying quotes, --, ::, or — for multi-word values — a SQL keyword is refused, and a refused value that is interpolated fails the request with 400.

Bind free-form values instead, and the screen does not apply at all. On PostgreSQL, a bound value travels to the database out of band, where it can never be parsed as SQL:

-- interpolated: screened, and rejected for values like 'compra do mes'
SELECT * FROM articles WHERE slug = '{{.slug}}'

-- bound: the caller's value arrives verbatim, whatever it contains
SELECT * FROM articles WHERE slug = {{sqlVal "slug"}}
Helper Use for Renders
{{sqlVal "key"}} a single value $1
{{sqlList "key"}} a repeated query parameter (?tag=a&tag=b) ($1,$2)
{{ident "key"}} a table/column name, which cannot be bound "public"."users"

That table is the PostgreSQL rendering. On MySQL, {{sqlVal "key"}} renders ?, {{sqlList "key"}} renders (?,?), and {{ident "key"}} renders backtick names such as `shop`.`users`. With the default prepare = false, MySQL interpolates those ? placeholders into the statement. prepare = true uses binary prepared statements, and then the values travel out of band.

sqlVal and sqlList also reach headers as {{sqlVal "header.X-Application"}}. Credential headers (Authorization, Cookie, …) are always withheld.

Prefer binding for anything user-supplied — search phrases especially, since a phrase containing a common word such as do, as or or is exactly what the interpolation screen refuses.

1-Click Deploy

Heroku

Deploy to Heroku and get a realtime RESTful API backed by Heroku Postgres:

Deploy to Heroku

More: Deploy in Heroku.

Contributing

Contributions are welcome. See the Development Guide and Contributing to pREST. Please sign the CLA.

Questions? GitHub Discussions or Discord.

Testing

Run unit tests locally:

make test-unit

Run integration suites inside Docker (no local database required):

# Postgres (full stack: default, auth, multicluster, queries) — also: make test-integration
make test-integration-postgres

# TimescaleDB (Timescale-specific E2E only)
make test-integration-timescaledb

# MySQL 8 (./integration/mysql/... only). Default image mysql:8.4.
# Override: MYSQL_IMAGE=mysql:8.0 make test-integration-mysql
make test-integration-mysql

Or with Docker Compose:

docker compose -f integration/postgres/docker-compose.yml up -d --wait \
  postgres postgres-b db-init prestd prestd-multicluster prestd-auth prestd-queries
docker compose -f integration/postgres/docker-compose.yml run --rm --no-deps tests
docker compose -f integration/postgres/docker-compose.yml down -v --remove-orphans

Postgres compose runs ./integration/suites/... and ./integration/postgres/.... TimescaleDB compose runs ./integration/timescaledb/... only (see .github/workflows/test-integration-timescaledb.yml). MySQL compose runs ./integration/mysql/... only (see .github/workflows/test-integration-mysql.yml). CI runs mysql:8.0, mysql:8.4, and mysql:latest. Network tests require PREST_TEST_URL (and flavor-specific URLs for the Postgres job); outside Compose those tests skip when the URLs are unset.

Example: Docker Build

Build the Docker image locally for development (compiles from source):

docker build -t prest/prest:latest .

For release builds, GoReleaser uses the same Dockerfile / Dockerfile.noplugins with a pre-built prestd binary. Local source builds can pass version metadata via build arguments:

docker build \
  --build-arg VERSION=v1.0.0 \
  --build-arg COMMIT=hash \
  --build-arg DATE=2026-02-11 \
  -t prest/prest:latest .

README fetched from the repository 4 hours ago. The original is authoritative.

Questions

About Prest

How do I install Prest?

No package has been published for this server, so install it from source: clone the repository and follow its README.

Is Prest safe to use with an AI agent?

Its trust score is 64 out of 100 (good). It passes 5 of the 5 static security checks run so far. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Prest still maintained?

Yes — the latest release is v2.5.1 (8 Oct 2026), and the last commit was 2 days ago. The repository has 4.6K stars and 149 open issues.