AI-Pair Coding
on a live BASIC VM
Most code-exec MCP servers fork and die per call. jdBasic keeps a persistent VM, hands the AI a cited language reference so it stops hallucinating, and can compile your script to a redistributable EXE via LLVM — all from inside one tool call.
What makes this different
Four things you don't get from a sandboxed Python REPL or a forking shell-exec MCP.
Persistent VM — state carries
One jdBasic VM lives across every tool call in your session.
Variables, FUNCs,
IMPORTed modules — all
stick around. The AI can iterate like a human at the REPL.
jdb_doc — anti-hallucination
The AI can substring-search jdBasic's own language spec
(doc/languages.md)
before it writes code. "Does jdBasic have REDUCE?"
stops being a guess.
jdb_run_native — compile & ship
jdBasic ships an LLVM-18 native compiler in the same binary.
jdb_run_native lets the AI
turn your script into a standalone EXE — no Docker, no
pip install, no toolchain on
the user's machine.
STOP / RESUME — live-tweak
Loaded a game loop or long-running agent via
jdb_load?
jdb_stop pauses the VM, your
AI mutates state or rewrites a FUNC,
jdb_resume continues — without
losing world state.
Setup in 60 seconds
Works with Claude Code, Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf — every MCP-aware client.
-
1
Grab a binary
Download the latest release for your platform — or build from source with
build.sh MCPSERVER=1(build.bat MCPSERVER HTTPon Windows). -
2
Drop this into
.mcp.jsonProject root (Claude Code) or your client's MCP config (Claude Desktop, Cursor, Cline, …). Replace the path with the absolute path to your jdBasic binary.
{ "mcpServers": { "jdbasic": { "command": "/absolute/path/to/jdbasic", "args": ["--mcp"] } } }doc/languages.mdships next to the binary on purpose —jdb_docresolves it relative to the EXE first, so nocwdsetting is needed. -
3
Restart the client
Ask the agent to call
jdb_evalwithcode: "PRINT SUM(IOTA(20))". You should see210. You're paired up.
5-minute walkthrough
The exact loop from the video above: three on-camera tweaks to a running space-shooter, driven by Claude Code (Anthropic's terminal CLI) over MCP, and the VM never restarts. Any MCP client works — Claude Code is just the one on screen. Same shape works for agents, simulations, training loops.
Load the game into the VM
Just ask — no path, no tool name. Claude Code calls
jdb_load for you, which reads
space_shooter.jdb into the
persistent VM and starts it on a worker thread. The MCP server
keeps responding to tool calls while the game loop spins.
Pause it with F6
Press F6
in the game window (or have the AI call
jdb_stop). The VM parks the
frame thread at a deterministic safe point — score, lives, sprite
positions and the music thread all frozen in place.
“Turn the ship red and give me 100 lives”
Pure state change — one jdb_eval,
two values, evaluated against the live VM. No source edit needed.
Resume and the ship is red, the HUD reads 100, the same enemies are
still on screen.
jdb_eval code="g_palette{"player"} = [255, 80, 80] : lives = 100"
jdb_resume
“Move the shield bar 20 pixels up”
This one is a source edit. The AI changes the HUD-draw
FUNC and calls
jdb_recompile: the function
body is swapped into the live VM while the module state — score,
wave, combo — survives untouched.
# edit the shield-bar Y in the HUD draw FUNC, then
jdb_recompile ' FUNC body swaps in, score preserved
jdb_resume
“Let me shoot rainbow bullets”
Another recompile — the AI rewrites the bullet-colour logic and swaps it in. Resume and the same wave, the same enemies, the same score are right where you left them, only the bullets are now a rolling rainbow.
# edit the per-bullet colour, then
jdb_recompile ' same enemies, same wave on screen
jdb_resume
Ship a binary (optional)
Happy with where the game ended up? Ask the AI to call
jdb_run_native with the same
source. You get a standalone Windows EXE — drop it on a
USB stick, hand it to anyone, no jdBasic install on the target.
Tool reference
Every tool shares one persistent VM. Full schemas are advertised by the server itself — your client will surface them automatically.
| Tool | Purpose |
|---|---|
| jdb_eval | Execute jdBasic statements. Captured stdout is returned. State persists across calls. |
| jdb_check | Lint without running. Faster than the --lint subprocess; keeps the VM warm. |
| jdb_load | Load a .jdb file into the VM so subsequent jdb_eval can call its functions. |
| jdb_vars | List currently-bound variables with their tags / shapes. |
| jdb_funcs | List user-defined FUNC / SUB / ASYNC FUNC with signatures. |
| jdb_doc | Substring lookup against doc/languages.md. The authoritative answer for "does jdBasic have X" — kills hallucination. |
| jdb_stop | Pause a script loaded via jdb_load at a deterministic safe point. World state preserved. |
| jdb_resume | Resume a paused script. Picks up exactly where it stopped, with any mutations you made in between in effect. |
| jdb_recompile | Re-parse + re-compile the loaded source after edits. FUNC bodies get swapped; module state survives. |
| jdb_status | Where is the VM right now — running / stopped / idle? Useful gate before jdb_resume / jdb_stop. |
| jdb_run_native | Compile a snippet via the LLVM-18 backend, run the produced binary, capture stdout. Requires the Full build (NATIVEC=1). |
Full client-config (Claude Desktop / Cursor / Cline / Continue / Zed / Windsurf) and a deeper protocol breakdown live in doc/MCP.md.
⚠ Security
Every tool here can execute arbitrary jdBasic code, which means
arbitrary process actions inside the jdBasic VM. Treat the
MCP server like a local shell. The stdio transport is safe by default
(your client launches the process directly). The HTTP transport
(--mcp-http) binds to 127.0.0.1 only — never expose it on a
public interface without auth in front.
Ready to pair up?
Grab a release, paste the .mcp.json snippet, and ask your AI to call
jdb_eval. That's the whole setup.

