mcp-decision-lab
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-decision-labHelp me decide between Postgres and DynamoDB for our backend."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-decision-lab
MCP server for structured decision-making — weighted decision matrices, exact weight and score sensitivity, Monte Carlo robustness and a defensible, auditable recommendation.
Why
LLMs are good at listing pros and cons and then picking whatever "feels" right. That reasoning is opaque, unstable, and impossible to audit: change one adjective in the prompt and the answer flips. mcp-decision-lab is a thinking tool: the model uses it to structure its own reasoning as an explicit weighted decision matrix. Every score needs a written rationale, weights are normalized and visible, and analyze does real math instead of vibes:
Which weight would flip the winner, and at what value (exact, closed form).
Which single judgment the decision hinges on: the smallest change to any one score that changes the winner, quoted together with the rationale you gave for it.
How often the winner survives when everything is uncertain at once: a seeded Monte Carlo that perturbs all weights and all scores together.
An honest verdict:
robust,fragile, ortie. A tie is never presented as a winner.
Related MCP server: mcpdeployment
Tools
Tool | Arguments | Returns |
|
|
|
|
| The recorded cell, remaining cells, next step |
|
| Raw, effective and weighted scores, totals, every rationale, missing cells |
|
| Ranking and margin, weight sensitivity, score sensitivity, Monte Carlo, strengths/weaknesses, verdict, recommendation (details) |
|
| The ranking, totals, margin and winner under the hypothesis. The stored session is never changed. |
|
| A decision record (ADR-style Markdown or JSON) with every rationale and the full analysis |
|
| Removes the session from the store (marked |
| — | Every session with its status ( |
Every argument has a typed JSON schema: bounds, minItems, and a Criterion object with additionalProperties: false. Tools also carry MCP annotations (read-only, destructive, idempotent). When a call is rejected, the message is returned to the model verbatim (for example Unknown option 'C'. Valid options: A, B.) so it can correct itself.
Criteria where a high raw score is bad (cost, risk, complexity) take "higher_is_better": false. Score the raw quantity (cost 10 = very expensive) and the tool uses 10 - score as the effective score.
What analyze returns
Field | Meaning |
| Options by weighted total. Tied totals share a rank. |
| Non-empty only for a tie at the top. Then |
| Per criterion: the exact |
| For every cell, the score beyond which the winner changes ( |
| Per option: |
| The three checks behind the verdict (see below), each with pass/fail and what failed. |
| Each option's best and worst criterion, or |
| A text summary built from all of the above. |
Verdict rules. robust means all three checks pass:
Weights: no ±50% relative change to any single criterion weight flips the winner.
Scores: no change of 1 point or less to any single score flips the winner.
Monte Carlo: the winner ranks first in at least 80% of the joint perturbations (skipped when
simulations=0).
Otherwise the verdict is fragile, and the recommendation says which check failed and by how much. tie means the top options have equal totals.
How it works
flowchart TD
A[start_decision<br/>question + options + weighted criteria] --> B[weights normalized to sum 1.0<br/>session dec-xxxx saved to disk]
B --> C[score_option x N<br/>score 0-10 + mandatory rationale]
C -->|cells missing| C
C -->|matrix complete| E[analyze]
E --> F[ranking + margin<br/>tie detection]
E --> G["weight sensitivity<br/>exact flip weight per criterion"]
E --> H["score sensitivity<br/>smallest single-score change that flips it"]
E --> M["Monte Carlo<br/>all weights + scores perturbed together"]
F --> I[verdict: robust / fragile / tie]
G --> I
H --> I
M --> I
I --> J[recommendation naming the hinge cell]
J --> K[what_if: test other weights or scores]
J --> L[export_decision: Markdown decision record]Weight sensitivity. Move criterion c from weight w to w′ while the other criteria keep their relative weights. Every total is then linear in w′. For the winner A against a challenger B, gap(w′) = w′·d + (1−w′)·r, where d is their effective-score difference on c and r is their weighted difference on everything else. Solving gap(w′) = 0 gives the exact flip weight w* = r/(r−d). It is reported only if B strictly wins somewhere in [0, 1]. r is computed from the other criteria's relative weights and never by dividing by 1 − w, so a criterion that carries essentially all of the weight is still exact.
Score sensitivity. Totals are linear in every cell. The runner-up takes over once the winner's effective score on c drops by more than margin / w_c. A challenger takes over once its own score rises by more than (total_A − total_B) / w_c. Inverted criteria are mapped back to raw scores.
Monte Carlo. Weights are drawn from a Dirichlet distribution centred on your weights (α = concentration × w), and every score gets independent uniform noise ±score_noise, clipped to 0–10. Every draw comes from random.Random(seed).random() alone (Marsaglia–Tsang gamma sampling on Box–Muller normals). random() is the one part of the random module whose output Python guarantees not to change between versions, so the same seed gives the same numbers on every supported Python.
Install
Not on PyPI yet.
pip install mcp-decision-labanduvx mcp-decision-labwill only work once the first release is published (server.jsonand the publish workflow are ready for it). Until then, install from GitHub:
# Run straight from GitHub with uv (nothing to install)
uvx --from git+https://github.com/AleBrito124356/mcp-decision-lab mcp-decision-lab
# Or install into any Python 3.10+ environment
pip install git+https://github.com/AleBrito124356/mcp-decision-labClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"decision-lab": {
"command": "uvx",
"args": ["--from", "git+https://github.com/AleBrito124356/mcp-decision-lab", "mcp-decision-lab"]
}
}
}If you installed it with pip, use "command": "mcp-decision-lab" with no args (or the full path to that executable).
Claude Code:
claude mcp add decision-lab -- uvx --from git+https://github.com/AleBrito124356/mcp-decision-lab mcp-decision-labFrom a source checkout: python -m mcp_decision_lab.server (or python -m mcp_decision_lab).
See it work without an MCP client: mcp-decision-lab demo runs the example below in a temporary directory and prints the full analysis. It works offline.
Command line
With no arguments, mcp-decision-lab serves MCP over stdio, which is how MCP clients launch it. The subcommands work offline:
Command | What it does |
| Serve MCP over stdio |
| Run the database example below in a temporary store |
| List stored sessions with status and result |
| Export a decision record |
| Package and MCP SDK versions |
Example session
User: Help me pick a database for the new SaaS backend — Postgres, MongoDB or DynamoDB. Cost matters most, then scalability, then how well the team knows it.
The model starts a session:
start_decision(
question="Which database should we use for the new SaaS backend?",
options=["Postgres", "MongoDB", "DynamoDB"],
criteria=[
{"name": "cost", "weight": 0.5, "higher_is_better": False},
{"name": "scalability", "weight": 0.3},
{"name": "team-familiarity", "weight": 0.2},
],
)
# → {"decision_id": "dec-34b5", "cells_total": 9, "next_step": "Score each option ..."}Then it scores all 9 cells, each with a rationale (score_option("dec-34b5", "Postgres", "cost", 3, "Managed Postgres ..."), and so on). Cost is a raw cost score where 10 = very expensive:
Option | cost (lower is better) | scalability | team-familiarity |
Postgres | 3 — Managed Postgres (RDS/Neon) is cheap and predictable at our scale | 6 — Vertical scaling plus read replicas covers years of growth; sharding is manual | 9 — Every backend engineer has run Postgres in production |
MongoDB | 5 — Atlas is moderate at first but dedicated clusters get pricey fast | 7 — Built-in sharding scales writes horizontally with some tuning | 5 — Two engineers have used it; the rest only know tutorials |
DynamoDB | 6 — On-demand pricing gets expensive with our read-heavy access patterns | 10 — Effectively unlimited managed horizontal scale | 4 — Only one engineer knows single-table design patterns |
And analyzes:
analyze("dec-34b5")Output, abridged: monte_carlo.options shows two of its six fields, and most_fragile shows the first two of five cells. Every number here is pinned by a test against mcp-decision-lab demo --format json.
{
"ranking": [
{
"rank": 1,
"option": "Postgres",
"total": 7.1
},
{
"rank": 2,
"option": "DynamoDB",
"total": 5.8
},
{
"rank": 3,
"option": "MongoDB",
"total": 5.6
}
],
"winner": "Postgres",
"tied": [],
"runner_up": "DynamoDB",
"margin": 1.3,
"sensitivity": [
{
"criterion": "cost",
"weight": 0.5,
"decisive": true,
"flip": {
"flip_weight": 0.1176,
"direction": "decrease",
"new_winner": "DynamoDB",
"weight_change": -0.3824,
"within_50pct_band": false
}
},
{
"criterion": "scalability",
"weight": 0.3,
"decisive": true,
"flip": {
"flip_weight": 0.4717,
"direction": "increase",
"new_winner": "DynamoDB",
"weight_change": 0.1717,
"within_50pct_band": false
}
},
{
"criterion": "team-familiarity",
"weight": 0.2,
"decisive": false,
"flip": null
}
],
"decisive_criteria": [
"cost",
"scalability"
],
"score_sensitivity": {
"flippable_cells": 5,
"cells_total": 9,
"most_fragile": [
{
"option": "Postgres",
"criterion": "cost",
"current_score": 3.0,
"flip_score": 5.6,
"direction": "above",
"change_needed": 2.6,
"new_winner": "DynamoDB",
"within_1pt": false,
"rationale": "Managed Postgres (RDS/Neon) is cheap and predictable at our scale"
},
{
"option": "DynamoDB",
"criterion": "cost",
"current_score": 6.0,
"flip_score": 3.4,
"direction": "below",
"change_needed": 2.6,
"new_winner": "DynamoDB",
"within_1pt": false,
"rationale": "On-demand pricing gets expensive with our read-heavy access patterns"
}
]
},
"monte_carlo": {
"simulations": 2000,
"seed": 7,
"score_noise": 1.0,
"weight_concentration": 20.0,
"options": {
"Postgres": {
"win_probability": 0.929,
"expected_rank": 1.084
},
"MongoDB": {
"win_probability": 0.003,
"expected_rank": 2.576
},
"DynamoDB": {
"win_probability": 0.068,
"expected_rank": 2.34
}
}
},
"robustness": "robust",
"robustness_checks": {
"weights": {
"passed": true
},
"scores": {
"passed": true
},
"monte_carlo": {
"passed": true
}
},
"recommendation": "Choose Postgres (7.1 weighted) over DynamoDB (5.8); margin 1.3. Postgres is strongest on 'team-familiarity' (9/10) and weakest on 'scalability' (6/10). The result is robust: no ±50% relative change to any single criterion weight changes the winner, no single score is within 1 point of flipping it (the closest needs a 2.6-point change). (Extreme shifts could still flip it: 'cost' would have to decrease from 0.5 to 0.1176 for DynamoDB to win; 'scalability' would have to increase from 0.3 to 0.4717 for DynamoDB to win.) The decision hinges most on the judgment that Postgres scores 3 on 'cost' (\"Managed Postgres (RDS/Neon) is cheap and predictable at our scale\"): above 5.6, DynamoDB wins. Monte Carlo (2000 joint perturbations of all weights and scores ±1, seed 7): win probability Postgres 92.9%, DynamoDB 6.8%."
}Model (to user): Postgres wins at 7.1 weighted vs DynamoDB's 5.8, and the result is robust. No reasonable (±50%) shift in any single weight changes it. The closest single judgment is Postgres's cost score: if managed Postgres really costs above 5.6 on our scale instead of 3, DynamoDB wins. With all weights and scores wobbling at once, Postgres still comes first in 92.9% of 2,000 simulations. If you expect hockey-stick scale, revisit scalability's weight (DynamoDB overtakes above ~0.47). Otherwise Postgres is the defensible choice.
Probe the result without touching the session:
what_if("dec-34b5", weights={"scalability": 0.5})
# cost and team-familiarity keep their 0.5 : 0.2 proportion over the remaining 0.5
# → {"winner": "DynamoDB", "winner_changed": true,
# "summary": "Winner changes from Postgres to DynamoDB. Hypothetical margin 0.2143.", ...}
what_if("dec-34b5", score_overrides=[{"option": "Postgres", "criterion": "cost", "score": 6}])
# → {"summary": "Winner changes from Postgres to DynamoDB. Hypothetical margin 0.2.", ...}In weights, name every criterion to give new relative importances (they are normalized). Name only some criteria to set their exact normalized weight (for example a flip_weight from analyze). The rest then share what is left in their current proportions.
Finally, export_decision("dec-34b5") or mcp-decision-lab report dec-34b5 produces a Markdown decision record. It contains the question, the weights, the score table, every rationale, the ranking, both sensitivity tables, the Monte Carlo table and the recommendation. It is ready to paste into a PR or an ADR folder.
Persistence and multiple clients
Sessions are stored in ~/.mcp-decision-lab/decisions.json. Set DECISION_LAB_DIR or pass --data-dir to use another directory. Several server processes can share the same store, for example Claude Desktop and Claude Code at the same time:
Every write runs under a cross-process lock file (
decisions.json.lock,O_CREAT | O_EXCL, stdlib only). It re-reads the file, applies the one change, and writes atomically. Sessions created by other processes are never lost. A lock left behind by a crashed process is recovered after 30 s.Reads pick up changes made by other processes without a restart.
A corrupt or foreign store file is never overwritten. Tools return a clear "Fix or delete the file" error, and the server keeps running.
The file carries a format version. 0.1.x stores are migrated transparently, and a store written by a newer version is refused rather than damaged.
Compatibility
Python 3.10+.
MCP Python SDK
>=1.5,<3. Both lines are supported: mcp 2.x (MCPServer) and mcp 1.x (FastMCP). The full test suite, including the stdio tests, passes on mcp 2.2.0, 1.30.0 and 1.5.0. Tool annotations need mcp 1.6 or newer; on 1.5 the tools work without them. 1.4 and older have stdio transport bugs on Windows.
Development
git clone https://github.com/AleBrito124356/mcp-decision-lab
cd mcp-decision-lab
python -m venv .venv
.venv/bin/pip install -e ".[dev]" # Windows: .venv\Scripts\pip ...
.venv/bin/python -m pytest
# The same suite against the 1.x SDK line
.venv/bin/pip install "mcp<2" && .venv/bin/python -m pytestTest file | What it covers |
| Validation, normalization, the original hand-computed sensitivity cases, status lifecycle |
| Ties, extreme weights, score thresholds (checked by re-scoring across them), Monte Carlo properties, |
| Two instances sharing a store, a 4-process × 50-write stress test, corrupt stores, migration, stale and live locks |
| A real MCP client in-process: schemas, the end-to-end flow, error messages reaching the model. Plus a stdio smoke test that launches the server as a subprocess |
| CLI commands, decision records, and a check that this README's example numbers match the code |
The core (core.py, analysis.py, store.py, report.py) is pure stdlib. test_server.py is skipped when the mcp package is not installed.
Related MCP servers
Part of a family of small, dependency-light MCP servers:
mcp-devils-advocate: stress-test a claim with devil's advocate, premortem and assumption audits
mcp-secret-sentinel: scan code for exposed secrets, always redacted
mcp-git-historian: churn hotspots, blame summaries, bus factor
mcp-memory-vault: persistent memory with SQLite FTS5 search
License
MIT
Available Tools
8 toolsanalyzeAnalyze the decisionAIdempotent
Analyze a fully scored matrix and give a defensible recommendation.
Returns the ranking and margin; for each criterion the exact weight at which the winner would flip (closed form); the cells whose score alone could change the winner, with the threshold and the rationale behind them; Monte Carlo win probabilities under joint weight and score perturbation; per-option strengths/weaknesses; and a verdict: "robust", "fragile" (a ±50% single-weight change, a ≤1-point single-score change, or a win probability below 80% flips it) or "tie" (winner is null and the tie-breakers are listed). Fails with the list of missing cells if the matrix is incomplete.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | Random seed; same seed, same numbers. | |
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. | |
| score_noise | No | Uniform ± noise added to every score in the simulation. | |
| simulations | No | Monte Carlo samples (0 disables the simulation). | |
| weight_concentration | No | Dirichlet concentration of the simulated weights; lower = more weight uncertainty. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, but the description adds rich behavioral context beyond that: exact returned artifacts (ranking, margin, closed-form flip weights, Monte Carlo probabilities, strengths/weaknesses, verdict categories with specific thresholds), failure mode (incomplete matrix), and the robustness criteria that define 'fragile.' This is substantial additional disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then a dense but well-organized list of outputs and the verdict taxonomy. No filler sentences. The long enumeration of returns is justified by the tool's complexity, though it could be trimmed slightly by relying on the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a mutation-like tool with annotations covering safety, a complete 100%-covered parameter schema, an output schema, and sibling tools, the description provides exactly what's needed: what it produces, when it fails, and how to interpret the verdict. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all five parameters including defaults and bounds. The description adds no syntax or format details beyond the schema. Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Analyze a fully scored matrix and give a defensible recommendation.' Distinct from siblings like get_matrix (retrieve) and what_if (single perturbation) by emphasizing the full defense-quality output. An agent can distinguish this from what_if without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by requiring a 'fully scored matrix' and noting it 'Fails with the list of missing cells if the matrix is incomplete,' which implicitly tells the agent to finish scoring first. However, it never explicitly names what_if or get_matrix as alternatives, nor states when-not to use this tool. Minimal viable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_decisionDelete a decisionADestructiveIdempotent
Permanently delete a decision session. Consider export_decision first.
| Name | Required | Description | Default |
|---|---|---|---|
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, so the safety profile is covered. The description adds the crucial irreversibility note ('Permanently delete') and a pre-step recommendation, which goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short, front-loaded sentences. The destructive warning is first, the alternative second. Zero waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given annotations cover safety and an output schema exists, the description is nearly complete for a delete tool. The only missing element is any scope/authorization note, but that is often implied and not critical for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents decision_id with an example format. The description adds no parameter detail, but baseline is 4 for a single fully documented required parameter; it could have restated the ID origin but doesn't need to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: 'Permanently delete a decision session.' Distinguishes itself from siblings by naming export_decision as the alternative and the permanent-delete nature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly recommends considering export_decision first, giving a clear when-to-use-this-vs-alternative cue. No explicit when-not-to-use beyond that, but the guidance is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_decisionExport a decision recordARead-onlyIdempotent
Export the decision as a reviewable record: question, weights, the full score table, every rationale, ranking, weight and score sensitivity, Monte Carlo result and recommendation. The text is in the "content" field.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | 'markdown' (an ADR-style record) or 'json' (machine-readable). | markdown |
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds real behavioral value by enumerating what the export contains (weight/score sensitivity, Monte Carlo, recommendation) and where the text lives ('content' field), which is not derivable from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and the record contents. The enumeration is long but every item conveys what the export produces; the trailing note about the 'content' field is well placed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be re-explained, and the description correctly focuses on what the record contains. A small gap remains: no guidance on when to prefer markdown vs json or on the source of decision_id beyond the schema's note.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are documented in the schema, including the format enum and the decision_id source. The description adds no parameter-level detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Export') and resource (the decision) and enumerates the record's contents. It is clearly distinguishable from siblings like get_matrix or analyze, which retrieve sub-parts rather than a full reviewable record.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage ('as a reviewable record' with ADR-style output), but never states when to choose export_decision over list_decisions, get_matrix, or analyze. No explicit when/when-not guidance is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_matrixShow the matrixBRead-onlyIdempotent
Show the full decision matrix: raw, effective and weighted scores, totals, every rationale, and any cells still missing.
| Name | Required | Description | Default |
|---|---|---|---|
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety and side-effect profile is fully covered externally. The description only recites the returned content, which the output schema largely carries, adding little behavioral context beyond that (e.g. no size/pagination or freshness info).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler; the colon-prefixed enumeration of contents is efficient. Nothing is wasted, though the long list pushes it slightly past minimal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a complete output schema, full annotation coverage, and a single documented required parameter, the definition gives an agent enough to invoke it correctly. The only missing piece is routing guidance against siblings such as analyze or what_if.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage, so the schema already fully documents decision_id including its origin and format. The description adds nothing about the parameter, matching the baseline for schema-covered params.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb ('Show') and resource ('the full decision matrix') and enumerates the payload contents (raw/effective/weighted scores, totals, rationale, missing cells). It is clearly distinct from siblings like score_option or start_decision, though it never explicitly contrasts itself with analyze or what_if, which could plausibly be confused with it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites stated in the description, and no named alternatives. The only hint of context is in the schema's decision_id description (from start_decision), which is structured data rather than description text.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_decisionsList decisionsARead-onlyIdempotent
List all decision sessions with their status ("pending": cells unscored, "complete": scored but not analyzed, "analyzed") and, once analyzed, the winner and verdict.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, non-destructive operation. The description adds useful behavioral context by explaining the status lifecycle ('pending', 'complete', 'analyzed') and that winner/verdict appear only once analyzed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single efficient sentence, front-loads the main action, and uses the remainder to clarify status values and post-analysis output. No sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter list tool with rich annotations and an output schema, the description covers the important status and return semantics. An agent does not need additional parameter or return-format detail from the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4. The schema also has 100% description coverage, and no additional parameter semantics are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List all decision sessions,' and adds returned scope (status, winner, verdict). This clearly distinguishes it from sibling actions like delete_decision, start_decision, analyze, and export_decision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says what is returned but not when to call this tool versus alternatives. There is no when-to-use, when-not-to-use, or sibling routing guidance such as using this before analyze or after score_option.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
score_optionScore one cellAIdempotent
Score one option against one criterion (one cell of the decision matrix).
Score each cell independently and honestly; analyze reports exactly which judgments the result hinges on. Re-scoring a cell overwrites it and marks any previous analysis stale.
| Name | Required | Description | Default |
|---|---|---|---|
| score | Yes | Raw score 0-10 for the quantity the criterion names (for 'cost', 10 = very expensive); inverted criteria are handled automatically. | |
| option | Yes | One of the options (case-insensitive). | |
| criterion | Yes | One of the criteria (case-insensitive). | |
| rationale | Yes | Why this score (at least 10 characters). Rationales are quoted back when the decision hinges on this cell. | |
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds key behavioral details beyond the annotations: re-scoring overwrites the cell and marks previous analysis stale. This is crucial side-effect information that annotations (idempotentHint=true, destructiveHint=false) alone do not convey—the idempotent hint correctly signals overwrite behavior, but the 'marks stale' consequence is non-obvious and important.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences, front-loading the tool's purpose followed by usage advice and a critical behavioral note. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema is present, the description need not explain return values. It covers the core operation, a key side effect, and hints at integration with analyze. However, it could be clearer about how this tool fits into the overall decision workflow with siblings like what_if or start_decision.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema fully documents all five parameters, including the scoring range and rationale requirements. The description adds no additional parameter details; a baseline of 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action: 'Score one option against one criterion (one cell of the decision matrix).' This distinguishes it as a single-cell scoring operation. However, it does not explicitly differentiate itself from sibling tools like analyze, which likely aggregates scores.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description advises to 'Score each cell independently and honestly,' implying the tool is used per-cell. It also notes that 'analyze reports exactly which judgments the result hinges on,' hinting at a downstream relationship, but does not state when not to use it or when to prefer analyze directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_decisionStart a decisionA
Start a structured decision: the question, the options and the weighted criteria.
Use this whenever a choice deserves explicit reasoning (a technology, a vendor, a plan, a design): it forces the trade-offs into a weighted decision matrix instead of a gut call. Returns the new decision_id, the normalized weights, the empty cells to fill with score_option, and the next step.
| Name | Required | Description | Default |
|---|---|---|---|
| options | Yes | At least 2 distinct alternatives, e.g. ["Postgres", "MongoDB"]. | |
| criteria | Yes | At least 2 weighted criteria. | |
| question | Yes | The decision, e.g. "Which database for the new backend?". |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-destructive, non-idempotent operation. The description adds real behavior beyond that: it returns a decision_id, normalized weights, empty cells expected to be filled by score_option, and a next step — i.e. it creates an unfilled matrix rather than a finished result. It stops short of stating persistence/auth requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads what is created, then the when-to-use condition, then the return payload and next step. Two sentences, no filler, though the parenthetical examples are slightly long for the information they carry.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values needn't be spelled out, yet the description usefully summarizes them and links the workflow to score_option. The remaining gap is invocation prerequisites (does a decision need to exist first, any permission constraints), which keeps this at a 4 rather than a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so names, minItems, and the weight-normalization semantics are already documented in the schema. The description restates the three inputs at a high level without adding constraints or formats beyond what the schema provides, which is the baseline 3 case.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('start a structured decision') plus the three inputs it takes (question, options, weighted criteria). It also names the next sibling tool ('the empty cells to fill with score_option'), so an agent can place it against list/delete/export/score_option without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear positive trigger: 'use this whenever a choice deserves explicit reasoning (a technology, a vendor, a plan, a design)', which covers the intended context well. It does not name an explicit when-not condition or contrast against siblings like analyze or what_if, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
what_ifWhat if…ARead-onlyIdempotent
Re-rank the options under hypothetical weights and/or scores, without changing the stored session. Answers "what if we cared more about X?" or "what if that estimate is wrong?" with the new ranking, totals, margin and whether the winner changes.
| Name | Required | Description | Default |
|---|---|---|---|
| weights | No | Criterion -> weight. Name EVERY criterion to give new relative importances, or name only some to set their exact normalized weight (0-1, e.g. a flip_weight from analyze) while the rest keep their proportions. | |
| decision_id | Yes | Id returned by start_decision, e.g. 'dec-a3f2'. | |
| score_overrides | No | Hypothetical raw scores for specific cells. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/not-destructive/idempotent, so the safety profile is covered. The description adds genuine behavioral context beyond that: the session is not modified, and the response includes ranking, totals, margin, and whether the winner changes. It does not disclose output schema contents in detail, but the output schema exists and carries that burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, front-loaded with the core operation and the non-mutation guarantee. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only hypothetical ranking tool with a rich schema and an output schema, the description covers purpose, safety, and return shape. The only minor gap is not naming which sibling to use instead for persisting changes, but overall it is complete enough to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it clarifies that both weights and score overrides are hypothetical and that omitting them falls back to stored values. It complements rather than repeats the parameter docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (re-rank) and resource (options under hypothetical weights/scores), and immediately distinguishes itself from the mutation siblings by declaring it does not change the stored session. An agent can separate this from score_option or analyze without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete motivating questions ('what if we cared more about X?', 'what if that estimate is wrong?') that define when to reach for it, and the read-only, non-persisting framing implies when not to (use score_option to persist). It stops short of naming the alternative tools explicitly, so no exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
analyze - First observed
delete_decision - First observed
export_decision - First observed
get_matrix - First observed
list_decisions - First observed
score_option - First observed
start_decision - First observed
what_if
TDQS
Scored across 8 tools
Each tool has a distinct role in the workflow (start, score, inspect, analyze, simulate, export, list, delete), and descriptions clarify boundaries. There is mild potential overlap between analyze and what_if, and between analyze and get_matrix, but the descriptions cleanly separate stored analysis from hypothetical re-ranking and raw inspection.
Most tools follow a consistent verb_noun pattern (start_decision, score_option, get_matrix, delete_decision, export_decision, list_decisions). The bare verbs 'analyze' and 'what_if' are minor deviations but remain readable and unambiguous.
Eight tools cleanly map onto a decision-analysis lifecycle with no superfluous entries. Each tool earns its place and the count is well within a comfortable range.
The surface covers the full lifecycle: create, score, inspect, analyze, simulate, export, list, and delete. A minor gap is the absence of an update/edit tool for changing the question, options, or criteria after start_decision, which agents would have to work around by restarting.
Maintenance
Related MCP Connectors
MCP server for VC pitch-deck scoring, thesis-fit matching, and deal-flow management.
Hybrid human + AI expertise for faster, trusted answers and decisions via MCP Server.
MCP server for building and testing AI agents with multi-model experimentation and insights.
The MCP server that vets MCP servers: identity, risk grade and per-tool risk before you install.
Related MCP Servers
- AlicenseAqualityDmaintenanceA MCP server that implements sequential thinking protocols, provides structured problem-solving methods, decomposes complex problems into manageable steps, and supports iterative optimization and alternative reasoning paths.12Apache 2.0
- FlicenseCqualityDmaintenanceMCP server that enables deployment and management of MCP servers through a simple configuration-based interface.1-
- AlicenseAqualityDmaintenanceAn MCP server that records decisions, rejected alternatives, and justifications, and retrieves them later to avoid re-litigating past choices. It stores data locally in SQLite and Markdown.262 PyPIApache 2.0
- AlicenseNot gradedqualityCmaintenanceMCP server that enforces evidence-graded, phase-gated, peer-reviewed research workflows for AI agents to conduct rigorous decision-making.MIT