API

mcdview.dev from the command line and CI

Everything the site does goes through two HTTP requests: one to create a diagram, one to update it without changing its link. No account, no API key — the management key returned at creation is the only secret.

Create a diagram

One multipart POST; the JSON response carries the public link and the management page:

curl -s -H 'accept: application/json' \
  -F fichier=@schema.sql \
  -F titre="Mon projet" \
  https://mcdview.dev/generate

{"url":     "https://mcdview.dev/v/Lfh_amk…",
 "gestion": "https://mcdview.dev/g/B98Opj…",
 "titre":   "Mon projet",
 "diagnostic": {"status": "ok", "dialect": "postgresql",
                "tables": 12, "fks": 8,
                "anomalies": {"empty_tables": 0,
                              "phantom_columns": 0,
                              "fks_without_target": 0}}}

Keep “gestion” safe (CI secret, vault…): it is the only way to update, rename or delete the page. The “url” link is public and shareable.

Form fields

fieldeffect
fichierrequired — the model: .sql (PostgreSQL, MySQL, SQLite and ~15 dialects, auto-detected), .dbm (pgModeler), .mwb (MySQL Workbench), .dbml (dbdiagram.io), .prisma, .rb (Rails), .mmd/.mermaid/.md (Mermaid erDiagram) or .ts (Drizzle ORM). Several “-F fichier=@…” at once are accepted if they are all .sql (a split schema, cross-file FKs resolved)
titredisplayed title (default: file name)
langdiagram language, fr or en (default: fr)
home_urlthe page logo links to this http(s) URL — e.g. the project repository (default: mcdview.dev)
logoimage replacing the logo (svg/png/jpg/gif/webp/ico, 100 KB max) — e.g. the project icon
fk_audit“auto” (default): obvious audit-trail FKs are detected and hidden; “aucune”: hide nothing. Fine-tunable later on the management page
expireephemeral link: number of days before the page is deleted automatically (1 to 365). Absent or 0 = kept until manually deleted

Update without changing the link

The CI flow: the public link stays stable, every update creates a version (history and rollback on the management page).

curl -s -H 'accept: application/json' \
  -F fichier=@schema.sql \
  https://mcdview.dev/g/<clé de gestion>/update

{"url": "https://mcdview.dev/v/Lfh_amk…", "version": 7, …}

The page’s title, language, logo, home link and audit FKs are kept — no need to send them again. From the 2nd version on, the response adds “diff” (a link to the changes since the previous version) and “changements” (counts of tables added / removed / changed) — enough to notify a migration review.

Update also accepts optional home_url and logo: they only change if supplied. Only the fields in the table above are read; an unknown field is ignored and listed in a warnings array in the response (not an error). To change logo / home_url / language without re-uploading a file: POST /g/<key>/settings. The legacy French paths (/generer, /actualiser, /renommer…) remain as aliases of the English names.

Schema diagnostics (handy in CI)

Every response (create and update) carries a “diagnostic” field, the result of analysing the uploaded schema. “status” is “ok”, “no_table” (no table found: format or dialect not covered), “anomaly” (empty tables, phantom columns, FKs without a target) or “error” (parser failure). It also gives the detected dialect, the number of tables and FKs, and the anomaly breakdown. In a pipeline you can fail the build when “status” is not “ok”:

