Skip to main content
Glama
thedv91
by thedv91

jev-agent-mcp

An MCP server that lets a coding or reasoning agent ask TypeSafe's Jev model for a typed judgment at a decision point. The agent keeps control of the workflow. The server returns answers, probabilities, and confidence as structured data, and it never returns generated prose.

It wraps POST https://api.typesafe.ai/v1/systemone through the official @typesafe-ai/sdk. See the TypeSafe docs for the model itself.

Tools

Tool

Use it to

Built on

judge

Ask any mix of Choice, Noul, and Score questions about one state, in a single request

the three primitives

rank_candidates

Rank 2 to 30 candidates on several weighted dimensions

one Score per dimension, one request per candidate, weights applied in code

verify_claim

Check claims against supplied evidence

a string match for quotes, then one Choice per claim (supports / contradicts / says_nothing)

review_changes

Review a diff the agent supplies, one unified patch per changed file, in any language

the staged jev-review pipeline: five Noul screens per file, then Choice and Score follow-ups on the strongest signals

review_files

Review source files the agent supplies, as they stand, for issues that already exist

the same pipeline, asking about the source as it stands and not about a patch

Each tool description tells the calling agent when to use the tool, what state to pass, and how to read the numbers. Every tool declares an outputSchema and returns structuredContent, with the same JSON repeated as text for clients that ignore structured results.

Related MCP server: Jev MCP

Setup

Requires Node.js 20 or newer. The server is published on npm as jev-agent-mcp, and an MCP client can start it with npx -y jev-agent-mcp without a separate install step.

To run it from a checkout instead, build it once and point the client at dist/index.js:

npm install
npm run build

API key

The server reads the key from the TYPESAFE_API_KEY environment variable and from nowhere else. Create a key in the TypeSafe console. The server does not log the key or write it to disk. Without a key the server still starts and lists its tools, and each tool call returns an error saying the key is missing.

The SDK also honors TYPESAFE_DEFAULT_MODEL (default jev-latest), TYPESAFE_BASE_URL, and TYPESAFE_LOG_LEVEL. All SDK logging goes to stderr because stdout carries the MCP protocol. TYPESAFE_LOG_LEVEL=debug logs request bodies, which include the state you send.

Register it in Claude Code

Export TYPESAFE_API_KEY in the shell that launches Claude Code, then add the server to a .mcp.json file in the project root. Claude Code expands ${VAR} in .mcp.json when it starts the server, so the file holds the variable name and the key itself stays out of it:

{
  "mcpServers": {
    "jev": {
      "command": "npx",
      "args": ["-y", "jev-agent-mcp"],
      "env": { "TYPESAFE_API_KEY": "${TYPESAFE_API_KEY}" }
    }
  }
}

The CLI writes the same file when you use project scope. The single quotes stop the shell from expanding the variable, so .mcp.json receives the name and not the value:

claude mcp add --scope project --transport stdio jev -e 'TYPESAFE_API_KEY=${TYPESAFE_API_KEY}' -- npx -y jev-agent-mcp

Claude Code asks you to approve a project-scoped server the first time you start it in that directory.

To make the server available in every project, use user scope. Claude Code 2.1.270 expands ${VAR} there as well (checked with a probe server that wrote its environment to a file), so ~/.claude.json stores the variable name and not the key:

claude mcp add --scope user --transport stdio jev -e 'TYPESAFE_API_KEY=${TYPESAFE_API_KEY}' -- npx -y jev-agent-mcp

To run a checkout, replace npx -y jev-agent-mcp with node /absolute/path/to/jev-mcp/dist/index.js in any of the commands above, or set "command": "node" and "args": ["/absolute/path/to/jev-mcp/dist/index.js"] in .mcp.json.

The variable has to exist in the environment Claude Code starts from. An export typed into one terminal does not reach the desktop app, which reads your shell profile.

Run /mcp inside Claude Code to confirm that jev is connected and shows five tools.

Agent skill

skills/jev-mcp/SKILL.md tells the agent which tool fits which situation, how to chain them (review a diff, confirm the findings, verify the completion claims), and what to do with a flagged answer. The tool descriptions cover each tool's arguments and output on their own, so the server works without the skill. The npm package includes it under skills/, but the simplest copy comes from GitHub. Put it in .claude/skills/ to use it in one project, or in ~/.claude/skills/ to use it everywhere:

mkdir -p .claude/skills/jev-mcp
curl -fsSL -o .claude/skills/jev-mcp/SKILL.md https://raw.githubusercontent.com/thedv91/jev-mcp/main/skills/jev-mcp/SKILL.md

Reading the results

Field

Meaning

choice, probabilities

The top option and the distribution over every option you supplied

noul

The probability that the answer is yes. Near 0.5 means the model cannot tell. It does not mean "medium" or "partly". Ask a Score question if you want a degree.

score, max_level

The probability-weighted mean level, from 0 to max_level. It can land between levels, and different distributions can give the same score.

confidence

How concentrated a Choice or Score distribution is, from 0 to 1. It describes the model's answer. It does not guarantee the answer is right. Noul answers have no confidence.

certainty

high, medium, or low, from applying the thresholds to confidence

verdict (Noul)

yes, no, or uncertain, from applying the Noul band

needs_escalation

The ids of every answer that came back low or uncertain

top_margin, top_tied (rank_candidates)

The composite gap between first and second place, and whether it is at or below tie_margin

Thresholds

Threshold

Default

Effect

confidence_high

0.8

Choice or Score confidence at or above this is high

confidence_low

0.5

Confidence below this is low and is flagged

noul_band

[0.35, 0.65]

A Noul inside the band is uncertain and is flagged

The defaults come from the examples in TypeSafe's confidence page and its citation-check cookbook. They have not been calibrated on your workload. Every tool accepts a thresholds object to override them for one call, so a risky action can demand more, for example { "confidence_high": 0.9, "noul_band": [0.1, 0.9] }.

The server flags uncertain answers and leaves the response to the agent. What escalation means depends on the agent: it can gather the missing evidence and ask again, reason the point through itself, or ask the user. medium certainty is not flagged. Treat it as a reason to verify first when the action is hard to undo.

