Back to MCP Servers

Forge

Terminal MCP server for AI coding agents with persistent PTY sessions, ring-buffer incremental reads, headless xterm screen capture, multi-agent orchestration, and a real-time web dashboard.

command-lineaiagent
By ferodrigop
153Updated 2 months agoTypeScriptMIT

Installation

npx -y forge

Configuration

{
  "mcpServers": {
    "forge": {
      "command": "npx",
      "args": ["-y", "forge"]
    }
  }
}

How to use

  1. Run the installation command above (if needed)
  2. Open your Claude Code settings file (~/.claude/settings.json)
  3. Add the configuration to the mcpServers section
  4. Restart Claude Code to apply changes
<p align="center"> <img src="docs/forge-logo.png" alt="Forge" width="120" /> </p> <h1 align="center">Forge</h1> <p align="center"> Terminal MCP server for AI coding agents. Spawn, manage, and monitor real PTY sessions via the Model Context Protocol. </p> <p align="center"> <a href="https://forgemcp.dev"><strong>forgemcp.dev</strong></a> </p> <p align="center"> <a href="https://www.npmjs.com/package/forge-terminal-mcp"><img src="https://img.shields.io/npm/v/forge-terminal-mcp?color=blue" alt="npm version" /></a> <a href="https://github.com/ferodrigop/forge/actions/workflows/ci.yml"><img src="https://github.com/ferodrigop/forge/actions/workflows/ci.yml/badge.svg" alt="CI" /></a> <a href="https://www.npmjs.com/package/forge-terminal-mcp"><img src="https://img.shields.io/npm/dm/forge-terminal-mcp?color=brightgreen" alt="npm downloads" /></a> <img src="https://img.shields.io/badge/license-MIT-green" alt="License" /> <img src="https://img.shields.io/badge/node-%3E%3D18-339933" alt="Node" /> </p>
<p align="center"> <img src="docs/forge-demo.gif" alt="Forge Demo" width="800" /> </p> <p align="center"> <img src="docs/screenshot-terminal.png" alt="Terminal View with Changes Panel" width="800" /> </p> <p align="center"> <img src="docs/screenshot-chats.png" alt="Chat Browser" width="800" /> </p>

Why

AI coding agents (Claude Code, Codex, etc.) typically run one command at a time. Forge gives them persistent terminals — run your React frontend, Java API, and Postgres migrations in parallel, monitor all three, and only read what changed. Full-stack work without the bottleneck.

Works with any MCP-compatible client — Claude Code, Codex, Gemini CLI, or your own agent.

Key differentiators:

  • Real PTY via node-pty (same lib as VS Code terminal) — interactive programs, colors, TUI apps all work
  • Incremental reads — ring buffer with per-consumer cursors means each read_terminal only returns NEW output, saving context window tokens
  • Clean screen reads@xterm/headless renders the terminal server-side, so read_screen returns exactly what a human would see (no ANSI escape codes)
  • Multi-agent orchestration — spawn Claude, Codex, and Gemini sub-agents, session groups, output multiplexing, event subscriptions, and templates for managing multiple concurrent sessions
  • Web dashboard — real-time Preact-based browser UI to watch what your agents are doing across all terminals, browse past chat sessions, and monitor activity
  • Zero config — single npx command or HTTP MCP endpoint

Install

# bun (recommended)
bun install -g forge-terminal-mcp

# npm (requires Node.js ≥ 18)
npm install -g forge-terminal-mcp

# Or standalone binary (no Node.js required)
curl -fsSL https://forgemcp.dev/install.sh | sh

After install, the forge command is available globally:

forge start              # Start the server
forge start -d           # Start as background daemon
forge start -d --dashboard --port 3141   # With web dashboard

Update

# bun
bun update -g forge-terminal-mcp

# npm
npm update -g forge-terminal-mcp

# Standalone binary — re-run the install script
curl -fsSL https://forgemcp.dev/install.sh | sh

# Desktop app updates automatically on restart

Quick Start

1. Add to Your Agent

<details open> <summary><strong>Claude Code</strong></summary>
# Recommended: auto-starts daemon and registers HTTP transport
forge setup --agent claude-code

# Or manually:
forge start -d                  # Start daemon in background
claude mcp add --transport http forge http://127.0.0.1:3141/mcp

Note: Always use HTTP transport so Claude Code connects to the running daemon. This ensures sessions appear in the dashboard and avoids conflicts from isolated processes.

</details> <details> <summary><strong>Codex</strong></summary>
# Add Forge as HTTP MCP server
codex mcp add forge --url http://127.0.0.1:3141/mcp

# Verify
codex mcp list
codex mcp get forge

Codex stores this in ~/.codex/config.toml:

[mcp_servers.forge]
url = "http://127.0.0.1:3141/mcp"
</details> <details> <summary><strong>Gemini CLI</strong></summary>
# Start Forge daemon first
npx forge-terminal-mcp start -d --dashboard --port 3141

# Add Forge as HTTP MCP server
gemini mcp add --transport http forge http://127.0.0.1:3141/mcp
</details> <details> <summary><strong>HTTP MCP (any client)</strong></summary>

Start the daemon (choose one launch mode), then point any MCP client at the HTTP endpoint:

# If forge is on PATH (global install or npm link)
forge start -d

# From this repo (local clone)
node dist/cli.js start -d

# Without install (published package)
npx forge-terminal-mcp start -d
{
  "mcpServers": {
    "forge": {
      "type": "http",
      "url": "http://127.0.0.1:3141/mcp"
    }
  }
}
</details>

Restart your agent and Forge tools are available.

Important: Claude Code, Codex, and Gemini CLI load MCP servers at process start. If you add/remove servers, restart the current agent session.

