mathter-mcp 0.1.0 → 0.2.0
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 +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +50 -6
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -69,6 +69,7 @@ so the first start takes a little longer than later ones. You need Node 18 or ne
|
|
|
69
69
|
> "What math skills can Mathter do for grade 3?"
|
|
70
70
|
> "Make a 5-page grade 3 subtraction pack called Warm-Ups, easy difficulty."
|
|
71
71
|
> "A blank multiplication chart for grade 4."
|
|
72
|
+
> "How many Mathter packs do I have left this month?"
|
|
72
73
|
> "Ten worksheets of grade 6 fractions, hard, with worked solutions."
|
|
73
74
|
|
|
74
75
|
The assistant replies with the path to the PDF. Open it and print.
|
|
@@ -83,6 +84,11 @@ Asks mathter.ca which skills exist right now and which grades each one covers. Y
|
|
|
83
84
|
should call this before generating, so it picks a real skill rather than guessing. No key is sent
|
|
84
85
|
— that list is public.
|
|
85
86
|
|
|
87
|
+
### `check_allowance`
|
|
88
|
+
|
|
89
|
+
Tells you how many packs your account has left, which plan it is on, and the date the allowance
|
|
90
|
+
resets. It uses nothing, so ask any time: "How many Mathter packs do I have left?"
|
|
91
|
+
|
|
86
92
|
### `generate_worksheet_pack`
|
|
87
93
|
|
|
88
94
|
Makes the pack. Only `skill` and `grade` are required; everything else has a sensible default.
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ export declare function buildGenerateBody(args: Args): Record<string, unknown>;
|
|
|
76
76
|
export declare function packFilename(skill: string, grade: number, now?: Date): string;
|
|
77
77
|
export declare function generateWorksheetPack(args: Args, cfg: MathterConfig): Promise<string>;
|
|
78
78
|
export declare function listSkills(cfg: MathterConfig): Promise<string>;
|
|
79
|
+
export declare function checkAllowance(cfg: MathterConfig): Promise<string>;
|
|
79
80
|
export declare function handleCallTool(name: string, args: Args, cfg: MathterConfig): Promise<CallToolResult>;
|
|
80
81
|
export declare function createMcpServer(cfg: MathterConfig): Server;
|
|
81
82
|
export interface MainIO {
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import { homedir, tmpdir } from "node:os";
|
|
|
32
32
|
import { join } from "node:path";
|
|
33
33
|
import { pathToFileURL } from "node:url";
|
|
34
34
|
/** Kept in step with package.json by hand; it is only ever reported, never compared. */
|
|
35
|
-
const VERSION = "0.
|
|
35
|
+
const VERSION = "0.2.0";
|
|
36
36
|
const DEFAULT_BASE_URL = "https://mathter.ca";
|
|
37
37
|
/**
|
|
38
38
|
* A pack render drives headless Chrome on the server, so it is slow by nature — minutes, not
|
|
@@ -230,16 +230,26 @@ export const TOOLS = [
|
|
|
230
230
|
name: "generate_worksheet_pack",
|
|
231
231
|
title: "Generate a Mathter worksheet pack",
|
|
232
232
|
description: "Generate a printable math worksheet pack as a PDF and save it to this computer, then " +
|
|
233
|
-
"return the file path.
|
|
234
|
-
"
|
|
235
|
-
"Call list_skills first to choose a valid skill
|
|
236
|
-
"the account
|
|
233
|
+
"return the file path. Each pack uses one pack from the monthly allowance of the Mathter " +
|
|
234
|
+
"account that owns MATHTER_API_KEY, the same as making it on mathter.ca; call " +
|
|
235
|
+
"check_allowance to see how many are left. Call list_skills first to choose a valid skill " +
|
|
236
|
+
"for the grade. A Premium account's logo prints automatically: the teacher uploads it once " +
|
|
237
|
+
"at https://mathter.ca/account, so there is nothing to pass here for it.",
|
|
237
238
|
// `as const` above keeps the literal types (so a typo in an enum value is a compile error
|
|
238
239
|
// here rather than a silent runtime oddity); the SDK's Tool type wants a mutable JSON Schema
|
|
239
240
|
// object, hence the one cast.
|
|
240
241
|
inputSchema: GENERATE_SCHEMA,
|
|
241
242
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
242
243
|
},
|
|
244
|
+
{
|
|
245
|
+
name: "check_allowance",
|
|
246
|
+
title: "Check the Mathter allowance",
|
|
247
|
+
description: "How many worksheet packs the account that owns MATHTER_API_KEY has left this period, its " +
|
|
248
|
+
"plan, and the date the allowance resets. Free to call; it uses nothing. Check it before " +
|
|
249
|
+
"making several packs, or when the teacher asks how many they have left.",
|
|
250
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
251
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
252
|
+
},
|
|
243
253
|
{
|
|
244
254
|
name: "list_skills",
|
|
245
255
|
title: "List Mathter skills",
|
|
@@ -522,6 +532,37 @@ export async function listSkills(cfg) {
|
|
|
522
532
|
});
|
|
523
533
|
return `${skills.length} skills available (grade 0 is kindergarten):\n${lines.join("\n")}`;
|
|
524
534
|
}
|
|
535
|
+
export async function checkAllowance(cfg) {
|
|
536
|
+
const url = `${cfg.baseUrl}/api/usage`;
|
|
537
|
+
const res = await request(url, {
|
|
538
|
+
method: "GET",
|
|
539
|
+
headers: { Authorization: `Bearer ${cfg.apiKey}`, Accept: "application/json", "User-Agent": `mathter-mcp/${VERSION}` },
|
|
540
|
+
}, cfg);
|
|
541
|
+
if (!res.ok) {
|
|
542
|
+
const { parsed, text } = await readErrorBody(res);
|
|
543
|
+
// describeHttpError's 503 is about the PDF renderer's queue; here it means the usage count
|
|
544
|
+
// itself could not be read, and nothing about a renderer applies.
|
|
545
|
+
if (res.status === 503) {
|
|
546
|
+
throw new ToolError("Mathter could not check the allowance right now. Try again in a minute." + serverSaid(text));
|
|
547
|
+
}
|
|
548
|
+
throw new ToolError(describeHttpError(res.status, parsed, res.headers.get("retry-after"), { caller: "key", url }) + serverSaid(text));
|
|
549
|
+
}
|
|
550
|
+
const u = (await res.json().catch(() => null));
|
|
551
|
+
if (!u || typeof u.remaining !== "number" || typeof u.quota !== "number") {
|
|
552
|
+
throw new ToolError(`Mathter answered ${url} without allowance figures. Try again shortly.`);
|
|
553
|
+
}
|
|
554
|
+
const reset = u.resetsAt ? new Date(u.resetsAt) : null;
|
|
555
|
+
const resetText = reset && !Number.isNaN(reset.getTime())
|
|
556
|
+
? reset.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", timeZone: "America/Toronto" })
|
|
557
|
+
: "the start of the next period";
|
|
558
|
+
const plan = `${u.plan ?? "Mathter"} plan${u.onTrial ? " (free trial)" : ""}`;
|
|
559
|
+
const perPack = typeof u.maxWorksheets === "number" ? ` Each pack can hold up to ${u.maxWorksheets} worksheets.` : "";
|
|
560
|
+
if (u.remaining <= 0) {
|
|
561
|
+
return (`No packs left: all ${u.quota} on the ${plan} are used. The allowance resets on ${resetText}; ` +
|
|
562
|
+
"to make more before then, upgrade at https://mathter.ca/pricing.");
|
|
563
|
+
}
|
|
564
|
+
return `${u.remaining} of ${u.quota} packs left on the ${plan}, resetting on ${resetText}.${perPack}`;
|
|
565
|
+
}
|
|
525
566
|
/**
|
|
526
567
|
* The single outbound filter for tool results. Every text block of every result — success,
|
|
527
568
|
* mapped error, unexpected throw, unknown tool name — passes through here on its way to the
|
|
@@ -548,11 +589,14 @@ async function runTool(name, args, cfg) {
|
|
|
548
589
|
if (name === "list_skills") {
|
|
549
590
|
return { content: [{ type: "text", text: await listSkills(cfg) }] };
|
|
550
591
|
}
|
|
592
|
+
if (name === "check_allowance") {
|
|
593
|
+
return { content: [{ type: "text", text: await checkAllowance(cfg) }] };
|
|
594
|
+
}
|
|
551
595
|
return {
|
|
552
596
|
isError: true,
|
|
553
597
|
content: [{
|
|
554
598
|
type: "text",
|
|
555
|
-
text: `mathter-mcp has no tool called "${name}". It offers generate_worksheet_pack and
|
|
599
|
+
text: `mathter-mcp has no tool called "${name}". It offers generate_worksheet_pack, list_skills and check_allowance.`,
|
|
556
600
|
}],
|
|
557
601
|
};
|
|
558
602
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mathter-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"mcpName": "ca.mathter/mathter",
|
|
4
5
|
"description": "MCP server for Mathter \u2014 ask your AI assistant for a printable math worksheet pack and get a PDF on disk.",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "Mathter (https://mathter.ca)",
|