mcp-tmux-server

Zdendys79/mcp-tmux-server

3.2

If you are the rightful owner of mcp-tmux-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

The MCP Tmux Server is a universal Model Context Protocol server designed for bidirectional interaction with tmux terminal panes, enabling AI assistants to read and optionally write to terminal sessions.

Tools
7
Resources
0
Prompts
0

MCP Tmux Server

MCP (Model Context Protocol) server for real-time tmux terminal interaction. Enables AI assistants like Claude Code to execute commands and read terminal output.

Features

✅ Command Execution

  • Synchronous execution - blocks until command completes (up to 10s default)
  • Progress reporting - real-time STDERR updates during execution
  • Output capture - returns all command output
  • Prompt detection - automatically detects when command finishes

✅ Real-Time Terminal Reading

  • NO CACHING - always returns fresh, current terminal state
  • Multiple sessions - monitor multiple tmux sessions simultaneously
  • Session management - list and inspect active tmux sessions

✅ Advanced Controls

  • Keyboard shortcuts - send Ctrl+C, Ctrl+D, arrows, function keys
  • Text input - type text into interactive programs (editors, prompts)
  • Session whitelist - restrict access to specific tmux sessions

Installation

# Clone repository
cd ~/mcp-servers
git clone git@github.com:Zdendys79/mcp-tmux-server.git tmux
cd tmux

# Install dependencies and build
npm install
npm run build

# Configure Claude Code MCP
# Add to ~/.claude.json:
{
  "mcpServers": {
    "tmux": {
      "command": "node",
      "args": ["/home/zdendys/mcp-servers/tmux/dist/index.js"]
    }
  }
}

# Enable write mode (required for command execution)
# Create config file: ~/.config/mcp-tmux/config.json
{
  "version": "auto",
  "write_enabled": true,
  "allowed_sessions": [],
  "buffer_size": 1000,
  "auth_token": null
}

MCP Tools Reference

execute - Execute command and wait for completion

CRITICAL: This tool BLOCKS until command completes. Do NOT respond to user before tool returns!

Description: Executes command in tmux pane and waits synchronously for completion (up to 10 seconds by default). Returns all command output. Progress is reported to STDERR during execution.

Parameters:

  • session (string, required) - Tmux session name
  • command (string, required) - Command to execute
  • window (int, default: 0) - Window index
  • pane (int, default: 0) - Pane index
  • timeout (int, default: 10, max: 300) - Timeout in seconds

Returns:

{
  "target": "session-1:0.0",
  "command": "ls -la",
  "completed": true,
  "timeout_occurred": false,
  "elapsed_seconds": 0.52,
  "output_lines": [
    "total 48",
    "drwxrwxr-x 3 user user 4096 Nov  8 12:00 .",
    "drwxrwxr-x 9 user user 4096 Nov  8 11:00 .."
  ],
  "timestamp": "2025-11-08T12:34:56.789"
}

STDERR Progress Messages:

[MCP execute] Command started: ls -la
[MCP execute] ✓ Command COMPLETED in 0.52s

Example:

// ✅ CORRECT - call tool, wait silently, then report results
const result = await execute({session: "work", command: "npm install"});
console.log(`Installation completed in ${result.elapsed_seconds}s`);

// ❌ WRONG - don't say "waiting" - tool already waits!
execute({session: "work", command: "npm install"});
console.log("Command is running, waiting for completion...");  // NO!

read_tmux_pane - Read current pane content

Description: Reads FRESH content from tmux pane - NO CACHING, always returns current state. Use this to check terminal output at any time.

Parameters:

  • session (string, required) - Tmux session name
  • window (int, default: 0) - Window index
  • pane (int, default: 0) - Pane index

Returns:

{
  "target": "session-1:0.0",
  "lines": [
    "user@host:~/project$ ls",
    "file1.txt  file2.txt  README.md",
    "user@host:~/project$ "
  ],
  "total_lines": 3,
  "timestamp": "2025-11-08T12:34:56.789"
}

Example:

// Read current terminal state
const content = await read_tmux_pane({session: "monitoring"});
const lastLine = content.lines[content.lines.length - 1];
console.log(`Current prompt: ${lastLine}`);

write_tmux_pane - Type text into pane

