Skip to main content
Glama
yapp

termius-mcp

by yapp
README.md
# termius-mcp

<p align="center">
  <img src="assets/logo.png" alt="termius-mcp logo" width="256">
</p>

MCP server that drives visible terminals in a running Termius app.

> **Local only.** This server connects to a locally running Termius desktop app via the Chrome DevTools Protocol on `localhost:9229`.

## Prerequisites

Termius must be running with remote debugging enabled. On macOS:

    /Applications/Termius.app/Contents/MacOS/Termius --remote-debugging-port=9229

At least one Termius window must be open. The server connects to the primary renderer (the main Termius UI), injects a bridge that exposes the Termius mediator API, and registers MCP tools that call into that bridge.

## Quick Start (with an MCP client)

Install once globally, or use `npx` to always run the latest version without install:

    npx -y termius-mcp

Then wire it into your MCP client. Pick your client below.

### Claude Desktop / Claude Code

`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows:

```json
{
  "mcpServers": {
    "termius-mcp": {
      "command": "npx",
      "args": ["-y", "termius-mcp"]
    }
  }
}
```

On Windows, Claude Desktop needs the `cmd /c` wrapper:

```json
{
  "mcpServers": {
    "termius-mcp": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "termius-mcp"]
    }
  }
}
```

### Cursor

`~/.cursor/mcp.json` (or `.cursor/mcp.json` in the repo for project-scoped):

```json
{
  "mcpServers": {
    "termius-mcp": {
      "command": "npx",
      "args": ["-y", "termius-mcp"]
    }
  }
}
```

### opencode

Add to your `opencode.json` / `opencode.jsonc`:

```json
{
  "mcp": {
    "termius-mcp": {
      "type": "local",
      "command": ["npx", "-y", "termius-mcp"]
    }
  }
}
```

### Cline (VS Code)

`cline_mcp_settings.json`:

```json
{
  "mcpServers": {
    "termius-mcp": {
      "command": "npx",
      "args": ["-y", "termius-mcp"]
    }
  }
}
```

### From source (for development)

    git clone https://github.com/yapp/termius-mcp.git
    cd termius-mcp
    npm install
    npm start

A repo-root `.mcp.json` is provided so Cursor / Claude Code / VS Code MCP builds can auto-discover the server without writing the config by hand.

## Usage

Once connected, ask the client to:

1. Open a local terminal in Termius (`terminal_create`).
2. Send a command to it (`terminal_send`).
3. Read the output (`terminal_read`).

The initial CDP connection is non-fatal. If Termius is not running when the server starts, the next tool call retries the connection.

## Tools

### Local terminals

| Tool | Description |
|---|---|
| `terminal_create` | Open a new Local Terminal in the Termius UI. Optional `command`, `cols`, `rows`. Returns the terminal id (UUID). |
| `terminal_send` | Write a raw string to terminal stdin via `mediator.shell.sendData`. |
| `terminal_read` | Drain buffered output. `wait=true` blocks up to `timeoutMs`; `snapshot=true` also returns visible xterm buffer lines. |
| `terminal_resize` | Resize both the xterm renderer and the pty (`shell.sendSize`). |
| `terminal_kill` | Close the terminal via `mediator.shell.close`. |
| `terminal_list` | List terminals managed by the bridge, including terminals opened in the UI before the server connected. |
| `terminal_send_keys` | Send a named special key (`Ctrl+C`, `Enter`, `Tab`, arrow keys, etc.) as the right escape sequence. |

### Existing SSH saved-host sessions

These tools operate on terminals that already exist in the running Termius app, typically SSH saved-host sessions opened from the UI. They auto-sync the bridge with the Redux state, so SSH terminals whose `.terminal` DOM element is not mounted (hidden tabs) remain addressable by `terminalId`. No credentials are needed: the bridge piggybacks on Termius's already-authenticated session.

| Tool | Description |
|---|---|
| `ssh_list_sessions` | List live terminal sessions from the Redux store with metadata: `connectionProtocol`, `address`, `hostLabel`, `isActive`, `osName`, `managed`. Optional `protocol` / `active` filters. |
| `ssh_send` | Write a raw string to an existing SSH session stdin. |
| `ssh_read` | Drain buffered output from an existing SSH session. Same options as `terminal_read`. |
| `ssh_wait_for` | Wait for a substring to appear in the output buffer. Useful for waiting for a prompt or a marker. Optional `drainOnMatch`. |
| `ssh_send_keys` | Send a named special key to an existing SSH session. |
| `ssh_sync` | Manually sync the bridge with the live Termius state. Called automatically by the other SSH tools. |

## Configuration

| Variable | Default | Description |
|---|---|---|
| `TERMIUS_CDP_HOST` | `localhost` | CDP endpoint host. |
| `TERMIUS_CDP_PORT` | `9229` | CDP endpoint port. Must match the `--remote-debugging-port` flag passed to Termius. |

## Testing

Smoke test against a running Termius instance (exercises `list`, `create`, `send`, `read`, `resize`, `sendKeys`):

    npm run smoke

End-to-end test that creates terminals, sends commands, and reads output:

    npm test

Both require Termius running with `--remote-debugging-port=9229`.

## Requirements

- Node.js with ESM support
- Termius desktop app (developed against v10.0.6)
- Network access to `localhost:9229`