Example calls

The arguments below are what an MCP client sends. scripts/smoke.ts holds the same cases plus ambiguous ones for each tool.

judge

Guard a consequential tool call with three independent questions in one request:

{
  "state": {
    "proposed_tool_call": { "tool": "issue_customer_refund", "order_id": "ord_7429", "amount_usd": 680 },
    "side_effects": ["Moves funds", "Changes the order payment state"],
    "safeguards": ["Customer identity and duplicate charge verified"],
    "policy": "Refunds above USD 500 require human approval."
  },
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "What should happen to `proposed_tool_call` under `policy`?",
      "criteria": {
        "allow": "Execute the call now without asking anyone",
        "confirm": "A human must approve before the call executes",
        "deny": "The call must not execute at all"
      }
    },
    "policy_requires_approval": {
      "type": "noul",
      "instructions": "Does `policy` require human approval for `proposed_tool_call`?"
    },
    "risk": {
      "type": "score",
      "instructions": "How much damage would `proposed_tool_call` do if it turned out to be wrong?",
      "criteria": [
        "Nothing changes outside the agent's own workspace",
        "A change that is easy to undo completely",
        "Money or customer-visible state changes and can only partly be undone",
        "Irreversible loss of money or data"
      ]
    }
  }
}

Result from jev-1.13.0 (the Score legend repeats the four levels and is omitted here):

{
  "answers": {
    "action": {
      "type": "choice",
      "choice": "confirm",
      "probabilities": { "confirm": 1, "deny": 0, "allow": 0 },
      "confidence": 1,
      "certainty": "high"
    },
    "policy_requires_approval": { "type": "noul", "noul": 0.98, "verdict": "yes" },
    "risk": {
      "type": "score",
      "score": 2.09,
      "max_level": 3,
      "probabilities": { "0": 0, "1": 0.01, "2": 0.89, "3": 0.1 },
      "confidence": 0.9,
      "certainty": "high"
    }
  },
  "needs_escalation": [],
  "model": "jev-1.13.0",
  "usage": { "input_tokens": 558, "output_tokens": 72 }
}

The stop-or-continue case in scripts/smoke.ts ("Make the dashboard faster", an index added, nothing measured) came back decisive: task_complete was 0.05 (no) and next_step was measure with confidence 1. Thin evidence gave a confident "not done", not an uncertain answer.

A request with unclear scope did get flagged. The state held the message "Can you clean up the old branches?" and the facts that 4 of 12 branches are merged and 3 of the 8 unmerged ones are stale:

{
  "answers": {
    "wants_unmerged_deleted": { "type": "noul", "noul": 0.55, "verdict": "uncertain" },
    "scope": {
      "type": "choice",
      "choice": "merged_and_stale",
      "probabilities": { "merged_only": 0.32, "all_but_main": 0.07, "merged_and_stale": 0.61 },
      "confidence": 0.41,
      "certainty": "low"
    }
  },
  "needs_escalation": ["wants_unmerged_deleted", "scope"],
  "model": "jev-1.13.0",
  "usage": { "input_tokens": 442, "output_tokens": 69 }
}

The Noul of 0.55 says the model cannot tell whether the user wants unmerged branches deleted. It does not say the user wants about half of them deleted. Deleting branches is hard to undo, so the right move for an agent here is to ask the user.

rank_candidates

Route a task to a model. Each candidate is graded in its own request and sees only context and its own content, which the questions refer to as candidate. Order the levels so that a higher level is always better, including for cost.

{
  "context": {
    "task": "Review a complex customer dispute: 100k tokens of history, needs tool use, a wrong answer is costly."
  },
  "candidates": [
    { "id": "fast-model", "content": "Fast general model. 32k context. No tool use. Very low cost." },
    { "id": "reasoning-model", "content": "Strong multi-step reasoning. 200k context. Tool use. High cost." },
    { "id": "mid-model", "content": "Solid general model. 128k context. Tool use. Moderate cost." }
  ],
  "dimensions": [
    {
      "id": "capability_fit",
      "instructions": "Can `candidate` handle `context.task`, given its context size, tool use, and reasoning needs?",
      "levels": [
        "Cannot do the task: a hard requirement such as context size or tool use is missing",
        "Meets the hard requirements but reasoning quality is a concern for this task",
        "Meets every requirement comfortably"
      ],
      "weight": 3
    },
    {
      "id": "cost",
      "instructions": "How expensive is `candidate` to run?",
      "levels": ["High cost", "Moderate cost", "Low or very low cost"],
      "weight": 1
    }
  ]
}

composite is the weighted mean of each dimension's score / max_level. The raw scores come back too, so the agent can change the weights without another call. top_margin is the gap between first and second place. top_tied is true when that gap is at or below tie_margin (default 0.05, a starting value that does not come from the TypeSafe docs), and the order of the top two then means nothing.

Result from jev-1.13.0:

{
  "ranking": [
    {
      "id": "reasoning-model",
      "composite": 0.74,
      "dimensions": {
        "capability_fit": { "score": 1.97, "normalized": 0.985, "confidence": 0.96, "certainty": "high" },
        "cost": { "score": 0.01, "normalized": 0.005, "confidence": 0.98, "certainty": "high" }
      }
    },
    {
      "id": "mid-model",
      "composite": 0.675,
      "dimensions": {
        "capability_fit": { "score": 1.47, "normalized": 0.735, "confidence": 0.25, "certainty": "low" },
        "cost": { "score": 0.99, "normalized": 0.495, "confidence": 0.98, "certainty": "high" }
      }
    },
    {
      "id": "fast-model",
      "composite": 0.2488,
      "dimensions": {
        "capability_fit": { "score": 0, "normalized": 0, "confidence": 1, "certainty": "high" },
        "cost": { "score": 1.99, "normalized": 0.995, "confidence": 0.99, "certainty": "high" }
      }
    }
  ],
  "top_margin": 0.065,
  "top_tied": false,
  "needs_escalation": [{ "candidate": "mid-model", "dimension": "capability_fit" }],
  "model": "jev-1.13.0",
  "usage": { "input_tokens": 1358, "output_tokens": 99 }
}

