Skip to main content
Glama
unfallenwill

nodejs-repl-mcp

by unfallenwill

nodejs-repl-mcp

Session-stateful Node.js REPL exposed as an MCP server, packaged as a Docker image.

Each named session keeps a real node:repl context alive in its own child process: let/const declarations, top-level await, required modules, and per-session npm packages persist across tool calls until the session is removed. Designed for AI agents and automation that need to build up state across many small evaluations — no terminal UI, no stdin scraping.

Architecture

MCP client ──stdio──> MCP server (this process)
                          │  session table (in-memory)
                          ├── worker: node child process ── repl.REPLServer (own context)
                          ├── worker: node child process ── repl.REPLServer (own context)
                          └── ...
  • One worker process per session — crash isolation, independent require cache, killable individually.

  • Native REPL semantics — the worker drives the server's own default evaluator (REPLServer.prototype.eval), so let/const redeclaration, multi-line continuation (Recoverable), on-demand core-module loading, and top-level await behave exactly like the interactive node REPL.

  • Runtime errors — the REPL's internal domain prints Uncaught ... without invoking the eval callback; the worker taps its output stream and still returns a structured error, so the session survives bugs in evaluated code.

  • Per-session workspace — each session gets ~/.nodejs-repl/sessions/<name> (override with NODEJS_REPL_SESSIONS_DIR); the worker's cwd and require resolution root live there. install_packages runs npm install into that directory only.

Related MCP server: jupyter-kernel-mcp

Tools

Tool

Arguments

Description

create_session

name

Create a persistent session (^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$)

exec

name, code

Evaluate JS in the session; syntax-incomplete input is buffered and continues on the next exec. Returns { ok, output, error?, incomplete?, console? }

history

name, limit?

Evaluation history (inputs, outputs, errors, captured console)

list_sessions

All sessions with pid, workspace, liveness

remove_session

name

Kill the worker. Workspace dir is kept (deps/files survive)

install_packages

name, packages[], saveDev?

npm install into that session's workspace

Usage

The prebuilt image on GHCR (multi-arch: amd64 + arm64) needs no local build. MCP stdio transport needs stdin, so run with -i:

{
  "mcpServers": {
    "nodejs-repl": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/unfallenwill/nodejs-repl-mcp:latest"],
      "volumes": ["nodejs-repl-data:/data"]
    }
  }
}

Or with Claude Code:

claude mcp add nodejs-repl -- docker run -i --rm -v nodejs-repl-data:/data ghcr.io/unfallenwill/nodejs-repl-mcp:latest

Pin a release with :X.Y.Z instead of :latest for reproducible setups.

Build From Source

git clone https://github.com/unfallenwill/nodejs-repl-mcp.git
cd nodejs-repl-mcp
docker build -t nodejs-repl-mcp .

Then use the config above with the local tag, e.g. args: ["run", "-i", "--rm", "nodejs-repl-mcp"]. A different Playwright version can be baked in with --build-arg PLAYWRIGHT_VERSION=x.y.z.

Releases

Pushing a tag vX.Y.Z triggers .github/workflows/publish.yml and publishes ghcr.io/unfallenwill/nodejs-repl-mcp:{X.Y.Z, X.Y, latest} (pre-release tags get the exact version only):

git tag v0.1.0 && git push origin v0.1.0

The first push creates the package as private; flip it to public in the package's visibility settings for unauthenticated pulls.

Preinstalled Packages

The image ships with Playwright — package, headless Chromium build, and the system libraries it needs — so browser automation works out of the box, no install_packages required:

create_session { "name": "browser" }
exec { "name": "browser", "code": "const { chromium } = require('playwright'); const b = await chromium.launch(); const p = await b.newPage(); await p.setContent('<h1>hi</h1>'); await p.textContent('h1')" }   // 'hi'

The preinstalled set lives at /opt/session-deps and is exposed to sessions via NODE_PATH, so packages installed with install_packages (session-local node_modules) still take precedence. Pin a different version at build time with --build-arg PLAYWRIGHT_VERSION=x.y.z.

Local

npm install
npm run build
node dist/index.js          # MCP stdio server
claude mcp add nodejs-repl -- node /path/to/nodejs-repl-mcp/dist/index.js

Example session

create_session { "name": "analysis" }
exec { "name": "analysis", "code": "let data = [3,1,2]; data.sort()" }
exec { "name": "analysis", "code": "data" }                        // state persists: [1,2,3]
exec { "name": "analysis", "code": "const r = await fetch('https://example.com').then(r => r.status); r" }
install_packages { "name": "analysis", "packages": ["lodash@^4"] }
exec { "name": "analysis", "code": "require('lodash').chunk([1,2,3,4], 2)" }
history { "name": "analysis" }
remove_session { "name": "analysis" }

Design notes

