mcp-postgresdb-readonly
Provides read-only access to PostgreSQL databases, allowing querying (SELECT only), listing tables, describing table schemas, listing schemas, and listing configured environments. Supports multiple environments (staging, test, prod) with configurable protection limits.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-postgresdb-readonly show me the users table schema"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-postgresdb-readonly
Serveur MCP pour accès PostgreSQL en lecture seule. Expose des outils d'exploration et de requêtage à tout client compatible MCP (Claude Code, Cursor, OpenCode, etc.).
Les opérations d'écriture sont bloquées au niveau applicatif, indépendamment des droits de l'utilisateur de la base de données.
Deux modes de fonctionnement :
stdio : utilisé localement, l'agent IA lance le process directement.
HTTP : hébergé sur un serveur, les agents s'y connectent via une URL.
Supporte jusqu'à trois environnements : staging, test, prod. Seuls ceux avec un HOST configuré sont chargés.
Outils MCP
Outil | Description |
| Exécute une requête SELECT (écritures rejetées) |
| Liste les tables d'un schéma (ou de tous les schémas si aucun schéma par défaut n'est configuré) |
| Affiche colonnes, types, nullabilité, valeurs par défaut (tous les schémas si aucun par défaut) |
| Liste tous les schémas définis par l'utilisateur |
| Liste les environnements configurés (sans credentials) |
Related MCP server: Postgres MCP Server
Mode stdio (usage local)
Dans ce mode, chaque développeur installe le serveur sur sa propre machine. Le client IA (Claude Code, Cursor…) démarre automatiquement le serveur au moment où il en a besoin, et s'y connecte directement — pas de réseau, pas d'URL, pas de token.
Chaque développeur a ses propres credentials DB dans son .env local.
Prérequis : Node.js 18+ installé sur la machine.
1. Installer et builder
npm install
npm run build2. Configurer
cp .env.dist .envRenseigner dans .env au minimum un environnement :
POSTGRES_PROD_HOST=your-cluster.rds.amazonaws.com
POSTGRES_PROD_DATABASE=mydb
POSTGRES_PROD_USER=reader
POSTGRES_PROD_PASSWORD=secret.env est git-ignoré et ne doit jamais être commité.
3. Déclarer le serveur dans le client IA
Le client IA a besoin du chemin absolu vers le fichier compilé. Récupérer ce chemin :
pwd
# exemple : /Users/alice/dev/mcp-postgresdb-readonly
# le fichier à déclarer : /Users/alice/dev/mcp-postgresdb-readonly/dist/index.jsClaude Code : ~/.claude/settings.json :
{
"mcpServers": {
"postgresdb-readonly": {
"command": "node",
"args": ["/chemin/absolu/vers/mcp-postgresdb-readonly/dist/index.js"]
}
}
}Cursor : .cursor/mcp.json (projet) ou ~/.cursor/mcp.json (global) :
{
"mcpServers": {
"postgresdb-readonly": {
"command": "node",
"args": ["/chemin/absolu/vers/mcp-postgresdb-readonly/dist/index.js"]
}
}
}Une fois configuré, redémarrer le client IA. Le serveur démarre automatiquement en arrière-plan à chaque session.
Mode HTTP (serveur hébergé)
Le serveur tourne sur une machine distante et expose un endpoint HTTPS. Les agents locaux s'y connectent via URL + Bearer token. Personne n'a besoin d'installer Node ou les credentials DB en local.
Architecture
Agents locaux (Claude, Cursor, OpenCode)
│ HTTPS + Bearer token
▼
nginx (SSL termination)
│ HTTP loopback
▼
Docker container ←─── accès DB (prod/staging/test)
(node dist/index.js, PORT=3000)1. Prérequis serveur
Un nom de domaine pointant vers le serveur (ex:
mcp.example.com)Docker + Docker Compose
Nginx
Certbot (Let's Encrypt)
make(optionnel, pour les commandes de gestion)
Installation sur Ubuntu/Debian :
# Docker
curl -fsSL https://get.docker.com | sh
# Nginx + Certbot
apt install -y nginx certbot python3-certbot-nginx make
# Démarrer et activer nginx
systemctl start nginx && systemctl enable nginx2. Cloner le repo sur le serveur
git clone <repo-url> /opt/mcp-postgresdb-readonly
cd /opt/mcp-postgresdb-readonly3. Configurer .env
cp .env.dist .envRenseigner les credentials de base de données et impérativement générer un token d'auth :
# Générer un token sécurisé
openssl rand -hex 32Exemple de .env :
# Token d'auth (obligatoire en mode HTTP)
MCP_AUTH_TOKEN=votre-token-généré-ici
# Connexion prod
POSTGRES_PROD_HOST=your-cluster.rds.amazonaws.com
POSTGRES_PROD_PORT=5432
POSTGRES_PROD_DATABASE=mydb
POSTGRES_PROD_USER=reader
POSTGRES_PROD_PASSWORD=secret
# POSTGRES_PROD_SCHEMA=myschema # optional: restrict to a single schema; omit to access all schemas
POSTGRES_PROD_SSL=true
# Protections (optionnel, valeurs par défaut)
RATE_LIMIT_PER_MINUTE=60
QUERY_TIMEOUT_MS=30000
MAX_ROWS=1000
PORTne doit pas être dans.envpour le mode Docker, il est imposé à3000pardocker-compose.yml.
4. Lancer le container
docker compose up -d --buildVérifier que le container est en bonne santé :
docker compose ps
docker compose logs -f
curl http://localhost:3000/healthLa réponse attendue :
{"status":"ok","version":"2.0.0","environments":["prod"],"transport":"streamable-http"}5. Obtenir un certificat SSL
La config nginx fournie référence les certificats Let's Encrypt. Il faut les obtenir avant d'activer cette config.
Laisser nginx tourner avec sa config par défaut (port 80), puis :
certbot certonly --nginx -d votre-domaine.comcertonly récupère uniquement le certificat sans modifier nginx.
6. Configurer nginx
Les certs existent maintenant, nginx -t passera :
DOMAIN=votre-domaine.com make nginx-setupOu manuellement :
cp .docker/nginx.conf /etc/nginx/sites-available/mcp-postgresdb
sed -i 's/mcp.example.com/votre-domaine.com/g' /etc/nginx/sites-available/mcp-postgresdb
ln -sf /etc/nginx/sites-available/mcp-postgresdb /etc/nginx/sites-enabled/mcp-postgresdb
nginx -t && systemctl reload nginx7. Tester le endpoint
Vérifier que le token est bien exigé :
curl -s -o /dev/null -w "%{http_code}" -X POST https://votre-domaine.com/mcp
# doit retourner 401Lister les outils disponibles (valide le token + la connexion MCP) :
curl -s -X POST https://votre-domaine.com/mcp \
-H "Authorization: Bearer votre-token-généré-ici" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'8. Mettre à jour
make deployOu manuellement :
git pull
docker compose up -d --buildConfigurer les agents en mode HTTP
Une fois le serveur en ligne, partager le token aux PMs et développeurs. Chacun ajoute la config suivante dans son agent.
Claude Code
~/.claude/settings.json :
{
"mcpServers": {
"postgresdb-readonly": {
"type": "http",
"url": "https://votre-domaine.com/mcp",
"headers": {
"Authorization": "Bearer votre-token"
}
}
}
}Cursor
.cursor/mcp.json (projet) ou ~/.cursor/mcp.json (global) :
{
"mcpServers": {
"postgresdb-readonly": {
"url": "https://votre-domaine.com/mcp",
"headers": {
"Authorization": "Bearer votre-token"
}
}
}
}OpenCode
~/.config/opencode/config.json :
{
"mcp": {
"postgresdb-readonly": {
"type": "remote",
"url": "https://votre-domaine.com/mcp",
"headers": {
"Authorization": "Bearer votre-token"
}
}
}
}Makefile
Le Makefile regroupe les commandes courantes pour la gestion du serveur.
Commande | Description |
|
|
| Redémarre le container sans rebuild |
| Arrête le container |
| Affiche les logs en temps réel |
| État du container |
| Vérifie que le serveur répond sur |
| Génère un nouveau Bearer token |
| Installe et active la config nginx |
| Obtient un certificat SSL via Certbot |
Troubleshooting
Le container ne démarre pas
make logs
# ou
docker compose logsPort 3000 déjà utilisé
ss -tlnp | grep 3000La config nginx est invalide
nginx -tRenouvellement SSL
Certbot configure un timer systemd automatique. Pour forcer le renouvellement :
certbot renew --dry-runVérifier que le container est en bonne santé
make ps
make healthVariables d'environnement
Connexions base de données
Chaque environnement utilise le préfixe POSTGRES_{ENV}_ où {ENV} vaut STAGING, TEST ou PROD.
Si POSTGRES_{ENV}_HOST est absent, l'environnement est ignoré.
Variable | Obligatoire | Défaut | Description |
| oui | - | Hostname PostgreSQL |
| non |
| Port TCP |
| oui | - | Nom de la base |
| oui | - | Utilisateur |
| oui | - | Mot de passe |
| non | aucun (tous les schémas) | Restreint |
| non |
|
|
Serveur HTTP
Variable | Obligatoire | Défaut | Description |
| non | - | Si défini, démarre en mode HTTP sur ce port. Absent = mode stdio. |
| recommandé | - | Bearer token requis dans l'en-tête |
Protections
Variable | Défaut | Description |
|
| Nombre max de requêtes par minute (fenêtre glissante globale) |
|
| Timeout PostgreSQL côté serveur (ms). La requête est annulée si dépassé. |
|
| Si aucun |
Protections
Trois mécanismes protègent la base contre les requêtes abusives (boucles IA, hallucinations) :
Rate limiter : fenêtre glissante d'une minute. Au-delà de
RATE_LIMIT_PER_MINUTE, les requêtes sont rejetées.Statement timeout : durée max d'exécution côté PostgreSQL. La requête est annulée automatiquement si dépassée.
Auto LIMIT : si aucun
LIMITn'est présent,LIMIT {MAX_ROWS}est injecté. Évite les scans complets accidentels.Blocage écriture : les mots-clés
INSERT,UPDATE,DELETE,DROP,TRUNCATE,ALTER,CREATE,REPLACE,GRANT,REVOKE,MERGE,UPSERT,VACUUM,REINDEX,COPY,DO,CALLsont rejetés avant que la requête n'atteigne la base. Les commentaires SQL en tête de requête (--,/* */) sont strippés avant détection.EXPLAIN ANALYZE <write>est également bloqué (PostgreSQL exécute réellement la requête avecANALYZE).
Logs
Chaque requête est loggée sur stderr :
[HH:MM:SS] ENV outil | clé=valeur | ...Exemples :
[11:52:26] PROD query | duration=257ms | rows=3 | sql=SELECT id, mail FROM users.user LIMIT 3
[11:52:26] STAGING list-tables | schema=all | duration=300ms | tables=212
[11:52:26] STAGING list-tables | schema=public | duration=300ms | tables=94
[11:52:26] TEST describe-table | schema=all | table=orders | duration=247ms | columns=32
[11:52:26] PROD query | duration=12ms | rows=1000 | limit=auto:1000 | sql=SELECT * FROM public.orders
[11:52:26] STAGING query | status=BLOCKED (write) | sql=INSERT INTO ...
[11:52:26] PROD query | status=RATE LIMITED | limit=60/minPROD s'affiche en rouge, STAGING en jaune, TEST en cyan (si stderr est un TTY).
Sécurité
Utiliser un utilisateur PostgreSQL dédié en lecture seule. Ne jamais utiliser
ownerou un superutilisateur.En mode HTTP, toujours configurer
MCP_AUTH_TOKEN. Générer un token paropenssl rand -hex 32..envest dans.gitignoreet ne doit jamais être commité.En production, nginx est le seul point d'entrée public. Le container écoute uniquement sur
127.0.0.1:3000.
Available Tools
5 toolsdescribe-tableB
Get the structure of a table (columns, types, nullability, defaults)
Inputs: env (required), table (required), schema.
list-environmentsB
List all configured database environments
Inputs: no named parameters.
list-schemasB
List all user-defined schemas in the database
Inputs: env (required).
list-tablesC
List all tables in a schema
Inputs: env (required), schema.
queryA
Execute a read-only SQL query on a PostgreSQL database.
⛔ WRITE OPERATIONS ARE STRICTLY FORBIDDEN (INSERT, UPDATE, DELETE, DROP, etc.)
Always use schema-qualified table names (e.g., schema.table_name)
Only SELECT queries are accepted
Use parameterized queries for user-provided values
Inputs: env (required), sql (required), params.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 5 tools
Each tool has a clearly distinct target: query executes SQL, list-tables and list-schemas enumerate metadata, describe-table inspects a single table's structure, and list-environments reports configured connections. There is no meaningful overlap between any pair.
Four tools follow a clean verb_noun kebab-case pattern (list-tables, describe-table, list-schemas, list-environments) with uniform casing. The lone exception is 'query', a bare verb with no object, which is a minor deviation from the established pattern.
Five tools is well-scoped for a read-only database accessor: one execution tool plus four discovery/introspection tools. Nothing feels redundant or missing at the count level.
The surface covers the natural discovery-to-query workflow (schemas → tables → structure → SQL), and omitting writes is intentional for a read-only server. Minor gaps exist, such as listing views/indexes or an EXPLAIN tool, but core workflows are fully supported.
Maintenance
Related MCP Connectors
Managed Postgres MCP: projects, SQL, docs search, and storage buckets via OAuth.
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables secure querying of PostgreSQL databases through MCP-compatible clients. Supports read-only SQL execution, table exploration, and connection management with built-in security validation.345 npm9MIT
- FlicenseNot gradedqualityDmaintenanceEnables interaction with PostgreSQL databases through MCP, allowing users to explore database structures, inspect table schemas, and execute read-only SQL queries.-
- AlicenseNot gradedqualityDmaintenanceEnables inspecting database schemas and executing read-only SQL queries on a PostgreSQL database via MCP tools.7 npmMIT
- AlicenseNot gradedqualityDmaintenanceProvides read-only access to PostgreSQL databases via MCP, enforcing least-privilege roles, row-level security, masked views, and SQL AST guardrails to prevent data leakage and unauthorized operations, enabling AI agents to safely query sensitive production data.MIT