The model could not place mid-model between "reasoning quality is a concern" and "meets every requirement" (confidence 0.25), so that pair is flagged. The runner-up's composite rests on that uncertain grade, and the 0.065 margin is close to the tie threshold, so an agent should check mid-model's capabilities before treating the order as settled.

In the ambiguous case, two vague documents both landed on "Same topic but does not answer the query" with confidence 0.97 and 0.99. Their composites were 0.34 and 0.33, so top_margin was 0.01 and top_tied was true. needs_escalation stayed empty, because the model was sure that both documents are weak. The signals to read there are top_tied and the low composite of the winner.

verify_claim

Check completion claims against real test output before reporting success:

{
  "evidence": "$ npm test\n PASS  src/cart.test.ts (12 tests)\n PASS  src/checkout.test.ts (8 tests)\n FAIL  src/refund.test.ts\n   x refunds above the limit require approval (expected \"pending_approval\", received \"refunded\")\nTests: 1 failed, 27 passed, 28 total",
  "claims": [
    { "id": "cart_passes", "claim": "The cart tests pass." },
    { "id": "all_green", "claim": "All tests pass." },
    { "id": "quoted", "claim": "The refund suite passes.", "quote": "PASS  src/refund.test.ts" }
  ]
}

Result from jev-1.13.0:

{
  "verdicts": [
    {
      "id": "cart_passes",
      "verdict": "verified",
      "checked_by": "model",
      "probabilities": { "contradicts": 0, "says_nothing": 0, "supports": 1 },
      "confidence": 1,
      "certainty": "high"
    },
    {
      "id": "all_green",
      "verdict": "contradicted",
      "checked_by": "model",
      "probabilities": { "contradicts": 1, "says_nothing": 0, "supports": 0 },
      "confidence": 1,
      "certainty": "high"
    },
    {
      "id": "quoted",
      "verdict": "fabricated",
      "checked_by": "string_match",
      "probabilities": null,
      "confidence": null,
      "certainty": null
    }
  ],
  "needs_escalation": [],
  "model": "jev-1.13.0",
  "usage": { "input_tokens": 584, "output_tokens": 90 }
}

The ambiguous case shows why a verdict has to be read together with its certainty. Against the same test output, the claim "The refund failure is caused by a missing approval-limit check in the refund service" came back verified, but with probabilities of 0.62 supports, 0.36 says_nothing, and 0.02 contradicts. Confidence was 0.42, so certainty was low and the claim appeared in needs_escalation. "The change did not slow down checkout" came back unsupported with confidence 0.96.

A claim with a quote that does not appear in the evidence comes back fabricated from an exact string match, without a model call, so its probabilities, confidence, and certainty are null. The match normalizes whitespace and curly quotes and nothing else, so a reworded or truncated quote also counts as fabricated. A verdict covers only the evidence passed in.

Using it for code review

The server reviews code in two ways. review_changes and review_files run the whole staged review and return one report. With judge, rank_candidates, and verify_claim the agent runs each stage itself. The packaged tools give a ranked list of places to look. The separate tools are for reviews that need questions other than the fixed ones.

The packaged review

review_changes reads nothing from disk and runs no git. The agent collects the diff and passes it in, so the agent and the tool always judge the same change:

{
  "files": [
    { "path": "src/routes/invoices.ts", "patch": "diff --git a/src/routes/invoices.ts b/src/routes/invoices.ts\n--- a/src/routes/invoices.ts\n+++ b/src/routes/invoices.ts\n@@ -12,11 +12,8 @@ ..." }
  ],
  "test_files": []
}

Each patch is the unified diff of one file with its @@ hunk headers, exactly as git printed it, because findings take their line numbers from those headers. The agent decides the scope first: which base to diff against, and whether uncommitted and untracked work is included. It leaves out generated files, lock files, and anything that must not leave the machine, since every patch goes to the TypeSafe API. test_files are not reviewed. The model receives them as evidence for the test-gap screen, so leaving them out makes that screen fire on every behavioral change.

review_files works the same way on whole files. It takes files as { "path", "content" } entries holding the complete, unmodified text, plus optional test_files, and asks whether an issue exists in the code as it stands. Neither tool touches the disk or runs a command, and neither is tied to one language. The agent picks the files at the center of the flow it cares about. A whole repository does not fit, because every file passes through the agent's context first.

Each call runs these stages, with at most three requests in flight:

Stage

Question

Limit

Screen

Five Nouls per file: correctness, security, reliability, compatibility, test gap

every file; a patch over 40,000 characters is screened in slices and the highest probability per dimension is kept

Profile

A Choice for the kind of change or file role, and a Score for review priority

the 5 files with the strongest signals

Locate

A Choice over diff hunks or 80-line source regions, with a noMatch option

the 8 strongest signals at or above 0.7; a selection below 0.55 confidence is dropped

Classify

A Choice over the mechanisms of that dimension, with a noIssue option

noIssue drops the finding

Score

Severity on a 0 to 3 rubric

none

Route

A Choice over reviewer roles

only at severity 1.5 or above

Those limits are constants in src/review-core/domain/config.ts. Both tools accept the same thresholds object as the other tools, which sets how the report is flagged.

Reading the report

src/review-report.ts reshapes the pipeline's report for an agent:

Field

Meaning

findings

Sorted by severity. Each carries the three confidences it rests on (location_confidence, mechanism_confidence, severity_confidence), a certainty taken from the lowest of them, and weakest_judgment, which names it

needs_escalation

The findings with low certainty

unresolved_signals

Every screen at or above 0.7 that produced no finding. no_evidence_located means it was followed and then dropped at the Locate or Classify stage. not_followed means it fell past the cap of 8. request_failed means the follow-up request itself failed

screening, quiet_files

Per file, the probability of each dimension that is not a clear no (at or above the lower bound of noul_band). Files where every dimension was a clear no are only counted

profiles

Category and review priority for the 5 strongest files, with a certainty

failed_requests

Every request that still failed after the SDK's retries, with its file, stage (screen, profile, locate), and error message. A file that failed at screen was not judged at all and is absent from screening and quiet_files

workflow, config

Stage counts and the pipeline constants