Session-state persistence for REPLs has four known approaches (see research in .firecrawl/):

  1. History replay (.save/.load, Nesh) — simple, but replaying Math.random() or side-effecting statements yields wrong state.

  2. Runtime serialization — impractical in JS: closures are opaque; sockets/native handles can't be serialized.

  3. Process snapshotting (VM/CRIU, the RunKit/Tonic approach) — perfect semantics ("time travel") but heavy infrastructure.

  4. Session residency — keep the session process alive; state persists naturally. This is what nodejs-repl-mcp implements: the MCP server is already a long-lived process, so the coordinator layer of designs like node-repl-cli collapses into the server itself, and each session is a detached worker with a real REPL context.

Limitations

  • Sessions are process state: they do not survive server restarts or container restarts (workspace directories do, via the /data volume).

  • exec has no built-in timeout by design (long evaluations are legitimate). A wedged session can be killed with remove_session.

  • Workers run with full Node.js capabilities — no sandboxing. Do not expose the server to untrusted input; for untrusted code use a container/gVM-level boundary (the vm module is not a security boundary — vm2 escape).

Development

npm run build
node scripts/smoke.mjs                                  # local stdio smoke test (22 assertions)
SMOKE_CMD=docker SMOKE_ARGS="run -i --rm nodejs-repl-mcp" node scripts/smoke.mjs   # against the container
SMOKE_PLAYWRIGHT=1 SMOKE_CMD=docker SMOKE_ARGS="run -i --rm nodejs-repl-mcp" node scripts/smoke.mjs   # + preinstalled Playwright check

Available Tools

6 tools
create_sessionCreate REPL sessionA

Create a named, persistent Node.js REPL session. Each session runs in its own child process with an isolated context: variables, let/const declarations, required modules and top-level await state persist across exec calls until the session is removed.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesSession name (alphanumeric, -, _; max 64 chars)

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly explains that each session runs in its own child process, has an isolated context, preserves runtime state across exec calls, and persists until removed. This gives the agent important behavioral expectations without needing annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences and front-loads the core purpose before adding behavioral detail. There is no redundancy, and every sentence contributes useful information for correct usage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema, the description is quite complete: it explains persistence, isolation, and lifespan. It does not mention duplicate-name behavior or the exact response shape, but those are minor gaps for a simple creation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully documents the single `name` parameter with type, pattern, and description. The tool description adds little param-specific detail beyond referring to the session as 'named', so the schema already does the heavy lifting. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: creating a named, persistent Node.js REPL session. It also distinguishes itself from siblings by explaining that session state persists across exec calls and is removed only via removal, making its role clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: when a persistent, isolated REPL session is needed, as opposed to just executing one-off code. It does not explicitly name alternatives or state when not to use it, but the context around child-process isolation and persistence is strong enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

execEvaluate code in sessionA

Evaluate JavaScript in a named REPL session with full node:repl semantics. Syntax-incomplete input is buffered and continues on the next exec (multi-line). Returns the inspected result, captured console output, and any error. State persists between execs.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesJavaScript to evaluate (supports top-level await)
nameYesTarget session name

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description carries the full behavioral burden. It discloses state persistence between execs, buffering of syntax-incomplete input across calls, and the return content (inspected result, console output, error). It omits minor details like the exact response structure or whether a missing session is auto-created, but the core execution semantics are transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short, information-dense sentences, each earning its place: the primary action and semantics, the buffering behavior, the return values, and state persistence. The most important fact (evaluate JavaScript in a named session) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a side-effecting, stateful execution tool with no annotations and no output schema, the description is largely complete: it covers return values, multi-line buffering, and persistence. It could be stronger by stating whether the session must already exist or whether exec auto-creates it, but overall an agent has enough to call and interpret the result correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters already have meaningful descriptions, so the baseline is 3. The description adds extra value by linking the name parameter to persistent session state and clarifying that code is evaluated with full node:repl multi-line semantics, which enriches the meaning of both parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Evaluate JavaScript in a named REPL session.' It goes beyond a generic restatement by naming node:repl semantics and explicitly distinguishing the tool's behavior (evaluation with persistent state) from the session-management siblings like create_session or list_sessions, so an agent can tell it apart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The tool's use case is explicit: evaluate JavaScript in an existing named session, with multi-line input continuing on subsequent exec calls. It does not explicitly name alternatives or exclusions, but the sibling set and the phrase 'named REPL session' make the division of responsibility clear: exec is for evaluation, while create_session/list_sessions/history handle session management.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historySession historyA

Return the evaluation history of a session (inputs, outputs, errors, captured console) — useful for reviewing what state was built up.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesTarget session name
limitNoReturn only the last N entries

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the read-only nature through 'Return' and details what the history includes (inputs, outputs, errors, captured console). While ordering and limit behavior are not elaborated, the description gives sufficient behavioral context for a read-only query tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that names the action, resource, and content types. The parenthetical adds useful detail without unnecessary words. Every element earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with no output schema, the description covers the return contents and the intended use case. It does not describe the exact ordering of entries or the format of errors/console output, but the phrase 'last N entries' in the schema plus the description provides enough context for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (name and limit) are already documented in the schema. The description does not add per-parameter meaning beyond the schema, but it does clarify what kind of data the session history contains. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns evaluation history for a session and lists the specific contents (inputs, outputs, errors, captured console). The verb 'Return' plus the resource 'evaluation history of a session' is specific and clearly distinguishes it from sibling tools like exec, list_sessions, and create_session.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: it is useful for reviewing what state was built up in a session. It does not explicitly name exclusions or alternatives, but the context is strong enough for an agent to select this tool when a review of session history is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

