REA
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
MCP server that provides architecture design expertise to AI coding agents
Wähle die KI-App, die du nutzt, und kopiere die Einstellungen.
2/2 Prüfungen bestanden · Läuft auf deinem Computer
Zuerst: Welche KI nutzt du?
Wähle deine App, dann erscheinen die Schritte unten.
Klappt mit Claude, aber erst etwas vorbereiten
Du brauchst einen Schlüssel von Architecture Pattern MCP (auf der Seite des Anbieters erstellen) · Installiere zuerst Docker auf deinem Computer (nur einmal) · Nur in der Claude-App für den Computer (Windows oder Mac), nicht im Web oder auf dem Handy
Nur einmal; gilt für alle Server, die Docker brauchen
Öffne die Seite des Anbieters, registriere dich und erstelle einen API-Schlüssel für den nächsten Schritt. Preise und Gratis-Tarife siehst du auf seiner Seite.
Wie du einen Schlüssel bekommst, steht unten im README des Anbieters
SettingsDeveloperEdit Config
{
"mcpServers": {
"architecture-pattern": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GENERATOR_API_KEY",
"-e",
"GENERATOR_PROVIDER",
"-e",
"GENERATOR_MODEL",
"-e",
"GENERATOR_BASE_URL",
"-e",
"PATTERN_DIRECTORY",
"-e",
"EMBEDDER_PROVIDER",
"-e",
"EMBEDDER_BASE_URL",
"-e",
"EMBEDDER_API_KEY",
"-e",
"RERANKER_BASE_URL",
"docker.io/olkowa/architecture-pattern-mcp:1.1.3",
"--transport",
"stdio"
],
"env": {
"GENERATOR_API_KEY": "your-value",
"GENERATOR_PROVIDER": "your-value",
"GENERATOR_MODEL": "your-value",
"GENERATOR_BASE_URL": "your-value",
"PATTERN_DIRECTORY": "your-value",
"EMBEDDER_PROVIDER": "your-value",
"EMBEDDER_BASE_URL": "your-value",
"EMBEDDER_API_KEY": "your-value",
"RERANKER_BASE_URL": "your-value"
}
}
}
}Füge den Schlüssel nur in das Feld der App ein, nie in einen Chat und schick ihn niemandem
Nutze Architecture Pattern MCP und sag mir, was du für mich tun kannst; zeig mir dann eine Sache✓ Wenn Claude sagt, dass es Architecture Pattern MCP nutzt, oder ein Werkzeug von Architecture Pattern MCP in der Antwort zeigt, bist du verbunden
Menünamen am 11. Nov. 2026 mit der Hilfe von Anthropic abgeglichen · dein Bildschirm kann je nach App-Version leicht abweichen
ChatGPT kann Architecture Pattern MCP noch nicht verbinden
Architecture Pattern MCP läuft auf deinem Computer, aber ChatGPT verbindet nur Server, die im Web laufen
A · Eine App nutzen, die Architecture Pattern MCP verbinden kann
B · Andere in Entwicklertools, die mit ChatGPT funktionieren
Aus den meistgenutzten derselben Kategorie, nur solche, die per Adresse ohne Schlüssel verbinden
Klappt mit Claude Code, aber erst etwas vorbereiten
Du brauchst einen Schlüssel von Architecture Pattern MCP (auf der Seite des Anbieters erstellen) · Installiere zuerst Docker auf deinem Computer (nur einmal)
Nur einmal; gilt für alle Server, die Docker brauchen
Öffne die Seite des Anbieters, registriere dich und erstelle einen API-Schlüssel für den nächsten Schritt. Preise und Gratis-Tarife siehst du auf seiner Seite.
Wie du einen Schlüssel bekommst, steht unten im README des Anbieters
Mac: Command+Leertaste drücken und Terminal tippen · Windows: PowerShell öffnen
claude mcp add --scope user architecture-pattern --env GENERATOR_API_KEY=your-value --env GENERATOR_PROVIDER=your-value --env GENERATOR_MODEL=your-value --env GENERATOR_BASE_URL=your-value --env PATTERN_DIRECTORY=your-value --env EMBEDDER_PROVIDER=your-value --env EMBEDDER_BASE_URL=your-value --env EMBEDDER_API_KEY=your-value --env RERANKER_BASE_URL=your-value -- docker run -i --rm -e GENERATOR_API_KEY -e GENERATOR_PROVIDER -e GENERATOR_MODEL -e GENERATOR_BASE_URL -e PATTERN_DIRECTORY -e EMBEDDER_PROVIDER -e EMBEDDER_BASE_URL -e EMBEDDER_API_KEY -e RERANKER_BASE_URL docker.io/olkowa/architecture-pattern-mcp:1.1.3 --transport stdioErsetze „your-value“ vor dem Enter durch deinen Schlüssel
Füge den Schlüssel nur in das Feld der App ein, nie in einen Chat und schick ihn niemandem
Architecture Pattern MCP sollte in der Liste als verbunden erscheinen
Nutze Architecture Pattern MCP und sag mir, was du für mich tun kannst; zeig mir dann eine Sache✓ Wenn Claude Code sagt, dass es Architecture Pattern MCP nutzt, oder ein Werkzeug von Architecture Pattern MCP in der Antwort zeigt, bist du verbunden
Menünamen am 11. Nov. 2026 mit der Hilfe von Anthropic abgeglichen · dein Bildschirm kann je nach App-Version leicht abweichen
Klappt mit Cursor, aber erst etwas vorbereiten
Du brauchst einen Schlüssel von Architecture Pattern MCP (auf der Seite des Anbieters erstellen) · Installiere zuerst Docker auf deinem Computer (nur einmal)
Nur einmal; gilt für alle Server, die Docker brauchen
Öffne die Seite des Anbieters, registriere dich und erstelle einen API-Schlüssel für den nächsten Schritt. Preise und Gratis-Tarife siehst du auf seiner Seite.
Wie du einen Schlüssel bekommst, steht unten im README des Anbieters
In den Einstellungen von Architecture Pattern MCP ist GENERATOR_API_KEY, GENERATOR_PROVIDER, GENERATOR_MODEL, GENERATOR_BASE_URL, PATTERN_DIRECTORY, EMBEDDER_PROVIDER, EMBEDDER_BASE_URL, EMBEDDER_API_KEY, RERANKER_BASE_URL leer; trag deinen Schlüssel ein und speichere
Füge den Schlüssel nur in das Feld der App ein, nie in einen Chat und schick ihn niemandem
Nutze Architecture Pattern MCP und sag mir, was du für mich tun kannst; zeig mir dann eine Sache✓ Wenn Cursor sagt, dass es Architecture Pattern MCP nutzt, oder ein Werkzeug von Architecture Pattern MCP in der Antwort zeigt, bist du verbunden
Menünamen am 11. Nov. 2026 mit der Hilfe von Cursor abgeglichen · dein Bildschirm kann je nach App-Version leicht abweichen
Klappt mit VS Code, aber erst etwas vorbereiten
Du brauchst einen Schlüssel von Architecture Pattern MCP (auf der Seite des Anbieters erstellen) · Installiere zuerst Docker auf deinem Computer (nur einmal)
Nur einmal; gilt für alle Server, die Docker brauchen
Öffne die Seite des Anbieters, registriere dich und erstelle einen API-Schlüssel für den nächsten Schritt. Preise und Gratis-Tarife siehst du auf seiner Seite.
Wie du einen Schlüssel bekommst, steht unten im README des Anbieters
VS Code fragt nach einer Bestätigung; klicke Install
In den Einstellungen von Architecture Pattern MCP ist GENERATOR_API_KEY, GENERATOR_PROVIDER, GENERATOR_MODEL, GENERATOR_BASE_URL, PATTERN_DIRECTORY, EMBEDDER_PROVIDER, EMBEDDER_BASE_URL, EMBEDDER_API_KEY, RERANKER_BASE_URL leer; trag deinen Schlüssel ein und speichere
Füge den Schlüssel nur in das Feld der App ein, nie in einen Chat und schick ihn niemandem
Nutze Architecture Pattern MCP und sag mir, was du für mich tun kannst; zeig mir dann eine Sache✓ Wenn VS Code sagt, dass es Architecture Pattern MCP nutzt, oder ein Werkzeug von Architecture Pattern MCP in der Antwort zeigt, bist du verbunden
Menünamen am 11. Nov. 2026 mit der Hilfe von VS Code abgeglichen · dein Bildschirm kann je nach App-Version leicht abweichen
Andere Apps mit MCP, etwa Windsurf, Zed oder Gemini CLI, fügen Server unterschiedlich hinzu. Sieh in der App-Liste nach
JSON-Einstellungen stehen unten unter „Für Entwickler“
Claude Code
claude mcp add --scope user architecture-pattern --env GENERATOR_API_KEY=your-value --env GENERATOR_PROVIDER=your-value --env GENERATOR_MODEL=your-value --env GENERATOR_BASE_URL=your-value --env PATTERN_DIRECTORY=your-value --env EMBEDDER_PROVIDER=your-value --env EMBEDDER_BASE_URL=your-value --env EMBEDDER_API_KEY=your-value --env RERANKER_BASE_URL=your-value -- docker run -i --rm -e GENERATOR_API_KEY -e GENERATOR_PROVIDER -e GENERATOR_MODEL -e GENERATOR_BASE_URL -e PATTERN_DIRECTORY -e EMBEDDER_PROVIDER -e EMBEDDER_BASE_URL -e EMBEDDER_API_KEY -e RERANKER_BASE_URL docker.io/olkowa/architecture-pattern-mcp:1.1.3 --transport stdioClaude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"architecture-pattern": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GENERATOR_API_KEY",
"-e",
"GENERATOR_PROVIDER",
"-e",
"GENERATOR_MODEL",
"-e",
"GENERATOR_BASE_URL",
"-e",
"PATTERN_DIRECTORY",
"-e",
"EMBEDDER_PROVIDER",
"-e",
"EMBEDDER_BASE_URL",
"-e",
"EMBEDDER_API_KEY",
"-e",
"RERANKER_BASE_URL",
"docker.io/olkowa/architecture-pattern-mcp:1.1.3",
"--transport",
"stdio"
],
"env": {
"GENERATOR_API_KEY": "your-value",
"GENERATOR_PROVIDER": "your-value",
"GENERATOR_MODEL": "your-value",
"GENERATOR_BASE_URL": "your-value",
"PATTERN_DIRECTORY": "your-value",
"EMBEDDER_PROVIDER": "your-value",
"EMBEDDER_BASE_URL": "your-value",
"EMBEDDER_API_KEY": "your-value",
"RERANKER_BASE_URL": "your-value"
}
}
}
}Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"architecture-pattern": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GENERATOR_API_KEY",
"-e",
"GENERATOR_PROVIDER",
"-e",
"GENERATOR_MODEL",
"-e",
"GENERATOR_BASE_URL",
"-e",
"PATTERN_DIRECTORY",
"-e",
"EMBEDDER_PROVIDER",
"-e",
"EMBEDDER_BASE_URL",
"-e",
"EMBEDDER_API_KEY",
"-e",
"RERANKER_BASE_URL",
"docker.io/olkowa/architecture-pattern-mcp:1.1.3",
"--transport",
"stdio"
],
"env": {
"GENERATOR_API_KEY": "your-value",
"GENERATOR_PROVIDER": "your-value",
"GENERATOR_MODEL": "your-value",
"GENERATOR_BASE_URL": "your-value",
"PATTERN_DIRECTORY": "your-value",
"EMBEDDER_PROVIDER": "your-value",
"EMBEDDER_BASE_URL": "your-value",
"EMBEDDER_API_KEY": "your-value",
"RERANKER_BASE_URL": "your-value"
}
}
}
}VS Code (mcp.json)
{
"servers": {
"architecture-pattern": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GENERATOR_API_KEY",
"-e",
"GENERATOR_PROVIDER",
"-e",
"GENERATOR_MODEL",
"-e",
"GENERATOR_BASE_URL",
"-e",
"PATTERN_DIRECTORY",
"-e",
"EMBEDDER_PROVIDER",
"-e",
"EMBEDDER_BASE_URL",
"-e",
"EMBEDDER_API_KEY",
"-e",
"RERANKER_BASE_URL",
"docker.io/olkowa/architecture-pattern-mcp:1.1.3",
"--transport",
"stdio"
],
"env": {
"GENERATOR_API_KEY": "your-value",
"GENERATOR_PROVIDER": "your-value",
"GENERATOR_MODEL": "your-value",
"GENERATOR_BASE_URL": "your-value",
"PATTERN_DIRECTORY": "your-value",
"EMBEDDER_PROVIDER": "your-value",
"EMBEDDER_BASE_URL": "your-value",
"EMBEDDER_API_KEY": "your-value",
"RERANKER_BASE_URL": "your-value"
}
}
}
}GENERATOR_API_KEY geheim erforderlich envGENERATOR_PROVIDER envGENERATOR_MODEL envGENERATOR_BASE_URL envPATTERN_DIRECTORY envEMBEDDER_PROVIDER envEMBEDDER_BASE_URL erforderlich envEMBEDDER_API_KEY geheim envRERANKER_BASE_URL erforderlich envDiese Einstellungen werden aus dem Registry-Eintrag des Entwicklers erzeugt. Wenn in der README etwas anderes steht, folge der README.
Basierend darauf, wie sich dieser Server verbindet, und auf der eigenen Doku jeder App, geprüft am 10. Nov. 2026.
Laufen auf deinem Computer in
ClaudeGooseLM StudioMsty StudioCherry StudioCursorVS Code + GitHub CopilotVisual StudioWindsurf (Devin Desktop)ZedKiroClineContinueJetBrains AI AssistantClaude CodeCodex CLIGemini CLIOpenCodenodecodeWarpLibreChatRaycast
Läuft auf deinem Computer; die Tool-Liste erscheint nach der Installation in deiner KI-App.
Wir prüfen Informationen, die jeder sehen kann; den Code haben wir nicht gelesen. Checks, die nicht zutreffen, werden nicht mitgezählt. · Geprüft am 12. Nov. 2026
Der Registry-Name wurde mit dem GitHub-Konto olk bestätigt, dem das Repo gehört
Code zuletzt geändert: vor 17 Tagen
Dieses Repo haben wir noch nicht von GitHub gelesen
Dieser Server läuft auf deinem Computer; es gibt keinen Endpunkt im Internet
Läuft auf deinem Computer und nutzt stattdessen lokale Einstellungen
Läuft auf deinem Computer; Tool-Listen können wir nur von Endpunkten im Internet lesen
Fragen, Tipps teilen oder melden, dass etwas nicht geht. Sortiert nach „hilfreich“.
Noch keine Beiträge. Stell die erste Frage oder teile einen Tipp.
Beiträge hier stammen von Nutzern, nicht vom PopNx-Team.
Noch keine Bewertungen
Verglichen mit allen aktiven Servern dieser Kategorie in der Registry. Sterne zählen nur, wenn dem Herausgeber das Repo gehört.
Er hat 2 von 2 zutreffenden Basischecks bestanden. Den Code haben wir nicht gelesen. Bevor du einen Schlüssel oder Token hinzufügst, sieh nach, welche Zugriffe der Server verlangt, und nutze einen Schlüssel, der nur die Berechtigungen hat, die du brauchst.
Das musst du eintragen: GENERATOR_API_KEY, EMBEDDER_BASE_URL, EMBEDDER_API_KEY, RERANKER_BASE_URL
Er läuft auf deinem Computer. Deine KI-App startet ihn bei Bedarf, und die Daten laufen nicht über die Server des Entwicklers (außer der Server ruft selbst einen Onlinedienst auf).
Das GitHub-Repo wurde zuletzt vor 17 Tagen geändert, und die neueste Version (1.1.5) kam vor 33 Tagen in die Registry.
Apps, die MCP unterstützen, etwa Claude Desktop, Claude Code, Cursor und VS Code. Außerdem brauchst du Docker auf deinem Computer.
In derselben Kategorie: REA, GitHub, Serena MCP: the IDE for your agent
Server derselben Kategorie von anderen Entwicklern, sortiert nach Sternen.
So liest du eine Karte:↓ Downloads pro Wochei★ GitHub-SterneiDrei Säulen: Bewertungen · Checks · NutzungiAktualisiert = neueste Version in der Registry veröffentlichti
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.
A powerful toolkit for coding, providing semantic retrieval and editing capabilities.
Unverändert aus dem Repo des Entwicklers übernommen. PopNx MCP hat den Inhalt weder geprüft noch empfiehlt es ihn. HTML, Bilder und Skripte wurden entfernt. Links führen von dieser Website weg.
An MCP (Model Context Protocol) server that provides architecture design expertise to AI coding agents. Given a requirements string and a domain, it analyses the problem, selects matching architecture patterns (from 128 built-in patterns), generates a concrete architecture design with components, relationships, API contracts, data models, and event contracts, and evaluates it against quality attributes (maintainability, scalability, reliability, security, performance).
# 1. Clone
git clone https://github.com/olk/architecture-pattern-mcp.git && cd architecture-pattern-mcp
export GENERATOR_API_KEY=your_key_here
docker compose -f docker/docker-compose.yml up --build
make client-analyze
Server starts on streamable-http at http://localhost:8820/mcp (dev compose host port; systemd uses 8810). Then connect your agent below.
To have an AI coding agent install the Docker stack from prebuilt images (no local build), point it at [INSTALL.md](INSTALL.md) — the non-interactive agent runbook (copy-paste commands, expected outputs, verification probes).
Clone this repo, then follow INSTALL.md Path A (compose stack, port 8820).
My generator API key is: sk-...
Pick one path in INSTALL.md:
:8820): evaluating / developing, no sudo needed. Own TEI sidecar copies.:8810): persistent host service, starts at boot, needs sudo. Uses the shared pattern-tei-infra TEI stack.The agent needs a repo clone, Docker ≥ v2.20 with group membership, ~5 GB free, a MINIMAXAI_API_KEY (or another provider per INSTALL.md#switching-the-generator-llm), and linux/amd64 (on arm64 it builds locally via make docker-build-all). After install, continue with Connect Your Agent below.
# Install (one-time)
uv pip install -e .
claude mcp add architecture-pattern \ -e GENERATOR_API_KEY=your_key \ -e GENERATOR_PROVIDER=openai \ -- architecture-pattern-mcp --transport stdio
Or add to your project for the whole team:
claude mcp add --scope project architecture-pattern \
-e GENERATOR_API_KEY=your_key \ -- architecture-pattern-mcp --transport stdio
OpenCode uses HTTP transport. Start the server first, then configure opencode:
# Terminal 1: start the server
docker compose -f docker/docker-compose.yml up --build
uv run python -m src.main --port 8050
{
"$schema": "https://opencode.ai/config.json", "mcp": { "architecture-pattern": { "type": "remote", "url": "http://localhost:8820/mcp" } } }
Note:
GENERATOR_API_KEYis read from the server's config file (~/.config/architecture-pattern-mcp/config.json), not from opencode's environment.
# Install (one-time)
uv pip install -e .
Add to ~/.codex/config.toml:
[mcp_servers.architecture-pattern]
command = "architecture-pattern-mcp" args = ["--transport", "stdio"]
[mcp_servers.architecture-pattern.env] GENERATOR_API_KEY = "your_key" GENERATOR_PROVIDER = "openai"
Or via CLI:
codex mcp add architecture-pattern \
-e GENERATOR_API_KEY=your_key \ -- architecture-pattern-mcp --transport stdio
The SKILL in skills/architecture-pattern-mcp/ is written for Oh My Pi (OMP), where this server's tools are reached as xd://mcp__architecture_pattern_* devices and every MCP request is bounded by a deadline (OMP_MCP_TIMEOUT_MS → per-server timeout → 30 s). It teaches the agent which entry point fits that deadline, how to read the results, and the full workflow recipes.
skills/architecture-pattern-mcp/
├── SKILL.md # OMP constraints, entry-point decision guide, device quick reference └── references/ ├── tools.md # 11 tool signatures, output schemas, error codes, design-dict shape └── workflows.md # 5 recipes, result interpretation, OMP troubleshooting
Install for OMP — copy the skill directory into the user skills root, or point skills.customDirectories at this repository's skills/ directory in OMP's config:
cp -r skills/architecture-pattern-mcp ~/.omp/agent/skills/
The skill then tells the agent:
design_architecture only after raising the server's timeout (analyze_architecture alone measured 66 s, evaluate_architecture 197 s)requirements, domain, and style as separate structured argumentsfinal_quality_score, attempts > 1, and evaluation.recommendationsread mcp://pattern://… is ambiguous while the sibling agent-pattern server is connected, so the tool route (get_architecture_pattern) is authoritativeThe tool schemas, error codes and design-dict shape in references/ are client-agnostic; only the deadline/device guidance is OMP-specific.
All tools accept requirements (free text) and domain (e.g. data-processing, microservices, e-commerce) as arguments. The examples below show the exact tool call shape so you can use them in any MCP client or API consumer.
In Claude Code (or any MCP client), paste the natural-language instruction:
Build a scalable ETL pipeline for IoT sensor data: ingest 10k events/sec
from Kafka, parse JSON, enrich with geolocation from Redis, write to InfluxDB and S3.
Your agent calls design_architecture internally. The server returns a full architecture design: components (Kafka source, JSON parser filter, geolocation enricher, InfluxDB sink, S3 sink), quality attribute scores (scalability: 9.1, maintainability: 8.2, …), and specific recommendations.
That is the design path: the server's LLM generates the design artifact for you, which is why a call takes minutes. If your agent writes the code itself and only needs the pattern expertise, call analyze_architecture instead — it returns the recommended style, selected patterns with scores, requirement weights, quality metrics and matched domains without generating a design. Two measured facts from the committed benchmark corpus: generate + evaluate are ~92 % of a design call's wall clock (benchmarks/base-noreasoning/), and the two paths agree on the style in all 31 completed records (15 base + 16 no-reasoning; the one remaining base record is a design call that failed with a malformed-JSON validation error and produced no design) — a design call buys the artifact, not a better pattern choice.
Or call tools directly from your agent:
Call analyze_architecture with:
requirements: "Real-time data processing pipeline for 10k events/sec IoT sensor data" domain: "data-processing"
Call generate_architecture with: requirements: "ETL pipeline: Kafka → JSON parse → Redis geo-enrich → InfluxDB + S3" domain: "data-processing" selected_patterns: ["pipe-and-filter"]
Call evaluate_architecture with: architecture: { ... paste a design dict here ... } criteria: "scalability, reliability"
Call list_architecture_patterns() # all 128 patterns Call list_architecture_patterns(category="messaging") # filter by category Call get_architecture_pattern(name="event-driven") # full pattern JSON
submit_architecture_design_job + get_architecture_design_statusONLY for clients with short request timeouts (Cursor, Claude Desktop, TS-SDK). The default is design_architecture with heartbeat defence. submit_architecture_design_job returns a job_id immediately; poll get_architecture_design_status until done:
# Step 1: start the job
Call submit_architecture_design_job with: requirements: "ETL pipeline for IoT: Kafka → JSON → Redis geo-enrich → InfluxDB + S3" domain: "data-processing"
Call get_architecture_design_status with: job_id: " "
In Python (via the MCP HTTP API directly — see examples/architecture_client_async.py):
import asyncio, aiohttp
SERVER = "http://localhost:8820/mcp" POLL_EVERY = 15 # seconds
async def main(): async with aiohttp.ClientSession() as sess:
async with sess.post(SERVER, json={ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "submit_architecture_design_job", "arguments": { "requirements": "ETL pipeline for IoT: Kafka → JSON → Redis → InfluxDB + S3", "domain": "data-processing", } }, "id": 1 }) as resp: job_id = (await resp.json())"result"0["job_id"]
print(f"Job started: {job_id}")
while True: await asyncio.sleep(POLL_EVERY) async with sess.post(SERVER, json={ "jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_architecture_design_status", "arguments": {"job_id": job_id}}, "id": 2 }) as resp: result = (await resp.json())"result"0 print(f" status={result['status']}") if result["status"] in ("completed", "failed", "cancelled"): break
print(result.get("result", result)) # full design when completed
See examples/architecture_client_async.py for the complete runnable example. Run it with:
docker compose -f docker/docker-compose.yml up --build # Terminal