⚠️ WARNING: This tool is for TYPING TEXT ONLY (like into vim/nano). For executing commands, use execute instead!

Description: Simulates typing text into tmux pane. Does NOT wait for completion or capture output. Use only for interactive text input (editors, prompts), NOT for command execution.

Parameters:

  • session (string, required) - Tmux session name
  • text (string, required) - Text to type
  • window (int, default: 0) - Window index
  • pane (int, default: 0) - Pane index

Returns:

{
  "target": "session-1:0.0",
  "sent": "Hello World\n",
  "timestamp": "2025-11-08T12:34:56.789"
}

Use cases:

  • Typing into text editors (vim, nano)
  • Entering input at interactive prompts
  • Sending text that should NOT be executed

Example:

// ✅ CORRECT - typing into vim
await write_tmux_pane({session: "edit", text: "i"});  // Enter insert mode
await write_tmux_pane({session: "edit", text: "Hello World"});  // Type text

// ❌ WRONG - use execute for commands!
await write_tmux_pane({session: "work", text: "ls -la\n"});  // NO! Use execute instead

send_keys_tmux - Send keyboard shortcuts

Description: Sends special keys and keyboard shortcuts to tmux pane. Use for control keys, arrows, function keys.

Parameters:

  • session (string, required) - Tmux session name
  • key (string, required) - Key or key combination to send
  • window (int, default: 0) - Window index
  • pane (int, default: 0) - Pane index

Supported keys:

  • Control keys: C-c (Ctrl+C), C-u, C-k, C-w, C-a, C-e, C-l, C-d, C-z
  • Special keys: Enter, Escape, Tab, BSpace, Space
  • Arrow keys: Up, Down, Left, Right
  • Function keys: F1 through F12

Returns:

{
  "target": "session-1:0.0",
  "key": "C-c",
  "timestamp": "2025-11-08T12:34:56.789"
}

Examples:

// Interrupt running process
await send_keys_tmux({session: "work", key: "C-c"});

// Clear current line
await send_keys_tmux({session: "work", key: "C-u"});

// Clear screen
await send_keys_tmux({session: "work", key: "C-l"});

// Navigate command history
await send_keys_tmux({session: "work", key: "Up"});

get_tmux_sessions - List active tmux sessions

Description: Returns list of all active tmux sessions. Filtered by allowed_sessions config if set.

Parameters: None

Returns:

{
  "sessions": [
    {
      "name": "work",
      "windows": 3,
      "panes": 1
    },
    {
      "name": "monitoring",
      "windows": 1,
      "panes": 1
    }
  ],
  "count": 2
}

Example:

const sessions = await get_tmux_sessions();
for (const session of sessions.sessions) {
  console.log(`Session: ${session.name} (${session.windows} windows)`);
}

get_pane_info - Get detailed pane information

Description: Returns detailed information about specific tmux pane including dimensions, running command, and prompt detection.

Parameters:

  • session (string, required) - Tmux session name
  • window (int, default: 0) - Window index
  • pane (int, default: 0) - Pane index

Returns:

{
  "target": "session-1:0.0",
  "width": 120,
  "height": 40,
  "command": "bash",
  "active": true
}

Example:

const info = await get_pane_info({session: "work"});
console.log(`Pane size: ${info.width}x${info.height}`);
console.log(`Running: ${info.command}`);

get_server_version - Get server version and status

Description: Returns MCP server version, capabilities, and current configuration.

Parameters: None

Returns:

{
  "version": "v2025-11-08 build 125023",
  "write_enabled": true,
  "tmux_available": true,
  "config_path": "/home/user/.config/mcp-tmux/config.json"
}

Configuration

Config file location: ~/.config/mcp-tmux/config.json

Default configuration:

{
  "version": "auto",
  "write_enabled": false,
  "allowed_sessions": [],
  "buffer_size": 1000,
  "auth_token": null
}

Configuration options:

  • write_enabled (bool) - Enable command execution and text input (default: false)
  • allowed_sessions (array) - Whitelist of allowed session names (empty = allow all)
  • buffer_size (int) - Reserved for future use (buffering should be disabled)
  • auth_token (string) - Reserved for future authentication

Example with restrictions:

{
  "version": "auto",
  "write_enabled": true,
  "allowed_sessions": ["work", "monitoring", "dev"],
  "buffer_size": 1000,
  "auth_token": null
}