install_packagesInstall npm packages into sessionA

Run npm install in the session workspace so subsequent exec calls can require/import the packages. Installs into that session only.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesTarget session name
saveDevNoSave as devDependencies
packagesYesPackage specifiers, e.g. ["lodash@^4"]

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It does reveal that the operation only affects that session and that packages become available to subsequent exec calls. However, it does not mention side effects like modifying package.json, network requirements, or the need for package-lock updates, which an agent might need to predict outcomes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The core command, its purpose, and the session-isolation behavior are all presented efficiently, with the most important information front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter tool with no output schema and no annotations, the description covers the core invocation, purpose, and scope. Minor gaps remain around expected output/errors and whether this modifies package manifests, but the essentials for correct invocation are present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters clearly. The description adds no parameter-specific meaning beyond what is in the schema, matching the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Run `npm install`'), a target resource ('in the session workspace'), and the intended outcome ('subsequent exec calls can require/import the packages'). It is clearly differentiated from siblings like create_session, exec, and remove_session by focusing on package installation into an existing session.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: use this to install packages so later exec calls can import them. It does not explicitly list when not to use it or name alternatives such as exec for running commands directly, so it falls just short of full usage-guideline coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sessionsList REPL sessionsA

List all REPL sessions with pid, workspace and liveness.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It states that all sessions are listed and that pid, workspace, and liveness are included, which implies a read-only, comprehensive operation. It does not explicitly state side effects or output format, but for a simple list operation the behavioral surface is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, tightly worded sentence that front-loads the action and resource, then specifies the returned fields. No filler or redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list tool, the description adequately covers purpose and output fields. It does not specify response formatting or error behavior, but with no output schema and such a simple operation, the missing details are minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the baseline is 4. The description adds useful context about the fields returned, even though it does not explain any parameters (there are none to explain).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and identifies the resource ('REPL sessions') while naming the returned fields (pid, workspace, liveness). This clearly distinguishes it from siblings like create_session and remove_session by operation, and from history/exec by resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied: use this when you need to enumerate all REPL sessions. However, there is no explicit mention of when not to use it or how it compares to alternative tools like history or exec, so the guidance is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_sessionRemove REPL sessionA

Stop and remove a session (kills its worker process). The session workspace directory is kept, so installed dependencies and written files survive.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesSession name to remove

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It explicitly states the destructive effect ('kills its worker process') and the non-destructive persistence ('workspace directory is kept... dependencies and written files survive'), which goes well beyond what the name and schema alone communicate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no wasted words. It front-loads the primary action and side effect, then adds the important persistence detail. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter destructive tool, the description is complete: it states what is removed, the side effect on the worker process, and what survives. There is no output schema, but for this tool the return value is not essential to correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The only parameter, 'name', is already fully documented in the schema with 'Session name to remove', giving 100% schema description coverage. The tool description adds no additional parameter-level meaning beyond the schema, so it meets but does not exceed the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb-resource pair ('Stop and remove a session') and adds a distinguishing side effect: 'kills its worker process'. This clearly separates it from siblings like create_session, list_sessions, and exec, so the agent knows exactly what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage context is implied: use this when you want to terminate and remove a REPL session. However, it does not explicitly name alternatives or state when not to use it, so the agent must infer when this tool is the right choice among the siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.3/5.0
Disambiguation5/5

Each tool maps to a distinct operation: session lifecycle (create/list/remove), code execution, history retrieval, and package installation. There is no meaningful overlap or risk of selecting the wrong tool.

Naming Consistency4/5

Most tools follow a clear verb_noun pattern (create_session, list_sessions, remove_session, install_packages), but exec and history are terse single-word names that break the pattern. Overall still readable and predictable.

Tool Count5/5

Six tools is a well-scoped set for managing persistent Node.js REPL sessions. Each tool serves a clear need without redundancy or bloat.

Completeness5/5

The surface covers the full lifecycle: create a session, execute code in it, inspect history, install dependencies, list sessions, and remove sessions. No obvious dead ends or missing critical operations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    B
    maintenance
    A secure Node.js execution environment that allows coding agents and LLMs to run JavaScript dynamically, install NPM packages, and retrieve results while adhering to the Model Control Protocol.
    7
    134
    4
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables creation and management of persistent REPL sessions for various languages and shells, with web-based monitoring and session recovery capabilities.
    33
    3
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI agents to start and manage pseudo-terminal sessions, run shell commands and interact with REPLs programmatically.
    7

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/unfallenwill/nodejs-repl-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server