The pipeline's action field (request_changes at severity 2 or above) is left out. That is jev-review's merge policy, and here the agent decides what a finding warrants.

A review_changes call on three patches (a removed ownership check, a dropped Math.min in a pagination helper, and a typo fix in a string constant) took 4.0 seconds on jev-1.13.0. All five signals at or above 0.7 became findings. The top one:

{
  "file": "src/routes/invoices.ts",
  "line": 12,
  "dimension": "security",
  "probability": 0.97,
  "location_confidence": 1,
  "mechanism": "authorization",
  "mechanism_confidence": 1,
  "severity": 2.84,
  "severity_confidence": 0.84,
  "owner": "security",
  "owner_confidence": 1,
  "certainty": "high",
  "weakest_judgment": "severity"
}

The typo fix screened as a clear no on every dimension, so it appears only in quiet_files: 1. Its profile came back routine at low certainty (category confidence 0.5).

A review_files call with two of this repository's own files, src/review-core/domain/patch.ts and src/verify-claim.ts, took about 3 seconds. Neither has a test, and the test-gap screen fired on both (0.94 and 0.96). One became a finding at medium certainty, with location as its weakest judgment (confidence 0.61). The other was followed and dropped, and the report says so:

{
  "unresolved_signals": [
    { "file": "src/verify-claim.ts", "dimension": "testGap", "probability": 0.96, "reason": "no_evidence_located" }
  ],
  "needs_escalation": [],
  "failed_requests": []
}

A 0.96 screen with no finding is a place the agent still has to read for itself.

line is the first line of the selected hunk or region, which is usually not the line of the defect. A finding tells the agent where to read, and the agent still has to open the file and confirm it. Progress lines go to stderr because stdout carries the MCP protocol.

Where the review code comes from

src/review-core/ is a copy of the domain and review layers of jev-review. jev-review runs its TypeScript directly on Node.js 24 and this server compiles with tsc, so the code is copied and not imported. The copy differs from the original in four places. Relative imports end in .js. The judgment modules call the shared typesafeClient(), which is created on first use, so the server still starts without a key. isReviewReport is left out because only the jev-review dashboard uses it. runReview in review/workflow.ts no longer aborts on the first failed request: it records the failure in the report's failures list and carries on, and it raises an error only when every file fails to screen, which points at a bad key or an unreachable API and not at a partial result. Both review tools run the copied stages over what the agent passes in, so the parts of jev-review that find files are not copied: the adapters layer, review/changes.ts, review/codebase.ts, and the SOURCE_FILE, TEST_FILE, and patchForNewFile helpers that only they used. The dashboard and the report store were not copied, so these tools do not write reviews/latest.json. When jev-review changes a prompt or a threshold, copy the file again and reapply those four edits.

Running the stages yourself

With judge the agent also owns the questions: it picks the files, cuts a large patch into pieces that fit one request, and writes each screen. The server only judges what it is sent. The stages are the ones review_changes runs.

Review step

Tool

Screen a file's patch: one Noul per concern (correctness, security, reliability, compatibility, test gap), all in one call

judge

Pick the hunk that best supports a concern: a Choice over hunk ids plus a no_match option

judge

Classify the mechanism, then score severity

judge, as follow-up calls, because each needs the previous answer

Order files by how closely they need review

rank_candidates

Check a finding the agent wrote against the actual diff before reporting it

verify_claim

instructions, Choice option descriptions, Noul true/false criteria, and Score levels accept a string, an object, or an array, as the TypeSafe API does. An object helps when a review question needs scoping:

{
  "type": "noul",
  "instructions": {
    "question": "Does `file.patch` introduce or weaken a security boundary?",
    "focus": "Authorization, injection, secret exposure, unsafe defaults"
  },
  "criteria": {
    "true": { "what": "The patch opens a concrete path around a security control", "examples": ["An ownership check is removed"] },
    "false": { "what": "No security boundary is weakened", "not_for": "Code that merely uses security-related names" }
  }
}

When the agent quotes a line in a finding, pass it as quote to verify_claim. A line that is not in the patch character for character, including its +, -, or space prefix, comes back fabricated.

Results from jev-1.13.0 on the three review cases in scripts/smoke.ts, which ask three Noul screens and one severity Score per patch:

Patch

correctness

security

compatibility

severity

Flagged

Removes the account ownership check from GET /invoices/:id

0.84 yes

0.97 yes

0.90 yes

2.98 of 3, confidence 0.98

none

Drops Math.min(start + size, items.length) from a pagination helper

0.28 no

0.05 no

0.50 uncertain

0.67 of 3, confidence 0.33 (low)

compatibility, severity

The pagination patch is harmless only because Array.prototype.slice clamps its end index, which the patch does not show. The model leaned toward "no bug" and flagged the two answers it could not settle, so the agent knows to open the file before it writes a finding. On the first patch, the 0.90 for compatibility is debatable: no caller should depend on receiving a 403. Read each screen as a prompt to look.

verify_claim then checked three findings against the first patch. "Any authenticated user can read another account's invoice", quoted with the removed line, came back verified at confidence 0.99. "This patch introduces a SQL injection through req.params.id" came back unsupported (0.91 says_nothing, 0.09 contradicts, confidence 0.86). A finding that quoted the 404 line with a - prefix came back fabricated, because the patch carries that line as unchanged context.

Jev judges the patch text it is given. It does not compile the code, run tests, or follow calls into files it was not sent, so treat a fired screen as a place to look and not as proof of a defect.

Smoke test

Run it from a checkout after npm run build:

npm run smoke

The script starts dist/index.js over stdio, lists the tools, and calls each one against the real API with a representative case and at least one ambiguous case. It needs TYPESAFE_API_KEY in the environment and Node.js 22.18 or newer, because it runs the TypeScript file directly.

Limits

Answers are not bit-for-bit repeatable. Two runs of the same smoke cases on jev-1.13.0 gave the same choices, verdicts, and flags, while individual numbers moved by a few hundredths (a risk score of 2.11 then 2.09, a confidence of 0.33 then 0.25). Leave room for that when you set a threshold close to a value you have observed.

