Decisionmatrix Mcp

io.github.inity13Published by GitHub account inity13v1.0.2Updated Oct 24, 2026

Deterministic multi-criteria decision analysis for AI agents — score, rank & explain options.

VerifiedStreamable HTTPWeb executableProductivity & WorkflowData & Analytics

Overview

AI-generated overview

Deterministic multi-criteria decision engine that lets an assistant score, rank and explain options against weighted criteria.

What you can do
  • Rank options against weighted criteria and get a winner, full ranking, per-criterion breakdowns, methodology and a plain-language explanation
  • Score options and return the full normalized option-by-criterion matrix without the narrative
  • Run sensitivity analysis that sweeps each criterion's weight and reports robustness, fragile criteria and flip points
  • Compare exactly two options head-to-head with score margin and per-criterion win counts
  • List the available scoring methods (weighted sum, weighted product, TOPSIS) and check server health
When to use it
Useful when an assistant has gathered several alternatives and needs a consistent, reproducible way to weigh them, such as vendor or product selection, prioritization, or trade-off analysis. Also handy when you want to show how sensitive a result is to the chosen weights.
Requirements
Either the hosted remote endpoint over Streamable HTTP, or the npm package run locally over stdio with Node.js 18 or later. No account or key is needed for the free hosted tier; a paid plan key is sent as X-API-Key. Self-hosting on Cloudflare Pages needs a Cloudflare account.
Before you install
The hosted server is free at 15 calls per day per IP; higher quotas require a paid Stripe subscription, and an API key is sent as X-API-Key. The server is stateless and only computes from the inputs you supply, so results are relative to the option set and weights given. Self-hosting billing requires Stripe secrets such as STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.

Installation

In SourceWeft

  1. Open Decisionmatrix Mcp in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.inity13%2Fdecisionmatrix-mcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "decisionmatrix": {
      "type": "http",
      "url": "https://decisionmatrix-mcp.pages.dev/mcp"
    }
  }
}

README

DecisionMatrix MCP

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.

🌐 Live hosted server (free, no install)

A public remote MCP server runs on Cloudflare's edge — point any Streamable-HTTP MCP client at it:

https://decisionmatrix-mcp.pages.dev/mcp
json
{ "mcpServers": { "decisionmatrix": {    "type": "http", "url": "https://decisionmatrix-mcp.pages.dev/mcp" } } }

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.


What it does

Six tools, all returning a uniform, agent-parseable envelope:

ToolPurpose
create_decisionMain tool. Rank options against weighted criteria → winner, full ranking, per-criterion breakdowns, methodology, weights, and a plain-language explanation.
score_optionsReturn the full normalized scored matrix when scores are supplied separately.
sensitivity_analysisSweep each criterion's weight ±X% and report how robust the winner is (and where it flips).
compare_twoHead-to-head comparison of exactly two options with per-criterion win counts.
list_methodsDiscovery: available scoring methods and when to use each.
health_checkVersion, status, and capabilities.

Scoring methods

