An MCP server that provides design-pattern selection expertise to AI coding agents.
180
An MCP server that provides design-pattern selection expertise to AI coding agents. Analyzes a free-text system description, retrieves from 438 built-in patterns (each with 13 language bindings), generates a concrete design with participants/interactions/implementation steps, and evaluates it against eight quality axes.
This Docker image contains a complete MCP (Model Context Protocol) server that brings design-pattern expertise to your AI coding agents. Given a description string plus optional language / paradigm / focus hints, it:
DESIGN_PATTERN_LOOP_MAX_TRIES attempts)pattern/; alias-aware loader with startup enum-drift guard┌───────────────────────────────────────────────────────────────────┐
│ OpenCode / Claude Code / VS Code / any MCP client │
│ ────────── HTTP ──────────► :8062/mcp (Path A or B) │
│ │
│ ┌──────────────────────────────┐ │
│ │ design-pattern-mcp │ │
│ └───────────────┬──────────────┘ │
│ │ │
│ ┌───────────────────┼────────────────────┐ │
│ │ design-pattern- │ design-pattern- │ ← pattern-tei-infra │
│ │ tei-embed :8080 │ tei-rerank :8080 │ (Path B shares it)│
│ │ (TEI) │ (TEI) │ │
│ └───────────────────┴────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
This image is the MCP server only. The TEI embedder (Qwen3-Embedding-0.6B) and TEI reranker (gte-reranker-modernbert-base) are
separate infrastructure (see pattern-tei-infra project)
published as
Olkowa/pattern-tei-embed and
Olkowa/pattern-tei-rerank.
They connect via Docker DNS using the hostnames design-pattern-tei-embed and design-pattern-tei-rerank on a shared Docker network. Published server images bake in the dense embedding cache, so first start is fast; a locally built cache-less image embeds the whole catalog at first start (~19 min on CPU).
| Tool | Description |
|---|---|
select_design_patterns | Full pipeline (analyze → weights ∥ retrieval → generate → evaluate → refine). 2–10 min |
analyze_design | Requirements analysis only: decision-part decomposition, category recommendations (~1 min) |
generate_design | Generate a design from explicitly named patterns (~1 min) |
evaluate_design | Score an existing design JSON against the eight quality axes (~30 s) |
submit_design_job | Start background job, get job_id immediately — for clients with short timeouts |
get_design_status | Poll job status; returns full DesignResult when completed |
cancel_design | Cancel a running job (best-effort, takes effect at next stage boundary) |
list_design_patterns | List all 438 patterns; filter by category and/or language |
get_design_pattern | Get full JSON for a specific pattern (alias-aware) |
Example call:
Call select_design_patterns with:
description: "IoT ingestion path: Kafka consumer (10k events/sec) → JSON parse → Redis geo-enrich → InfluxDB + S3 sink. At-least-once, backpressure."
language: "python"
| Prompt | Args | What it does |
|---|---|---|
/select_design_patterns_workflow | description*, language, architecture_style, paradigm, focus | Guided end-to-end selection workflow |
/explore_pattern_catalog | category | Live catalog discovery |
/evaluate_my_design | description* | Compare the catalog's selection against an existing design |
/compare_pattern_candidates | decision*, candidates* | Two or three named patterns side-by-side (one selection run per candidate) |
* = required
Tool-only clients (no native prompts/list) reach the same four workflows via the generated list_prompts / get_prompt tools.
test -f docker/docker-compose.yml)docker compose version), Docker group membership, ~8 GB free (MCP ≈ 1 GB with baked dense cache, TEI ≈ 6 GB)MINIMAXAI_API_KEY); any LiteLLM-compatible provider works (OpenAI, Anthropic, DeepSeek, Ollama, vLLM, OpenRouter, …)make docker-build-allselect_design_patterns runs a multi-stage LLM pipeline that takes minutes per call (2–10 min) — the generator LLM processes fused retrieval candidates plus per-part quality weights and emits a large strictly-structured JSON document; the design loop repeats generate → evaluate up to DESIGN_PATTERN_LOOP_MAX_TRIES times.
MCP clients implement client-side idle timeouts (typically 30–120 s). If no data is received, the client aborts — even though the server is still working correctly.
| Client | Timeout | Notes |
|---|---|---|
| Claude Desktop (TS-SDK) | 60 s | Hardcoded; does not reset on progress |
| Cursor (TS-SDK) | 60 s | Same as Claude Desktop |
| Claude Code | ~300 s | Heartbeat every 30 s resets idle timer |
| OpenCode | ~300 s | Heartbeat every 30 s resets idle timer |
| Codex CLI | ~300 s | Heartbeat every 30 s resets idle timer |
Heartbeat defence (default) — The server emits progress notifications every 30 s (DESIGN_PATTERN_TASKS_HEARTBEAT_INTERVAL_SECONDS), resetting idle timers for most HTTP clients. TS-SDK clients do not reset on progress — use the job trio.
Async job trio — For timeout-constrained clients (Claude Desktop, Cursor), use submit_design_job + get_design_status + cancel_design. Returns a job_id immediately; poll every 10–30 s. Jobs persist in SQLite (DESIGN_PATTERN_JOBS_DB).
Direct HTTP client — make client bypasses MCP SDK entirely with no idle timeout.
Two paths (full runbook: INSTALL.md). Pick exactly one — both default to host port 8062, so they cannot run concurrently on the defaults (set MCP_HOST_PORT in one env file to run both).
| Path A — Compose stack | Path B — systemd stack | |
|---|---|---|
| Use when | evaluating / developing; no sudo | persistent host service, starts at boot |
| Host port | 8062 | 8062 |
| TEI sidecars | own copies in the compose project | shared pattern-tei-infra stack |
| Survives reboot | no | yes |
# 0. Clone (compose files + config template ship with the repo)
git clone https://github.com/olk/design-pattern-mcp.git && cd design-pattern-mcp
# A1. Resolve versions and pull. TEI pins differ from the MCP version
# (TEI images release rarely and are shared with architecture-pattern-mcp);
# TEI is currently 1.1.1
VERSION=$(grep -m 1 '^version' pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')
TEI_VERSION=1.1.1
docker pull "olkowa/design-pattern-mcp:${VERSION}"
docker pull "olkowa/pattern-tei-embed:${TEI_VERSION}"
docker pull "Olkowa/pattern-tei-rerank:${TEI_VERSION}"
# A2. Write the env file next to the compose file
cat > docker/.env <<EOF
MCP_IMAGE=Olkowa/design-pattern-mcp:${VERSION}
TEI_IMAGE=Olkowa/pattern-tei-embed:${TEI_VERSION}
TEI_RERANK_IMAGE=Olkowa/pattern-tei-rerank:${TEI_VERSION}
MINIMAXAI_API_KEY=sk-REPLACE-ME
MCP_HOST_PORT=8062
EOF
# A3. Start. TEI sidecars cold-start model weights; first start takes ~2 min.
# (Published server images bake in the dense embedding cache; a locally
# built cache-less image instead embeds the whole catalog at first start,
# ~19 min on CPU.)
docker compose --env-file docker/.env -f docker/docker-compose.yml up -d
# A4. Wait until all three report "healthy" (poll if still "starting").
docker inspect -f '{{.Name}} {{.State.Health.Status}}' \
design-pattern-tei-embed-dev design-pattern-tei-rerank-dev design-pattern-mcp-dev
# A5. Probe the MCP endpoint — must print 200.
# (GET /health is 404 by design; the JSON-RPC initialize POST is the probe.
# The MCP image has no curl binary; probe from the host.)
curl -s -o /dev/null -w '%{http_code}\n' -X POST "http://localhost:8062/mcp" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"probe","version":"0.0.0"}},"id":1}'
The server starts on streamable-http at http://localhost:8062/mcp. Config is the repo file config/config.json (mounted at /app/config); restart the server container after editing.
Path B (systemd,
:8062, shared TEI infra,sudorequired) and uninstall steps: see INSTALL.md Path B.
Standalone stack: Path A starts its own TEI sidecar copies. If you already run the shared
pattern-tei-infrastack, you can alternatively drop the two sidecar services and pointDESIGN_PATTERN_EMBEDDER_BASE_URL/DESIGN_PATTERN_RERANKER_BASE_URLat the existing sidecars instead (or start with--profile offlinefor deterministic lexical-only retrieval with no sidecars).
The default stack uses MiniMax (DESIGN_PATTERN_GENERATOR_PROVIDER=minimax, DESIGN_PATTERN_GENERATOR_MODEL=minimax/MiniMax-M2.7, key from MINIMAXAI_API_KEY, falling back from DESIGN_PATTERN_GENERATOR_API_KEY). To use another LiteLLM provider, edit the four DESIGN_PATTERN_GENERATOR_* lines in the compose file and put your key in the env file, then restart:
- DESIGN_PATTERN_GENERATOR_PROVIDER=openai
- DESIGN_PATTERN_GENERATOR_MODEL=openai/gpt-4o-mini # LiteLLM syntax: provider/model
- DESIGN_PATTERN_GENERATOR_BASE_URL=https://api.openai.com/v1
- DESIGN_PATTERN_GENERATOR_API_KEY=${OPENAI_API_KEY}
| Provider | .env / compose additions |
|---|---|
| OpenAI | DESIGN_PATTERN_GENERATOR_PROVIDER=openai · DESIGN_PATTERN_GENERATOR_MODEL=openai/gpt-4o-mini · DESIGN_PATTERN_GENERATOR_BASE_URL=https://api.openai.com/v1 · DESIGN_PATTERN_GENERATOR_API_KEY=sk-... |
| Anthropic | DESIGN_PATTERN_GENERATOR_PROVIDER=anthropic · DESIGN_PATTERN_GENERATOR_MODEL=anthropic/claude-sonnet-4-5 · DESIGN_PATTERN_GENERATOR_API_KEY=sk-ant-... |
| MiniMax (default) | DESIGN_PATTERN_GENERATOR_PROVIDER=minimax · DESIGN_PATTERN_GENERATOR_MODEL=minimax/MiniMax-M2.7 · DESIGN_PATTERN_GENERATOR_BASE_URL=https://api.minimax.io/v1 · key via MINIMAXAI_API_KEY |
| DeepSeek | DESIGN_PATTERN_GENERATOR_PROVIDER=deepseek · DESIGN_PATTERN_GENERATOR_MODEL=deepseek-chat · DESIGN_PATTERN_GENERATOR_BASE_URL=https://api.deepseek.com/v1 · DESIGN_PATTERN_GENERATOR_API_KEY=sk-... |
| Ollama / vLLM / OpenRouter / any OpenAI-compatible | DESIGN_PATTERN_GENERATOR_BASE_URL=http://host:11434/v1 · DESIGN_PATTERN_GENERATOR_MODEL=... · DESIGN_PATTERN_GENERATOR_API_KEY=... |
The generator LLM is accessed through the LlamaIndex LiteLLM integration (llama-index-llms-litellm). All provider settings therefore follow LiteLLM's model syntax: <provider>/<model> (e.g. openai/gpt-4o-mini, anthropic/claude-sonnet-4-5, openrouter/minimax/minimax-m2); the provider prefix lives in the model string (LiteLLM convention) while DESIGN_PATTERN_GENERATOR_PROVIDER labels error messages.
<provider>/<model> syntax: LiteLLM Providers documentationDESIGN_PATTERN_GENERATOR_BASE_URL — it is passed as the LiteLLM api_baseDESIGN_PATTERN_GENERATOR_API_KEY is passed as the LiteLLM api_key; temperature, top_p, top_k, and timeout_seconds map to the corresponding LiteLLM parametersThe MCP server reaches the sidecars by Docker DNS (design-pattern-tei-embed, design-pattern-tei-rerank) — these match the defaults, so no URL overrides are required in the standard stacks:
| Variable | Default | Description |
|---|---|---|
DESIGN_PATTERN_EMBEDDER_BASE_URL | http://design-pattern-tei-embed:8080 | TEI embedder URL (dev compose uses the /v1 OpenAI-compatible route) |
DESIGN_PATTERN_RERANKER_BASE_URL | http://design-pattern-tei-rerank:8080 | TEI reranker URL (POST /rerank directly, no /v1) |
The embedder must be TEI serving the same model — the embedder config has no model field, so openai / ollama / vllm providers cannot address an arbitrary remote model without a code change. The reranker is not a LiteLLM client. Keep DESIGN_PATTERN_RETRIEVAL_MAX_CONCURRENT_PARTS=1 (shipped default) — one full-text rerank request already saturates the CPU sidecar's token buffer (HTTP 429 otherwise).
Full env var reference: GitHub README → Configuration
Point at Path A (:8062) or Path B (:8062) depending on which stack you installed (both default to 8062 — set MCP_HOST_PORT in one env file to run both).
Add to ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"design-patterns": {
"type": "remote",
"url": "http://localhost:8062/mcp"
}
}
}
Note:
DESIGN_PATTERN_GENERATOR_API_KEYis read from the server's config file / environment, not from opencode's environment.
Add to .vscode/mcp.json:
{
"servers": {
"design-patterns": {
"url": "http://localhost:8062/mcp",
"type": "http"
}
}
}
Stdio transport — this section is for Claude Code / Codex CLI subprocess mode. It requires a local
git clone(one-time setup). If you want HTTP transport (recommended for Docker Hub users), use the Quick start above instead.
# Install (one-time)
git clone https://github.com/olk/design-pattern-mcp.git && cd design-pattern-mcp
make install
# Add to your agent
claude mcp add design-patterns \
-e DESIGN_PATTERN_GENERATOR_PROVIDER=minimax \
-e DESIGN_PATTERN_GENERATOR_MODEL=minimax/MiniMax-M2.7 \
-e DESIGN_PATTERN_GENERATOR_BASE_URL=https://api.minimax.io/v1 \
-e DESIGN_PATTERN_GENERATOR_API_KEY=sk-... \
-- design-pattern-mcp --transport stdio
Stdio mode needs the TEI endpoints reachable (defaults http://design-pattern-tei-embed:8080 and the reranker URL from config/config.json) — either run the compose stack's sidecars or set DESIGN_PATTERN_EMBEDDER_BASE_URL / DESIGN_PATTERN_RERANKER_BASE_URL to your own. For a no-network smoke run, start with --offline (deterministic lexical-only retrieval instead of TEI).
Full client docs: GitHub README → Connect Your Agent
Ask your agent (or use the Inspector):
Build the cache-miss path of a geolocation enricher: look up keys in Redis, fall back to an external geo API on miss, protect the fallback with a circuit breaker and retry. Python.
This should call select_design_patterns with:
description: "cache-aside enrichment with Redis fallback, circuit-breaker + retry on the miss path"language: "python"Expect a circuit-breaker + retry design with participants, implementation_steps, and a Python code_sketch bound to the catalog variant. Sibling workflow: run the architecture-pattern-mcp server first for the system shape (pipe-and-filter ETL: Kafka source → parser filter → enricher → InfluxDB/S3 sinks), then bring each component's internals here.
# Update images (re-resolve VERSION first, then pull + restart)
docker compose --env-file docker/.env -f docker/docker-compose.yml pull
docker compose --env-file docker/.env -f docker/docker-compose.yml up -d
# View logs
docker compose --env-file docker/.env -f docker/docker-compose.yml logs -f design-pattern-mcp
# Stop (keep the env file — it holds the API key)
docker compose --env-file docker/.env -f docker/docker-compose.yml down
# Change host port (then update your client URL)
MCP_HOST_PORT=8063 docker compose --env-file docker/.env -f docker/docker-compose.yml up -d
On Linux with a shared host, restrict your env file:
chmod 600 docker/.env
| Symptom | Fix |
|---|---|
GET /health returns 404 | Expected — FastMCP streamable-http exposes no GET /health. Probe POST /mcp (Quick start A5). |
401 Unauthorized from LLM | Check the API key in docker/.env; verify the key is active and the DESIGN_PATTERN_GENERATOR_* provider block matches it |
| TEI connection errors / unhealthy sidecars | TEI cold-starts model weights (~2 min, start_period: 120s) — recheck health after ~2 min; verify sidecar containers are running and design-pattern-tei-embed resolves on the compose network |
| MCP unhealthy for many minutes; logs show dense-cache re-embed | Cache-less image embeds the whole catalog at first start (~19 min on CPU) — wait, or rebuild with make docker-build-all (bakes the cache) |
| Reranker HTTP 429 "Model is overloaded" | One full-text rerank request saturates the CPU sidecar's token buffer — keep DESIGN_PATTERN_RETRIEVAL_MAX_CONCURRENT_PARTS=1 (shipped default) |
| Port already in use | MCP_HOST_PORT=8063 ... up -d, then update your client URL (both paths default to 8062) |
Image pull fails for ${VERSION}/${TEI_VERSION} | Tag not published; list tags at https://hub.docker.com/v2/repositories/Olkowa/design-pattern-mcp/tags and use latest |
:8060 / :8062): Olk/architecture-pattern-mcpContent type
Image
Digest
sha256:bfc885ee4…
Size
285.1 MB
Last updated
9 days ago
docker pull olkowa/design-pattern-mcp