One request carries the state and all its questions in a budget of roughly 32,000 tokens. rank_candidates sends one request per candidate in parallel, so 30 candidates means 30 requests. The SDK retries 408, 429, and 5xx responses with backoff, and each attempt times out after 10 seconds.

review_changes and review_files send at least one request per file, three at a time. Three files took about 4 seconds from call to report. Both accept at most 100 files per call, and a call that large can outlast an MCP client's tool timeout, so review in batches.

License

MIT

Available Tools

5 tools
judgeJudge (Choice / Noul / Score)A
Read-only

Get fast, calibrated judgments from the Jev model at a decision point, instead of guessing in free text. Returns typed answers with probabilities. It never returns prose or reasoning, and it does not decide for you.

WHEN TO USE: you are about to pick between known options (which tool, route, plan, or file; allow/confirm/deny a risky action), check whether a condition holds (is the task complete, is there enough information to stop, does this need user confirmation), or grade something on a dimension you can describe (risk, relevance, severity). Do not use it for open-ended reasoning, arithmetic, exact lookups, or anything plain code or a tool can settle.

QUESTION TYPES:

  • choice: exactly one of a set of options you define.

  • noul: whether a condition holds. Use one noul per label when several labels may apply.

  • score: a position on ordered levels you describe.

HOW TO READ THE RESULT:

  • choice: "choice" is the top option, "probabilities" covers every option, "confidence" (0-1) says how concentrated that distribution is. Low confidence means no option clearly wins, which can also happen when two options are both acceptable.

  • noul: "noul" is the probability that the answer is yes. Near 1 is a strong yes, near 0 a strong no. Near 0.5 means the model cannot tell. It does NOT mean "medium" or "partly". If you want a degree, ask a score question.

  • score: "score" is the probability-weighted mean level, from 0 to "max_level", and can land between levels. Different distributions give the same score, so read "probabilities" and "confidence" with it.

  • "certainty" (high/medium/low) and the noul "verdict" (yes/no/uncertain) apply the thresholds to those numbers. "needs_escalation" lists every question id whose answer is low certainty or uncertain.

WHEN AN ANSWER IS FLAGGED: do not act on it as if it were settled. Escalate in whatever way fits your situation: gather the missing evidence and ask again, reason the point through yourself, or ask the user. Medium certainty means proceed with caution, and verify first if the action is hard to undo. High confidence describes the model's answer, not a guarantee of truth or permission to act.

ParametersJSON Schema
NameRequiredDescriptionDefault
stateYesThe facts the judgment is about. Prefer an object with named fields (e.g. { user_request, plan_a, plan_b, test_output }) over one blob of text. Pass only what bears on the decision, and pass actual content (the log, the diff), not your summary of it: the model sees nothing else and knows nothing about your conversation.
questionsYesMap of question id -> question. Put every independent question about this state in the same call, including ones you may not need: they run in parallel and cannot see each other's answers.
thresholdsNoOverride the uncertainty thresholds for this call. Tighten them (e.g. confidence_high 0.9, noul_band [0.1, 0.9]) when acting on a wrong answer would be costly or irreversible.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modelYes
usageYes
answersYes
needs_escalationYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds substantial behavioral context beyond that: it never returns prose or reasoning, it does not decide for you, it returns probabilities and confidence, low confidence can mean two options are both acceptable, noul near 0.5 means 'cannot tell' not 'medium', and flagged answers must not be acted on as settled. This is rich, non-obvious behavior that an agent must know before invoking. It loses one point only because it does not explicitly discuss rate limits or latency, which are minor for a read-only judgment tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every section earns its place: purpose, when-to-use, question types, result interpretation, and escalation behavior. It is front-loaded with the core purpose and the 'never returns prose' constraint. It loses one point because the result-reading section is dense and could be tightened; some sentences (e.g., the escalation paragraph) repeat the 'do not act on flagged answers' idea in slightly different forms. Still, for a tool with three question types and a rich output, this length is justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (3 question types, nested question objects, thresholds, rich output schema), the description is remarkably complete. It explains the three question types, how to interpret each result field, what the certainty/verdict/escalation fields mean, and how to handle flagged answers. The output schema exists, so return values need not be re-explained. The only minor gap is no explicit mention of rate limits or cost, but those are not essential for correct invocation. For a tool this complex, this is a model definition.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds real value beyond the schema: it explains how to read the result fields (choice/probabilities/confidence, noul, score, certainty, verdict, needs_escalation), which is not in the input schema. It also gives guidance on state ('pass actual content, not your summary') and questions ('put every independent question in the same call'). However, the description does not add much about the thresholds parameter beyond what the schema already says, and the question-type semantics are mostly carried by the schema's detailed per-type descriptions. So it is a solid 4, not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Get fast, calibrated judgments from the Jev model at a decision point') and immediately contrasts with free-text guessing. It names the three question types (choice, noul, score) and explicitly says what it never returns (prose/reasoning) and what it does not do (decide for you). This clearly distinguishes it from siblings like review_files or verify_claim, which are about reviewing or verifying rather than producing calibrated probabilistic judgments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'WHEN TO USE' section is explicit and actionable: it lists concrete decision scenarios (pick between known options, check a condition, grade on a dimension) and gives a 'Do not use' list (open-ended reasoning, arithmetic, exact lookups, plain code/tool-settable things). This is exactly the when/when-not guidance an agent needs to route correctly among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rank_candidatesRank candidates on weighted dimensionsA
Read-only

Rank 2-30 candidates (search results, candidate plans, next actions, models to route to) by grading each one on several described dimensions and combining the grades with your weights. Returns numbers only, never prose.

WHEN TO USE: you have a shortlist and the better choice depends on more than one factor (relevance and freshness; expected benefit, risk, and effort). For picking one option on a single question, use judge with a choice question instead.

WHAT TO PASS: "context" holds what every candidate is judged against (the query, the goal, constraints). Each candidate is graded in its own request, seeing only "context" and its own "content" as candidate, so grades are comparable and a candidate is never judged relative to the others. Dimensions must be independent; split "good and cheap" into two dimensions.

