proofread-mcp
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., "@proofread-mcpCheck the case citations in this brief before we file."
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.
proofread-mcp
An MCP server for proofread.law. It lets Claude Desktop, Claude Code, Cursor and the OpenAI Agents SDK check US case citations before a draft is filed.
proofread.law checks each citation against an open register of about 10 million court opinions (CourtListener bulk data). Every result says what was checked, what was found, and what the register cannot see.
What it does
Six tools:
Tool | Input | What comes back |
| text, | The coverage statement, counts per tier, one line per row that needs a human, the number of citations found, a report id |
| path to a | The same, for a file on disk |
| one citation string | The register's answer for that citation: found (case, court, date, parallel citations, link), ambiguous (candidates), not in the register, cannot verify, known citation, or no citation recognised; the coverage of that volume; the coverage statement |
| a list of up to 500 citation strings | Counts by status, one line per citation in input order, the coverage statement |
| nothing | The coverage statement and the storage notice |
| a report id from a previous check, or the full report JSON | A markdown diligence report |
check_citations and check_document read prose: they compare the case name and any quotation with the register. resolve_citation and resolve_citations look the citation string up in the register (the /v1/resolve API) and tell you which case sits there; they do not compare it with the name you have.
Tiers, in the words the tools use:
Tier | Word | Meaning |
red | check this | The register holds something concrete that disagrees: a different case at that citation, a volume or page that does not match, quoted words not in the opinion |
orange | cannot verify | Nothing to check against: a Westlaw or Lexis identifier, a volume newer than the register, a reporter the register holds only in part. Not evidence either way |
green | found | The citation resolves to a case whose caption matches |
white | deep check | With |
What it cannot do: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law. Those limits are stated in every tool description and in the coverage statement that comes with every result.
Related MCP server: CourtListener Citation Validation MCP Server
Install
Needs Node 20 or newer. No install step is required; npx fetches it.
Until the package is on npm, clone this repository, run npm install && npm run build, and use node /absolute/path/to/proofread-mcp/dist/cli.js wherever the snippets below say npx -y proofread-mcp.
Claude Desktop
Edit claude_desktop_config.json (Settings, Developer, Edit Config):
{
"mcpServers": {
"proofread": {
"command": "npx",
"args": ["-y", "proofread-mcp"],
"env": {
"PROOFREAD_API_KEY": "pl_..."
}
}
}
}Leave out env to use the free tier.
Claude Code
claude mcp add proofread -- npx -y proofread-mcp
# with a Firm key:
claude mcp add proofread -e PROOFREAD_API_KEY=pl_... -- npx -y proofread-mcpCursor
Settings, MCP, Add new global MCP server, or write .cursor/mcp.json in the project:
{
"mcpServers": {
"proofread": {
"command": "npx",
"args": ["-y", "proofread-mcp"],
"env": { "PROOFREAD_API_KEY": "pl_..." }
}
}
}OpenAI Agents SDK (over HTTP)
Start the server with the HTTP transport:
PROOFREAD_API_KEY=pl_... npx proofread-mcp --http --port 3333
# MCP endpoint: http://127.0.0.1:3333/mcp health: http://127.0.0.1:3333/healthThen connect from the Agents SDK:
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
async with MCPServerStreamableHttp(params={"url": "http://127.0.0.1:3333/mcp"}) as proofread:
agent = Agent(name="Drafting assistant", instructions="Check every case citation before you rely on it.", mcp_servers=[proofread])
result = await Runner.run(agent, "Check the citations in this paragraph: ...")import { Agent, run, MCPServerStreamableHttp } from "@openai/agents";
const proofread = new MCPServerStreamableHttp({ url: "http://127.0.0.1:3333/mcp", name: "proofread" });
await proofread.connect();
const agent = new Agent({ name: "Drafting assistant", mcpServers: [proofread] });
const result = await run(agent, "Check the citations in this paragraph: ...");The HTTP server binds to 127.0.0.1 by default. To expose it on a network use --host 0.0.0.0 and put it behind something that adds authentication; the server has none of its own.
Any MCP client
stdio: run proofread-mcp. Streamable HTTP: run proofread-mcp --http --port 3333 and point the client at /mcp.
Environment variables
Variable | Default | Meaning |
| unset | A Firm plan API key ( |
|
| Base URL, for a self-hosted or test instance |
Free tier
Without a key, per IP address and per month:
Tools | Quota |
| 20 checks, of which 3 may be deep checks |
| 1,000 resolves (each citation in a list counts as one) |
| free, not counted |
There is also a limit of 20 requests an hour per IP. When a limit is reached the tool returns a plain message with the retry time or the upgrade link; nothing is thrown at the protocol level.
.docx upload and unlimited checks need a paid plan. See proofread.law/pricing.
Privacy
The text or file goes to proofread.law, which runs on its own machine, not a cloud provider's API. It is processed in memory and discarded when the report is returned. Only counts (citations, tiers, timing) are logged, never text.
A citation string the local register cannot resolve may be looked up in the CourtListener citation API. Only the citation string leaves, never a party name or prose.
Deep check (
deep: true) is opt-in. In that mode the clause before each citation (up to 700 characters) is sent to a model judge, together with the cited opinion. That is the only mode in which any of the document's prose leaves proofread.law.This server stores nothing on disk. It keeps the last 50 reports in memory so
render_reportcan be called with a short id; they are gone when the process exits.
The coverage caveat
Every result starts with the coverage statement, for example:
Checked against 10.1 M cases (CourtListener bulk data 2026-06-30, last refreshed 2026-09-19); federal appellate 2019 to 2023 is 10 to 15% incomplete; Westlaw/Lexis identifiers are not resolvable; statutes, regulations and secondary sources are not checked.
Read it. A citation that is not in the register is a register fact with a coverage qualifier, not proof that the case does not exist. A red row says "check this"; the tools say what was checked and what was found, never that a case is invented.
Example
Input:
Title VII forbids discrimination because of sexual orientation. Bostock v. Clayton County, 509 U.S. 644 (2020).
check_citations returns (real output, review instance, 2026-09-20):
Coverage: Checked against 10.1 M cases (CourtListener bulk data 2026-06-30, last refreshed 2026-09-19); federal appellate 2019 to 2023 is 10 to 15% incomplete; Westlaw/Lexis identifiers are not resolvable; statutes, regulations and secondary sources are not checked.
Summary: 1 citation, 1 row. Check this (red): 1. Cannot verify (orange): 0. Found (green): 0.
Flagged rows:
- CHECK THIS: 509 U.S. 644 (Bostock v. Clayton County). Register has Bostock v. Clayton County at 590 U.S. 644. Check the volume. In the register, 509 U.S. 644 is Shaw v. Reno. The case named in the document exists; this citation does not point to it. Register: https://www.courtlistener.com/opinion/4760997/bostock-v-clayton-county/
Found: 0 rows resolved to a case in the register.
Report id: r_1ff74051 (give it to render_report for a markdown report). Elapsed: 0.03 s.
Storage: Nothing you submit is stored. The document is processed in memory and discarded when this report is returned; only counts (citations, tiers, timing) are logged, never text.Development
npm install
npm run build # tsc -> dist/
npm test # vitest, mocked fetch, no network
LIVE=1 npm test -- test/live.test.ts # three live calls against proofread.law (counts against the free tier)
node scripts/smoke-stdio.mjs # spawn the stdio server, initialize, tools/list, four live tool calls
node scripts/smoke-stdio.mjs --offline # the same without networkLayout: src/client.ts is the typed HTTP client (/verify, /render, /api/coverage, /v1/resolve single and batch), src/format.ts the compact formatter for checks, src/resolve_format.ts the one for register answers, src/tools/<name>.ts one file per tool, src/server.ts registers them, src/cli.ts picks the transport. The remaining register routes (/v1/extract, /v1/case/{id}, /v1/coverage per reporter) slot in the same way: one method on the client, one file under src/tools/.
Publishing
See RELEASE.md. The package is not on npm yet and the repository is private until the owner makes it public.
License
MIT, Data Alchemy Labs.
Available Tools
6 toolscheck_citationsCheck legal citations in textARead-onlyIdempotent
Check every case citation in a text against proofread.law's register of about 10 million US court opinions (CourtListener bulk data). Use it on a draft brief, memo, letter or any prose that cites cases, before the citations are relied on. Returns the coverage statement, counts per tier, one line per row that needs a human (red = check this: the register holds something concrete that disagrees, such as a different case at that citation or quoted words not in the opinion; orange = cannot verify: nothing to check against, such as a Westlaw/Lexis identifier or a volume newer than the register), the number of citations found, and a report id for render_report. Cannot: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law. A red row means 'check this', never 'this case does not exist'; an orange row means the register has nothing to check against, which is not evidence either way. deep=true also asks, for each found citation, whether the opinion supports the sentence it is cited for (white rows). It is slower (1 to 2 s per citation), opt-in because the clause before each citation is sent to a model judge, limited to 3 per month on the free tier, and its answers are a review queue, not a verdict. Free tier: 20 checks a month per IP; a Firm API key in PROOFREAD_API_KEY lifts that.
| Name | Required | Description | Default |
|---|---|---|---|
| deep | No | Also check whether each cited opinion supports the sentence it is cited for. Slower, opt-in, 3 per month on the free tier. | |
| text | Yes | The text to check, as written (paragraphs, footnotes, a whole brief). Pasted text is fine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, openWorld, idempotent, non-destructive), the description details the output structure (coverage statement, counts per tier, red/orange rows), the meaning of red and orange (check this vs cannot verify), and the deep mode behavior (slower, opt-in, limited to 3/month, answers are a review queue not a verdict). It also discloses free tier limits and API key lifting. No contradictions with 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?
The description is long but every sentence carries critical information. It is front-loaded with the core function, then usage, then output details, limitations, deep mode, and free tier. It is organized logically without redundancy, making efficient use of the reader's attention.
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?
This is a complex tool with no output schema, so the description must explain the return values. It does: coverage statement, counts per tier, one line per row needing human, number of citations, and report id for render_report. It also explains what it cannot do and the meaning of red/orange. The description fully equips an agent to call the tool correctly and interpret results.
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?
Although schema coverage is 100%, the description adds substantial meaning to the 'deep' parameter: it explains that it checks whether the opinion supports the sentence, is slower (1-2s per citation), sends the clause to a model judge, is limited to 3/month, and returns a review queue. For 'text', the schema already describes it, but the description reinforces its use for prose. The description adds value beyond the schema.
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: 'Check every case citation in a text against proofread.law's register of about 10 million US court opinions'. It also specifies the use case (draft brief, memo, letter) and differentiates from siblings by explicitly stating what it cannot do (resolve WL/Lexis, check statutes/regulations).
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?
It explicitly instructs when to use it: 'Use it on a draft brief, memo, letter or any prose that cites cases, before the citations are relied on.' It also lists exclusions (cannot resolve WL/Lexis, check statutes, etc.) and describes the deep mode option with clear trade-offs (slower, opt-in, limited). This provides clear guidance for selecting this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_documentCheck legal citations in a fileARead-onlyIdempotent
Check every case citation in a document on disk (PDF, DOCX or TXT, up to 10 MB) against proofread.law's register of about 10 million US court opinions. The file is read here and uploaded to proofread.law, which extracts the text in memory, checks it and discards it. Returns the same compact result as check_citations: coverage statement, counts per tier, one line per red (check this) or orange (cannot verify) row, the number of citations found, and a report id for render_report. Scanned PDFs without a text layer, encrypted PDFs and legacy .doc files cannot be read; .docx needs a paid plan. Cannot: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law. A red row means 'check this', never 'this case does not exist'; an orange row means the register has nothing to check against, which is not evidence either way. deep=true also asks, for each found citation, whether the opinion supports the sentence it is cited for (white rows). It is slower (1 to 2 s per citation), opt-in because the clause before each citation is sent to a model judge, limited to 3 per month on the free tier, and its answers are a review queue, not a verdict.
| Name | Required | Description | Default |
|---|---|---|---|
| deep | No | Also check whether each cited opinion supports the sentence it is cited for. Slower, opt-in, 3 per month on the free tier. | |
| path | Yes | Absolute path to a .pdf, .docx or .txt file on this machine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Richly discloses behavior beyond annotations: file is uploaded to proofread.law, processed in memory, and discarded; deep mode sends clauses to a model judge with speed/cost limits; red/orange row semantics are explicitly defined. This gives agents crucial context that annotations (readOnlyHint, openWorldHint) do not cover.
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 the main purpose and then details, but is a dense block of text that could be broken into bullets for readability. Still, every sentence carries informative value, so it is appropriately sized for the tool's complexity.
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?
Covers purpose, input constraints, data handling, output shape (coverage statement, counts, red/orange rows, report id), limitations, and deep-mode semantics. With no output schema, the description proactively explains what the agent will receive and how to interpret results, making it highly complete.
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?
Although schema coverage is 100%, the description adds significant meaning: for path it adds the 10 MB limit and unreadable formats; for deep it explains what it does, the performance cost, free-tier quota, and that results are a review queue rather than a verdict. This is well beyond the schema's basic property descriptions.
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 action ('Check every case citation in a document on disk') with explicit formats, size limit, and target register. It distinguishes from siblings by referencing the 'same compact result as check_citations' and explicitly excludes 'resolve Westlaw (WL) or Lexis identifiers', separating it from resolve tools.
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 clear context for when to use (file-based citation checking) and lists exclusions (scanned PDFs, encrypted PDFs, legacy .doc, .docx paid plan). It also states what it cannot do, which is an implicit when-not, but it does not explicitly name sibling tools as alternatives for specific cases (e.g., 'use check_citations for text input').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
coverageWhat proofread.law checks againstARead-onlyIdempotent
The coverage statement (which opinions the register holds, its date, its known gaps, what is not checked: Westlaw/Lexis identifiers, statutes, regulations, secondary sources) and the storage notice (nothing submitted is stored). Call it when a user asks what the check covers, how current it is, or what happens to their text. Free, not counted as a check.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description adds meaningful behavioral details: nothing submitted is stored, known gaps and un-checked item types are disclosed, and the call has no billing impact. This gives the agent accurate expectations about side effects and scope.
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 compact and well-structured, with the main claim front-loaded and parenthetical details kept relevant. Every clause adds either content coverage, usage timing, or a caveat about cost, so 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 parameterless informational tool with no output schema, the description is complete: it explains what the result contains, when to invoke the tool, and the privacy/billing implications. An agent has everything needed to decide to call it and to understand the response.
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?
The tool has zero parameters and the schema coverage is 100%, so there is nothing for the description to clarify about inputs. The description instead explains what information the call returns, which is the appropriate contribution for a parameterless tool.
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 exactly what the tool returns: a coverage statement and a storage notice, with the scope of the coverage spelled out. It is clearly distinguished from the sibling tools, which perform checking, resolution, or report rendering, by being the meta-informational tool.
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 explicit trigger conditions: use it when a user asks what the check covers, how current it is, or what happens to their text. It also clarifies that the call is free and not counted as a check, which prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
render_reportRender a check as a markdown reportARead-onlyIdempotent
Turn a finished check into a markdown diligence report: header, coverage and storage notices, a summary table sorted check-this, cannot-verify, support, found, and a detail block per flagged row with the register evidence. Use it when the user wants a report to keep or attach to the file. Pass the report_id returned by check_citations or check_document (ids live in this server's memory until it exits), or the full report JSON from proofread.law's /verify endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| report | No | A full report JSON as returned by POST /verify, if you have one instead of an id. | |
| report_id | No | The 'Report id' from a previous check_citations or check_document result. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive behavior; the description adds valuable non-obvious details: the exact output structure and the fact that report ids live only in server memory until the server exits. There is no contradiction with 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 dense sentences carry all essential information: the first covers purpose and output composition, the second covers usage context and parameter provenance. There is no filler or redundant restatement of the title.
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 rendering tool with two optional parameters and no output schema, the description fully covers what the tool does, what it produces, and how to obtain valid inputs. The server-memory warning is especially valuable for correct invocation. Nothing critical appears 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?
Both parameters are already documented in the schema, so the baseline is 3. The description adds meaning by clarifying that report and report_id are alternatives, where each comes from, and the server-memory lifetime constraint that affects whether a report_id remains valid.
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 tool's function: turning a finished check into a markdown diligence report, and enumerates the report's components. It distinguishes render_report from check_citations and check_document by positioning those as producers of the report_id this tool consumes.
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 an explicit use condition: 'Use it when the user wants a report to keep or attach to the file.' It also explains the expected input sources (report_id from check tools or full JSON from /verify), but it does not explicitly list when not to use the tool or compare it against coverage/resolve siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_citationLook up one citation in the registerARead-onlyIdempotent
Look up a single case citation (for example '590 U.S. 644', or 'Bostock v. Clayton County, 590 U.S. 644 (2020)') in proofread.law's register and answer: is there a case at this citation, which one (name, court, date, parallel citations, link), and how complete the register is for that volume. This is a register lookup of the citation, not a comparison with the case name you have: if the case it returns is not the one you expected, the citation points elsewhere. Statuses: found; ambiguous (several entries, candidates listed); not in the register (a register fact with a coverage qualifier, never proof that the case does not exist); cannot verify (a Westlaw/Lexis identifier, or a volume the register cannot see yet); known citation (other opinions cite it, the opinion itself is not held); no citation recognised. Use it when one citation is in doubt; use check_citations for prose, and resolve_citations for a list. Cannot: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law. A red row means 'check this', never 'this case does not exist'; an orange row means the register has nothing to check against, which is not evidence either way. Counts against the resolve quota (1,000 a month free), not the check quota.
| Name | Required | Description | Default |
|---|---|---|---|
| citation | Yes | One citation string. A case name and year around it are fine; only the reporter citation is resolved. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds extensive behavioral context beyond annotations: it enumerates all possible statuses, explains that 'not in the register' is never proof of nonexistence, clarifies the meaning of red and orange rows, and discloses quota impact. This is consistent with the openWorldHint and readOnlyHint 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?
Although long, every sentence carries essential operational information: purpose, scope, statuses, exclusions, interpretive warnings, and quota behavior. The opening sentence front-loads the core function, and the rest is a compact structured list of caveats.
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 no output schema, the description compensates fully by explaining what the tool answers, the statuses an agent may encounter, and how to interpret ambiguous or negative results. Nothing critical is missing for an agent deciding whether and how to invoke the tool.
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?
The single parameter is fully documented in the schema, which already explains that 'only the reporter citation is resolved.' The description adds concrete examples ('590 U.S. 644', 'Bostock v. Clayton County, 590 U.S. 644 (2020)') and clarifies that surrounding case name and year are acceptable, slightly enriching what the schema provides.
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 action ('look up a single case citation ... in proofread.law's register') and the exact question it answers, including the fields returned. It explicitly distinguishes itself from sibling tools by noting this is a register lookup and that a mismatch means 'the citation points elsewhere.'
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?
It gives explicit when-to-use guidance: 'Use it when one citation is in doubt; use check_citations for prose, and resolve_citations for a list.' It also lists clear exclusions ('Cannot: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_citationsLook up a list of citations in the registerARead-onlyIdempotent
Look up up to 500 case citation strings in proofread.law's register in one call and get one line per citation, in input order: found (the case, court, date, link), ambiguous, not in the register (a register fact with a coverage qualifier, never proof that the case does not exist), cannot verify (Westlaw/Lexis identifier, or a volume the register cannot see yet), known citation, or no citation recognised. Use it for a table of authorities or any list of citations you already have; use check_citations for prose (it also checks names and quotations). Cannot: resolve Westlaw (WL) or Lexis identifiers, check statutes, regulations or secondary sources, or say whether a case is still good law. A red row means 'check this', never 'this case does not exist'; an orange row means the register has nothing to check against, which is not evidence either way. Each citation counts against the resolve quota (1,000 a month free), not the check quota.
| Name | Required | Description | Default |
|---|---|---|---|
| cites | Yes | Citation strings, one per entry, up to 500. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide read-only, open-world, idempotent, and non-destructive hints. The description goes further by disclosing result categories, quota accounting, red/orange row semantics, and unsupported inputs. It adds substantial operational context beyond the annotations with no contradiction.
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 dense but front-loaded with the core purpose, followed by usage guidance, limitations, and quota. Every clause contributes useful information, though it is slightly long and repeats 'up to 500', keeping it from a perfect 5.
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?
The tool has one well-described parameter, rich annotations, and no output schema, so the description must carry return-value and interpretation details. It fully covers result categories, ordering, limitations, quota, and how to interpret ambiguous rows, making it complete for agent 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?
The schema already fully describes the single 'cites' parameter at 100% coverage, so the baseline of 3 applies. The description reinforces that these are case citation strings and that output preserves input order, but it does not add syntax, formatting, or example details beyond the schema.
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 ('look up'), a specific resource ('up to 500 case citation strings in proofread.law's register'), and a clear output shape (one line per citation). It explicitly contrasts this tool with check_citations, distinguishing it from a key sibling.
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 explicit usage contexts: 'table of authorities or any list of citations you already have.' It names the alternative for prose (check_citations) and lists exclusions (Westlaw/Lexis identifiers, statutes, regulations, secondary sources, good-law checks), so an agent can decide when not to use it.
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.
6 tool updates
v0.1.0- First observed
check_citations - First observed
check_document - First observed
coverage - First observed
render_report - First observed
resolve_citation - First observed
resolve_citations
TDQS
Scored across 6 tools
Tools form two near-identical pairs: check_citations/check_document (text vs file) and resolve_citation/resolve_citations (single vs batch). The descriptions explicitly direct usage and distinguish them, so ambiguity is low but not zero.
Most tools follow a clear verb_noun snake_case pattern: check_citations, check_document, resolve_citation, resolve_citations, render_report. 'coverage' breaks the pattern by being a bare noun, though it is still readable and consistent in style.
Six tools is well-scoped for the server's purpose: checking prose, checking a file, single lookup, batch lookup, coverage information, and report rendering. No tool is redundant padding and nothing essential seems missing.
The core workflow of checking citations, resolving individual citations, and rendering reports is complete. Minor gaps exist: deep-support checking is opt-in/quota-limited, and resolve_citations output cannot be passed directly to render_report.
Maintenance
Related MCP Connectors
Verify legal citations, case treatment, quotes and whole briefs against 10.7M U.S. opinions
Resolve, search and verify legal citations against the official sources, with provenance.
Search U.S. case law, fetch opinions, and ask matter-aware legal questions over your documents.
Verifies legal citations vs primary sources: existence, quote match, proposition support.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables US case law search, citation parsing, practice management via Clio, and federal court filings through PACER.-
- AlicenseNot gradedqualityDmaintenanceValidates legal citations against the CourtListener database to detect hallucinated citations in legal documents.5MIT
- AlicenseNot gradedqualityCmaintenanceEnables secure access to legal documents from Clio via Claude Desktop, with local processing and semantic search to ground AI responses in actual documents.12 npm29Mozilla Public 2.0
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code to index and semantically search through PDFs, code, and documents with exact citations and zero hallucinations.MIT