codecalc
An MCP server that lets AI models run code in 31 languages, evaluate symbolic math and logic problems, and measure complexity—exposed as 48 tools for execution, session management, translation, optimization, and more.
README
codecalc — universal code & logic calculator for AI models
Run code in 31 languages, evaluate symbolic math, solve logic problems, and measure complexity — all exposed as MCP tools any AI model or agent can call.
Architecture (language-per-strength)
| Layer | Language | Why |
|---|---|---|
Executor core (executor/) |
Rust | Sandbox + rlimits + process-group kill + JSON CLI. No eval() anywhere near user input; memory-safe host; single static binary |
Logic layer (codecalc/logic.py) |
Python | sympy (symbolic math, equation solving) and z3 (SMT) have no Rust equivalents |
MCP server (codecalc/server.py) |
Python | fastmcp auto-generates tool schemas from type hints |
Python orchestrates; Rust executes; sympy/z3 reason. Each layer does what it's best at. The Rust binary is preferred automatically; a pure-Python executor is the fallback if the binary is missing.
Older-computer support
target-cpu=generic— no modern instruction-set requirements- Static musl builds run on any Linux regardless of glibc version:
bin/codecalc-exec-x86_64-musl(421K),bin/codecalc-exec-aarch64-musl(453K) - Size-optimized profile (
opt-level="z", LTO, panic=abort, stripped) - Lazy sympy/z3 imports: server starts in ~40ms, not ~600ms
list_languagesprobes runtime availability and reports which languages actually work on the machine (graceful degradation on minimal installs)
Build the Rust core
cd executor
cargo build --release # native
cargo zigbuild --release --target x86_64-unknown-linux-musl # static x86_64 (uses zig)
cargo zigbuild --release --target aarch64-unknown-linux-musl # static arm64
cp target/release/codecalc-exec ../bin/ # Python picks it up from ../bin
Requires: Rust 1.97+, cargo-zigbuild for the static cross-builds (zig is used as the linker; no x86_64 GCC needed).
MCP tools (48) + MCP resources
Every session file is also exposed as an MCP resource:
codecalc://session/<session_id>/files/<path> — images render inline for the
model, text returns as text, other files download.
Exact arithmetic & programmer-mode: exact rationals, threshold checks, bit analysis, binary64 introspection.
| Tool | Description |
|---|---|
calc_exact |
EXACT arithmetic: 0.1+0.2 == 0.3 is True; arbitrary-precision ints, bitwise ops inline, whitelisted math funcs, pi/e/tau |
compare_threshold |
Exact threshold verdict with shortfall: ('1/25', '>', '0.05') → False, shortfall 1/100 |
percentage |
Exact share and percentage of PART/TOTAL (rationals accepted) |
calc_stats |
mean, median, sample stdev, CV (CV > 0.2 = noise swamps the effect) |
percentiles |
p50/p90/p95/p99 by nearest-rank AND interpolation; warns n<100 |
collision_probability |
Birthday-bound hash collision: 1e5 items/32 bits ≈ 0.69, 1e6/64 ≈ 2.7e-8 |
data_sizes |
Byte sizes both ways: KiB/MiB (binary) AND KB/MB (decimal) |
human_duration |
Humanised duration + per-day/per-30d rates |
epoch_time |
Epoch s/ms/µs/ns → ISO 8601 UTC, implausible readings suppressed |
base_repr |
hex/oct/bin + two's complement at WIDTH + signed-overflow detection |
radix_convert |
Any base 2..36, fractions included, non-termination flagged (0.1 base 2) |
float_repr |
What binary64 actually stores: exact value, raw bits, ULP, neighbours, representable-or-not |
int_widths |
Which i8..i64/u8..u64 hold N + wrapped values; 2^53 JS/JSON caveat |
bit_analysis |
popcount, bit length, trailing zeros, next pow2, alignment padding |
bitop |
Programmer mode: and/or/xor/nand/nor/xnor/not/shl/shr/sar/rol/ror at 8/16/32/64, unsigned+signed+hex+oct+bin; shr vs sar distinction; shift-overflow flagged |
algebraic_equiv |
Are (a*b)/c and a*(b/c) identical? refactor verification (with float/truncation caveat) |
solve_expression |
Solve roots/crossovers: x**2 - 4 = 0, 2*x + 1 = 7 |
limit_expression |
Asymptotic limits: n*log(n)/n**2 → 0 (settles complexity arguments) |
simplify_expression |
Simplified + factored + expanded forms |
Core tools
| Tool | Description |
|---|---|
list_languages |
31 languages with extension, compile flag, runtime availability |
execute_code |
Run code in any language → stdout/stderr/exit_code/verdict (OK/TLE/MLE/OLE/RTE)/cpu_ms/peak_memory_kb; per-call limits (max_memory_mb, max_output_kb, max_cpu), no_net, compact |
execute_code_stream |
Like execute_code but reports progress + partial output while running |
session_start |
Persistent session; python3/node get a stateful REPL worker (variables/imports persist across calls), other languages a workspace dir |
session_stop / session_list |
Session lifecycle |
session_files / session_read_file / session_write_file |
Workspace file tools, jailed to the session dir; session_read_file returns images inline (as_image) |
session_run |
Multi-file programs: execute an entry file that imports other session files (helper.py, data/...) in the workspace |
session_artifacts |
List files created by executed code (results, images, CSVs) |
install_package |
Install packages (uv pip/npm/gem/go/cargo...) into a session or shared cache |
translate_code |
Port code between languages with verification: LLM translates, executor runs both versions on the same test inputs, accepted only if outputs match (one retry with diff feedback) |
optimize_code |
Optimize code with proof: LLM proposes, executor verifies correctness AND measures speedup (same sizes, min-of-repeats); accepted only if correct AND measurably faster, else retried or honestly rejected |
extract_function |
Pull a named function + its dependency closure (imports, referenced helpers) into a standalone program and run it (ast-exact for python3, best-effort elsewhere) |
compare_edge_cases |
Run the same logic in N languages on edge-case inputs (empty, zero, negative, float precision) and flag behavioral divergence |
context7_docs |
Fetch up-to-date library docs from context7 (/numpy/numpy, /golang/go, /Z3Prover/z3...) — current API knowledge for any language |
convert_units |
Dimensional unit conversion via sympy: length, mass, time, speed, energy, power, force, pressure, temperature (°C/°F/K), volume, area, data, frequency |
physical_constants |
22 physical constants with values (c, h, N_A, k_B, G, g, m_e, R, ...) |
list_units |
All 140+ unit aliases for convert_units |
evaluate_expression |
Symbolic math: integrate(x**2, x), sqrt(144) + 2**10 |
truth_table |
Boolean algebra: a and b or not c, p xor q, a implies b |
z3_check |
SMT-LIB2 satisfiability + model |
solve_linear |
Systems of equations: x + y = 10; x - y = 2 |
analyze_complexity |
Static Big-O estimate from code structure |
benchmark |
Empirical Big-O: runs code at increasing N, fits growth curve |
compare_execution |
Same code across N languages side-by-side |
runtimes_status |
Non-mutating update check: current vs latest for every language runtime, which package manager owns it, and the command that would run |
update_runtimes |
Update runtimes. Dry-run by default (apply=False returns the commands); apply=True executes them |
Runtime self-update
Every language is mapped to its package manager, and codecalc can update its own runtimes:
| Manager | Languages | Update command |
|---|---|---|
| mise | python3, node, bun, deno, ruby, go, erlang, elixir, gleam, zig, java, kotlin, sqlite, duckdb, gradle | mise up |
| rustup | rust (stable/nightly toolchains) | rustup update |
| swiftly | swift | swiftly update |
| apt | c, c++, fortran, csharp, php, perl, lua, tcl, r, jq, bash, zsh | apt-get install --only-upgrade (language packages only) |
| npm | typescript/tsc | npm update -g |
| uv | mojo | uv tool upgrade mojo |
| nix | haskell (on-demand) | nothing persistent |
runtimes_status is always safe. update_runtimes refuses to mutate unless
apply=True is passed explicitly — and it only touches the package manager
that owns each language (never the Rust sandbox, which has no update powers).
Run the server
cd /path/to/codecalc && .venv/bin/python -m codecalc.server
# stdio transport — register with any MCP client
Point an MCP client at it:
{ "mcpServers": { "codecalc": { "command": "/path/to/codecalc/.venv/bin/python",
"args": ["-m", "codecalc.server"],
"env": {
"PYTHONPATH": "/path/to/codecalc",
"CODECALC_RUNTIME_PATH": "/path/to/mise/shims:/usr/local/bin:/usr/bin:/bin"
} } } }
Configuration
All optional. codecalc runs with none of these set.
| Variable | Default | What it does |
|---|---|---|
CODECALC_RUNTIME_PATH |
the server's own PATH, else /usr/local/bin:/usr/bin:/bin |
The PATH executed code resolves runtimes on. Set this when an MCP client spawns the server: clients often launch with a stripped environment, so an inherited PATH can miss a toolchain manager's shims entirely and most languages silently become unavailable. list_languages reports what actually resolved. |
CODECALC_EXEC_BIN |
bin/codecalc-exec (arch-matched) |
Override the sandbox binary. Without one, codecalc falls back to a pure-Python executor — list_languages and execute_code still work, but the Rust path is the production one. |
CODECALC_SESSION_ROOT |
~/.codecalc/sessions |
Where session workspaces live. |
CODECALC_PROCESS_HEADROOM |
512 |
Fork-bomb guard. RLIMIT_NPROC is a uid-wide task budget, not a per-sandbox one — the kernel compares it against every thread your user owns, machine-wide. So codecalc measures the ambient count per execution and sets the limit to ambient + headroom: a bomb can add at most this many tasks, while a runtime wanting a few threads always has room however busy the box is. |
CODECALC_MAX_PROCESSES |
(unset) | Escape hatch: pin RLIMIT_NPROC to an absolute value and skip the measurement. |
CODECALC_LLM_GATEWAY |
(unset — the two LLM tools report themselves unconfigured) | An OpenAI-compatible /v1/chat/completions endpoint. Only translate_code and optimize_code need it; the other 46 tools work without it. There is deliberately no default: sending your source to a third party nobody configured would be a worse failure than a clear error. |
CODECALC_LLM_API_KEY |
(unset) | Bearer token for that gateway, if it needs one. |
CODECALC_LLM_MODEL |
gpt-4o-mini |
Model name passed to the gateway. |
CODECALC_COMPLEXITY_LLM |
(unset) | Opt in to an LLM second opinion on analyze_complexity. Off by default, and a separate variable from the gateway on purpose — configuring translate_code should not silently add a network round-trip to every complexity analysis. |
Both backends resolve CODECALC_RUNTIME_PATH identically, and
scripts/check_parity.py fails CI if the Rust and Python copies of that
contract ever drift — including if a machine-specific home directory finds its
way back into the default.
Test
cd /path/to/codecalc
PYTHONPATH=. .venv/bin/python tests/test_smoke.py # 31 languages via Rust executor
PYTHONPATH=. .venv/bin/python tests/test_mcp_all.py # all 9 tools over MCP stdio
Platform support
Linux, macOS and Windows. The three do not offer the same primitives, and the
executor reports which ones it could not apply in an unenforced array on
every result rather than letting a caller assume they all held.
| Guarantee | Linux | macOS | Windows |
|---|---|---|---|
| Wall-clock timeout | yes | yes | yes |
| Kill the whole process tree | killpg |
killpg |
TerminateJobObject |
| Fork-bomb guard | RLIMIT_NPROC (uid-wide) |
RLIMIT_NPROC (uid-wide) |
Job ActiveProcessLimit (job-scoped) |
| Memory ceiling | RLIMIT_AS |
reported unenforced¹ | Job ProcessMemoryLimit |
| CPU-time ceiling | RLIMIT_CPU |
RLIMIT_CPU |
reported unenforced |
| Open-file ceiling | RLIMIT_NOFILE |
RLIMIT_NOFILE |
reported unenforced |
| Output cap | yes | yes | yes (on read) |
no_net |
LD_PRELOAD shim² |
DYLD_INSERT_LIBRARIES²˒³ |
reported unenforced |
| Stateful sessions | yes | yes | yes |
¹ Darwin accepts setrlimit(RLIMIT_AS) but does not enforce address space the
way Linux does, so setting it would buy an illusion.
² Dynamically-linked programs only — a statically linked binary (Go, by default)
ignores it.
³ Weaker still on macOS, in two ways. SIP and the hardened runtime strip
DYLD_INSERT_LIBRARIES for protected and hardened-signed binaries (most signed
interpreters), and dyld interposing does not reach calls made inside the
shared cache where libSystem lives — a program's own connect() is intercepted,
a system framework opening a connection internally is not. Treat macOS no_net
as a speed bump, never as isolation.
Windows' ActiveProcessLimit is scoped to the job, which makes it a
genuinely better fork-bomb guard than RLIMIT_NPROC's uid-wide budget — the
failure mode that broke 14 of 31 runtimes on Linux cannot occur there.
Two things degrade rather than fail on a given platform: languages whose runtime
is absent (list_languages reports available: false), and the shell-wrapper
languages — bash, zsh, csharp, gleam, haskell — which need a POSIX
shell and so are unavailable on Windows unless one is installed.
Sandbox guarantees
- Fresh temp dir per run, deleted on exit (source + binaries + outputs)
- rlimits: CPU (timeout+8s), address space 2TiB (V8/JVM need huge VA), file size 256MiB, 256 FDs, core dumps off
- Wall-clock timeout kills the whole process group (SIGKILL)
- Output capped at 64KiB per stream
- Fork-bomb guard via
RLIMIT_NPROC, sized from the measured ambient task count plus headroom rather than a fixed number. This is a mitigation, not isolation: the budget is shared with every other process your user owns, so concurrent executions draw on the same pool. cgroup v2pids.maxis the real per-sandbox answer and needs delegated cgroup access a stdio MCP server cannot assume — reach for it when this moves behind a container. - No network namespace isolation (single-host tool; containerize for untrusted code)
Language list
python3, node, bun, deno, typescript, ruby, php, perl, lua, tcl, r, elixir, erlang, bash, zsh, mojo, swift, c, cpp/c++, rust, go, fortran, zig, java, kotlin, csharp, gleam, haskell, sqlite, jq, awk — 31 runtimes.
codecalc does not install any of them. It runs whatever is already on
CODECALC_RUNTIME_PATH, and list_languages probes each one and reports which
actually resolved, so a minimal machine degrades to the subset it has rather
than failing opaquely.
Notes
- Java uses single-file source launch (JEP 330). Kotlin compiles to a jar.
- csharp/gleam/haskell scaffold a temp project (dotnet new / gleam new / nix-shell).
benchmarkuses the stdin-N contract: code reads N from stdin, work sized by N.
CI
Five workflows, each documented inline with what it gates and — where a tool was considered and rejected — why it is not there.
| Workflow | Gates |
|---|---|
ci-rust |
clippy -D warnings; the executor's JSON contract, asserted by running the built binary (OK/TLE/OLE/unknown-language) and confirming a canary secret in the executor's own env does not reach executed code; both static musl cross-builds, checked with file for static linkage; blocknet.so built -Werror, symbol-checked, and confirmed to actually block an outbound connection |
ci-python |
ruff at a genuine zero residual (ruleset and every exception in pyproject.toml, each with a reason); calc parity on 3.11 and 3.14; the security suite against the Rust backend, with an assertion that the Rust backend is the one under test; MCP stdio round-trip |
ci-security |
scripts/check_no_eval.py (the CRITICAL-01 invariant), scripts/check_parity.py (the three security constants duplicated in Rust and Python must match), scripts/check_claims.py (README counts and licence), actionlint, gitleaks, trufflehog, osv-scanner, cargo-deny, cargo-audit, and opengrep on a schedule |
ci-quality |
typos, shellcheck |
dco |
Signed-off-by on every non-merge commit |
Two conventions run through all of them, both borrowed from harder-won experience:
- Actions are pinned by commit SHA and downloaded tools by SHA-256. A tag is mutable; a digest is not.
- Every scan asserts it scanned something. A linter pointed at a renamed directory, a dependency scanner with no lockfile to read, and a clean repo all produce the same output — exit 0. Each gate counts its inputs first and fails if the count is implausible.
Licence
Apache-2.0. See LICENSE.
Contributions require a DCO sign-off (git commit -s); dco.yml enforces it.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。