@cyanheads/calculator-mcp-server
v0.4.3
Published
Evaluate, simplify, and differentiate mathematical expressions via MCP. STDIO or Streamable HTTP.
Maintainers
Readme
Public Hosted Server: https://calculator.caseyjhand.com/mcp
Overview
Calculator powered by math.js. Verify numeric results, simplify algebraic expressions, and compute symbolic derivatives through one tool. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
| Tool | Description |
|:----------|:------------|
| calculate | Evaluate math expressions, simplify algebraic expressions, or compute symbolic derivatives. |
Resources
| Resource | Description |
|:------------|:------------|
| calculator://help | Available functions, operators, constants, and syntax reference. |
Capability reference
calculate tool
- One
expressionper call.operationselectsevaluate(default),simplify, orderivative; derivatives requirevariable(e.g."x"). - Evaluate arithmetic, trigonometry, logarithms, statistics, matrices, complex numbers, units, and combinatorics; assign numeric variables through
scope, e.g.{ "x": 5 }. numericTypeselectsnumber,BigNumber, orFraction. Fractions require exact rational results; irrational or transcendental results returnfraction_unsupportedwith guidance to change numeric type.precisionsets 1–16 significant digits for numeric results. Blank optionalvariableandprecisionvalues are treated as omitted; scope and precision do not affect symbolic operations.- Simplification includes algebraic and trigonometric identities (
2x + 3x→5 * x);unchanged: trueidentifies expressions the simplifier cannot reduce, including polynomial factoring and rational cancellation cases. - Returns the result string, result type, original expression, and operation. Validation failures include typed reasons and recovery hints.
calculator://help resource
- Markdown reference for functions, operators, constants, units, and expression syntax; no parameters.
- Examples cover scope, matrices, complex numbers, precision, and all three operations.
- Cacheable for 24 hours with public scope (
cacheHint) — static content that never changes at runtime.
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Calculator-specific:
- Hardened math.js v15 instance — dangerous functions disabled, evaluation sandboxed via
vm.runInNewContext()with timeout - No auth required — all operations are read-only and stateless
- Input validation: expression length limits and rejection of multiple statements; matrix row separators and string contents remain valid
- Result validation: blocked result types (functions, parsers, result sets), configurable max result size
- Scope sanitization: numeric-only values, prototype pollution prevention (blocked
__proto__,constructor, etc.)
Agent-friendly output:
- Effective-call echo — every response echoes the expression and operation, plus which scope variables and what precision were applied, so agents can verify what was actually computed
- Discriminated output contracts —
unchanged: trueonsimplifyflags a no-op result instead of silently returning the same expression - Typed error reasons — validation and evaluation failures carry a typed
reason(e.g.fraction_unsupported,evaluation_timeout,disallowed_result_type) plus an actionable recovery hint, rather than a raw exception
Getting started
Public Hosted Instance
A public instance is available at https://calculator.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"calculator-mcp-server": {
"type": "streamable-http",
"url": "https://calculator.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Add one of the following to your MCP client configuration file:
{
"mcpServers": {
"calculator-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/calculator-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"calculator-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/calculator-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"calculator-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/calculator-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the built server:
MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
- Bun v1.4.0 or higher
Installation
- Clone the repository:
git clone https://github.com/cyanheads/calculator-mcp-server.git- Navigate into the directory:
cd calculator-mcp-server- Install dependencies:
bun installConfiguration
| Variable | Description | Default |
|:---------|:------------|:--------|
| CALC_MAX_EXPRESSION_LENGTH | Maximum allowed expression string length (10–10,000). | 1000 |
| CALC_EVALUATION_TIMEOUT_MS | Maximum evaluation time in milliseconds (100–30,000). | 5000 |
| CALC_MAX_RESULT_LENGTH | Maximum result string length in characters (1,000–1,000,000). | 100000 |
| MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
| MCP_HTTP_HOST | Hostname for the HTTP server. | 127.0.0.1 |
| MCP_HTTP_PORT | Port for HTTP server. | 3010 |
| MCP_HTTP_ENDPOINT_PATH | Path for the HTTP MCP endpoint. | /mcp |
| MCP_HTTP_MAX_BODY_BYTES | Maximum inbound HTTP request size; 0 disables the limit. | 1048576 |
| MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
| MCP_SESSION_MODE | auto, stateful, or stateless. The server declares stateless in code, so every launch path resolves the same way; setting this overrides that declaration. | stateless |
| MCP_LOG_LEVEL | Log level (RFC 5424). | info |
See .env.example for optional session, resumability, logging, and telemetry settings.
Running the server
Local development
Build and run the production version:
bun run build bun run start:http # or start:stdioRun checks and tests:
bun run devcheck # Lints, formats, type-checks bun run test # Runs test suite
Docker
docker build -t calculator-mcp-server .
docker run -p 3010:3010 calculator-mcp-serverThe image defaults to Streamable HTTP on port 3010, stateless sessions, and logs at /var/log/calculator-mcp-server. OpenTelemetry dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|:----------|:--------|
| src/mcp-server/tools/ | Tool definitions (*.tool.ts). |
| src/mcp-server/resources/ | Resource definitions (*.resource.ts). |
| src/services/ | Domain service integrations (MathService). |
| src/config/ | Environment variable parsing and validation with Zod. |
| docs/ | Generated directory tree. |
| tests/ | Calculation, configuration, and response-contract tests. |
Development guide
See AGENTS.md or CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging - Register new tools and resources in
src/index.ts
Contributing
Issues are welcome. Run checks before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