HOW TO READ THE RESULT:

  • "ranking" is sorted best first. "composite" is the weighted mean of the normalized dimension scores, from 0 to 1.

  • Each dimension reports "score" (probability-weighted level, can fall between levels), "normalized" (score divided by the top level), "confidence", and "certainty". The raw scores are returned so you can re-weight without calling again.

  • "top_margin" is the composite gap between first and second place. "top_tied" is true when that gap is at or below "tie_margin": the ranking does not separate the two, so do not trust their order. Break the tie on something else or treat both as equal.

  • Read the winner's "composite" as well as its rank. When every candidate is weak, the top one still has a low composite, and the right move may be to look for better candidates.

  • "needs_escalation" lists each candidate/dimension pair graded with low certainty. That usually means the candidate's content does not say enough about that dimension, or the levels overlap. If a flagged pair involves a top candidate, get the missing information or verify before acting on the ranking.

ParametersJSON Schema
NameRequiredDescriptionDefault
contextYesNamed fields shared by every candidate: the query or goal, constraints, relevant facts.
candidatesYes
dimensionsYes
thresholdsNoOverride the uncertainty thresholds for this call. Tighten them (e.g. confidence_high 0.9, noul_band [0.1, 0.9]) when acting on a wrong answer would be costly or irreversible.
tie_marginNoFirst and second place count as tied when their composite gap is at or below this. Default 0.05.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modelYes
usageYes
rankingYes
top_tiedYes
top_marginYes
needs_escalationYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, and the description adds meaningful behavioral context: each candidate is judged in its own request seeing only 'context' and its own 'content', candidates are never compared against each other, and low-certainty pairs are surfaced via 'needs_escalation'. It also explains how ties are handled and warns not to trust the order when 'top_tied' is true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but tightly organized with clear sections (WHEN TO USE, WHAT TO PASS, HOW TO READ THE RESULT) and front-loads the core instruction. Each section earns its place by addressing a distinct decision the agent must make: when to call, what to pass, and how to interpret the response.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite the rich output schema, the description adds essential interpretation details: how to read 'composite', 'top_margin', 'top_tied', and 'needs_escalation', plus a warning about weak candidates where the top one still has a low composite. For a complex tool with nested parameters and multiple siblings, nothing needed for correct invocation or result interpretation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60%, so the description needs to add meaning, and it does. It clarifies that 'context' is the shared basis for judging all candidates, that each candidate's 'content' is judged only against that context, that dimensions must be independent ('split good and cheap into two dimensions'), and that levels are ordered worst to best with cost-like dimensions having the most expensive case first.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Rank 2-30 candidates... by grading each one on several described dimensions'. It also states the output contract ('Returns numbers only, never prose') and explicitly distinguishes itself from judge, making the tool's purpose and scope immediately clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'WHEN TO USE' section states the exact condition for selection ('you have a shortlist and the better choice depends on more than one factor') and names the alternative for the opposite case: 'For picking one option on a single question, use judge with a choice question instead.' This is explicit when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

review_changesReview a diffA
Read-only

Run the staged Jev review over a diff you supply and return a structured report, never prose. The tool reads nothing from disk and runs no git: it judges exactly the patches you pass, so you and the tool are always looking at the same change.

WHEN TO USE: before committing, before opening or merging a pull request, or when asked to review a branch, once you have collected the diff. For a single judgment about one patch, use judge. To check a finding you wrote yourself, use verify_claim.

WHAT TO PASS: "files" holds one entry per changed source file, each with its own unified diff. Decide the scope yourself first (which base, whether uncommitted and untracked work is included) and leave out generated files, lock files, and anything that must not leave the machine: every patch is sent to the TypeSafe API. "test_files" holds the changed test files in the same shape. They are not reviewed; they are the evidence used when judging whether changed behavior lacks a test, so omitting them makes every test-gap screen fire.

COST: one request per file for screening (more for a patch over about 40,000 characters, which is split by hunk), then up to five profiling requests and about four requests for each of at most eight followed signals. Three files take a few seconds; a hundred take minutes.

HOW TO READ THE RESULT:

  • "findings" is sorted by descending "severity" (0 to config.severity_max). Each one names a "file", a "line" (the first line of the evidence region, not the exact defect line), a "dimension" (correctness, security, reliability, compatibility, testGap), and a "mechanism". As a reference point, the jev-review workflow this pipeline comes from requests changes at severity 2 or above and comments below that. What to do with a finding is your decision.

  • A finding is a lead, not a verdict. Open the file at the cited line and confirm it yourself before you repeat it. Pass the confirmed claim and the code to verify_claim if you want a second check.

  • Each finding rests on three judgments: where the evidence is, which mechanism it shows, and how severe it is. "certainty" (high/medium/low) applies the thresholds to the least confident of the three, and "weakest_judgment" names it. A weak "location" often means the line is wrong even when the concern is real. "needs_escalation" lists the findings with low certainty: do not treat those as settled.

  • "unresolved_signals" lists every screening signal at or above config.screen_threshold that produced no finding. "no_evidence_located" means it was followed, but no region was selected with enough confidence or the mechanism check found no concrete issue. "not_followed" means it fell past the config.max_follow_ups cap and was never examined. "request_failed" means the follow-up request itself failed. None of them means the file is fine: a screen fired and nothing confirmed or refuted it, so those files still need your own read, strongest probability first.

  • "screening" holds, per file, the probability of every dimension that is not a clear no (at or above the lower bound of the noul band). A probability near 0.5 means the screen could not tell, not that the file is half broken. "quiet_files" counts the files where every dimension was a clear no; they are left out to keep the report small.

  • "profiles" covers the config.max_profiles files with the strongest signals: a category and a "review_priority" from 0 (routine) to 3 (specialist review), with a "certainty" from the less confident of the two.

  • "failed_requests" lists every request that still failed after retries, with its "file" and "stage". A file that failed at the "screen" stage was not judged at all: it is missing from "screening", is not counted in "quiet_files" or "workflow.screened_files", and needs either a second call with just that file or your own read. A "profile" failure only costs that file its profile. When every file fails to screen, the tool returns an error instead of a report.

  • "owner" is set only for findings at severity 1.5 or above.

  • An empty "findings" array does not mean the code is free of defects. Check "unresolved_signals" first. Jev reads only the text it is sent and does not compile, run tests, or follow calls into other files.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesYesChanged source files to review.
