proofread-mcp 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -22
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +14 -3
- package/dist/client.js +73 -16
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +8 -4
- package/dist/errors.js +44 -10
- package/dist/errors.js.map +1 -1
- package/dist/format.d.ts +6 -4
- package/dist/format.js +86 -35
- package/dist/format.js.map +1 -1
- package/dist/http.d.ts +8 -1
- package/dist/http.js +43 -10
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +3 -2
- package/dist/server.js.map +1 -1
- package/dist/sse.d.ts +1 -0
- package/dist/sse.js +42 -20
- package/dist/sse.js.map +1 -1
- package/dist/tools/billing_link.d.ts +8 -0
- package/dist/tools/billing_link.js +31 -0
- package/dist/tools/billing_link.js.map +1 -0
- package/dist/tools/check_citations.d.ts +7 -4
- package/dist/tools/check_citations.js +18 -12
- package/dist/tools/check_citations.js.map +1 -1
- package/dist/tools/check_document.js +22 -14
- package/dist/tools/check_document.js.map +1 -1
- package/dist/tools/index.js +3 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/render_report.js +4 -4
- package/dist/tools/render_report.js.map +1 -1
- package/dist/tools/resolve_citation.js +2 -2
- package/dist/tools/resolve_citation.js.map +1 -1
- package/dist/tools/resolve_citations.js +2 -2
- package/dist/tools/resolve_citations.js.map +1 -1
- package/dist/tools/sign_up.d.ts +5 -0
- package/dist/tools/sign_up.js +42 -0
- package/dist/tools/sign_up.js.map +1 -0
- package/dist/tools/tool.d.ts +11 -2
- package/dist/tools/tool.js +20 -7
- package/dist/tools/tool.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/package.json +2 -1
package/dist/format.js
CHANGED
|
@@ -5,53 +5,88 @@ export const TIER_WORD = {
|
|
|
5
5
|
green: "FOUND",
|
|
6
6
|
white: "DEEP CHECK",
|
|
7
7
|
};
|
|
8
|
+
/** Compact output stays inside a model's budget; the full list is one render_report call away. */
|
|
9
|
+
export const MAX_COMPACT_CHARS = 12_000;
|
|
8
10
|
const PASSAGE_CHARS = 300;
|
|
9
11
|
/**
|
|
10
|
-
* A compact, model-friendly view of a report: the coverage statement first, then the counts,
|
|
11
|
-
* then
|
|
12
|
-
* Westlaw/Lexis identifiers are collapsed into one line, as on the site.
|
|
12
|
+
* A compact, model-friendly view of a report: the coverage statement first, then the counts, then one line per row that needs a human
|
|
13
|
+
* (red, then orange, then deep-check rows whose passage was not confirmed or states the opposite), then the count of found rows.
|
|
14
|
+
* Westlaw/Lexis identifiers are collapsed into one line, as on the site. Long lists are cut at MAX_COMPACT_CHARS.
|
|
13
15
|
*/
|
|
14
16
|
export function formatReport(report, reportId) {
|
|
15
17
|
const s = report.summary;
|
|
16
|
-
const
|
|
17
|
-
lines
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
18
|
+
const deep = report.mode === "deep";
|
|
19
|
+
const lines = [`Coverage: ${report.coverage}`];
|
|
20
|
+
if (s.citations === 0 || report.rows.length === 0) {
|
|
21
|
+
lines.push("No case citations were recognised in the text. Reporter citations look like '590 U.S. 644' (volume, reporter, page).");
|
|
22
|
+
lines.push(`Storage: ${report.storage}`);
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}
|
|
25
|
+
const rows = report.rows;
|
|
26
|
+
const red = rows.filter((r) => r.tier === "red");
|
|
27
|
+
const orange = rows.filter((r) => r.tier === "orange");
|
|
28
|
+
const ids = orange.filter((r) => r.reason === "database_id");
|
|
29
|
+
const white = rows.filter((r) => r.tier === "white");
|
|
30
|
+
const found = rows.filter((r) => r.tier === "green" || r.tier === "white");
|
|
31
|
+
const support = countSupport(white);
|
|
32
|
+
const review = white.filter((r) => r.support?.status === "opposite" || r.support?.status === "not_confirmed");
|
|
33
|
+
lines.push(`Summary: ${plural(s.citations, "citation")}, ${plural(s.rows, "row")}. ` +
|
|
34
|
+
`Check this (red): ${red.length}. Cannot verify (orange): ${orange.length}` +
|
|
35
|
+
(ids.length ? `, of which ${plural(ids.length, "Westlaw/Lexis identifier")}` : "") +
|
|
36
|
+
`. Found (green): ${found.length}.` +
|
|
37
|
+
(deep ? ` Deep-checked (white): ${white.length}: ${support.confirmed} confirmed, ${support.likely} likely, ${support.not_confirmed} not confirmed, ${support.opposite} opposite` +
|
|
38
|
+
(support.not_checked ? `, ${support.not_checked} not checked` : "") + "." : ""));
|
|
39
|
+
// Flagged rows in tier order: red, orange (identifiers collapsed at the end of orange), then deep-check rows to review.
|
|
40
|
+
const flagged = [
|
|
41
|
+
...red.map(formatRowLine),
|
|
42
|
+
...orange.filter((r) => r.reason !== "database_id").map(formatRowLine),
|
|
43
|
+
...(ids.length ? [databaseIdsLine(ids)] : []),
|
|
44
|
+
...review.filter((r) => r.support?.status === "opposite").map(formatRowLine),
|
|
45
|
+
...review.filter((r) => r.support?.status === "not_confirmed").map(formatRowLine),
|
|
46
|
+
];
|
|
47
|
+
const tail = [];
|
|
48
|
+
tail.push(`Found: ${plural(found.length, "row")} resolved to a case in the register` +
|
|
49
|
+
(deep ? `; ${support.confirmed} of them confirmed by the deep check (a passage states the proposition)` : "") + ".");
|
|
50
|
+
if (deep) {
|
|
51
|
+
tail.push("Deep check rows are a review queue, not a verdict: confirm the passage yourself before relying on it." +
|
|
52
|
+
(support.likely ? ` ${plural(support.likely, "row")} marked likely (a passage may state this, lower confidence) are listed by render_report.` : ""));
|
|
53
|
+
}
|
|
54
|
+
const closing = [];
|
|
55
|
+
if (reportId)
|
|
56
|
+
closing.push(`Report id: ${reportId} (give it to render_report for the full markdown report).`);
|
|
57
|
+
if (report.elapsed_s !== undefined)
|
|
58
|
+
closing.push(`Elapsed: ${report.elapsed_s} s.`);
|
|
59
|
+
if (closing.length)
|
|
60
|
+
tail.push(closing.join(" "));
|
|
61
|
+
tail.push(`Storage: ${report.storage}`);
|
|
26
62
|
if (flagged.length === 0) {
|
|
27
63
|
lines.push("Flagged rows: none.");
|
|
28
64
|
}
|
|
29
65
|
else {
|
|
30
66
|
lines.push("Flagged rows:");
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
const budget = MAX_COMPACT_CHARS - lines.join("\n").length - tail.join("\n").length - 120;
|
|
68
|
+
let used = 0;
|
|
69
|
+
let shown = 0;
|
|
70
|
+
for (const line of flagged) {
|
|
71
|
+
if (shown > 0 && used + line.length > budget)
|
|
72
|
+
break;
|
|
73
|
+
lines.push(line);
|
|
74
|
+
used += line.length + 1;
|
|
75
|
+
shown += 1;
|
|
76
|
+
}
|
|
77
|
+
if (shown < flagged.length) {
|
|
78
|
+
lines.push(`... and ${plural(flagged.length - shown, "more flagged row")} not shown here` +
|
|
79
|
+
(reportId ? `; render_report ${reportId} has the full list.` : "; render_report has the full list."));
|
|
80
|
+
}
|
|
35
81
|
}
|
|
36
|
-
lines.
|
|
37
|
-
if (report.mode === "deep") {
|
|
38
|
-
lines.push("Deep check rows are a review queue, not a verdict: confirm the passage yourself before relying on it.");
|
|
39
|
-
}
|
|
40
|
-
const tail = [];
|
|
41
|
-
if (reportId)
|
|
42
|
-
tail.push(`Report id: ${reportId} (give it to render_report for a markdown report).`);
|
|
43
|
-
if (report.elapsed_s !== undefined)
|
|
44
|
-
tail.push(`Elapsed: ${report.elapsed_s} s.`);
|
|
45
|
-
if (tail.length)
|
|
46
|
-
lines.push(tail.join(" "));
|
|
47
|
-
lines.push(`Storage: ${report.storage}`);
|
|
48
|
-
return lines.join("\n");
|
|
82
|
+
return [...lines, ...tail].join("\n");
|
|
49
83
|
}
|
|
50
84
|
/** One line: tier word, citation (parties), headline, detail, register link. */
|
|
51
85
|
export function formatRowLine(row) {
|
|
52
86
|
const who = row.parties ? ` (${row.parties}${row.year ? `, ${row.year}` : ""})` : "";
|
|
53
87
|
const times = row.occurrences && row.occurrences > 1 ? ` [cited ${row.occurrences} times]` : "";
|
|
54
|
-
const
|
|
88
|
+
const label = row.tier === "white" && row.support ? `${tierWord(row.tier)} (${supportWord(row.support.status)})` : tierWord(row.tier);
|
|
89
|
+
const parts = [`- ${label}: ${row.citation}${who}${times}.`];
|
|
55
90
|
if (row.tier === "white" && row.support) {
|
|
56
91
|
parts.push(supportText(row));
|
|
57
92
|
}
|
|
@@ -64,7 +99,7 @@ export function formatRowLine(row) {
|
|
|
64
99
|
parts.push(`Register: ${row.evidence.url}`);
|
|
65
100
|
return parts.join(" ");
|
|
66
101
|
}
|
|
67
|
-
/** A full view of one row
|
|
102
|
+
/** A full view of one row. */
|
|
68
103
|
export function formatRowDetail(row) {
|
|
69
104
|
const lines = [
|
|
70
105
|
`${tierWord(row.tier)}: ${row.citation}` + (row.parties ? ` (${row.parties}${row.year ? `, ${row.year}` : ""})` : ""),
|
|
@@ -94,21 +129,37 @@ export function formatRowDetail(row) {
|
|
|
94
129
|
}
|
|
95
130
|
return lines.join("\n");
|
|
96
131
|
}
|
|
132
|
+
function countSupport(white) {
|
|
133
|
+
const c = { confirmed: 0, likely: 0, not_confirmed: 0, opposite: 0, not_checked: 0 };
|
|
134
|
+
for (const r of white) {
|
|
135
|
+
const status = r.support?.status ?? "not_checked";
|
|
136
|
+
if (status in c)
|
|
137
|
+
c[status] += 1;
|
|
138
|
+
else
|
|
139
|
+
c.not_checked += 1;
|
|
140
|
+
}
|
|
141
|
+
return c;
|
|
142
|
+
}
|
|
143
|
+
function supportWord(status) {
|
|
144
|
+
return status.replace(/_/g, " ");
|
|
145
|
+
}
|
|
97
146
|
function databaseIdsLine(rows) {
|
|
98
147
|
const cites = rows.map((r) => r.citation);
|
|
99
|
-
|
|
100
|
-
return `- CANNOT VERIFY: ${n} Westlaw/Lexis identifier${n === 1 ? "" : "s"} (${cites.join("; ")}). ` +
|
|
148
|
+
return `- CANNOT VERIFY: ${plural(rows.length, "Westlaw/Lexis identifier")} (${cites.join("; ")}). ` +
|
|
101
149
|
"Open registers cannot resolve these; check them in Westlaw or Lexis.";
|
|
102
150
|
}
|
|
103
151
|
function supportText(row) {
|
|
104
152
|
const sup = row.support;
|
|
105
|
-
const parts = [sentence(sup.headline ?? `Support: ${sup.status}`)];
|
|
153
|
+
const parts = [sentence(sup.headline ?? `Support: ${supportWord(sup.status)}`)];
|
|
106
154
|
if (sup.confidence !== undefined)
|
|
107
155
|
parts.push(`(confidence ${sup.confidence.toFixed(2)}${sup.band ? `, ${sup.band}` : ""})`);
|
|
108
156
|
if (sup.passage && sup.status !== "confirmed")
|
|
109
157
|
parts.push(`Closest passage: "${clip(sup.passage, PASSAGE_CHARS)}"`);
|
|
110
158
|
return parts.join(" ");
|
|
111
159
|
}
|
|
160
|
+
function plural(n, noun) {
|
|
161
|
+
return `${n} ${noun}${n === 1 ? "" : "s"}`;
|
|
162
|
+
}
|
|
112
163
|
function sentence(text) {
|
|
113
164
|
const t = text.trim();
|
|
114
165
|
return /[.!?]$/.test(t) ? t : `${t}.`;
|
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAEA,2HAA2H;AAC3H,MAAM,CAAC,MAAM,SAAS,GAAyB;IAC7C,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,YAAY;CACpB,CAAC;AAEF,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,QAAiB;IAC5D,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;IACzB,MAAM,KAAK,GAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAEA,2HAA2H;AAC3H,MAAM,CAAC,MAAM,SAAS,GAAyB;IAC7C,GAAG,EAAE,YAAY;IACjB,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,YAAY;CACpB,CAAC;AAEF,kGAAkG;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,QAAiB;IAC5D,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;IACzB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC;IACpC,MAAM,KAAK,GAAa,CAAC,aAAa,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEzD,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,sHAAsH,CAAC,CAAC;QACnI,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,eAAe,CAAC,CAAC;IAE9G,KAAK,CAAC,IAAI,CACR,YAAY,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI;QACvE,qBAAqB,GAAG,CAAC,MAAM,6BAA6B,MAAM,CAAC,MAAM,EAAE;QAC3E,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,0BAA0B,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,oBAAoB,KAAK,CAAC,MAAM,GAAG;QACnC,CAAC,IAAI,CAAC,CAAC,CAAC,0BAA0B,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,SAAS,eAAe,OAAO,CAAC,MAAM,YAAY,OAAO,CAAC,aAAa,mBAAmB,OAAO,CAAC,QAAQ,WAAW;YAC9K,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,WAAW,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACpF,CAAC;IAEF,wHAAwH;IACxH,MAAM,OAAO,GAAa;QACxB,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC;QACzB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;QACtE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;QAC5E,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,eAAe,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;KAClF,CAAC;IACF,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,qCAAqC;QAClF,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,SAAS,yEAAyE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IACvH,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,IAAI,CAAC,uGAAuG;YAC/G,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,0FAA0F,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzJ,CAAC;IACD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,cAAc,QAAQ,2DAA2D,CAAC,CAAC;IAC9G,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC;IACpF,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAExC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC;QAC1F,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM;gBAAE,MAAM;YACpD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YACxB,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;QACD,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK,EAAE,kBAAkB,CAAC,iBAAiB;gBACvF,CAAC,QAAQ,CAAC,CAAC,CAAC,mBAAmB,QAAQ,qBAAqB,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,WAAW,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtI,MAAM,KAAK,GAAG,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,QAAQ,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC;IAC7D,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnC,IAAI,GAAG,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;IACnE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,eAAe,CAAC,GAAQ;IACtC,MAAM,KAAK,GAAG;QACZ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACrH,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;KACvB,CAAC;IACF,IAAI,GAAG,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC;IACvB,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,aAAa;YAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC,aAAa;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,CAAC,cAAc;YAAE,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;QACjF,IAAI,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,KAAY;IAChC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACrF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,aAAa,CAAC;QAClD,IAAI,MAAM,IAAI,CAAC;YAAE,CAAC,CAAC,MAAwB,CAAC,IAAI,CAAC,CAAC;;YAC7C,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,eAAe,CAAC,IAAW;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,oBAAoB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,0BAA0B,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QAClG,sEAAsE,CAAC;AAC3E,CAAC;AAED,SAAS,WAAW,CAAC,GAAQ;IAC3B,MAAM,GAAG,GAAG,GAAG,CAAC,OAAQ,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5H,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IACpH,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,MAAM,CAAC,CAAS,EAAE,IAAY;IACrC,OAAO,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AACxC,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,GAAW;IACrC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AACzD,CAAC;AAED,SAAS,QAAQ,CAAC,IAAU;IAC1B,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AACvD,CAAC"}
|
package/dist/http.d.ts
CHANGED
|
@@ -4,10 +4,17 @@ export interface HttpOptions extends ServerOptions {
|
|
|
4
4
|
host?: string;
|
|
5
5
|
/** Hosts allowed in the Host header (DNS-rebinding protection). Defaults to localhost forms when binding to loopback. */
|
|
6
6
|
allowedHosts?: string[];
|
|
7
|
+
/** Close a session after this long without a request. Default 30 minutes. */
|
|
8
|
+
idleMs?: number;
|
|
9
|
+
/** Refuse new sessions past this many open ones. Default 200. */
|
|
10
|
+
maxSessions?: number;
|
|
7
11
|
}
|
|
12
|
+
/** A request body larger than this is refused before the transport reads it (the API caps input at 10 MB). */
|
|
13
|
+
export declare const MAX_BODY_BYTES: number;
|
|
8
14
|
/**
|
|
9
15
|
* Serves MCP over Streamable HTTP at /mcp: one McpServer and transport per session (initialize starts one,
|
|
10
|
-
* the Mcp-Session-Id header names it, DELETE ends it). GET /health answers 200 for load balancers.
|
|
16
|
+
* the Mcp-Session-Id header names it, DELETE ends it, idle sessions are reaped). GET /health answers 200 for load balancers.
|
|
17
|
+
* Single-tenant by design: no authentication of its own, and report ids are shared across sessions.
|
|
11
18
|
*/
|
|
12
19
|
export declare function startHttp(options: HttpOptions): Promise<{
|
|
13
20
|
close(): Promise<void>;
|
package/dist/http.js
CHANGED
|
@@ -2,15 +2,23 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { createServer as createHttpServer } from "node:http";
|
|
3
3
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
4
|
import { createServer } from "./server.js";
|
|
5
|
+
/** A request body larger than this is refused before the transport reads it (the API caps input at 10 MB). */
|
|
6
|
+
export const MAX_BODY_BYTES = 12 * 1024 * 1024;
|
|
7
|
+
const SWEEP_MS = 60_000;
|
|
5
8
|
/**
|
|
6
9
|
* Serves MCP over Streamable HTTP at /mcp: one McpServer and transport per session (initialize starts one,
|
|
7
|
-
* the Mcp-Session-Id header names it, DELETE ends it). GET /health answers 200 for load balancers.
|
|
10
|
+
* the Mcp-Session-Id header names it, DELETE ends it, idle sessions are reaped). GET /health answers 200 for load balancers.
|
|
11
|
+
* Single-tenant by design: no authentication of its own, and report ids are shared across sessions.
|
|
8
12
|
*/
|
|
9
13
|
export function startHttp(options) {
|
|
10
14
|
const host = options.host ?? "127.0.0.1";
|
|
15
|
+
const idleMs = options.idleMs ?? 30 * 60_000;
|
|
16
|
+
const maxSessions = options.maxSessions ?? 200;
|
|
11
17
|
let port = options.port; // replaced by the bound port once listening (port 0 lets the OS pick)
|
|
12
|
-
const allowedHosts = () => options.allowedHosts ?? loopbackHosts(host, port);
|
|
13
18
|
const sessions = new Map();
|
|
19
|
+
function jsonError(res, status, code, message) {
|
|
20
|
+
res.writeHead(status, { "content-type": "application/json" }).end(JSON.stringify({ jsonrpc: "2.0", error: { code, message }, id: null }));
|
|
21
|
+
}
|
|
14
22
|
async function handle(req, res) {
|
|
15
23
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
16
24
|
if (url.pathname === "/health") {
|
|
@@ -21,26 +29,40 @@ export function startHttp(options) {
|
|
|
21
29
|
res.writeHead(404, { "content-type": "text/plain" }).end("not found; MCP is served at /mcp");
|
|
22
30
|
return;
|
|
23
31
|
}
|
|
32
|
+
const length = Number(req.headers["content-length"] ?? 0);
|
|
33
|
+
if (length > MAX_BODY_BYTES) {
|
|
34
|
+
jsonError(res, 413, -32000, `request body too large (${length} bytes; the cap is ${MAX_BODY_BYTES})`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
24
37
|
const sessionId = req.headers["mcp-session-id"];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
if (typeof sessionId === "string") {
|
|
39
|
+
const session = sessions.get(sessionId);
|
|
40
|
+
if (!session) {
|
|
41
|
+
jsonError(res, 404, -32001, "Session not found"); // the signal SDK clients use to re-initialize
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
session.lastSeen = Date.now();
|
|
45
|
+
await session.transport.handleRequest(req, res);
|
|
28
46
|
return;
|
|
29
47
|
}
|
|
30
48
|
if (req.method !== "POST") {
|
|
31
|
-
res
|
|
49
|
+
jsonError(res, 400, -32000, "no session; POST initialize first");
|
|
32
50
|
return;
|
|
33
51
|
}
|
|
34
|
-
|
|
52
|
+
if (sessions.size >= maxSessions) {
|
|
53
|
+
jsonError(res, 503, -32000, `too many open sessions (${sessions.size}); try again later`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const hosts = options.allowedHosts ?? loopbackHosts(host, port);
|
|
35
57
|
const transport = new StreamableHTTPServerTransport({
|
|
36
58
|
sessionIdGenerator: () => randomUUID(),
|
|
37
59
|
onsessioninitialized: (id) => {
|
|
38
|
-
sessions.set(id, transport);
|
|
60
|
+
sessions.set(id, { transport, lastSeen: Date.now() });
|
|
39
61
|
},
|
|
40
62
|
onsessionclosed: (id) => {
|
|
41
63
|
sessions.delete(id);
|
|
42
64
|
},
|
|
43
|
-
...(hosts ? { allowedHosts: hosts, enableDnsRebindingProtection: true } : {}),
|
|
65
|
+
...(hosts ? { allowedHosts: hosts, allowedOrigins: hosts.map((h) => `http://${h}`), enableDnsRebindingProtection: true } : {}),
|
|
44
66
|
});
|
|
45
67
|
transport.onclose = () => {
|
|
46
68
|
if (transport.sessionId)
|
|
@@ -50,6 +72,16 @@ export function startHttp(options) {
|
|
|
50
72
|
await server.connect(transport);
|
|
51
73
|
await transport.handleRequest(req, res);
|
|
52
74
|
}
|
|
75
|
+
const sweeper = setInterval(() => {
|
|
76
|
+
const cutoff = Date.now() - idleMs;
|
|
77
|
+
for (const [id, s] of sessions) {
|
|
78
|
+
if (s.lastSeen < cutoff) {
|
|
79
|
+
sessions.delete(id);
|
|
80
|
+
void s.transport.close().catch(() => { });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, Math.min(SWEEP_MS, idleMs));
|
|
84
|
+
sweeper.unref();
|
|
53
85
|
const httpServer = createHttpServer((req, res) => {
|
|
54
86
|
handle(req, res).catch((err) => {
|
|
55
87
|
console.error("proofread-mcp http:", err);
|
|
@@ -68,7 +100,8 @@ export function startHttp(options) {
|
|
|
68
100
|
resolve({
|
|
69
101
|
url: `http://${host}:${port}/mcp`,
|
|
70
102
|
close: async () => {
|
|
71
|
-
|
|
103
|
+
clearInterval(sweeper);
|
|
104
|
+
await Promise.all([...sessions.values()].map((s) => s.transport.close()));
|
|
72
105
|
await new Promise((done) => httpServer.close(() => done()));
|
|
73
106
|
},
|
|
74
107
|
});
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAA6C,MAAM,WAAW,CAAC;AACxG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,YAAY,EAAsB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { createServer, INSTRUCTIONS, SERVER_NAME, SERVER_VERSION } from "./server.js";
|
|
2
|
-
export { startHttp } from "./http.js";
|
|
2
|
+
export { startHttp, loopbackHosts, MAX_BODY_BYTES } from "./http.js";
|
|
3
3
|
export { createClient, verifyPath, MAX_BATCH_CITES, type Client, type VerifyOptions } from "./client.js";
|
|
4
4
|
export { configFromEnv, DEFAULT_BASE_URL, type Config } from "./config.js";
|
|
5
5
|
export { ProofreadError, explain } from "./errors.js";
|
|
6
|
-
export { formatReport, formatRowLine, formatRowDetail, TIER_WORD } from "./format.js";
|
|
6
|
+
export { formatReport, formatRowLine, formatRowDetail, TIER_WORD, MAX_COMPACT_CHARS } from "./format.js";
|
|
7
7
|
export { formatResolve, formatResolveLine, formatResolveBatch, STATUS_WORD } from "./resolve_format.js";
|
|
8
8
|
export { tools } from "./tools/index.js";
|
|
9
|
-
export type { Report, Row, Summary, Tier, Coverage, ResolveResult, ResolveBatch, ResolveStatus, ResolveCase, ResolveCoverage } from "./types.js";
|
|
9
|
+
export type { Report, Row, Summary, Tier, Coverage, ResolveResult, ResolveBatch, ResolveStatus, ResolveCase, ResolveCoverage, SignupResult, CheckoutLink } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { createServer, INSTRUCTIONS, SERVER_NAME, SERVER_VERSION } from "./server.js";
|
|
2
|
-
export { startHttp } from "./http.js";
|
|
2
|
+
export { startHttp, loopbackHosts, MAX_BODY_BYTES } from "./http.js";
|
|
3
3
|
export { createClient, verifyPath, MAX_BATCH_CITES } from "./client.js";
|
|
4
4
|
export { configFromEnv, DEFAULT_BASE_URL } from "./config.js";
|
|
5
5
|
export { ProofreadError, explain } from "./errors.js";
|
|
6
|
-
export { formatReport, formatRowLine, formatRowDetail, TIER_WORD } from "./format.js";
|
|
6
|
+
export { formatReport, formatRowLine, formatRowDetail, TIER_WORD, MAX_COMPACT_CHARS } from "./format.js";
|
|
7
7
|
export { formatResolve, formatResolveLine, formatResolveBatch, STATUS_WORD } from "./resolve_format.js";
|
|
8
8
|
export { tools } from "./tools/index.js";
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAmC,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { type Client } from "./client.js";
|
|
3
3
|
import { type Config } from "./config.js";
|
|
4
4
|
export declare const SERVER_NAME = "proofread-mcp";
|
|
5
|
-
export declare const SERVER_VERSION = "0.1.
|
|
5
|
+
export declare const SERVER_VERSION = "0.1.2";
|
|
6
6
|
export declare const INSTRUCTIONS: string;
|
|
7
7
|
export interface ServerOptions {
|
|
8
8
|
config?: Config;
|
package/dist/server.js
CHANGED
|
@@ -3,13 +3,14 @@ import { createClient } from "./client.js";
|
|
|
3
3
|
import { configFromEnv } from "./config.js";
|
|
4
4
|
import { tools } from "./tools/index.js";
|
|
5
5
|
export const SERVER_NAME = "proofread-mcp";
|
|
6
|
-
export const SERVER_VERSION = "0.1.
|
|
6
|
+
export const SERVER_VERSION = "0.1.2";
|
|
7
7
|
export const INSTRUCTIONS = "proofread.law checks US case citations against an open register of about 10 million court opinions. " +
|
|
8
8
|
"Tiers: red = check this (the register holds something concrete that disagrees), orange = cannot verify (nothing to check against; not evidence either way), " +
|
|
9
9
|
"green = found, white = deep check (does the opinion support the sentence; a review queue, not a verdict). " +
|
|
10
10
|
"Never call a red or orange row invented or untrue: say what was checked and what was found. " +
|
|
11
11
|
"Every result carries a coverage statement; repeat it when reporting to the user. " +
|
|
12
|
-
"Not covered: Westlaw/Lexis identifiers, statutes, regulations, secondary sources, whether a case is still good law."
|
|
12
|
+
"Not covered: Westlaw/Lexis identifiers, statutes, regulations, secondary sources, whether a case is still good law. " +
|
|
13
|
+
"Without an API key the free tier applies per IP; sign_up creates an account and key for the owner's inbox, billing_link gives the owner a checkout page when a quota is used up.";
|
|
13
14
|
/** Builds an McpServer with every tool registered. The client can be injected for tests. */
|
|
14
15
|
export function createServer(options = {}) {
|
|
15
16
|
const config = options.config ?? configFromEnv();
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GACvB,sGAAsG;IACtG,8JAA8J;IAC9J,4GAA4G;IAC5G,8FAA8F;IAC9F,mFAAmF;IACnF,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GACvB,sGAAsG;IACtG,8JAA8J;IAC9J,4GAA4G;IAC5G,8FAA8F;IAC9F,mFAAmF;IACnF,sHAAsH;IACtH,kLAAkL,CAAC;AAOrL,4FAA4F;AAC5F,MAAM,UAAU,YAAY,CAAC,OAAO,GAAkB,EAAE;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;IAC7G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EACnJ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/sse.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Report, Row } from "./types.js";
|
|
|
3
3
|
* Reads a `POST /verify?deep=1` Server-Sent Events body into one report.
|
|
4
4
|
* Events: `report` (the full report, rows provisional), `row` (one row with `support` filled), `done` ({summary, elapsed_s}).
|
|
5
5
|
* Comment lines (`: keepalive`) are skipped. `onRow` fires as each row arrives.
|
|
6
|
+
* A stream that ends without `done` is an error carrying the partial report: the deep check did not finish.
|
|
6
7
|
*/
|
|
7
8
|
export declare function readSseReport(body: ReadableStream<Uint8Array>, onRow?: (row: Row, report: Report) => void): Promise<Report>;
|
|
8
9
|
interface SseEvent {
|
package/dist/sse.js
CHANGED
|
@@ -1,35 +1,57 @@
|
|
|
1
|
+
import { ProofreadError } from "./errors.js";
|
|
1
2
|
/**
|
|
2
3
|
* Reads a `POST /verify?deep=1` Server-Sent Events body into one report.
|
|
3
4
|
* Events: `report` (the full report, rows provisional), `row` (one row with `support` filled), `done` ({summary, elapsed_s}).
|
|
4
5
|
* Comment lines (`: keepalive`) are skipped. `onRow` fires as each row arrives.
|
|
6
|
+
* A stream that ends without `done` is an error carrying the partial report: the deep check did not finish.
|
|
5
7
|
*/
|
|
6
8
|
export async function readSseReport(body, onRow) {
|
|
7
9
|
let report;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
10
|
+
let rowsSeen = 0;
|
|
11
|
+
let done = false;
|
|
12
|
+
try {
|
|
13
|
+
for await (const event of sseEvents(body)) {
|
|
14
|
+
if (event.name === "report") {
|
|
15
|
+
report = JSON.parse(event.data);
|
|
16
|
+
}
|
|
17
|
+
else if (event.name === "row" && report) {
|
|
18
|
+
const row = JSON.parse(event.data);
|
|
19
|
+
const at = report.rows.findIndex((r) => r.n === row.n);
|
|
20
|
+
if (at >= 0)
|
|
21
|
+
report.rows[at] = row;
|
|
22
|
+
else
|
|
23
|
+
report.rows.push(row);
|
|
24
|
+
rowsSeen += 1;
|
|
25
|
+
onRow?.(row, report);
|
|
26
|
+
}
|
|
27
|
+
else if (event.name === "done" && report) {
|
|
28
|
+
const d = JSON.parse(event.data);
|
|
29
|
+
if (d.summary)
|
|
30
|
+
report.summary = { ...report.summary, ...d.summary };
|
|
31
|
+
if (d.elapsed_s !== undefined)
|
|
32
|
+
report.elapsed_s = d.elapsed_s;
|
|
33
|
+
delete report.summary.deep_pending; // the provisional count; every row has arrived
|
|
34
|
+
done = true;
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
37
|
}
|
|
38
|
+
catch (cause) {
|
|
39
|
+
throw incomplete(report, rowsSeen, cause);
|
|
40
|
+
}
|
|
29
41
|
if (!report)
|
|
30
|
-
throw new
|
|
42
|
+
throw new ProofreadError(0, "stream_incomplete", "proofread.law's deep-check stream ended before it sent a report. Run the check again.");
|
|
43
|
+
if (!done)
|
|
44
|
+
throw incomplete(report, rowsSeen);
|
|
31
45
|
return report;
|
|
32
46
|
}
|
|
47
|
+
function incomplete(report, rowsSeen, cause) {
|
|
48
|
+
const expected = report?.summary.deep_pending;
|
|
49
|
+
const how = cause instanceof Error && cause.name !== "TypeError" ? ` (${cause.name === "TimeoutError" ? "timed out" : cause.message})` : "";
|
|
50
|
+
const progress = expected !== undefined ? `${rowsSeen} of ${expected} citations were deep-checked` : `${rowsSeen} citations were deep-checked`;
|
|
51
|
+
const message = `proofread.law's deep-check stream ${cause ? "was cut" : "ended"} before it finished${how}: ${progress}. ` +
|
|
52
|
+
"The result is incomplete; run the check again (without deep=true if this keeps happening).";
|
|
53
|
+
return new ProofreadError(0, "stream_incomplete", message, { rows_seen: rowsSeen, expected, partial: report });
|
|
54
|
+
}
|
|
33
55
|
/** Splits an SSE byte stream into events. One event = the lines up to a blank line. */
|
|
34
56
|
export async function* sseEvents(body) {
|
|
35
57
|
const decoder = new TextDecoder();
|
package/dist/sse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineTool, fail, ok } from "./tool.js";
|
|
3
|
+
export const billingLink = defineTool({
|
|
4
|
+
name: "billing_link",
|
|
5
|
+
title: "Get a checkout link for a paid plan",
|
|
6
|
+
description: "Get a Stripe Checkout link that upgrades this API key's account to a paid plan (POST /agent/checkout-link). Use it when a check answers " +
|
|
7
|
+
"'needs the ... plan' (402) or 'monthly allowance used' (429), or when the user asks to upgrade. Needs an API key (PROOFREAD_API_KEY, or one from sign_up). " +
|
|
8
|
+
"Plans: payg = pay as you go (no monthly fee; per check and per deep-checked citation), solo = monthly, firm = monthly with more keys; current prices at https://proofread.law/pricing. " +
|
|
9
|
+
"Give the link to the account owner to open in a browser; the plan is live within a minute of payment. No charge happens until the owner pays. " +
|
|
10
|
+
"An account that already has a subscription answers 409 (the owner changes plans in the billing portal at https://proofread.law/account).",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
plan: z.enum(["payg", "solo", "firm"]).default("payg").describe("payg (pay as you go), solo or firm."),
|
|
13
|
+
},
|
|
14
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
15
|
+
async run({ plan }, { client }, extra) {
|
|
16
|
+
if (!client.hasApiKey())
|
|
17
|
+
return fail("billing_link needs an API key: set PROOFREAD_API_KEY, or call sign_up first to create an account and key.");
|
|
18
|
+
try {
|
|
19
|
+
const link = await client.checkoutLink(plan, extra.signal);
|
|
20
|
+
const text = [
|
|
21
|
+
`Checkout link for the ${link.plan ?? plan} plan: ${link.checkout_url}`,
|
|
22
|
+
link.note ?? "Open it in a browser or hand it to the account owner. The plan activates within a minute of payment.",
|
|
23
|
+
].join("\n");
|
|
24
|
+
return ok(text, { plan: link.plan ?? plan, checkout_url: link.checkout_url });
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
return fail(err);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=billing_link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing_link.js","sourceRoot":"","sources":["../../src/tools/billing_link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;IACpC,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,qCAAqC;IAC5C,WAAW,EACT,0IAA0I;QAC1I,6JAA6J;QAC7J,yLAAyL;QACzL,gJAAgJ;QAChJ,0IAA0I;IAC5I,WAAW,EAAE;QACX,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KACvG;IACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACvG,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK;QACnC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;YAAE,OAAO,IAAI,CAAC,2GAA2G,CAAC,CAAC;QAClJ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC3D,MAAM,IAAI,GAAG;gBACX,yBAAyB,IAAI,CAAC,IAAI,IAAI,IAAI,UAAU,IAAI,CAAC,YAAY,EAAE;gBACvE,IAAI,CAAC,IAAI,IAAI,sGAAsG;aACpH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { Report, Row } from "../types.js";
|
|
3
|
-
import { type ToolExtra } from "./tool.js";
|
|
3
|
+
import { type Progress, type ToolExtra } from "./tool.js";
|
|
4
4
|
export declare const checkCitations: import("./tool.js").ToolDef<{
|
|
5
5
|
text: z.ZodString;
|
|
6
6
|
deep: z.ZodOptional<z.ZodBoolean>;
|
|
7
7
|
}>;
|
|
8
8
|
/** Deep checks stream rows; each finished row becomes a progress notification when the client asked for progress. */
|
|
9
9
|
export declare function verifyOptions(deep: boolean | undefined, extra: ToolExtra): {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
options: {
|
|
11
|
+
deep?: boolean;
|
|
12
|
+
onRow?: (row: Row, report: Report) => void;
|
|
13
|
+
signal: AbortSignal;
|
|
14
|
+
};
|
|
15
|
+
progress: Progress;
|
|
13
16
|
};
|