Ternux
MCP

Available Tools

The two MCP tools Ternux exposes, and their limits.

list_open_connections

Lists SSH tabs currently open in Ternux — no arguments. Returns each session's session_id, host, port, user, and display name. A session only appears here while its tab is open; closing the tab removes it immediately.

run_command

Runs a shell command on an open SSH connection over a fresh exec channel.

ArgumentRequiredDescription
session_idYesMust match an id from list_open_connections. Any other value is rejected.
commandYesShell command to execute.
stdinNoText written to the command's stdin before EOF (e.g. a sudo password). Never written to the audit log.
timeout_msNoDefaults to 30000 (30s), clamped to a max of 300000 (5 min).

Limits to plan around

  • Not your interactive terminal. The command runs over a brand-new SSH connection, not the tab's live PTY — it doesn't share that shell's working directory, exported variables, or activated environments (e.g. a cd or source venv/bin/activate you ran interactively won't apply).
  • No PTY, no interactive prompts. Anything expecting a tty (password prompts, confirmation dialogs, interactive sudo) will hang or fail. Feed required input through stdin, and write commands defensively (e.g. sudo -S -p '' <cmd>, apt-get -y ...).
  • 5-minute hard ceiling. Long-running jobs (builds, large upgrades) that don't finish in time return as an error — there's no extension, pause, or resume.
  • No polling or streaming. Each call is a single blocking request/response; there's no job ID or status endpoint. To track something long-running, start it detached from one call (e.g. nohup ./upgrade.sh > /tmp/upgrade.log 2>&1 &) and check progress with separate, short calls (tail /tmp/upgrade.log, pgrep -f upgrade.sh).
  • Can't target new hosts. session_id is the only way in — the tool never accepts a host, user, or credentials, so it can only reach connections you already opened in Ternux.

Errors

Tool-level failures (session not found, timeout, non-zero exit) come back as {"isError": true, ...} inside a successful JSON-RPC response, not as a protocol-level error — check isError in the result, not just the HTTP status.

On this page