test_filesNoChanged test files, used only as evidence for the test-gap dimension.
thresholdsNoOverride the uncertainty thresholds for this call. Tighten them (e.g. confidence_high 0.9, noul_band [0.1, 0.9]) when acting on a wrong answer would be costly or irreversible.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
scopeYes
configYes
findingsYes
profilesYes
workflowYes
screeningYes
quiet_filesYes
failed_requestsYes
needs_escalationYes
unresolved_signalsYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint/openWorldHint annotations, it discloses that the tool reads nothing from disk, runs no git, sends patches to the TypeSafe API, does not compile or run tests, and explains that findings are leads requiring manual confirmation. This adds substantial trust and safety context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with headings, purpose front-loaded, and no filler. The length is considerable but justified by the tool's complexity; every section earns its place, though it could be slightly tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even with an output schema present, the description explains how to interpret findings, uncertainty, unresolved_signals, failed_requests, and cost/performance. It covers edge cases like empty findings and screen failures, making it fully complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description explains scope decisions (choose base, include uncommitted/untracked work), what to exclude (generated files, lock files, sensitive data), the exact patch format required (unified diff as git printed), and the role of test_files as evidence whose omission fires test-gap screens. This goes far beyond the schema's field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource: 'Run the staged Jev review over a diff you supply and return a structured report, never prose.' It explicitly names alternatives (judge, verify_claim) for different use cases, distinguishing it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Has a dedicated WHEN TO USE section listing concrete scenarios (before committing, before opening/merging a PR, when asked to review a branch) and explicitly directs to judge for single-patch judgments and verify_claim for checking findings. This is clear and complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

review_filesReview source files as they standA
Read-only

Run the staged Jev review over source files you supply and return a structured report, never prose. It asks whether an issue exists in the code as it stands, not whether a change introduced one. The tool reads nothing from disk: it judges exactly the text you pass, so you and the tool are always looking at the same code.

WHEN TO USE: to audit files you did not just change, or to find where to start reading unfamiliar code. To review work in progress or a branch, collect the diff and use review_changes, which sends far less text.

WHAT TO PASS: "files" holds the source files to review, each with its full content. Choose them yourself: the files at the center of the flow you care about, not a whole repository, because every file passes through your context and then goes to the TypeSafe API. Leave out generated code, vendored code, and anything that must not leave the machine. "test_files" holds related test files in the same shape. They are not reviewed; they are the evidence used when judging whether behavior lacks a test, so omitting them makes every test-gap screen fire.

COST: one screening request per 160 lines of each file, three files at a time, then up to five profiling requests and about four requests for each of at most eight followed signals.

HOW TO READ THE RESULT:

  • "findings" is sorted by descending "severity" (0 to config.severity_max). Each one names a "file", a "line" (the first line of the evidence region, not the exact defect line), a "dimension" (correctness, security, reliability, compatibility, testGap), and a "mechanism". As a reference point, the jev-review workflow this pipeline comes from requests changes at severity 2 or above and comments below that. What to do with a finding is your decision.

  • A finding is a lead, not a verdict. Open the file at the cited line and confirm it yourself before you repeat it. Pass the confirmed claim and the code to verify_claim if you want a second check.

  • Each finding rests on three judgments: where the evidence is, which mechanism it shows, and how severe it is. "certainty" (high/medium/low) applies the thresholds to the least confident of the three, and "weakest_judgment" names it. A weak "location" often means the line is wrong even when the concern is real. "needs_escalation" lists the findings with low certainty: do not treat those as settled.

  • "unresolved_signals" lists every screening signal at or above config.screen_threshold that produced no finding. "no_evidence_located" means it was followed, but no region was selected with enough confidence or the mechanism check found no concrete issue. "not_followed" means it fell past the config.max_follow_ups cap and was never examined. "request_failed" means the follow-up request itself failed. None of them means the file is fine: a screen fired and nothing confirmed or refuted it, so those files still need your own read, strongest probability first.

  • "screening" holds, per file, the probability of every dimension that is not a clear no (at or above the lower bound of the noul band). A probability near 0.5 means the screen could not tell, not that the file is half broken. "quiet_files" counts the files where every dimension was a clear no; they are left out to keep the report small.

  • "profiles" covers the config.max_profiles files with the strongest signals: a category and a "review_priority" from 0 (routine) to 3 (specialist review), with a "certainty" from the less confident of the two.

  • "failed_requests" lists every request that still failed after retries, with its "file" and "stage". A file that failed at the "screen" stage was not judged at all: it is missing from "screening", is not counted in "quiet_files" or "workflow.screened_files", and needs either a second call with just that file or your own read. A "profile" failure only costs that file its profile. When every file fails to screen, the tool returns an error instead of a report.

  • "owner" is set only for findings at severity 1.5 or above.

  • An empty "findings" array does not mean the code is free of defects. Check "unresolved_signals" first. Jev reads only the text it is sent and does not compile, run tests, or follow calls into other files.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesYesSource files to review.
test_filesNoRelated test files, used only as evidence for the test-gap dimension.
thresholdsNoOverride the uncertainty thresholds for this call. Tighten them (e.g. confidence_high 0.9, noul_band [0.1, 0.9]) when acting on a wrong answer would be costly or irreversible.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeYes
scopeYes
configYes
findingsYes
profilesYes
workflowYes
screeningYes
quiet_filesYes
failed_requestsYes
needs_escalationYes
unresolved_signalsYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, and the description reinforces them by noting the tool reads nothing from disk, judges exactly the text passed, and does not compile, run tests, or follow calls. It also discloses cost, retry/failure behavior, and the meaning of empty findings, which is materially useful and does not contradict 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well structured with clear headings and a front-loaded purpose. Nearly every section carries operational value, though a few points are repeated and the output-field walkthrough goes beyond what a shorter definition would need, preventing a perfect conciseness score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with nested parameters, a rich output schema, and several sibling tools, the description is unusually complete: it covers when to use it, what to pass, cost, how to interpret findings, failure stages, and the open-world limitation. An agent has enough context to select the tool, invoke it correctly, and act on the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents the parameters; the description adds real value for files and test_files: full unmodified content, no trimming or line numbers, choose only relevant files, leave out generated/vendored/confidential code, and test_files are evidence only for the test-gap dimension. thresholds is not elaborated in the prose, but the schema description covers it adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action: run the staged Jev review over supplied source files and return a structured report, never prose. It clarifies the scope (whether an issue exists in code as it stands, not whether a change introduced one) and differentiates itself from review_changes, which handles diffs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is an explicit WHEN TO USE section stating this tool is for auditing files you did not just change or for finding where to start reading unfamiliar code, and that review_changes should be used for work in progress or a branch. It also gives exclusion guidance: pass files at the center of the flow, not a whole repository, and omit generated, vendored, or sensitive code.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_claimVerify claims against evidenceA
Read-only

