Skip to main content
Glama
Louis75011

mcp-relances-postgres

by Louis75011

mcp-relances-postgres

CI License: MIT

Français · English


Français

Un petit serveur MCP en TypeScript qui répond, en lecture seule, à la question : « quelles relances sont dues aujourd'hui ? ». Il interroge une vue Postgres et expose deux outils à Claude (ou à tout client MCP). Une base de démonstration entièrement fictive est fournie.

But

Donner à un assistant l'accès à un besoin précis (les relances à traiter) sans lui ouvrir toute la base : une vue, deux outils, aucune écriture possible.

Outil

Rôle

relances_dues

Liste les relances à faire dont l'échéance est atteinte ou dépassée, de la plus ancienne à la plus récente, avec les jours de retard. Paramètres : date (AAAA-MM-JJ, aujourd'hui par défaut), limite (20 par défaut).

resume_relances

Compte les relances dues par canal (email, telephone, courrier). Paramètre : date.

Installation

Prérequis : Node.js 20 ou plus, un Postgres, psql.

git clone https://github.com/Louis75011/mcp-relances-postgres.git
cd mcp-relances-postgres
npm ci
npm run build

# Base de démonstration (fictive) : crée les tables, la vue et les données
export DATABASE_URL="postgresql://utilisateur:motdepasse@localhost:5432/relances_demo"
npm run seed

Pour une base réelle, créez le rôle de sql/lecteur-lecture-seule.sql : il ne peut lire que la vue v_relances_a_faire. Le serveur ouvre en plus chaque requête dans une transaction READ ONLY toujours annulée.

Variables d'environnement : DATABASE_URL (obligatoire), MAX_ROWS (facultatif, 50 par défaut, 200 au plus).

Tests et contrôles : npm run lint, npm run typecheck, npm test. Les tests tournent sur Postgres en mémoire (PGlite) ; avec DATABASE_URL défini, deux tests d'intégration s'exécutent aussi sur un vrai Postgres.

Exemple d'appel depuis Claude

Déclarer le serveur dans Claude Code :

claude mcp add relances \
  -e DATABASE_URL="postgresql://utilisateur:motdepasse@localhost:5432/relances_demo" \
  -- node /chemin/vers/mcp-relances-postgres/dist/index.js

ou dans la configuration de Claude Desktop (claude_desktop_config.json) :

{
  "mcpServers": {
    "relances": {
      "command": "node",
      "args": ["/chemin/vers/mcp-relances-postgres/dist/index.js"],
      "env": { "DATABASE_URL": "postgresql://utilisateur:motdepasse@localhost:5432/relances_demo" }
    }
  }
}

Puis, dans la conversation : « Quelles relances sont dues aujourd'hui ? » Claude appelle relances_dues ; avec la base de démonstration et la date du 27 octobre 2026, relances_dues avec {"date": "2026-10-27", "limite": 2} renvoie :

{
  "date": "2026-10-27",
  "total": 4,
  "renvoyees": 2,
  "relances": [
    {
      "relance_id": 1,
      "nom": "Camille Exemple",
      "organisation": "Atelier Fictif",
      "email": "camille@example.com",
      "canal": "email",
      "echeance": "2026-10-20",
      "jours_de_retard": 7,
      "note": "Relancer après l'envoi du devis"
    },
    {
      "relance_id": 2,
      "nom": "Dominique Modèle",
      "organisation": "Maison Imaginaire",
      "email": "dominique@example.com",
      "canal": "telephone",
      "echeance": "2026-10-26",
      "jours_de_retard": 1,
      "note": "Proposer un créneau de visio"
    }
  ]
}

Architecture en cinq lignes

  1. src/index.ts démarre le serveur MCP sur stdio (stdout réservé au protocole, journaux sur stderr).

  2. src/server.ts déclare les deux outils, avec validation des entrées par zod et l'annotation readOnlyHint.

  3. src/relances.ts contient les requêtes SQL paramétrées sur la vue v_relances_a_faire, sans aucune écriture.

  4. src/db.ts isole l'accès Postgres derrière une interface minimale ; chaque requête passe dans une transaction READ ONLY annulée.

  5. sql/ fournit le schéma, le seed fictif et le rôle en lecture seule ; les tests Vitest utilisent PGlite, la CI GitHub Actions ajoute un vrai Postgres et gitleaks.

Licence

MIT.


Related MCP server: Zendesk Live MCP

English

A small MCP server in TypeScript that answers, read-only, the question: "which follow-ups are due today?". It queries a Postgres view and exposes two tools to Claude (or any MCP client). A fully fictional demo database is included.

Purpose

Give an assistant access to one precise need (the follow-ups to handle) without opening the whole database: one view, two tools, no write path.

Tool

Role

relances_dues

Lists follow-ups still to do whose due date is reached or past, oldest first, with days overdue. Parameters: date (YYYY-MM-DD, today by default), limite (limit, 20 by default).

resume_relances

Counts due follow-ups per channel (email, telephone, courrier). Parameter: date.

Tool names and data fields are in French, as in the demo schema.

Installation

Requirements: Node.js 20 or later, a Postgres database, psql.

git clone https://github.com/Louis75011/mcp-relances-postgres.git
cd mcp-relances-postgres
npm ci
npm run build

# Demo database (fictional): creates the tables, the view and the data
export DATABASE_URL="postgresql://user:password@localhost:5432/relances_demo"
npm run seed

For a real database, create the role from sql/lecteur-lecture-seule.sql: it can only read the v_relances_a_faire view. On top of that, the server runs every query inside a READ ONLY transaction that is always rolled back.