Usage Examples

Basic command execution

// Execute command and get output
const result = await execute({session: "work", command: "ls -la"});
console.log(`Files: ${result.output_lines.length} lines`);
console.log(`Completed in ${result.elapsed_seconds}s`);

Monitor long-running process

// Start long process
await execute({session: "build", command: "npm run build", timeout: 300});

// Check progress
const content = await read_tmux_pane({session: "build"});
console.log(content.lines.slice(-5));  // Last 5 lines

Interactive session

// Start Python REPL
await execute({session: "repl", command: "python3"});

// Type code (not execute - just typing!)
await write_tmux_pane({session: "repl", text: "import sys\n"});
await write_tmux_pane({session: "repl", text: "print(sys.version)\n"});

// Read output
const content = await read_tmux_pane({session: "repl"});

Error handling

// Execute with timeout
const result = await execute({session: "work", command: "sleep 20", timeout: 5});

if (result.timeout_occurred) {
  console.log("Command timed out!");
  await send_keys_tmux({session: "work", key: "C-c"});  // Interrupt
} else {
  console.log("Command completed successfully");
}

Architecture Details

File Structure

tmux/
├── src/
│   └── index.ts            # Main MCP server (single file implementation)
├── dist/
│   └── index.js           # Compiled JavaScript
├── tools/
│   └── new-session.sh     # Helper script for session creation
├── package.json
├── tsconfig.json
├── README.md
├── STATUS.md              # Project status and completed improvements
└── .gitignore

Components

MCP Server (index.ts)

  • MCP protocol handler using @modelcontextprotocol/sdk
  • Stdio communication (reads stdin, writes stdout)
  • Tool registration and routing
  • Tmux command execution (inline, no separate manager)
  • Configuration management
  • Session whitelist enforcement
  • Progress reporting via STDERR

Data Flow

User types in tmux → command finishes
    ↓
AI calls execute(session="foo", command="ls")
    ↓
MCP Server execute handler
    ├─ Sends command to tmux
    ├─ Polls every 500ms
    ├─ Writes progress to STDERR
    ├─ Detects prompt return
    └─ Returns output to AI
    ↓
AI receives results and reports to user

Progress Reporting (STDERR)

Execute function should write to STDERR during execution:

[MCP execute] Command started: npm install
[MCP execute] Still running... (1.0s)
[MCP execute] Still running... (2.0s)
[MCP execute] ✓ Command COMPLETED in 2.34s

This allows Claude Code to see real-time progress without needing to poll.


Security

  • Read-only by default - Write mode must be explicitly enabled
  • Session whitelist - Restrict access to specific tmux sessions
  • No shell injection - All commands use subprocess with array args (never shell: true)
  • Timeout limits - Maximum 300s timeout to prevent indefinite blocking
  • No credential exposure - Never logs or returns passwords/tokens

Troubleshooting

MCP server not starting

# Check tmux is installed
tmux -V

# Test server manually
cd ~/mcp-servers/tmux
node dist/index.js

Commands not executing

  • Check write_enabled: true in ~/.config/mcp-tmux/config.json
  • Verify session exists: tmux list-sessions
  • Check session is in allowed_sessions if whitelist is set

Output issues

  • Server always returns fresh content (no caching)
  • If issues persist, try reconnecting MCP server or restart Claude Code

Version History

Version Format: vYYYY-MM-DD build HHMMSS

Current Version (v2025-11-08)

  • Full TypeScript implementation with MCP SDK
  • No caching - always returns fresh terminal content
  • execute tool with STDERR progress reporting
  • Date-based versioning (auto-generated from build time)
  • Default timeout: 10s
  • Clear WARNING banners in tool descriptions
  • Clean codebase (829 lines, no dead code)

Features

  • Execute commands with automatic completion detection
  • Real-time progress reporting via STDERR
  • Read fresh terminal content (no caching)
  • Type text into interactive programs
  • Send keyboard shortcuts (Ctrl+C, arrows, etc.)
  • Session management with auto-increment naming
  • Security: read-only by default, session whitelist support

Development

# Install dependencies
npm install

# Build
npm run build

# Test manually
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js

License

MIT License

Author

Created by Zdendys & Nyara for Claude Code integration

Links