Check whether supplied evidence actually supports claims you are about to state or act on. Returns a verdict and probabilities per claim, never prose.

WHEN TO USE: before reporting work as complete or a bug as fixed, before stating a root cause, before citing a source, or before building the next step on something you concluded earlier. Pass the claim and the raw evidence you believe backs it.

WHAT TO PASS: "evidence" is the actual material (test output, diff, log, document text), and "claims" are the specific statements to check against it. Several claims about the same evidence go in one call. Add "quote" when you attribute exact words to the evidence.

HOW TO READ THE RESULT, per claim:

  • verified: the evidence states or directly implies the claim.

  • contradicted: the evidence says the opposite. Retract or fix the claim.

  • unsupported: the evidence does not address the claim either way. The claim may still be true, but this evidence does not show it; find evidence that does.

  • fabricated: the "quote" is not in the evidence. Decided by string match with no model call, so "probabilities", "confidence", and "certainty" are null.

  • "probabilities" covers supports / contradicts / says_nothing. "confidence" (0-1) says how concentrated that distribution is, and "certainty" (high/medium/low) applies the thresholds to it.

  • "needs_escalation" lists claim ids whose verdict has low certainty. Do not treat those as settled, including a low-certainty "verified": get more direct evidence, check it yourself, or tell the user the claim is unconfirmed. A verdict only covers the evidence you passed; it cannot notice evidence you left out.

ParametersJSON Schema
NameRequiredDescriptionDefault
claimsYes
evidenceYesThe source material itself: test output, a diff, a log, a document section, fetched page text. Not your summary of it. The model judges the claim against this and nothing else.
thresholdsNoOverride the uncertainty thresholds for this call. Tighten them (e.g. confidence_high 0.9, noul_band [0.1, 0.9]) when acting on a wrong answer would be costly or irreversible.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modelYes
usageYes
verdictsYes
needs_escalationYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the readOnlyHint/openWorldHint annotations by disclosing exact verdict semantics ('verified', 'contradicted', 'unsupported', 'fabricated'), stating that fabricated verdicts use string matching with no model call, that probabilities are null in that case, and that needs_escalation means a verdict is not settled. It also warns that the tool cannot notice omitted evidence, reinforcing the openWorldHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but tightly organized with clear section headers ('WHEN TO USE', 'WHAT TO PASS', 'HOW TO READ THE RESULT'). Every paragraph contributes new, decision-relevant detail, and the most important guidance is front-loaded. Nothing feels redundant or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with nested claim objects, an evidence union type, tunable thresholds, and a rich result, the description covers all the tricky parts: claim splitting, quote handling, verdict interpretation, low-certainty escalation, and the fact that evidence scope bounds the conclusion. The presence of an output schema reduces the need to document return values, but the description adds even more clarity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though the schema already documents each parameter, the description adds operational meaning: evidence must be raw material, not a summary; claims should be split into separate entries; quote is checked by exact string match; thresholds can be tightened when the cost of a wrong answer is high. This makes the abstract schema actionable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Check whether supplied evidence actually supports claims') and a clear resource/scope ('claims you are about to state or act on'). It also immediately distinguishes the tool's output format ('verdict and probabilities per claim, never prose'), which separates it from vague review/judgment tools among siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'WHEN TO USE' section is explicit and practical, listing concrete moments such as 'before reporting work as complete', 'before citing a source', and 'before building the next step'. 'WHAT TO PASS' clarifies what counts as evidence versus claims. It does not explicitly name alternative tools or say when not to use it, so it falls just 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.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedjudge
    • First observedrank_candidates
    • First observedreview_changes
    • First observedreview_files
    • First observedverify_claim

TDQS

A4.6/5.0

Scored across 5 tools

Disambiguation4/5

The tools are generally distinct: review_files vs review_changes differ by input type (files vs diff), and judge/rank_candidates/verify_claim have clear use cases. However, review_files and review_changes could be confused by an agent scanning quickly, and judge with a choice question overlaps with rank_candidates for single-dimension ranking.

Naming Consistency4/5

All tool names follow a clear verb_noun pattern (review_files, review_changes, verify_claim, rank_candidates, judge). The pattern is consistent, though 'judge' is a single verb without a noun, which is a minor deviation from the otherwise consistent scheme.

Tool Count5/5

With 5 tools, the server is tightly scoped around the Jev review workflow: two review modes (files/changes), a verification tool, and two decision-support tools (judge, rank_candidates). Each tool has a distinct role and no redundancy; the count is ideal for this purpose.

Completeness4/5

The tool surface covers the core review lifecycle: review current code, review changes, verify claims, and make decisions. A minor gap is the lack of a tool to aggregate or compare multiple review results, but agents can work around that by calling review tools separately.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Provides coding agents and CI with a typed decision layer that sends bounded state and questions to Jev, then returns deterministic actions for review, risk assessment, requirement checks, and verification.
    9
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables frontier coding agents to delegate routine probabilistic judgments to TypeSafe Jev, providing calibrated triage signals for failures, attempts, completion, context ranking, findings, risk, and generic evidence-grounded questions.
    7
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI coding agents to make fast, zero-output-token decisions by evaluating context, diffs, logs, or options through the OpenRouter Decisions API using TypeSafe Jev, returning calibrated probabilities for binary, categorical, or scoring questions.
    1
    136 npm
    2
    MIT