Anonymous View
jdBasic

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.

# call 1
jdb_eval "DIM x = SUM(IOTA(100))"
# call 2 (an hour later)
jdb_eval "PRINT x" ' → 5050

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_doc query="FOLD"
→ "Use REDUCE (lambda, array). FOLD is
  not a jdBasic keyword."

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.

# 218 KB EXE, runs anywhere
jdb_run_native code="..."
→ stdout + dropped .exe path

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.

jdb_stop
jdb_eval "g_palette{"player"} = [255,80,80] : lives = 100"
jdb_resume ' game keeps running

Setup in 60 seconds

Works with Claude Code, Claude Desktop, Cursor, Cline, Continue, Zed, Windsurf — every MCP-aware client.

  1. 1

    Grab a binary

    Download the latest release for your platform — or build from source with build.sh MCPSERVER=1 (build.bat MCPSERVER HTTP on Windows).

  2. 2

    Drop this into .mcp.json

    Project 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.md ships next to the binary on purpose — jdb_doc resolves it relative to the EXE first, so no cwd setting is needed.

  3. 3

    Restart the client

    Ask the agent to call jdb_eval with code: "PRINT SUM(IOTA(20))". You should see 210. 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.

1

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.

you: "Let us code on space shooter"
2

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.

jdb_stop
3

“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
4

“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
5

“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
6

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.

jdb_run_native code="PRINT 'Hello from a fresh EXE'"

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_evalExecute jdBasic statements. Captured stdout is returned. State persists across calls.
jdb_checkLint without running. Faster than the --lint subprocess; keeps the VM warm.
jdb_loadLoad a .jdb file into the VM so subsequent jdb_eval can call its functions.
jdb_varsList currently-bound variables with their tags / shapes.
jdb_funcsList user-defined FUNC / SUB / ASYNC FUNC with signatures.
jdb_docSubstring lookup against doc/languages.md. The authoritative answer for "does jdBasic have X" — kills hallucination.
jdb_stopPause a script loaded via jdb_load at a deterministic safe point. World state preserved.
jdb_resumeResume a paused script. Picks up exactly where it stopped, with any mutations you made in between in effect.
jdb_recompileRe-parse + re-compile the loaded source after edits. FUNC bodies get swapped; module state survives.
jdb_statusWhere is the VM right now — running / stopped / idle? Useful gate before jdb_resume / jdb_stop.
jdb_run_nativeCompile 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.