R=$(curl -s -H 'accept: application/json' -F fichier=@schema.sql \
     https://mcdview.dev/generate)
echo "$R" | jq -e '.diagnostic.status == "ok"' > /dev/null \
  || { echo "schéma douteux : $(echo "$R" | jq -c .diagnostic)"; exit 1; }

Check without creating a version (drift gate)

A POST to “/g//verify” compares the uploaded schema to the stored version WITHOUT creating a new one. The “{drift, changements}” response says whether the database drifted from the committed diagram. In CI, fail the build on drift:

pg_dump --schema-only "$DATABASE_URL" \
  | curl -s -F fichier=@- https://mcdview.dev/g/${MCDVIEW_CLE}/verify \
  | jq -e '.drift == false' > /dev/null \
  || { echo "la base a dérivé du diagramme commité"; exit 1; }

{"drift": false, "changements": {}, "reference": "https://mcdview.dev/v/…"}

README badge

An SVG badge “mcdview | N tables” (green / amber / red depending on the diagnostic), to drop in a README and link to the diagram:

[![mcdview](https://mcdview.dev/badge/<jeton>.svg)](https://mcdview.dev/v/<jeton>)

Other output formats

A few handy endpoints derived from a diagram (public, no key):

GET /q/<jeton>.svg       QR code du lien public (SVG)
GET /f/<jeton>.txt       résumé texte du schéma (tables, FK, dialecte, anomalies)
GET /d/<jeton>/<n>.md     résumé Markdown du diff d'une version (commentaire de PR)
GET /m/<jeton>           bloc Mermaid erDiagram (texte brut)
GET /dico/<jeton>        dictionnaire de données en Markdown (une section par table)
GET /p/<jeton>.png       aperçu du diagramme en image (og:image ; .svg aussi) — vignette Slack/X
GET /compare/<a>/<b>      diff entre deux diagrammes publics — {drift, changements} (prod vs staging)
GET /lint/<jeton>        lint du schéma — {violations, counts} (PK manquante, FK non indexée, nommage…)
GET /t/<jeton>           time-lapse : fait défiler les versions dans le temps

View deep-links

URL parameters on the public link open the diagram in a given state — handy to point at a table from a doc. Read at load time, read-only:

/v/<jeton>?focus=users        ouvre en isolant la table « users »
/v/<jeton>?theme=dark         force le thème sombre
/v/<jeton>?audit=show         révèle les FK d'audit masquées
/v/<jeton>?hubs   |  ?cycles  ouvre direct sur l'analyse des hubs / cycles

GitHub Actions

The simplest way: the official action. Create the diagram once, put the management key in a MCDVIEW_CLE secret, then on every push:

- uses: Gheop/mcdview-action@v1
  with:
    file: db/schema.sql
    key: ${{ secrets.MCDVIEW_CLE }}   # met à jour sous le même lien
    fail-on: ok                        # échoue si le diagnostic n'est pas « ok »

Inputs, outputs and examples: github.com/Gheop/mcdview-action. Or with raw curl, without the action:

name: mcd
on:
  push:
    branches: [main]
    paths: [db/schema.sql]

jobs:
  publier-mcd:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: publier le diagramme sur mcdview.dev
        env:
          MCDVIEW_CLE: ${{ secrets.MCDVIEW_CLE }}
        run: |
          curl -sf -H 'accept: application/json' \
            -F fichier=@db/schema.sql \
            "https://mcdview.dev/g/${MCDVIEW_CLE}/update"

GitLab CI

The simplest way: the CI/CD Catalog component. Same logic as the GitHub action (create or update, fail-on the diagnostic):

include:
  - component: gitlab.com/Gheop/mcdview/mcdview@~latest
    inputs:
      file: db/schema.sql
      key: $MCDVIEW_CLE     # met à jour sous le même lien
      fail-on: ok           # échoue si le diagnostic n'est pas « ok »

Inputs, outputs and examples: gitlab.com/Gheop/mcdview. Or with raw curl, with the project icon and URL as a bonus:

publier-mcd:
  stage: deploy
  rules:
    - changes: [db/schema.sql]
  script:
    - |
      curl -sf -H 'accept: application/json' \
        -F fichier=@db/schema.sql \
        -F logo=@docs/logo.png \
        -F home_url="$CI_PROJECT_URL" \
        "https://mcdview.dev/g/${MCDVIEW_CLE}/update"

Declare MCDVIEW_CLE in Settings → CI/CD → Variables (GitLab) or Settings → Secrets (GitHub).

Zero-key (OIDC)

With oidc: true there is no key to manage: the pipeline proves which project it runs in via a signed identity token (GitLab id_tokens, GitHub id-token). The server verifies it and binds the diagram to the project’s numeric id (stable across renames). First run creates; later runs update the same link.

include:
  - component: gitlab.com/Gheop/mcdview/mcdview@~latest
    inputs:
      file: db/schema.sql
      oidc: true            # zéro clé : lié à CE projet par son identité

Only a pipeline actually running in that project can obtain the token, so nobody else can overwrite your diagram. Nothing to store, nothing to copy:

# équivalent en curl brut (le pipeline demande un id_token, aud = le service)
deploy:
  id_tokens:
    MCDVIEW_IDTOKEN: { aud: https://mcdview.dev }
  script:
    - |
      curl -sfS -H 'accept: application/json' \
        -H "Authorization: Bearer $MCDVIEW_IDTOKEN" \
        -F fichier=@db/schema.sql \
        https://mcdview.dev/upsert          # 1re fois: crée, ensuite: met à jour

# suppression : un job manuel, même identité, aucun secret imprimé
supprimer-mcd:
  when: manual
  id_tokens:
    MCDVIEW_IDTOKEN: { aud: https://mcdview.dev }
  script:
    - curl -sfS -H "Authorization: Bearer $MCDVIEW_IDTOKEN" -X POST https://mcdview.dev/upsert/delete

The response never carries a management link: on a public repo the job log would be readable by anyone. Management (deletion) goes through a manual job authenticated by the same identity. The key model stays available for a portable link you control.

Or manage them in the browser: sign in with GitLab or GitHub at mcdview.dev/my-diagrams to find and manage (open, rename, roll back a version, delete) every diagram linked to your projects, with no key — your maintainer role is what authorizes it.

Diff as a PR comment

On a pull request, post the model’s change summary and links (the “diff” field only appears from the 2nd version on):

- name: mcdview diff en commentaire de PR
  if: github.event_name == 'pull_request'
  env: { MCDVIEW_CLE: "${{ secrets.MCDVIEW_CLE }}", GH_TOKEN: "${{ github.token }}" }
  run: |
    R=$(curl -sf -H 'accept: application/json' -F fichier=@db/schema.sql \
        "https://mcdview.dev/g/${MCDVIEW_CLE}/update")
    DIFF=$(echo "$R" | jq -r '.diff // empty')
    [ -z "$DIFF" ] && exit 0
    T=$(echo "$R" | jq -r '.changements.tables | "+\(.added) ~\(.changed) −\(.removed) tables"')
    gh pr comment "${{ github.event.number }}" \
      --body "📐 Modèle mis à jour : **$T** — [diff]($DIFF) · [diagramme interactif]($(echo "$R" | jq -r .url))"

Same idea on GitLab with a project token and the merge request notes API.

Limits