Environment variables: DATABASE_URL (required), MAX_ROWS (optional, 50 by default, 200 at most).

Checks: npm run lint, npm run typecheck, npm test. Tests run on in-memory Postgres (PGlite); when DATABASE_URL is set, two integration tests also run against a real Postgres.

Example call from Claude

Register the server in Claude Code:

claude mcp add relances \
  -e DATABASE_URL="postgresql://user:password@localhost:5432/relances_demo" \
  -- node /path/to/mcp-relances-postgres/dist/index.js

or in the Claude Desktop configuration (claude_desktop_config.json):

{
  "mcpServers": {
    "relances": {
      "command": "node",
      "args": ["/path/to/mcp-relances-postgres/dist/index.js"],
      "env": { "DATABASE_URL": "postgresql://user:password@localhost:5432/relances_demo" }
    }
  }
}

Then ask: "Which follow-ups are due today?" Claude calls relances_dues; with the demo database and the date 27 October 2026, relances_dues with {"date": "2026-10-27", "limite": 2} returns the same JSON as shown in the French section above (4 due in total, the 2 oldest returned).

Architecture in five lines

  1. src/index.ts starts the MCP server over stdio (stdout is reserved for the protocol, logs go to stderr).

  2. src/server.ts declares the two tools, with zod input validation and the readOnlyHint annotation.

  3. src/relances.ts holds the parameterized SQL queries on the v_relances_a_faire view, with no write statement.

  4. src/db.ts hides Postgres behind a minimal interface; every query runs in a rolled-back READ ONLY transaction.

  5. sql/ provides the schema, the fictional seed and the read-only role; Vitest tests use PGlite, and the GitHub Actions CI adds a real Postgres and gitleaks.

License

MIT.

Available Tools

2 tools
relances_duesRelances duesA
Read-onlyIdempotent

Liste les relances à faire dont l'échéance est atteinte ou dépassée (lecture seule). Triées de la plus ancienne à la plus récente, avec le nombre de jours de retard.

NameRequiredDescriptionDefault
dateNoDate de référence (AAAA-MM-JJ). Par défaut : aujourd'hui.
limiteNoNombre maximal de relances renvoyées.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so the safety profile is covered. The description adds genuine context beyond that: the sort order (oldest to newest) and that results include the number of days overdue, which is not visible anywhere else.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with no filler, front-loading the resource and the overdue filter before the sorting and return detail. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with full schema coverage and no output schema, the description supplies the missing return context (sort order, days-late field). Only the relationship to the sibling tool is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (date, limite) are already fully documented with defaults and bounds. The description adds no syntax or semantic detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Liste) and resource (relances à faire) plus the defining filter (échéance atteinte ou dépassée). Clear on its own, but does not reference the sibling resume_relances, so an agent gets no explicit disambiguation from it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The overdue-only scope implies the usage context, so an agent can infer it should call this to find late follow-ups. However, there is no explicit when-to-use guidance and no mention of resume_relances as the alternative for non-due items.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resume_relancesRésumé des relances duesB
Read-onlyIdempotent

Compte les relances dues par canal (email, telephone, courrier) à une date donnée (lecture seule).

NameRequiredDescriptionDefault
dateNoDate de référence (AAAA-MM-JJ). Par défaut : aujourd'hui.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so 'lecture seule' merely repeats structured data. It does add useful behavior beyond annotations by enumerating the return breakdown (email, telephone, courrier), though with no output schema the actual return shape (object keyed by channel? totals only?) is still unknown.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence, front-loaded with the verb and resource, with no filler. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate for a zero-required-parameter read-only aggregate: purpose, channel breakdown, date and safety are all covered. Missing the disambiguation from 'relances_dues' and any hint of the response structure, which matter for an agent choosing between the two tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single 'date' parameter is fully documented with format and default in the schema. The description only echoes 'à une date donnée' without adding format or default detail, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Compte') and resource ('relances dues') plus the grouping dimension (canal) and reference date, so an agent knows exactly what the tool produces. It never names or contrasts with the sibling 'relances_dues', so the count-vs-list distinction must be inferred.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No statement of when to use this aggregate instead of the sibling 'relances_dues', and no prerequisites or exclusions. The only usage signal is implicit in the verb 'Compte'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedrelances_dues
    • First observedresume_relances

TDQS

A3.6/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct outputs: relances_dues returns a detailed ordered list of overdue reminders, while resume_relances returns aggregated counts by channel. An agent can easily choose the right one based on whether it needs rows or summary counts.

Naming Consistency4/5

Both names are French snake_case and readable, but they follow slightly different patterns: relances_dues is a noun phrase while resume_relances is verb+noun. This is a minor inconsistency rather than a confusing mix of conventions.

Tool Count3/5

Two tools is thin for a server surface, even a narrowly read-only one. The tools are well scoped, but the overall offering feels minimal and borderline underpowered.

Completeness3/5

The surface covers listing overdue reminders and summarizing counts by channel, which fits a read-only reporting purpose. However, there are notable gaps: no retrieval by client/reminder id, no filtering options, and no history or period-based reporting beyond a single date.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides a read-only PostgreSQL SQL surface for LLM agents via MCP, with defense-in-depth security layers for safe database queries.
    369 PyPI
    4
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Read-only MCP server connecting Claude to Vtiger CRM for leads, deals, and overdue follow-ups.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Read-only MCP server for Pipedrive that provides a digest-ready sales queue with overdue follow-ups, due today activities, and deals missing next action.
    4
    28 npm
    MIT