The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Decisionmatrix MCP listing page.
A transparent, 100% deterministic Model Context Protocol (MCP) server that gives LLM agents a reliable multi-criteria decision analysis (MCDA) engine.
Agents are great at gathering options but unreliable at weighing them: they lose precision, apply inconsistent weights, and can't show their work. DecisionMatrix offloads the scoring to an exact, explainable engine. You provide options and weighted criteria (plus a score matrix); it returns a fully scored, ranked, and explained result — with per-criterion breakdowns, the methodology used, the weights applied, and a plain-language explanation.
Every number flows through decimal.js at
40-digit precision (never floats), so identical inputs always produce
byte-identical output. The server is stateless — no database, no sessions.
A public remote MCP server runs on Cloudflare's edge — point any Streamable-HTTP MCP client at it:
It runs in open mode on the free tier (no key, 15 calls/day per IP). Paid plans
(Starter $12/mo · 5,000/day, Pro $39/mo · 50,000/day) are live via Stripe
Checkout — buy a plan, get an API key instantly, and send it as X-API-Key. Self-host
for unlimited calls with no keys. Landing page + pricing: https://decisionmatrix-mcp.pages.dev.
Six tools, all returning a uniform, agent-parseable envelope:
| Tool | Purpose |
|---|---|
create_decision | Main tool. Rank options against weighted criteria → winner, full ranking, per-criterion breakdowns, methodology, weights, and a plain-language explanation. |
score_options | Return the full normalized scored matrix when scores are supplied separately. |
sensitivity_analysis | Sweep each criterion's weight ±X% and report how robust the winner is (and where it flips). |
compare_two | Head-to-head comparison of exactly two options with per-criterion win counts. |
list_methods | Discovery: available scoring methods and when to use each. |
health_check | Version, status, and capabilities. |
| method | model | normalization | notes |
|---|---|---|---|
weighted_sum (default) | Simple Additive Weighting (SAW) | min-max per criterion | Most transparent; additive contributions. Handles negatives. |
weighted_product | Weighted Product Model (WPM) | ratio (x/max, min/x) | Punishes any single weak criterion; requires scores > 0. |
topsis | Closeness to ideal solution | vector (Euclidean) | 0–1 closeness coefficient; robust with many criteria. |
Each criterion has a direction: benefit (higher is better — quality, speed) or
cost (lower is better — price, latency, risk). Weights are relative; they are
normalized to sum to 1 internally.
Every successful response contains: status, method, winner, ranking
(with per-criterion breakdown), methodology, weights_used, inputs_used,
notes, and a natural-language explanation.
Errors never cross the tool boundary as exceptions — they come back as a structured, actionable envelope:
Design note — exact numbers:
scoreis a deterministically-rounded number (6 dp) for easy consumption;score_exact/raw_scoreare full-precision strings so no precision is lost in JSON. Rankings are computed on the exact values, with input order as a stable tie-break.
Separation of concerns: engine.mjs is pure and transport-agnostic (import it
directly in tests or any Node/Deno/edge runtime); index.mjs only handles the MCP
JSON-RPC wiring, HTTP, CORS, and the auth/metering seam.
decimal.js (math) and esbuild (bundler).Quick manual call:
Run the server locally over stdio with a single command — nothing to deploy:
Claude Desktop / any stdio MCP client (claude_desktop_config.json):
This is the same deterministic engine as the hosted server, running on your machine.
~/.cursor/mcp.jsonclaude_desktop_config.jsonClaude Desktop launches stdio servers, so bridge to the HTTP endpoint with mcp-remote:
.vscode/mcp.jsonPoint it at https://decisionmatrix-mcp.pages.dev/mcp (or your self-hosted URL). If
you enable auth, add X-API-Key (or Authorization: Bearer <key>) in the client's
headers.
create_decision(options, criteria, scores, method="weighted_sum")["Vendor A","Vendor B"]) or objects
([{"name":"Vendor A","scores":{...}}]). Minimum 2, names unique.{ "name", "weight" (>=0), "direction": "benefit"|"cost" }.
At least one weight must be > 0.{ "Vendor A": { "Price": 100, "Quality": 8 }, ... }[ { "option": "Vendor A", "scores": { ... } }, ... ]weighted_sum (default) · weighted_product · topsis (aliases like
saw, wpm, ideal also resolve).score_options(options, criteria, scores, method)Same inputs as create_decision; returns the full scored matrix (per-option,
per-criterion normalized scores + totals) without the winner narrative.
sensitivity_analysis(options, criteria, scores, method, variation=0.2, steps=10)Sweeps each criterion's weight from -variation to +variation (fractional, e.g.
0.2 = ±20%) in steps increments (2–100), renormalizing the others, and recomputes
the winner each time. Returns a robustness_score (share of scenarios the baseline
winner stays #1), the fragile_criteria, and per-criterion flip points.
compare_two(option_a, option_b, criteria, scores, method)Head-to-head between exactly two options (pass option_a/option_b names, or a
2-element options array). Returns the winner, score margin, criteria_wins, and a
per_criterion breakdown showing which option each criterion favours.
list_methods() / health_check()Discovery + status. No parameters.
Choose a laptop (price & weight are cost criteria):
Test how robust the winner is:
Head-to-head:
Same pattern as PrecisionCalc — one build step bundles worker-src/ into
site/_worker.js (Pages "advanced mode" Function), then Wrangler deploys the site/
directory.
Or wire it to Git: create a Pages project, set the build command to npm run build
and the output directory to site. Every push deploys automatically. The
compatibility_date and project name live in wrangler.toml.
To run fully free / private, you need no bindings, secrets, or env vars — the scoring engine is stateless and the server fails open (free tier, quota disabled).
The hosted server uses these — replicate them for your own paid deployment:
DECISIONMATRIX_KV
in wrangler.toml.[vars]
(PRICE_STARTER, PRICE_PRO) and the daily limits (FREE_DAILY, STARTER_DAILY,
PRO_DAILY).https://<your-domain>/webhook
for customer.subscription.updated + customer.subscription.deleted.Routes wired up: /checkout?plan=starter|pro → Stripe Checkout, /success provisions
and shows the API key (idempotent), /portal opens the Stripe billing portal,
/webhook handles subscription lifecycle (revoke/restore), /metrics reports usage.
The hosted server enforces tiered quotas in worker-src/billing.mjs:
identify() reads X-API-Key / Authorization: Bearer, looks the key
up in KV, and falls back to per-IP free tier.consumeQuota() is a KV daily counter (resets 00:00 UTC); the single
gating point in handleRpc where method === "tools/call".upsell
envelope with pricing + checkout URLs (agents can read and act on it)./metrics.DecisionMatrix has no paid-only tools — every tool works on every tier; paid plans
only raise the daily quota. To make a tool paid-only, add its name to PAID_ONLY_TOOLS
in index.mjs. Because the engine is pure and stateless, none of this touches the
scoring logic.
ROUND_HALF_UP
everywhere, and stable input-order tie-breaking. No floats, no randomness, no clocks
in the result.weighted_sum uses min-max
(best→1, worst→0); if a criterion is identical across all options it's treated as
neutral (normalized to 1) and noted. weighted_product uses ratio normalization and
requires strictly positive scores (clear error otherwise). topsis uses vector
normalization and ranks by closeness to the ideal/anti-ideal.[3,2,1] and [30,20,10]
give identical results.notes.status:"error" with a
machine type and an actionable hint. Validation covers duplicate names, missing
cells (listing exactly which), non-numeric scores, bad weights/directions, and
unknown methods.The suite pins the hand-verifiable weighted_sum arithmetic, checks determinism,
weight-relativity, direction handling, ties, all three methods, compare_two,
sensitivity_analysis, the multiple score-input shapes, and every error path.
MIT — see LICENSE.