@cyanheads/calculator-mcp-server 0.4.3 → 0.5.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/AGENTS.md +4 -4
- package/CLAUDE.md +4 -4
- package/README.md +4 -3
- package/changelog/0.5.x/0.5.0.md +44 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/calculate.tool.d.ts +28 -10
- package/dist/mcp-server/tools/definitions/calculate.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/calculate.tool.js +81 -23
- package/dist/mcp-server/tools/definitions/calculate.tool.js.map +1 -1
- package/dist/services/math/math-service.d.ts +62 -23
- package/dist/services/math/math-service.d.ts.map +1 -1
- package/dist/services/math/math-service.js +697 -257
- package/dist/services/math/math-service.js.map +1 -1
- package/dist/services/math/size-guard.d.ts +84 -0
- package/dist/services/math/size-guard.d.ts.map +1 -0
- package/dist/services/math/size-guard.js +733 -0
- package/dist/services/math/size-guard.js.map +1 -0
- package/package.json +3 -3
- package/server.json +3 -3
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Hardened math.js wrapper for secure expression evaluation.
|
|
3
3
|
* Creates a restricted math.js instance with dangerous functions disabled in
|
|
4
|
-
* the expression scope,
|
|
4
|
+
* the expression scope, parses each expression once and checks the tree before
|
|
5
|
+
* anything runs, and evaluates, inspects, and formats the result inside a vm
|
|
6
|
+
* sandbox with a timeout.
|
|
5
7
|
* @module services/math/math-service
|
|
6
8
|
*/
|
|
7
9
|
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
@@ -10,15 +12,16 @@ import type { MathResult, NumericType } from './types.js';
|
|
|
10
12
|
export declare class MathService {
|
|
11
13
|
/** Default IEEE 754 instance — used for the vast majority of evaluations. */
|
|
12
14
|
private readonly defaultInstance;
|
|
13
|
-
/** BigNumber instance —
|
|
15
|
+
/** BigNumber instance — 64 significant digits; selected via numericType: "BigNumber". */
|
|
14
16
|
private readonly bigNumberInstance;
|
|
15
17
|
/** Fraction instance — exact rational arithmetic; selected via numericType: "Fraction". */
|
|
16
18
|
private readonly fractionInstance;
|
|
17
|
-
private readonly parse;
|
|
18
19
|
private readonly simplify;
|
|
19
20
|
private readonly derivative;
|
|
20
21
|
private readonly simplifyRules;
|
|
21
22
|
private readonly config;
|
|
23
|
+
/** vm context reused by every timed call; see {@link runWithTimeout}. */
|
|
24
|
+
private readonly sandbox;
|
|
22
25
|
constructor(config: ServerConfig);
|
|
23
26
|
/** Select the pre-initialized evaluate/format/typeOf bundle for a given numeric type. */
|
|
24
27
|
private instanceFor;
|
|
@@ -31,36 +34,72 @@ export declare class MathService {
|
|
|
31
34
|
/** Get formatted help content listing available functions, operators, and syntax. */
|
|
32
35
|
getHelpContent(): string;
|
|
33
36
|
private validateInput;
|
|
37
|
+
/**
|
|
38
|
+
* Parse once and check the tree before anything evaluates. A parse failure is
|
|
39
|
+
* `parse_failed`. Multiple statements are detected structurally — math.js parses
|
|
40
|
+
* `a; b` and a top-level newline into a `BlockNode` — so `;` inside a matrix or
|
|
41
|
+
* inside either quote style (`"a;b"`, `'a;b'`) is data, transpose `A'` stays an
|
|
42
|
+
* operator, and a real separator is rejected before either statement runs (#32).
|
|
43
|
+
* math.js treats a bare carriage return as a syntax error rather than a
|
|
44
|
+
* separator; when it is what broke the parse, the input is re-parsed with line
|
|
45
|
+
* feeds purely to report `multiple_expressions` — the rewritten text is never
|
|
46
|
+
* evaluated. The same tree then gets the stringifier check, the
|
|
47
|
+
* operation-as-function check (#27), and the notation rename (#24), and yields
|
|
48
|
+
* the names it uses as values that resolve to functions (#38). Every operation
|
|
49
|
+
* starts here, so it also resets the instance's auto unit system (#37).
|
|
50
|
+
*/
|
|
51
|
+
private parseExpression;
|
|
52
|
+
/** Whether `expression` parses to multiple statements. */
|
|
53
|
+
private parsesAsBlock;
|
|
54
|
+
private multipleExpressions;
|
|
34
55
|
/** Reject scope keys that could pollute the object prototype chain. */
|
|
35
56
|
private validateScope;
|
|
36
57
|
/** Reject result types that leak internals (functions, parsers, multi-expression ResultSets). */
|
|
37
58
|
private validateResultType;
|
|
38
|
-
/**
|
|
39
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Inspect a result before it is formatted: reject a `help()` object (its
|
|
61
|
+
* rendering evaluates the documentation examples, #31), a collection too large
|
|
62
|
+
* to ever fit `maxResultLength` (checked before formatting, so it is never
|
|
63
|
+
* stringified), any non-finite number, scalar or nested (#21), and under
|
|
64
|
+
* numericType "Fraction", any float approximation, scalar or nested (#35).
|
|
65
|
+
*/
|
|
66
|
+
private validateResultValue;
|
|
40
67
|
/** Reject results that exceed the configured maximum size. */
|
|
41
68
|
private validateResultSize;
|
|
69
|
+
private resultTooLarge;
|
|
42
70
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* the prototype would reject legitimate expressions. No real calculator expression
|
|
51
|
-
* needs `.toString()`/`.toLocaleString()`, so blocking the accessor outright (dot
|
|
52
|
-
* or bracket form, on any operand) is both sufficient and side-effect-free. String
|
|
53
|
-
* literals that merely contain the text "toString" parse as ConstantNodes, not
|
|
54
|
-
* accessors, so they are unaffected.
|
|
71
|
+
* Runs a synchronous function inside a vm sandbox with timeout protection and
|
|
72
|
+
* maps anything it throws to a declared reason via {@link classifyFailure}.
|
|
73
|
+
*
|
|
74
|
+
* The context exists only to carry the timeout — `fn` and everything it calls
|
|
75
|
+
* run in this realm — so one context is reused for every call and cleared
|
|
76
|
+
* afterwards. A fresh context per call costs ~100 µs and, under Bun, retains
|
|
77
|
+
* ~100 KB of memory per call.
|
|
55
78
|
*/
|
|
56
|
-
private
|
|
79
|
+
private runWithTimeout;
|
|
57
80
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
81
|
+
* Classify a failure raised after the expression parsed (evaluation, result
|
|
82
|
+
* inspection, formatting, or a symbolic operation). First match wins:
|
|
83
|
+
*
|
|
84
|
+
* 1. Already-classified `McpError`s (result checks) pass through.
|
|
85
|
+
* 2. Timeout → `evaluation_timeout`.
|
|
86
|
+
* 3. A size guard (see size-guard.ts) → `result_too_large`.
|
|
87
|
+
* 4. Fraction mode calling a function with no Fraction implementation (sqrt,
|
|
88
|
+
* sin, log, factorial, …) → `fraction_unsupported` (#19); so does Fraction
|
|
89
|
+
* mode meeting a float with no equal Fraction (`pi * 2/3`, #35).
|
|
90
|
+
* 5. fraction.js `Division by Zero`, in any numericType → `undefined_result` (#21).
|
|
91
|
+
* 6. Name errors (undefined symbol/function/unit, disabled function, blocked
|
|
92
|
+
* property) → `parse_failed`.
|
|
93
|
+
* 7. A symbolic operation (simplify, derivative) that cannot process the parsed
|
|
94
|
+
* tree → `evaluation_failed`, with a hint about the symbolic engine rather
|
|
95
|
+
* than about argument values (see {@link symbolicFailure}).
|
|
96
|
+
* 8. Operand type/unit errors (typed-function `wrongType`, unit mismatch,
|
|
97
|
+
* string-to-number) → `type_mismatch`.
|
|
98
|
+
* 9. Anything else — arity, domain, singular matrix, dimensions, index →
|
|
99
|
+
* `evaluation_failed` (#29). Stage decides, not error class: a runtime
|
|
100
|
+
* `SyntaxError` such as `number("abc")` lands here, never in `parse_failed`.
|
|
62
101
|
*/
|
|
63
|
-
private
|
|
102
|
+
private classifyFailure;
|
|
64
103
|
}
|
|
65
104
|
/** Initialize the math service. Call once from createApp setup(). */
|
|
66
105
|
export declare function initMathService(config: ServerConfig): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"math-service.d.ts","sourceRoot":"","sources":["../../../src/services/math/math-service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"math-service.d.ts","sourceRoot":"","sources":["../../../src/services/math/math-service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAkBtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAQ9D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAioB1D,qBAAa,WAAW;IACtB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAe;IACjD,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAe;IAEhD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IAEpE,YAAY,MAAM,EAAE,YAAY,EAkB/B;IAED,yFAAyF;IACzF,OAAO,CAAC,WAAW;IAWnB,4FAA4F;IAC5F,kBAAkB,CAChB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,OAAO,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,SAAS,CAAC,EAAE,MAAM,EAClB,WAAW,GAAE,WAAsB,GAClC,UAAU,CAsCZ;IAED,qDAAqD;IACrD,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,CAe/D;IAED,mFAAmF;IACnF,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,CAStF;IAED,qFAAqF;IACrF,cAAc,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,aAAa;IAarB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,eAAe;IA6CvB,0DAA0D;IAC1D,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,mBAAmB;IAQ3B,uEAAuE;IACvE,OAAO,CAAC,aAAa;IAYrB,iGAAiG;IACjG,OAAO,CAAC,kBAAkB;IAU1B;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;IA0B3B,8DAA8D;IAC9D,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,cAAc;IAQtB;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAetB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,eAAe;CA8CxB;AAiFD,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAE1D;AAED,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,WAAW,CAG5C"}
|