methodmodelnormalizationnotes
weighted_sum (default)Simple Additive Weighting (SAW)min-max per criterionMost transparent; additive contributions. Handles negatives.
weighted_productWeighted Product Model (WPM)ratio (x/max, min/x)Punishes any single weak criterion; requires scores > 0.
topsisCloseness to ideal solutionvector (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.

Consistent response envelope

Every successful response contains: status, method, winner, ranking (with per-criterion breakdown), methodology, weights_used, inputs_used, notes, and a natural-language explanation.

json
{  "status": "success",  "method": "weighted_sum",  "winner": { "option": "Gamma", "score": 0.666667, "score_exact": "0.666667", "rank": 1, "tie": false, "tied_with": [] },  "ranking": [    { "rank": 1, "option": "Gamma", "score": 0.666667, "score_exact": "0.666667",      "breakdown": [        { "criterion": "Price", "direction": "cost", "weight": 0.5, "weight_raw": "3",          "raw_score": "900", "normalized_score": 1, "weighted_contribution": 0.5 }      ] }  ],  "methodology": {    "method": "weighted_sum",    "name": "Weighted Sum Model (Simple Additive Weighting)",    "normalization": "min-max per criterion (best value -> 1, worst -> 0)",    "score_range": "0 to 1 (higher is better)",    "weighting": "Criteria weights are normalized to sum to 1; only their relative sizes matter.",    "deterministic": true  },  "weights_used": [ { "criterion": "Price", "direction": "cost", "weight_input": "3", "weight_normalized": 0.5 } ],  "inputs_used": { "options": ["Alpha","Beta","Gamma"], "method": "weighted_sum", "option_count": 3, "criterion_count": 3 },  "notes": [ "Scores are normalized within this option set; they express relative standing, not an absolute grade." ],  "explanation": "Using the Weighted Sum Model, 'Gamma' ranks #1 with a score of 0.666667, ahead of 'Alpha' (0.527778) by 26.32% ..."}

Errors never cross the tool boundary as exceptions — they come back as a structured, actionable envelope:

json
{  "status": "error",  "error": {    "type": "incomplete_scores",    "message": "Missing 1 score(s) in the options x criteria matrix.",    "hint": "Provide a score for every option and criterion. Missing: Beta / Weight."  }}

Design note — exact numbers: score is a deterministically-rounded number (6 dp) for easy consumption; score_exact / raw_score are 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.


Project structure

decisionmatrix-mcp/├── worker-src/│   ├── index.mjs        # Cloudflare Pages Function (_worker.js): MCP over Streamable HTTP + billing routes│   ├── engine.mjs       # The deterministic MCDA engine: 3 methods + 6 tools + validation│   └── billing.mjs      # Stripe Checkout + KV-backed API keys, quota metering, webhook├── site/│   ├── index.html       # Static landing / pricing / docs page│   └── _worker.js        # Built bundle (esbuild output; git-ignored)├── tests/│   └── engine.test.mjs  # 21 core scoring-logic tests (node --test)├── examples/│   └── agent_example.mjs # End-to-end MCP client demo over HTTP├── package.json         # build / deploy / dev / test scripts├── wrangler.toml        # Cloudflare Pages config├── .env.example         # Optional auth/rate-limit env reference├── LICENSE              # MIT└── README.md

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.


Requirements

  • Node 18+ (for the build, tests, and local dev). Only two dev/runtime deps: decimal.js (math) and esbuild (bundler).
  • A Cloudflare account (free tier is fine) to deploy the hosted version.

Run it locally

bash
git clone <your-fork> decisionmatrix-mcp && cd decisionmatrix-mcpnpm install
# Run the test suite (no server needed)npm test
# Serve the MCP endpoint locally via Wrangler (builds + runs Pages dev)npm run dev          # -> http://127.0.0.1:8788/mcp
# Try the end-to-end client demo (hosted by default, or pass a local URL)node examples/agent_example.mjsnode examples/agent_example.mjs http://127.0.0.1:8788

Quick manual call:

bash
curl -s http://127.0.0.1:8788/mcp \  -H 'content-type: application/json' \  -H 'accept: application/json, text/event-stream' \  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{        "name":"list_methods","arguments":{}}}'

Install via npm (stdio, no hosting)

Run the server locally over stdio with a single command — nothing to deploy:

bash
npx -y decisionmatrix-mcp

Claude Desktop / any stdio MCP client (claude_desktop_config.json):

json
{ "mcpServers": { "decisionmatrix": { "command": "npx", "args": ["-y", "decisionmatrix-mcp"] } } }

This is the same deterministic engine as the hosted server, running on your machine.

Client configuration

Cursor — ~/.cursor/mcp.json

json
{ "mcpServers": { "decisionmatrix": {    "url": "https://decisionmatrix-mcp.pages.dev/mcp" } } }

Claude Desktop — claude_desktop_config.json

Claude Desktop launches stdio servers, so bridge to the HTTP endpoint with mcp-remote:

json
{ "mcpServers": { "decisionmatrix": {    "command": "npx", "args": ["-y", "mcp-remote", "https://decisionmatrix-mcp.pages.dev/mcp"] } } }

VS Code — .vscode/mcp.json

json
{ "servers": { "decisionmatrix": {    "type": "http", "url": "https://decisionmatrix-mcp.pages.dev/mcp" } } }

Any Streamable-HTTP MCP client

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


Tools & parameters

create_decision(options, criteria, scores, method="weighted_sum")

  • options — array of names (["Vendor A","Vendor B"]) or objects ([{"name":"Vendor A","scores":{...}}]). Minimum 2, names unique.
  • criteria — array of { "name", "weight" (>=0), "direction": "benefit"|"cost" }. At least one weight must be > 0.
  • scores — the option×criterion matrix. Accepted shapes:
    • object map: { "Vendor A": { "Price": 100, "Quality": 8 }, ... }
    • array: [ { "option": "Vendor A", "scores": { ... } }, ... ]
    • inline on each option object.
  • method — 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.


Example tool-call payloads

Choose a laptop (price & weight are cost criteria):

json
{ "name": "create_decision", "arguments": {  "options": ["Alpha", "Beta", "Gamma"],  "criteria": [    { "name": "Price",   "weight": 3, "direction": "cost" },    { "name": "Battery", "weight": 2, "direction": "benefit" },    { "name": "Weight",  "weight": 1, "direction": "cost" }  ],  "scores": {    "Alpha": { "Price": 1000, "Battery": 8,  "Weight": 1.5 },    "Beta":  { "Price": 1200, "Battery": 12, "Weight": 1.8 },    "Gamma": { "Price": 900,  "Battery": 6,  "Weight": 1.2 }  }} }

Test how robust the winner is:

json
{ "name": "sensitivity_analysis", "arguments": {  "options": ["Alpha", "Beta", "Gamma"],  "criteria": [    { "name": "Price", "weight": 3, "direction": "cost" },    { "name": "Battery", "weight": 2 }  ],  "scores": { "Alpha": {"Price":1000,"Battery":8}, "Beta": {"Price":1200,"Battery":12}, "Gamma": {"Price":900,"Battery":6} },  "variation": 0.3, "steps": 8} }

Head-to-head:

json
{ "name": "compare_two", "arguments": {  "option_a": "Alpha", "option_b": "Beta",  "criteria": [ { "name": "Price", "weight": 3, "direction": "cost" }, { "name": "Battery", "weight": 2 } ],  "scores": { "Alpha": {"Price":1000,"Battery":8}, "Beta": {"Price":1200,"Battery":12} }} }

Deploy on Cloudflare Pages

Same pattern as PrecisionCalc — one build step bundles worker-src/ into site/_worker.js (Pages "advanced mode" Function), then Wrangler deploys the site/ directory.

bash
npm installnpx wrangler login          # once
# Build + deploy in one shotnpm run deploy              # esbuild -> site/_worker.js, then wrangler pages deploy

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

Enabling billing (already live on the hosted server)

The hosted server uses these — replicate them for your own paid deployment:

  1. KV namespace for API keys + daily usage counters, bound as DECISIONMATRIX_KV in wrangler.toml.
  2. Stripe products/prices (subscription) — put the price IDs in [vars] (PRICE_STARTER, PRICE_PRO) and the daily limits (FREE_DAILY, STARTER_DAILY, PRO_DAILY).
  3. Stripe secrets (never in the repo):
    bash
    wrangler pages secret put STRIPE_SECRET_KEY     --project-name decisionmatrix-mcpwrangler pages secret put STRIPE_WEBHOOK_SECRET  --project-name decisionmatrix-mcp
  4. Webhook → create a Stripe webhook endpoint at 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.


Auth & rate limiting

The hosted server enforces tiered quotas in worker-src/billing.mjs:

  • Identity — identify() reads X-API-Key / Authorization: Bearer, looks the key up in KV, and falls back to per-IP free tier.
  • Quota — consumeQuota() is a KV daily counter (resets 00:00 UTC); the single gating point in handleRpc where method === "tools/call".
  • Paywall response — over-quota / invalid / revoked keys get a structured upsell envelope with pricing + checkout URLs (agents can read and act on it).
  • Usage metering — in-memory counters at /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.


Design decisions & assumptions

  • Deterministic by construction. 40-digit decimal math, ROUND_HALF_UP everywhere, and stable input-order tie-breaking. No floats, no randomness, no clocks in the result.
  • Normalization is per-criterion and direction-aware. 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.
  • Weights are relative — normalized to sum to 1, so [3,2,1] and [30,20,10] give identical results.
  • Scores are relative to the option set — they measure standing within the provided alternatives, not an absolute grade. This is stated in notes.
  • Errors are data, not exceptions — every tool returns 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.
  • Stateless & side-effect-free — trivially cacheable, horizontally scalable, and safe to run anywhere (Cloudflare, Node, Deno, Bun).

Testing

bash
npm test          # node --test tests/*.test.mjs  (21 tests, no network)

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.


Roadmap (post-MVP)

  1. More methods: AHP (pairwise weight elicitation), ELECTRE, PROMETHEE, Borda count.
  2. Group decisions: aggregate multiple stakeholders' weight/score sets.
  3. Monte-Carlo sensitivity (perturb all weights jointly) alongside one-at-a-time.
  4. Per-key usage dashboard + Redis/Durable-Object quotas for stronger consistency.
  5. Published npm package + a hosted multi-tenant tier.

License

MIT — see LICENSE.

Source: README.md at commit 4fde2b2

Tools

6

create_decision

Rank named options against weighted criteria and return the winner, full ranking, per-criterion score breakdowns, methodology, the weights used, and a plain-language explanation. This is the main tool. Provide options, criteria [{name, weight, direction}], and a scores matrix. method defaults to weighted_sum (also: weighted_product, topsis). 100% deterministic.

Parametersmethodscoresrequiredoptionsrequiredcriteriarequired

score_options

Score options against criteria when the score matrix is supplied separately. Returns the full normalized scored matrix (per-option, per-criterion) plus a ranking, without the narrative winner explanation. Use create_decision if you want a winner + explanation.

Parametersmethodscoresrequiredoptionsrequiredcriteriarequired

sensitivity_analysis

Test how robust the winner is to changes in criteria weights. Sweeps each criterion's weight +/- 'variation' (default 0.2 = 20%) over 'steps' (default 10) increments, recomputes the ranking, and reports a robustness score, which criteria are most likely to flip the result, and the flip points.

Parametersstepsmethodscoresrequiredoptionsrequiredcriteriarequiredvariation

compare_two

Direct head-to-head comparison of exactly two options. Returns the winner, the score margin, how many criteria each option wins, and a per-criterion breakdown of who each criterion favours. Pass option_a and option_b (names) or a 2-element options array, plus criteria and scores.

Parametersmethodscoresrequiredoptionscriteriarequiredoption_aoption_b

list_methods

List the available scoring methods (weighted_sum, weighted_product, topsis) with descriptions, normalization details, score ranges, and when to use each. No parameters.

Takes no parameters.

health_check

Server health, version, and capabilities. No parameters.

Takes no parameters.

Version history

1
  1. v1.0.2LatestSep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts