Multi-language code execution via mcp-server-code-runner — 37 languages, one tool
Looking for a credential-free MCP server that can execute code snippets across many programming languages via stdio, returning output or errors. The server should handle syntax errors, infinite loops (via timeout), and various language runtimes — ideal for agent-driven code testing, REPL-like interactions, or multi-language demonstrations.
mcp-server-code-runner v0.1.8 — verified execution recipe
Install: npm install mcp-server-code-runner Entry: dist/cli.js --transport stdio (NOT dist/stdio.js — that exits immediately) Transport: stdio via CLI with --transport stdio flag Tools: 1 tool — run-code with params code (string) and languageId (enum of 37 values)
Language enum (37 total)
javascript, php, python, perl, perl6, ruby, go, lua, groovy, powershell, bat, shellscript, fsharp, csharp, vbscript, typescript, coffeescript, scala, swift, julia, crystal, ocaml, r, applescript, clojure, racket, scheme, ahk, autoit, dart, haskell, nim, lisp, kit, v, sass, scss
Executor mapping (key gotcha)
Each language maps to a shell command: javascript → node, python → python -u, go → go run, typescript → ts-node, ruby → ruby, swift → swift, dart → dart, shellscript → bash, r → Rscript, applescript → osascript, etc. The server writes code to a temp file and runs it with the mapped command. No sandbox — code runs directly on the host.
Verified calls (18 calls, 13 OK, 2 runtime-not-found, 2 edge-case, 1 timeout)
Working languages (tested on macOS, runtimes present):
| Language | Latency | Notes |
|---|---|---|
| javascript | 33ms | node — fastest, console.log works |
| ruby | 94ms | v3.4.2, string interpolation works |
| shellscript | 7ms | bash, env vars accessible |
| go | 3077ms | go run — compilation overhead each call |
| perl | 34ms | strict/warnings, sqrt, push all work |
| php | 536ms | <?php prefix required |
| swift | 2092ms | compilation overhead |
| lua | 269ms | v5.4, _VERSION accessible |
| dart | 576ms | full Dart syntax, generics work |
Fails due to missing runtime (not server bugs):
python→ invokespythonnotpython3— fails on pyenv/macOS systems where onlypython3is on PATHtypescript→ requirests-nodeglobally installedr→ requiresRscriptscala→ requiresscala
Critical gotchas
- ⚠️ `stderr` TAKES PRIORITY over `stdout` — when a process writes to stderr, stdout is DROPPED entirely.
console.log("a"); console.error("b"); console.log("c")returns ONLY"Stderr: b\n". Both stdout lines are lost. This is a significant bug for languages that write warnings to stderr.
- ⚠️ `python` not `python3` — the executor command is
python -u, notpython3. On systems with pyenv or only python3, all Python execution fails with "command not found". No workaround except symlinking.
- ⚠️ NO SANDBOX — code runs directly on the host filesystem with the server's permissions.
rm -rf /via shellscript would execute. Not suitable for untrusted code.
- Infinite loop → 60s timeout —
while(true){}in JavaScript triggers MCP error -32001 after exactly 60 seconds. No configurable timeout.
- Empty code → graceful text — returns "Code is required." (text content, not MCP error)
- Syntax errors → Error text with stack trace — returned as successful tool call with error text in content, not as MCP error code
- `exit(1)` → Error text — non-zero exit codes return "Error: Command failed" text
- Unicode safe — Turkish şçğüöı, Japanese, emoji all render correctly in output
- Invalid languageId → validation error — enum validation returns full list of valid options (useful for discovery)
- Temp file location —
/var/folders/.../T/tmp.{ext}on macOS (system temp). File extension mapped per language (.js,.py,.rb, etc.); only 3 custom mappings (js, ts, ps1), rest use language name as extension.
- Go is SLOW — 3077ms per call due to
go runrecompilation. No caching between calls.
- Kotlin and Elixir NOT supported — despite being mentioned in the README's language list, they are NOT in the actual enum. Attempting them returns validation error.
MCP client setup (Node.js SDK
{ "server": "mcp-server-code-runner", "version": "0.1.8", "transport": "stdio", "tools": ["run-code"], "language_count": 37, "calls": [ { "tool": "run-code", "args": { "code": "const x=42; console.log(`Sum: ${x+58}`)", "languageId": "javascript" }, "result": "Sum: 100 Product: 2436 ", "ms": 33 }, { "tool": "run-code", "args": { "code": "puts "Hello Ruby #{RUBY_VERSION}"", "languageId": "ruby" }, "result": "Hello from Ruby 3.4.2 1^2 = 1 ...", "ms": 94 }, { "tool": "run-code", "args": { "code": "echo "Shell: $SHELL"", "languageId": "shellscript" }, "result": "Shell: /bin/zsh ...", "ms": 7 }, { "tool": "run-code", "args": { "code": "package main; import "fmt"; func main(){fmt.Println("1!=1")}", "languageId": "go" }, "result": "1! = 1 2! = 2 ...", "ms": 3077 }, { "tool": "run-code", "args": { "code": "use strict; my @primes; ...", "languageId": "perl" }, "result": "Primes: 2 3 5 7 11 13 17 19 23 29 ", "ms": 34 }, { "tool": "run-code", "args": { "code": "<?php sort([3,1,4]); echo implode(',',$arr);", "languageId": "php" }, "result": "Sorted: 1, 1, 2, 3, 4, 5, 5, 6, 9 ", "ms": 536 }, { "tool": "run-code", "args": { "code": "let greeting = "Hello Swift"; print(greeting)", "languageId": "swift" }, "result": "Hello Swift Sum: 15 ", "ms": 2092 }, { "tool": "run-code", "args": { "code": "print("Lua " .. _VERSION)", "languageId": "lua" }, "result": "Lua Lua 5.4 1² = 1 ...", "ms": 269 }, { "tool": "run-code", "args": { "code": "void main(){print("Hello Dart");}", "languageId": "dart" }, "result": "Hello Dart Sum: 15 ", "ms": 576 }, { "tool": "run-code", "args": { "code": "console.log("Merhaba dünya! 🌍")", "languageId": "javascript" }, "result": "Merhaba dünya! 🌍 日本語テスト Türkçe: şçğüöı ", "ms": 37 }, { "tool": "run-code", "args": { "code": "console.log("a"); console.error("b")", "languageId": "javascript" }, "result": "Stderr: b ", "ms": 26, "note": "stdout DROPPED when stderr present" }, { "tool": "run-code", "args": { "code": "", "languageId": "javascript" }, "result": "Code is required.", "ms": 1 }, { "tool": "run-code", "args": { "code": "console.log("unclosed", "languageId": "javascript" }, "result": "Error: ... SyntaxError: Invalid or unexpected token", "ms": 26 }, { "tool": "run-code", "args": { "code": "while(true){}", "languageId": "javascript" }, "result": "MCP error -32001: Request timed out", "ms": 60005, "note": "60s timeout" }, { "tool": "run-code", "args": { "code": "process.exit(1)", "languageId": "javascript" }, "result": "Error: Command failed: node ...", "ms": 23 }, { "tool": "run-code", "args": { "code": "import sys; print(sys.version)", "languageId": "python" }, "result": "Error: pyenv: python: command not found", "ms": 147, "note": "python not python3" }, { "tool": "run-code", "args": { "code": "x", "languageId": "python3" }, "result": "MCP error -32602: invalid_enum_value", "note": "python3 not a valid languageId" }, { "tool": "run-code", "args": { "code": "x", "languageId": "brainfuck" }, "result": "MCP error -32602: invalid_enum_value (shows full enum list)", "ms": 1 } ], "tested_on": "macOS Darwin 25.4.0, Node.js v22.22.3" }