MCP server that provides architecture design expertise to AI coding agents
1.8K
An MCP server that provides architecture design expertise to AI coding agents. Analyzes requirements, selects from 40 built-in patterns, generates concrete architecture designs with components/API contracts, and evaluates against quality attributes.
This Docker image contains a complete MCP (Model Context Protocol) server that brings architecture design expertise to your AI coding agents. Given a requirements string and a domain, it:
┌───────────────────────────────────────────────────────────────────┐
│ OpenCode / Claude Code / VS Code / any MCP client │
│ ────────── HTTP ──────────► :8060/mcp (Path A) │
│ or :8050/mcp (Path B) │
│ │
│ ┌──────────────────────────────┐ │
│ │ architecture-pattern-mcp │ │
│ └───────────────┬──────────────┘ │
│ │ │
│ ┌───────────────────┼────────────────────┐ │
│ │ pattern-tei-embed │ pattern-tei-rerank │ ← pattern-tei-infra │
│ │ :8080 (TEI) │ :8080 (TEI) │ (Path B shares it)│
│ └───────────────────┴────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
This image is the MCP server only. The TEI embedder (Qwen3-Embedding-0.6B) and TEI reranker 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 pattern-tei-embed and pattern-tei-rerank on a shared Docker network.
| Tool | Description |
|---|---|
analyze_architecture | Analyse requirements → recommended style, patterns, quality metrics |
generate_architecture | Generate architecture from requirements + selected patterns |
evaluate_architecture | Score an existing design against quality attributes |
design_architecture | Full pipeline (analyse → generate → evaluate → refine, up to 3 attempts). 5–10 min |
submit_architecture_design_job | Start background job, get job_id immediately — for clients with short timeouts |
get_architecture_design_status | Poll job status; returns full design when completed |
cancel_architecture_design | Cancel a running job (best-effort) |
list_architecture_patterns | List all 40 patterns; filter by category and/or domain |
get_architecture_pattern | Get full JSON for a specific pattern |
Example call:
Call design_architecture with:
requirements: "ETL pipeline for IoT: Kafka → JSON → Redis geo-enrich → InfluxDB + S3"
domain: "data-processing"
| Prompt | Args | What it does |
|---|---|---|
/design_architecture_workflow | requirements* | Full analyze → generate → evaluate pipeline |
/explore_pattern_catalog | domain, category | Live catalog discovery |
/evaluate_my_architecture | focus | Guide evaluation criteria + prioritisation |
/compare_architecture_styles | style_a*, style_b*, requirements* | Two designs side-by-side (~2× token cost) |
* = required
test -f docker/docker-compose.yml)docker compose version), Docker group membership, ~5 GB free (MCP ≈ 0.3 GB, TEI ≈ 2–4 GB)MINIMAXAI_API_KEY); any LiteLLM-compatible provider works (OpenAI, Anthropic, DeepSeek, Ollama, vLLM, OpenRouter, …)make docker-build-alldesign_architecture runs multi-stage LLM pipelines that can take 5–10 minutes — the generator LLM processes large input payloads across 9+ round trips.
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 (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_architecture_design_job + get_architecture_design_status + cancel_architecture_design. Returns a job_id immediately; poll every 10–30 s. Jobs persist in SQLite (ARCHITECTURE_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 can run concurrently (distinct container names and ports).
| Path A — Compose stack | Path B — systemd stack | |
|---|---|---|
| Use when | evaluating / developing; no sudo | persistent host service, starts at boot |
| Host port | 8060 | 8050 |
| 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/architecture-pattern-mcp.git && cd architecture-pattern-mcp
# A1. Resolve versions and pull. TEI pins differ from the MCP version
# (TEI images release rarely); TEI is currently 1.9.4
VERSION=$(grep -m 1 '^version' pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')
TEI_VERSION=1.9.4
docker pull "olkowa/architecture-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/architecture-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=8060
EOF
# A3. Start. TEI sidecars cold-start model weights; first start takes ~2 min.
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}}' \
pattern-tei-embed-dev pattern-tei-rerank-dev architecture-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:8060/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:8060/mcp. Config is the repo file config/config.json (mounted at /app/config); restart the server container after editing.
Path B (systemd,
:8050, shared TEI infra,sudorequired) and uninstall steps: see INSTALL.md Path B.
Standalone stack: Path A starts its own TEI sidecar copies. Do not run it alongside the shared
pattern-tei-infrastack with colliding container names — the dev compose uses distinct-devcontainer names so both can coexist. If you already run the shared stack, you can alternatively drop the two sidecar services and pointEMBEDDER_BASE_URL/RERANKER_BASE_URLat the existing sidecars instead.
The default stack uses MiniMax (GENERATOR_PROVIDER=minimax, GENERATOR_MODEL=minimax/MiniMax-M2.7, key from MINIMAXAI_API_KEY). To use another LiteLLM provider, edit the four GENERATOR_* lines in the compose file and put your key in the env file, then restart:
- GENERATOR_PROVIDER=openai
- GENERATOR_MODEL=openai/gpt-4o-mini # LiteLLM syntax: provider/model
- GENERATOR_BASE_URL=https://api.openai.com/v1
- GENERATOR_API_KEY=${OPENAI_API_KEY}
| Provider | .env / compose additions |
|---|---|
| OpenAI | GENERATOR_PROVIDER=openai · GENERATOR_MODEL=openai/gpt-4o-mini · GENERATOR_BASE_URL=https://api.openai.com/v1 · GENERATOR_API_KEY=sk-... |
| Anthropic | GENERATOR_PROVIDER=anthropic · GENERATOR_MODEL=anthropic/claude-sonnet-4-5 · GENERATOR_API_KEY=sk-ant-... |
| MiniMax (default) | GENERATOR_PROVIDER=minimax · GENERATOR_MODEL=minimax/MiniMax-M2.7 · GENERATOR_BASE_URL=https://api.minimax.io/v1 · key via MINIMAXAI_API_KEY |
| DeepSeek | GENERATOR_PROVIDER=deepseek · GENERATOR_MODEL=deepseek-chat · GENERATOR_BASE_URL=https://api.deepseek.com/v1 · GENERATOR_API_KEY=sk-... |
| Ollama / vLLM / OpenRouter / any OpenAI-compatible | GENERATOR_BASE_URL=http://host:11434/v1 · GENERATOR_MODEL=... · 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 server composes the LiteLLM model string from your configuration as generator.provider + generator.config.model:
| Config / env | Example | Resulting LiteLLM model string |
|---|---|---|
provider: "openai", model: "gpt-4o-mini" | GENERATOR_PROVIDER=openai, GENERATOR_MODEL=gpt-4o-mini | openai/gpt-4o-mini |
provider: "anthropic", model: "claude-sonnet-4-5" | GENERATOR_PROVIDER=anthropic, GENERATOR_MODEL=claude-sonnet-4-5 | anthropic/claude-sonnet-4-5 |
provider: "openrouter", model: "minimax/minimax-m2" | GENERATOR_PROVIDER=openrouter, GENERATOR_MODEL=minimax/minimax-m2 | openrouter/minimax/minimax-m2 |
If the configured model already contains a provider prefix (e.g. openai/gpt-4o-mini), that prefix is stripped and replaced by the configured provider.
<provider>/<model> syntax: LiteLLM Providers documentationGENERATOR_BASE_URL (generator.config.base_url) — it is passed as the LiteLLM api_baseGENERATOR_API_KEY is passed as the LiteLLM api_key; temperature, top_p, top_k, and stream map to the corresponding LiteLLM parametersThe MCP server reaches the sidecars by Docker DNS (pattern-tei-embed, pattern-tei-rerank) — these match the defaults, so no URL overrides are required in the standard stacks:
| Variable | Default | Description |
|---|---|---|
EMBEDDER_BASE_URL | http://pattern-tei-embed:8080 | TEI embedder URL (dev compose uses the /v1 OpenAI-compatible route) |
RERANKER_BASE_URL | http://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.
Full env var reference: GitHub README → Configuration
Point at Path A (:8060) or Path B (:8050) depending on which stack you installed.
Add to ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"architecture-pattern": {
"type": "remote",
"url": "http://localhost:8060/mcp"
}
}
}
Note:
GENERATOR_API_KEYis read from the server's config file / environment, not from opencode's environment.
Add to .vscode/mcp.json:
{
"servers": {
"architecture-pattern": {
"url": "http://localhost:8060/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/architecture-pattern-mcp.git && cd architecture-pattern-mcp
make install
# Add to your agent
claude mcp add architecture-pattern \
-e GENERATOR_API_KEY=sk-... \
-- architecture-pattern-mcp --transport stdio
Full client docs: GitHub README → Connect Your Agent
Ask your agent (or use the Inspector):
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.
This should call design_architecture with:
requirements: "ETL pipeline for IoT sensor data: ingest 10k events/sec from Kafka, parse JSON, enrich with geolocation from Redis, write to InfluxDB and S3"domain: "data-processing"style: "pipe-and-filter"# 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 architecture-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=8061 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 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 pattern-tei-embed resolves on the compose network |
| Port already in use | MCP_HOST_PORT=8061 ... up -d, then update your client URL |
Image pull fails for ${VERSION}/${TEI_VERSION} | Tag not published; list tags at https://hub.docker.com/v2/repositories/olkowa/architecture-pattern-mcp/tags and use latest |
Content type
Image
Digest
sha256:8c52e08f5…
Size
251.6 MB
Last updated
9 days ago
docker pull olkowa/architecture-pattern-mcp