
proofread.law
io.github.Data-Alchemy-Labs由 GitHub 账号 Data-Alchemy-Labs 发布v0.3.0更新于 Oct 24, 2026
Check US and Swiss case citations against open registers of court opinions, from any MCP client.
概览
对照公开的法院判决登记库检查草稿中的美国和瑞士案例引注,并报告哪些引注需要人工复核。
- 可以做什么
- 提供十四个工具,可检查文本或 PDF、DOCX、TXT、MD 文件中的引注,解析单条引注或最多 500 条引注的列表,并报告登记库覆盖范围。结果分级为红色(需检查)、橙色(无法核实)、绿色(已找到),深度检查时还有白色(深度检查)。还可按瑞士联邦法条推荐主要判例,测试版中可按句子推荐美国判例,并可将简报保存到账户并重新检查修改后的版本。
- 适用场景
- 适合在提交或发送法律草稿前使用,以发现指向错误案件、卷号或页码的引注,或判决书中找不到的引文。也适合查找某条瑞士联邦法条的主要联邦最高法院判例。
- 运行要求
- 通过 npx 以 stdio 在本地运行,或在本地端口以 HTTP 运行;需要 Node 20 或更高版本。可选的 PROOFREAD_API_KEY(pl_...)可解除免费额度限制,不设置则按 IP 适用免费额度。PROOFREAD_API 可指向自建或测试实例。需要能访问 proofread.law API 的网络。
安装
在 SourceWeft 中
- 打开 控制台中的 proofread.law,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
proofread-mcp
An MCP server for proofread.law. It lets Claude Desktop, Claude Code, Cursor and the OpenAI Agents SDK check case citations before a draft is filed: about 10 million US court opinions, and 1.1 million Swiss decisions (BGE/ATF/DTF, Federal Supreme Court dockets, the federal courts and all 26 cantons). The jurisdiction is detected from the draft, and a Swiss report comes back in the draft's language: German, French or Italian.
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
Fourteen tools:
The compact result of a check is capped at about 12,000 characters; when a long brief has more flagged rows than fit, the text says how many were left out and render_report has them all.
Saved briefs (opt-in)
Nothing is saved unless save_brief or update_brief is called; check_citations and check_document never save anything. A saved brief is stored encrypted in the user's proofread.law account until delete_brief removes it, so the brief tools need an API key (any PROOFREAD_API_KEY, or one from sign_up); without one they answer with a message and send nothing. A server with storage switched off answers storage_off, and the tools say so.
The loop for fixing flagged citations: save_brief once, fix a flagged row in the text (the citation, the case name, the quotation, or take the citation out), call update_brief with the id and the whole edited text, and read what changed: which flags were resolved (flagged before, not flagged now), which are new, and the rows that still need attention. The last 20 versions are kept; get_brief lists them and reads an earlier one. Ids are integers in the API and strings in the tools.
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:
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.
Case suggestions (Switzerland)
suggest_cases takes a Swiss federal statute article (Art. 41 OR, art. 41 CO, Art. 8 ZGB, art. 9 Cst.; lowercase and dotless forms such as art 41 or are read too) or a paragraph that cites articles, and lists the leading Federal Supreme Court cases (BGE) the court cites with it. Federal acts only; cantonal law is not covered. There is no free-text search: a query without an article answers with a message that no article was recognised. The answer is one ranked list in the measured order, each case labelled with its field of law; the domain filter keeps the same order within one field, so a filtered row keeps its overall rank (Rang 7, Rang 9, ...) and a filter note says which field is shown. Each row has the citation, date, field, the decision's language, its rank, the quoted passage (regeste or consideration), any later change of practice (a changed precedent is listed with its flag, never dropped), the decision at the court's site and a link that opens the check on proofread.law. Every string comes back in the query's language (German, French or Italian; lang: "en" for English), and the tool prints it as it is. A suggestion is a case to read: it has not been checked against your sentence, and a row without a flag is not evidence that its practice still holds. To check a citation, use check_citations.
Arguments: query (required, up to 20,000 characters; over 1,500 it is sent as POST), domain (all, civil, criminal, public or social; default all), lang (de, fr, it or en; default the query's language), k (number of rows, 1 to 50; default 10). With a large k, rows past about 20,000 characters of text keep their header line and any practice flag and leave out the passage and links, which stay in the structured result (with the counts per field). During the trial phase it needs a paid-plan or trial API key; otherwise the API answers plan_required and the tool says where to upgrade.
Example call, suggest_cases with {"query": "Art. 41 OR, Art. 97 OR", "k": 3} (dev instance, 2026-09-26; rows 2 and 3 cut):
With "domain": "civil" the list starts with the filter note and keeps the overall ranks:
A filter that leaves no rows answers with a message saying so. A later change of practice appears right under the row it concerns, for example Praxisänderung durch BGE 145 III 1, möglicherweise nur teilweise: <link> followed by the regeste sentence that marks it.
Case suggestions (United States, beta)
suggest_cases also takes a sentence from a US draft that states a rule of law (one sentence, or a short paragraph up to 1,500 characters) and lists up to 3 cases whose own text states it. A model reads the opinion of the court in each of the top 10 candidates, and a case is shown only when the model finds a passage in it that states the sentence. Each row has the reference, the court, the year, how the case stands to the court you name (binding here, same circuit, persuasive), any later history the citator found (reversed in part, superseded by statute), the passage the model matched with the paragraphs before and after it (each cut to about 600 characters), a link to the opinion on CourtListener and a link that opens the check on proofread.law. Cases that a later court overruled or reversed are left out, and a note names them.
This is a beta. Every answer starts with a line that says so, with the measured numbers: on the site's own index, of 94 cases shown for 50 sentences from filed briefs, 73 (78%) support the sentence and 4 do not, as read blind by two model readers, not practising lawyers (details). Read the passage before you cite the case. A suggestion is a case to read; to check a citation, use check_citations.
Arguments: court (optional, up to 200 characters) is the court the brief is filed in: a federal court of appeals (9th Cir., Ninth Circuit, ca9), a district court (N.D. Cal., S.D.N.Y., cand), or a state or territory name or postal code (California, CA) for the federal court there. Cases that bind that court come first; without a court, Supreme Court cases come first. State courts are not read yet; a court the API does not read comes back as an error that says what it reads. jurisdiction is auto by default: a Swiss statute article, or German, French or Italian text, is Swiss, and anything else is a US sentence; us or ch sets it. domain, lang and k apply to Swiss answers only, and a US answer is in English.
Input that states no rule of law (a question, a citation or case name, a heading, a statement about the record or a party's argument, or more than 1,500 characters) gets no list. The answer says what to paste instead and gives an example sentence, and it costs nothing. A US answer that ran the model counts as one deep-checked citation, not a resolve. When the day's budget for model calls is spent, US suggestions are back the next day (UTC).
Example call, suggest_cases with a sentence on the plausibility pleading standard and "court": "N.D. Cal." (dev instance, 2026-09-26; the passage and the paragraphs around it shortened, rows 2 and 3 cut):
A question gets the beta line, then the API's message and an example:
Install
Needs Node 20 or newer. No install step is required; npx fetches proofread-mcp from npm.
Claude Desktop (extension bundle)
Download proofread-mcp-<version>.mcpb from the latest GitHub release and open it with Claude Desktop (double-click, or Settings, Extensions, Install Extension). The bundle carries the server and its dependencies and uses the Node runtime that ships with Claude Desktop, so nothing else has to be installed. The only setting is the optional API key, stored by Claude Desktop as a sensitive value and passed to the server as PROOFREAD_API_KEY.
To build the bundle yourself: scripts/build-mcpb.sh (needs npx @anthropic-ai/mcpb) writes build/proofread-mcp-<version>.mcpb from manifest.json, icon.png and the npm package contents.
Claude Desktop (config file)
Edit claude_desktop_config.json (Settings, Developer, Edit Config):
Leave out env to use the free tier.
Claude Code
Cursor
Settings, MCP, Add new global MCP server, or write .cursor/mcp.json in the project:
OpenAI Agents SDK (over HTTP)
Start the server with the HTTP transport:
Then connect from the Agents SDK:
The HTTP server binds to 127.0.0.1 by default and is single-tenant by design: it has no authentication of its own, report ids are shared across sessions, and a key from sign_up is adopted by the whole process. Sessions that stay idle for 30 minutes are closed. To expose it on a network use --host 0.0.0.0 and put it behind something that adds authentication.
Any MCP client
stdio: run proofread-mcp. Streamable HTTP: run proofread-mcp --http --port 3333 and point the client at /mcp.
Environment variables
Accounts and keys
An agent can open an account itself: sign_up posts the owner's real email and a name to POST /agent/signup and gets a key back, shown once. The server uses that key for the rest of the session; put it in PROOFREAD_API_KEY to keep it. The owner receives one confirmation email. When a quota is used up (a tool answers "needs the ... plan" or "monthly allowance used"), billing_link returns a Stripe Checkout link for the owner; nothing is charged until they pay. Plans and prices: proofread.law/pricing. The onboarding text the API publishes for agents is at proofread.law/agent/onboarding.md.
Free tier
Per month, per IP address without a key or per account with a free-tier key:
There is also a limit of 20 requests an hour per IP (more on paid plans). 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 Policy
The full policy is at proofread.law/privacy. What applies to this server:
- What is collected. The text or file you check leaves your machine and goes to proofread.law's own server (
PROOFREAD_API, defaulthttps://proofread.law), over HTTPS, in the request that checks it.save_briefandupdate_briefsend the brief's text and title the same way;suggest_casessends the query (an article, a sentence, or the paragraph you give it) and the court, if you name one.sign_upsends the account owner's email address and the agent name you give it. Nothing else is sent: no conversation history, no other files, no telemetry. - Use and storage on proofread.law. A checked input is processed in memory and discarded when the report is returned; no copy is written to disk. The exception is opt-in: a brief saved with
save_brieforupdate_briefis stored encrypted in the user's account, with its reports and earlier versions, untildelete_briefdeletes it (permanently). No other tool saves anything. The log line per request carries the kind of input, its size, the number of citations, the tier counts and the time taken, never a citation, a party name or a word of text. With an account, proofread.law keeps the email address, the plan, a monthly count of checks and a hash of each API key. - Third parties. A citation string the register cannot resolve may be looked up in CourtListener's citation API (the citation string only, never prose). Deep check (
deep: true) is opt-in: the clause before each citation (up to 700 characters) and the cited opinion go to the model judge. A USsuggest_casesquery (the beta) goes to the same model judge, with the opinions of the candidate cases. Those two are the only cases in which words you send leave proofread.law. Sign-in links go through Resend; payments through Stripe, which sees the card and proofread.law does not. Requests pass through Cloudflare's edge in transit. - Retention. Inputs and reports: none, except saved briefs, which are kept until the user deletes them. Account records: until the owner asks for deletion at [email protected].
- This server. It stores nothing on disk, saved briefs included (they live in the proofread.law account, not here). 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 API key lives in your MCP client's configuration (Claude Desktop stores the extension's key as a sensitive setting); a key fromsign_upis held in memory for the session and shown to you once so you can store it. It is sent only toPROOFREAD_API, as anAuthorization: Bearerheader. If a deep-check stream stops before every citation was judged, the tool answers with an error that says how many were checked; it never presents a partial deep check as a finished one. - Contact. Data Alchemy Labs, [email protected].
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):
Development
Layout: src/client.ts is the typed HTTP client (/verify, /render, /api/coverage, /v1/resolve single and batch, /v1/briefs, /v1/suggest), src/format.ts the compact formatter for checks, src/resolve_format.ts the one for register answers, src/briefs_format.ts the one for saved briefs (/v1/briefs), src/suggest_format.ts the one for case suggestions (/v1/suggest), 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: npm, the MCP Registry (server.json is in the repository), the Claude Desktop extension bundle (manifest.json, scripts/build-mcpb.sh, attached to each GitHub release) and Anthropic's connector directory.
License
MIT, Data Alchemy Labs.
来源:README.md,提交 5316fb2
工具
0版本历史
5- v0.3.0最新Sep 26, 2026
- v0.2.0Sep 23, 2026
- v0.1.4Sep 21, 2026
- v0.1.3Sep 20, 2026
- v0.1.1Sep 20, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分