2. Smoke Test (60s)

# Codex MCP registration
codex mcp list
codex mcp get forge

# Forge daemon status
node dist/cli.js status

Expected:

  • codex mcp list shows forge as enabled
  • node dist/cli.js status reports running and http://127.0.0.1:3141

Troubleshooting

SymptomFix
forge: command not foundUse node dist/cli.js ... from the repo root, or npx forge-terminal-mcp ....
No MCP servers configured yet in CodexRun codex mcp add forge --url http://127.0.0.1:3141/mcp, then restart Codex.
listen EPERM ... 127.0.0.1:3141Run Forge in an environment that allows local port binding, or use a different port with --port and update the MCP URL to match.
A message appears typed but agent does not answerThe input may be queued; press Enter (or use submit=true when writing programmatically).
MCP server is configured but tools do not appearRestart the current agent session so MCP servers reload.

3. Use It

Your agent now has access to 23 tools across 7 categories:

Session Lifecycle

create_terminal      → Spawn a PTY session with optional name, tags, buffer size
create_from_template → Spawn from a built-in template (shell, next-dev, vite-dev, etc.)
spawn_claude         → Launch a Claude Code sub-agent in a dedicated session
spawn_codex          → Launch a Codex sub-agent in a dedicated session
spawn_gemini         → Launch a Gemini CLI sub-agent in a dedicated session
close_terminal       → Kill a session and free resources
close_group          → Close all sessions matching a tag
list_terminals       → List sessions, optionally filtered by tag
list_templates       → Show available session templates

I/O

write_terminal       → Send input (appends newline by default)
read_terminal        → Read NEW output since last read (incremental)
read_screen          → Get rendered viewport as clean text (no ANSI)
read_multiple        → Batch read from up to 20 sessions at once
send_control         → Send Ctrl+C, arrow keys, Tab, Enter, etc.
resize_terminal      → Change terminal dimensions

Search & Wait

grep_terminal        → Regex search across a session's output buffer
wait_for             → Block until output matches a pattern or process exits

Execution

run_command          → Run a command to completion, return output, auto-cleanup

Events

subscribe_events     → Get notified when a session exits or matches a pattern
unsubscribe_events   → Cancel an event subscription

Agent Delegation

delegate_task        → Delegate a task to another agent — oneshot or interactive multi-turn

Ops

health_check         → Server version, uptime, session count, memory usage
get_session_history  → Tool call history for agent sessions
clear_history        → Clear persisted stale session entries

Example Conversations

You: Start a Next.js dev server and run the test suite in parallel

Agent: (uses create_from_template with "next-dev", wait_for "Ready", then creates a second session for npm test, uses read_multiple to poll both)

You: Spin up 3 sub-agents to research different parts of the codebase

Agent: (uses spawn_claude three times with tag "research", monitors with list_terminals filtered by tag, cleans up with close_group)

You: Build and test, just give me the result

Agent: (uses run_command with npm run build && npm test — creates terminal, waits for exit, returns output, auto-cleans up)

Best Practices

run_command vs create_terminal

Use run_command when you want a result and don't need the session afterwards:

  • Build steps (npm run build, cargo build)
  • Test runs (npm test, pytest)
  • Install commands (npm install, pip install)
  • One-off scripts that exit cleanly

Use create_terminal when you need an ongoing session:

  • Dev servers (npm run dev, vite, next dev)
  • Watchers (npm run watch, tsc --watch)
  • REPLs or interactive processes
  • Long-running processes you'll poll with read_terminal
# Good — build is a one-shot task
run_command({ command: "npm run build && npm test" })

# Good — dev server needs to stay alive
create_terminal({ command: "npm run dev", name: "dev-server" })
wait_for({ id, pattern: "ready on" })

waitForExit vs pattern matching

Use pattern matching (default) when the process stays alive after printing the signal:

wait_for({ id, pattern: "Server running on port 3000" })
# returns as soon as the line appears — process keeps running

Use waitForExit: true when the process exits naturally and you want all output:

wait_for({ id, pattern: ".", waitForExit: true })
# waits for the process to finish, returns everything

fromSession for sub-agents

When spawning a sub-agent to work on the same project, use fromSession instead of hardcoding paths:

# Instead of this (brittle):
spawn_claude({ prompt: "...", cwd: "/Users/me/projects/my-app" })

# Do this (inherits cwd from current session):
spawn_claude({ prompt: "...", fromSession: currentSessionId })

This ensures the sub-agent works in the correct directory even when Forge is used across different machines or worktrees.

Worktrees for parallel agents

When running multiple agents on the same codebase, use worktree: true to isolate changes:

spawn_claude({ prompt: "Add auth", worktree: true, branch: "feature/auth" })
spawn_claude({ prompt: "Add payments", worktree: true, branch: "feature/payments" })
# Both agents work in parallel without stepping on each other

Tools Reference

create_terminal

ParameterTypeDefaultDescription
commandstringUser's $SHELLCommand to run
argsstring[][]Command arguments
cwdstringProcess cwdWorking directory
envobject{}Additional env vars (merged with process env)
colsnumber120Terminal width
rowsnumber24Terminal height
namestringHuman-readable session name
tagsstring[]Tags for filtering/grouping (max 10)
bufferSizenumberServer defaultRing buffer size in bytes (1 KB – 10 MB)

Returns session info including the id used by all other tools.

create_from_template

ParameterTypeDefaultDescription
templatestringrequiredTemplate name (see list_templates)
cwdstringWorking directory override
envobjectAdditional env vars
namestringTemplate nameSession name override

Built-in templates:

TemplateCommandTagsWait For
shell$SHELLshell

View source on GitHub