Brok: an MCP that reviews architecture, estimates capacity, and roasts bad design decisions.
Brok demonstrates strong naming conventions (verb-first: review_*, query_*, check_*, ask_*, list_) and comprehensive descriptions (150-400 chars each). All 6 tools have detailed docstrings explaining WHAT, WHEN, and RETURN structure. Input schemas are present with type annotations and descriptions. However, parameter descriptions lack explicit constraints (enums, ranges, formats), and output schemas are documented only in prose, not as formal JSON Schema. Error handling guidance is minimal, no recovery hints or categorization. The assumptions tools (check_assumptions, ask_assumption) have complex nested input structures (inferred dict with value/confidence/evidence) that lack validation examples.
Ask whether one specific property holds for a design, with the reasoning shown. Returns "true", "false", or "unknown" — where unknown genuinely means the facts do not settle it, not that the answer is no. A predicate caught in a contradiction also answers unknown rather than picking a side. Same entity arguments as check_assumptions. Use this when you need one answer and the derivation behind it; use check_assumptions when you want every problem found. Returns: truth, confidence, source (declared / inferred / derived), the citation chain, the step-by-step derivation, and a rendered explanation suitable for showing the user directly.
Call this when a design makes consistency, availability, or delivery claims, to check whether those claims can all be true at once. Catches things like: claiming strong consistency AND staying available during a network partition (CAP theorem); claiming strong consistency on replicas AND low latency (PACELC); claiming exactly-once processing over an at-least-once queue with a non-idempotent handler; claiming fresh reads with a quorum config that cannot deliver them. Pass what you know and nothing else. An undeclared predicate stays UNKNOWN and is never assumed False, so a partial fact set gives a partial answer rather than a wrong one. name — what you are checking, e.g. "orders_db" kind — "datastore", "service", or "channel" declared — {predicate: bool} for facts the user stated outright inferred — {predicate: {"value": bool, "confidence": 0.0-1.0, "evidence": str}} for facts you guessed from code. Confidence propagates: a conclusion is never more certain than its weakest input. n, w, r — replica count and write/read quorum sizes, for quorum arithmetic Call list_assumption_predicates first if you are unsure of the vocabulary; any predicate outside it comes back in "unknown_predicates" rather than being guessed at. Returns: contradiction_count, contradictions (each with the rule, the citation, the conflicting facts, a confidence, and all_declared so you can tell a hard conflict from one resting on a guess), every known fact with its provenance, and unknown_predicates.
Output schemas documented only in prose, not as formal JSON Schema. LLMs cannot parse return structure from docstrings alone, they need explicit schema definitions to plan downstream tool calls and extract fields reliably.
Parameter constraints (enums, ranges, formats) are missing. E.g., 'kind' accepts 'datastore|service|channel' but no enum is declared; 'expected_dau' is unbounded (LLM could pass negative or absurdly large values); 'read_write_ratio' lacks min/max bounds.
Error handling lacks recovery guidance. No tool description explains what to do if parsing fails (e.g., malformed YAML in review_architecture, invalid component types in review_components, or unknown predicates in check_assumptions). Errors should guide the LLM to retry or call a discovery tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
The predicate vocabulary check_assumptions and ask_assumption understand. Call this before the other two if you are unsure what to pass. Returns every predicate with a plain description, the four domains covered (CAP, PACELC, quorum, idempotency), and the numeric attributes used for quorum arithmetic.
Call this BEFORE choosing between technologies or architectural patterns. Works for: datastores, queues, caches, CDNs, load balancers, sharding strategies, cache eviction policies, delivery guarantees, and architectural patterns (CQRS, Saga, Circuit Breaker, Event Sourcing, etc.). Ask in natural language: "kafka vs pubsub for spiky writes" "should I use consistent hashing or range sharding" "when does CQRS make sense" "redis or memcached for session data" "how to avoid hot partitions in Kafka" "is Cassandra good for strong consistency" <- returns: no, here is why Returns matched KB entries with cited trade-offs, a head-to-head comparison when two technologies from the same category match, and a note that Brok surfaces the trade-offs but you decide. Return shape: matches — list of {name, type, category, when_to_pick, when_not_to_pick, key_tradeoff, extra, citation} comparison — head-to-head string when two same-category tech entries match, None otherwise note — "Brok surfaces trade-offs. You decide."
Estimate a system's capacity, find its bottleneck, and surface the trade-offs of its design choices. Use this when designing, scaling, or reviewing a system, or when choosing or changing a datastore, cache, or queue, so you decide with grounded numbers and known trade-offs instead of guessing. How to use this (for the calling assistant): 1. If the project has a docker-compose.yml, read it and pass its full contents as compose_yaml. 2. Ask the user for their expected scale and pass expected_dau (and read_write_ratio if known). Without expected_dau the result assumes 100k users and is reported as low confidence. 3. Prefer report["roast_text"] as the headline to show the user (Brok's voice); use the structured fields and report["tradeoffs"] to reason about the design. Returns a dict: bottleneck, max_dau, confidence, assumptions, utilizations, notes, tradeoffs (the grounded pros, cons, and next move for each component), cost (a rough monthly compute plus egress estimate), report_text, roast_text.
Estimate capacity and surface design trade-offs from a structured component list. Use this when designing or scaling a system and there is no docker-compose: infer the components yourself from the user's description or code and pass them. Pass components as a list of {"name", "type"} dicts. Valid types: relational_db, cache, queue, cdn, app_server, object_store, load_balancer. Any other type is reported as not estimated (Brok will not guess). Pass expected_dau for a high-confidence result. Prefer roast_text as the headline; use the structured fields, tradeoffs, and cost to reason. Returns the same dict shape as review_architecture.
Complex nested input structures (inferred dict with {value, confidence, evidence} shape) lack validation examples or schema documentation. LLMs may struggle to construct the correct nested object shape without explicit examples or JSON Schema definitions.
No pagination or result-limiting guidance. review_architecture and review_components return complex nested dicts (tradeoffs, utilizations, notes) with no documented size bounds. Large responses could exhaust context windows.