Sign inSign up

olkowa/design-pattern-mcp

By olkowa

•Updated 9 days ago

An MCP server that provides design-pattern selection expertise to AI coding agents.

Image
Machine learning & AI
0

180

olkowa/design-pattern-mcp repository overview

⁠Design-Pattern MCP server

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.

⁠What is this?

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:

  • Analyzes the problem into decision parts and recommends pattern categories
  • Retrieves matching patterns via fused dense (TEI) + BM25 retrieval with cross-encoder reranking
  • Generates a concrete design with primary + supporting patterns, participants, interactions, implementation steps, and language-bound code sketches
  • Evaluates the design against quality attributes (testability, extensibility, maintainability, simplicity, performance, reliability, security, scalability)

⁠Key Features

  • 438 Built-in Patterns: Observer, circuit-breaker, process-manager, retry, builder, saga participants, and more — each with generic + 13 language bindings (C, C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Rust, Scala, Swift, TypeScript; 4,924 per-language variants)
  • Full Design Pipeline: Analyze → Weights ∥ Retrieval → Generate → Evaluate → Bounded refine (DESIGN_PATTERN_LOOP_MAX_TRIES attempts)
  • Quality Attribute Scoring: Eight design-level axes plus an overall 0–100 score with early-stop threshold (default 50)
  • Dual Transport Support: Stdio for local agents, StreamableHTTP for remote deployments
  • Extensible: Pattern records are joined JSON files under 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)         │                     │
│    └───────────────────┴────────────────────┘                     │
└───────────────────────────────────────────────────────────────────┘

⁠Architecture

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).

⁠Tools at a Glance

ToolDescription
select_design_patternsFull pipeline (analyze → weights ∥ retrieval → generate → evaluate → refine). 2–10 min
analyze_designRequirements analysis only: decision-part decomposition, category recommendations (~1 min)
generate_designGenerate a design from explicitly named patterns (~1 min)
evaluate_designScore an existing design JSON against the eight quality axes (~30 s)
submit_design_jobStart background job, get job_id immediately — for clients with short timeouts
get_design_statusPoll job status; returns full DesignResult when completed
cancel_designCancel a running job (best-effort, takes effect at next stage boundary)
list_design_patternsList all 438 patterns; filter by category and/or language
get_design_patternGet 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"

⁠Prompts (Slash Commands)

PromptArgsWhat it does
/select_design_patterns_workflowdescription*, language, architecture_style, paradigm, focusGuided end-to-end selection workflow
/explore_pattern_catalogcategoryLive catalog discovery
/evaluate_my_designdescription*Compare the catalog's selection against an existing design
/compare_pattern_candidatesdecision*, 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.

⁠Prerequisites

  • A clone of the repo — compose files and config template ship with it (test -f docker/docker-compose.yml)
  • Docker with compose plugin ≥ v2.20 (docker compose version), Docker group membership, ~8 GB free (MCP ≈ 1 GB with baked dense cache, TEI ≈ 6 GB)
  • A generator LLM API key — defaults to MiniMax (MINIMAXAI_API_KEY); any LiteLLM-compatible provider works (OpenAI, Anthropic, DeepSeek, Ollama, vLLM, OpenRouter, …)
  • Images are linux/amd64 only; on arm64 build locally with make docker-build-all
  • GHCR mirrors exist but are not anonymously pullable — use Docker Hub

⁠Long-running Tools & Timeouts

select_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.

⁠The Timeout Problem

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.

ClientTimeoutNotes
Claude Desktop (TS-SDK)60 sHardcoded; does not reset on progress
Cursor (TS-SDK)60 sSame as Claude Desktop
Claude Code~300 sHeartbeat every 30 s resets idle timer
OpenCode~300 sHeartbeat every 30 s resets idle timer
Codex CLI~300 sHeartbeat every 30 s resets idle timer
⁠Solutions
  1. 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.

  2. 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).

  3. Direct HTTP client — make client bypasses MCP SDK entirely with no idle timeout.

⁠Quick start

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 stackPath B — systemd stack
Use whenevaluating / developing; no sudopersistent host service, starts at boot
Host port80628062
TEI sidecarsown copies in the compose projectshared pattern-tei-infra stack
Survives rebootnoyes
# 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, sudo required) 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-infra stack, you can alternatively drop the two sidecar services and point DESIGN_PATTERN_EMBEDDER_BASE_URL / DESIGN_PATTERN_RERANKER_BASE_URL at the existing sidecars instead (or start with --profile offline for deterministic lexical-only retrieval with no sidecars).

⁠Bringing your own LLM

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
OpenAIDESIGN_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-...
AnthropicDESIGN_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
DeepSeekDESIGN_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-compatibleDESIGN_PATTERN_GENERATOR_BASE_URL=http://host:11434/v1 · DESIGN_PATTERN_GENERATOR_MODEL=... · DESIGN_PATTERN_GENERATOR_API_KEY=...
⁠Generator LLM (LlamaIndex LiteLLM)

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 list, model names, and the exact <provider>/<model> syntax: LiteLLM Providers documentation⁠
  • Custom/OpenAI-compatible endpoints (proxies, vLLM, Ollama, …): set DESIGN_PATTERN_GENERATOR_BASE_URL — it is passed as the LiteLLM api_base
  • DESIGN_PATTERN_GENERATOR_API_KEY is passed as the LiteLLM api_key; temperature, top_p, top_k, and timeout_seconds map to the corresponding LiteLLM parameters

⁠TEI sidecar configuration

The 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:

VariableDefaultDescription
DESIGN_PATTERN_EMBEDDER_BASE_URLhttp://design-pattern-tei-embed:8080TEI embedder URL (dev compose uses the /v1 OpenAI-compatible route)
DESIGN_PATTERN_RERANKER_BASE_URLhttp://design-pattern-tei-rerank:8080TEI 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⁠

⁠Connect your agent

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).

⁠OpenCode

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_KEY is read from the server's config file / environment, not from opencode's environment.

⁠VS Code (MCP extension)

Add to .vscode/mcp.json:

{
  "servers": {
    "design-patterns": {
      "url": "http://localhost:8062/mcp",
      "type": "http"
    }
  }
}
⁠Claude Code / Codex CLI

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⁠

⁠Try it

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.

⁠Operations

# 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

⁠Troubleshooting

SymptomFix
GET /health returns 404Expected — FastMCP streamable-http exposes no GET /health. Probe POST /mcp (Quick start A5).
401 Unauthorized from LLMCheck the API key in docker/.env; verify the key is active and the DESIGN_PATTERN_GENERATOR_* provider block matches it
TEI connection errors / unhealthy sidecarsTEI 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-embedCache-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 useMCP_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

Tag summary

Content type

Image

Digest

sha256:bfc885ee4…

Size

285.1 MB

Last updated

9 days ago

docker pull olkowa/design-pattern-mcp