interminal
This server gives AI assistants terminal access to both local and remote SSH environments, supporting interactive and long-running commands.
Connect to SSH servers (
connect_ssh): Establish persistent SSH sessions with password or key-based authentication, receiving asession_idfor subsequent commands.Create local shell sessions (
create_local): Spawn a persistent local shell (bash, zsh, PowerShell, etc.) on the host machine with full execution privileges.Execute commands (
execute): Run shell commands in any active session; short commands return output immediately (status=completed), while long-running commands returnstatus=partialwith acommand_idfor further interaction.Poll running command output (
read_output): Retrieve new output from a still-running command without sending input — useful for monitoring builds or background processes.Respond to interactive prompts (
respond): Send text input (e.g., answering[Y/n]prompts or entering passwords) to a command waiting for user input.Send control keys and signals (
send_control): Transmit control characters and key sequences (Ctrl+C, arrow keys, F-keys, ESC, Tab, etc.) to interrupt commands or drive TUI applications like vim, htop, or Zellij.List active sessions (
list_sessions): View all currently open SSH and local sessions, including their type and connection details.Disconnect sessions (
disconnect): Gracefully close a session, terminating all associated processes and freeing resources.Configure command timeouts: Control response timing using
pause_timeout(output silence) andtotal_timeout(hard duration limits).
Interminal
Lightweight MCP server that gives AI assistants terminal access — SSH and local shells — with support for interactive and long-running commands.
Installation
# Run directly, no install needed (recommended)
uvx mcp-interminal
# Or install permanently
pip install mcp-interminalRequires Python ≥ 3.11.
Related MCP server: Terminal MCP
MCP Client Configuration
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"interminal": {
"command": "uvx",
"args": ["mcp-interminal"]
}
}
}Cursor / other clients: same command + args format above.
Tools
Tool | Description |
| Connect to an SSH server; returns |
| Run a command locally (no session needed) or over SSH; returns output or |
| Poll a running command for new output without sending input |
| Send text input to a command waiting at a prompt |
| Send control keys: |
| Close an SSH session and release all resources |
Persistent State
Each execute call runs in an isolated channel — there is no persistent shell between calls. For simple tasks, chaining with && works.
For multi-step workflows (project development, debugging, deployment), a terminal multiplexer (like Zellij) provides persistent state that survives across calls. The AI agent can create a persistent session where cd, environment variables, virtual environments, and long-running processes carry over naturally.
Key Behaviors
Stateless execute — each call is an isolated channel;
cd /foodoes not persist. Simple tasks: chain with&&. Multi-step workflows: use a terminal multiplexer.Long-running commands return
status="partial"with acommand_id; poll withread_outputor send input withrespondSSH PTY is 500×200 xterm-256color so multiplexer sessions render at your actual terminal size
Optional Dependencies
pip install "mcp-interminal[pty]" # Windows PTY support (pywinpty)
pip install "mcp-interminal[ansi]" # ANSI escape rendering (pyte)
pip install "mcp-interminal[pty,ansi]" # bothAvailable Tools
6 toolsconnect_sshA
Opens a persistent SSH connection and returns a session_id for use with
`execute`. The connection stays open until `disconnect`. Host keys are
auto-accepted. For local commands, call `execute` directly — no session needed.
PARAMETER GUIDANCE: Reuse session_id across multiple execute calls —
each connect_ssh opens a new TCP connection. key_filepath is tried
first when both key and password are provided; password acts as
fallback. With neither, SSH agent and system defaults are used. The
username defaults to the OS user if omitted. host is resolved at
connect time; unresolvable names raise an error. banner_timeout
controls MOTD capture — if exceeded, banner returns "" (not an error);
set to 0 to skip capture entirely.
SIDE EFFECTS: Opens a TCP socket with a 30-second keepalive. Leaks
the socket if `disconnect` is never called.
ERRORS: Raises on auth failure, unresolvable host, refused connection,
or network timeout.
RETURNS: {"session_id": str, "banner": str}
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | Hostname or IP of the SSH server (e.g. '192.168.1.10', 'example.com') | |
| port | No | SSH port number, 1–65535 | |
| password | No | Password for password-based auth; omit for key-based auth | |
| username | No | Login user for authentication; omit to use SSH agent or OS default | |
| key_filepath | No | Absolute path to a private key file (e.g. '/home/user/.ssh/id_rsa') | |
| banner_timeout | No | Max seconds to capture the MOTD/welcome banner after login |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses side effects (TCP socket with keepalive, leak if disconnect not called), errors (auth, unresolvable host, etc.), and behaviors like host resolution and banner capture. Adds context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections: overview, parameter guidance, side effects, errors, returns. Front-loaded purpose. No wasted words; each sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a complex tool: covers all 6 parameters, side effects, error conditions, and return format. No gaps in information needed for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds valuable guidance: key_filepath tried first, password fallback, username defaults, banner_timeout behavior (0 skips). Adds meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it opens a persistent SSH connection and returns a session_id for use with 'execute'. It distinguishes from sibling tools like 'execute' (for local commands) and 'disconnect'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance: 'For local commands, call execute directly — no session needed.' Details parameter precedence, default behavior, banner timeout, and the lifecycle (connect, execute, disconnect).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disconnectADestructiveIdempotent
Close an SSH session and release all associated resources. NOT needed
for local commands — those clean up automatically.
SESSION_ID LIFECYCLE: The id is an opaque UUID created by connect_ssh,
used with execute, and retired by this call. Each connect_ssh produces
a unique id — reconnecting the same host gives a new one. After
disconnect, execute() with the old id raises ValueError. Calling
disconnect on an already-closed or unknown id is a safe no-op
(idempotent), so cleanup logic never needs to guard against double-close.
SIDE EFFECTS: Terminates all running commands on this session (their
command_ids become invalid), closes SSH channels and TCP socket.
WHEN NOT TO USE: To stop a single command without closing the session,
use send_control with "ctrl+c" instead.
RETURNS: true (always succeeds).
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes | SSH session identifier obtained from connect_ssh |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructive and idempotent behavior. The description adds detailed transparency by explaining that calling disconnect on an already-closed or unknown id is a safe no-op, that it terminates all running commands, invalidates command_ids, and closes channels and sockets. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for lifecycle, side effects, when-not-to-use, and returns. It is front-loaded with the main purpose and every sentence adds value. Despite length, it is efficient and not verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and annotations, the description covers all necessary aspects: lifecycle, side effects, alternatives, idempotency, return value, and parameter semantics. It is fully complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers the session_id parameter with a basic description. The description adds substantial meaning: it explains that the id is an opaque UUID from connect_ssh, is used with execute, and is retired by disconnect. It also clarifies that each connect_ssh produces a unique id, and reconnecting the same host yields a new one.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Close an SSH session and release all associated resources.' It distinguishes from sibling tools by explicitly noting it is not needed for local commands and that for stopping a single command, send_control should be used.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use and when-not-to-use guidance. It states that disconnect is for closing SSH sessions, not for local commands, and advises using send_control to stop a single command. It also explains the session lifecycle, making usage context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
executeADestructive
Execute a command locally or over SSH in an isolated channel.
PARAMETER RELATIONSHIPS & VALIDATION:
- `session_id` vs `shell`: `session_id` determines the execution environment. If provided (must be a valid active session), it runs over SSH and `shell` is completely ignored. If omitted, it runs locally, and `shell` (e.g., 'powershell.exe', '/bin/bash') is used.
- `pause_timeout` vs `total_timeout`: These interact to manage execution time. `pause_timeout` (must be > 0) triggers an early return if the command goes silent for that many seconds. `total_timeout` (must be >= `pause_timeout`) sets a hard wall-clock limit even if output is constantly streaming. To wait longer for a quiet command (e.g., a build), increase `pause_timeout`.
- Both timeouts accept floats but invalid ranges (e.g., pause_timeout <= 0, or total_timeout < pause_timeout) or an unknown `session_id` will raise a ValueError.
WHEN NOT TO USE:
Do not use this to send input to an existing command (`respond`), send control keys (`send_control`), or poll a running command (`read_output`).
SIDE EFFECTS:
Spawns a new, stateless process. `cd` or environment variables do NOT persist between calls. For persistent state, start a terminal multiplexer in the foreground. Never use `&` to background TUI apps.
RETURNS:
- {"status": "completed", "output": str, "exit_code": int}
- {"status": "partial", "output": str, "command_id": str}
| Name | Required | Description | Default |
|---|---|---|---|
| shell | No | Shell for local execution (e.g. 'powershell.exe', '/bin/bash'); ignored for SSH | |
| command | Yes | Shell command to run (stateless — cd does not persist between calls) | |
| session_id | No | SSH session_id from connect_ssh; omit for local execution | |
| pause_timeout | No | Seconds of silence before returning a partial result (> 0, ≤ total_timeout) | |
| total_timeout | No | Hard cap on call duration in seconds (≥ pause_timeout) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses statelessness, non-persistence of cd/env, and warnings about backgrounding. Annotations provide destructiveHint and readOnlyHint, and description adds context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections: purpose, parameter relationships, when not to use, side effects, returns. Every sentence adds value; no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all aspects: purpose, usage guidance, behavioral traits, parameter details, return types. No gaps given the tool's complexity and absence of output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and description adds significant extra semantics: parameter relationships (session_id vs shell, pause_timeout vs total_timeout), validation (ValueError on invalid ranges), and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb+resource+context: 'Execute a command locally or over SSH in an isolated channel.' Distinguishes from sibling tools like respond, send_control, read_output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'WHEN NOT TO USE' section listing alternatives. Also explains parameter relationships and validation, guiding when to use local vs SSH.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_outputARead-only
Poll new output from a running command without sending input. Use after
execute returns status="partial" for non-interactive commands (builds,
training loops, long searches).
Each call returns only output produced since the last read. When the
command finishes, status changes to "completed" and the command_id is
retired — further calls raise ValueError.
WHEN NOT TO USE: If the command expects input, use respond. If you
need to interrupt or send keys, use send_control.
PARAMETER GUIDANCE: pause_timeout is the primary dial — it controls
how long to wait when the command is silent. total_timeout only caps
actively streaming output and has no effect during silence.
ERRORS: Raises ValueError if command_id is invalid or already completed.
RETURNS:
- {"status": "partial", "output": str, "command_id": str}
- {"status": "completed", "output": str, "exit_code": int}
| Name | Required | Description | Default |
|---|---|---|---|
| command_id | Yes | The command_id from a status='partial' response. Raises ValueError if invalid or already completed | |
| pause_timeout | No | Seconds of silence before returning. Primary dial for polling — raise it (e.g. 30, 60) for quiet jobs instead of total_timeout. Must be > 0 and ≤ total_timeout | |
| total_timeout | No | Hard cap on call duration in seconds. Only binds while output is streaming — silent polls return at pause_timeout. Must be ≥ pause_timeout |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses key behaviors beyond readOnlyHint: incremental output (each call returns new output since last read), command lifecycle (retired on completion, future calls raise ValueError), and error conditions. No contradiction with readOnlyHint or openWorldHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections like 'WHEN NOT TO USE', 'PARAMETER GUIDANCE', 'ERRORS', 'RETURNS'. Every sentence adds value; no filler. Concise yet comprehensive.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description fully documents return types with structure and meaning. Covers error scenarios, lifecycle, polling semantics. Complete for a polling tool of moderate complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (baseline 3), but the description adds significant value by explaining the roles of pause_timeout vs total_timeout: 'pause_timeout is the primary dial... total_timeout only caps actively streaming output.' This clarifies behavior beyond schema comments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a clear verb+resource: 'Poll new output from a running command without sending input.' It distinguishes itself from siblings like 'respond' and 'send_control' by specifying when to use each.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use: 'Use after execute returns status="partial" for non-interactive commands.' Also includes a 'WHEN NOT TO USE' section with direct alternatives (respond, send_control), guiding the agent clearly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
respondADestructive
Write text to a running command's stdin. Works for prompts (y/n,
passwords), shell input, or any text the process expects.
PARAMETER GUIDANCE: text auto-appends \n if missing. For control
keys use send_control — AI frameworks strip control bytes. Raise
pause_timeout (not total_timeout) for slow responses after input.
Raises ValueError if command_id is invalid or completed.
WHEN NOT TO USE: Inside zellij, prefer multiplexer CLI via execute.
SIDE EFFECTS: Writes to stdin; may trigger output, state change, or exit.
RETURNS:
- {"status": "partial", "output": str, "command_id": str}
- {"status": "completed", "output": str, "exit_code": int}
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Text to write to stdin (e.g. 'y', a password, a shell command) | |
| command_id | Yes | The command_id from a status='partial' response. Raises ValueError if invalid or already completed | |
| pause_timeout | No | Seconds of silence before returning (> 0, ≤ total_timeout) | |
| total_timeout | No | Hard cap on call duration in seconds (≥ pause_timeout) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses side effects (writes to stdin, may trigger output/state change/exit), auto-appends newline, and raises ValueError for invalid/closed commands. Complements annotations (destructiveHint=true) with actionable behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with labeled sections (parameter guidance, when not to use, side effects, returns). Every sentence adds necessary information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, description fully explains return values with status/output/exit_code structure. Covers error conditions and parameter interactions thoroughly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds value beyond 100% schema coverage by explaining auto-appending newline, recommending send_control for control codes, and clarifying pause_timeout/total_timeout usage. Each parameter gets contextual usage guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Write text to a running command's stdin' with specific verb and resource. Distinguishes from sibling send_control for control keys and execute for starting commands.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides 'WHEN NOT TO USE' clause (inside zellij) and guidance for parameter adjustments (pause_timeout vs total_timeout). Clearly contrasts with send_control for alternative input methods.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_controlADestructive
Send a control key or escape sequence to a running command. Use for
interrupts (ctrl+c), TUI navigation (arrows, F-keys), or any
non-printable input. Prefer this over `respond` for control keys —
AI frameworks strip raw control bytes from string arguments.
SIGNAL HANDLING: The signal parameter accepts any key name from the
supported list (case-insensitive, whitespace-tolerant — "Ctrl + C"
works). Common signals: ctrl+c (SIGINT/interrupt), ctrl+z (SIGTSTP/
suspend), ctrl+d (EOF), ctrl+\ (SIGQUIT). Local non-PTY subprocesses
only react to ctrl+c, ctrl+z, ctrl+\; SSH and PTY channels accept all.
SIDE EFFECTS: The signal may terminate the command (e.g. ctrl+c),
making the command_id invalid on the next read.
TIMEOUT INTERACTION: pause_timeout controls how long to wait for
output after the signal. Raise it for slow TUI repaints over
high-latency SSH; total_timeout only binds during active streaming.
ERRORS: Raises ValueError if command_id is invalid, already completed,
or signal name is unrecognized.
RETURNS: Same format as execute —
{"status": "completed"|"partial", "output": str, ...}
| Name | Required | Description | Default |
|---|---|---|---|
| signal | Yes | Case-insensitive key name. Values: ctrl+a..ctrl+z, ctrl+[/]/^/_/\, esc, tab, enter, return, space, backspace, up/down/left/right, home, end, pageup, pagedown, insert, delete, f1..f12, backtab, alt+<char>. Raises ValueError if unrecognized | |
| command_id | Yes | The command_id from a status='partial' response. Must be an active command. Raises ValueError if invalid or already completed | |
| pause_timeout | No | Seconds of output silence after sending the key before returning. Raise for slow TUI repaints (e.g. over high-latency SSH). Must be > 0 and ≤ total_timeout | |
| total_timeout | No | Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (destructiveHint=true, idempotentHint=false), the description explains side effects (signal may terminate command, making command_id invalid), timeout interaction, and error handling. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (signal handling, side effects, timeout interaction, errors, returns). Every sentence adds value, and the information is front-loaded with key usage guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters (2 required), no output schema, and the open-world/destructive annotations, the description fully covers behavior, return format, errors, and edge cases. It is complete for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage, the description adds value by explaining signal case-insensitivity, common signals, and when to raise pause_timeout or total_timeout. It enriches understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool sends control keys or escape sequences to a running command, listing specific use cases (interrupts, TUI navigation, non-printable input) and explicitly distinguishes it from sibling 'respond' by noting that AI frameworks strip raw control bytes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: 'Prefer this over respond for control keys.' It also details when to use different signals, how to adjust timeout for slow TUI repaints, and error conditions, giving clear context on when and when not to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
1 tool update
v1.0.17- Changed
send_control2 fields changed- changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of silence after sending the key before returning (> 0, ≤ total_timeout)"New value: +"Seconds of output silence after sending the key before returning. Raise for slow TUI repaints (e.g. over high-latency SSH). Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap on call duration in seconds (≥ pause_timeout)"New value: +"Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout"
1 tool update
v1.0.15- Changed
send_control2 fields changed- removed
Input schema / properties / signal / defaultRemoved value: -"ctrl+c" - changed
Input schema / requiredPrevious value: -[ - "command_id" -]New value: +[ + "command_id", + "signal" +]
1 tool update
v1.0.12- Changed
respond4 fields changed- changed
Input schema / properties / command_id / descriptionPrevious value: -"The command_id from a status='partial' response. Must be an active (not yet completed) command. Raises ValueError if invalid or already finished"New value: +"The command_id from a status='partial' response. Raises ValueError if invalid or already completed" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence before returning. Raise this (not total_timeout) when the command is slow to respond after receiving input. Must be > 0 and ≤ total_timeout"New value: +"Seconds of silence before returning (> 0, ≤ total_timeout)" - changed
Input schema / properties / text / descriptionPrevious value: -"Text to write to the command's stdin (e.g. 'y', a password, a shell command). A trailing newline is auto-appended if missing. For control keys (Ctrl+C, arrows, etc.) use send_control instead — AI frameworks strip control bytes from strings"New value: +"Text to write to stdin (e.g. 'y', a password, a shell command)" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout"New value: +"Hard cap on call duration in seconds (≥ pause_timeout)"
5 tool updates
v1.0.11- Changed
connect_ssh6 fields changed- changed
Input schema / properties / banner_timeout / descriptionPrevious value: -"Max seconds to capture the MOTD/welcome banner after login. If exceeded, banner returns '' (not an error). Increase for slow hosts; set to 0 to skip banner capture entirely"New value: +"Max seconds to capture the MOTD/welcome banner after login" - changed
Input schema / properties / host / descriptionPrevious value: -"Hostname or IP of the SSH server (e.g. '192.168.1.10', 'example.com'). DNS resolution happens at connect time; unresolvable hosts raise an error"New value: +"Hostname or IP of the SSH server (e.g. '192.168.1.10', 'example.com')" - changed
Input schema / properties / key_filepath / descriptionPrevious value: -"Absolute path to a private key file (e.g. '/home/user/.ssh/id_rsa'). Must be readable by the server process. Preferred over password for non-interactive use"New value: +"Absolute path to a private key file (e.g. '/home/user/.ssh/id_rsa')" - changed
Input schema / properties / password / descriptionPrevious value: -"Password for password-based auth. If both password and key_filepath are provided, key is tried first, password is the fallback"New value: +"Password for password-based auth; omit for key-based auth" - changed
Input schema / properties / port / descriptionPrevious value: -"SSH port, 1–65535. Most servers listen on 22; non-standard ports are common for hardened hosts"New value: +"SSH port number, 1–65535" - changed
Input schema / properties / username / descriptionPrevious value: -"Login user for authentication. If omitted, falls back to SSH agent or OS default user. Required when the remote user differs from the local one"New value: +"Login user for authentication; omit to use SSH agent or OS default"
- Changed
disconnect1 field changed- changed
Input schema / properties / session_id / descriptionPrevious value: -"The session_id returned by connect_ssh. After this call, the session_id becomes invalid — further execute() calls with it raise ValueError. Safe to call multiple times: disconnecting an already-closed or unknown session_id silently returns true (idempotent)"New value: +"SSH session identifier obtained from connect_ssh"
- Changed
execute5 fields changed- changed
Input schema / properties / command / descriptionPrevious value: -"Shell command to run. Each call is stateless — `cd /foo` does NOT persist. Chain with && for multi-step (e.g. 'cd /foo && ls'), or use a Zellij/tmux session for persistent state"New value: +"Shell command to run (stateless — cd does not persist between calls)" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence before returning. Controls how long to wait for a quiet command — raise this (not total_timeout) for slow-starting jobs. Must be > 0 and ≤ total_timeout"New value: +"Seconds of silence before returning a partial result (> 0, ≤ total_timeout)" - changed
Input schema / properties / session_id / descriptionPrevious value: -"SSH session_id from connect_ssh. Omit (or null) for local execution. Raises ValueError if the session_id is invalid or was already disconnected"New value: +"SSH session_id from connect_ssh; omit for local execution" - changed
Input schema / properties / shell / descriptionPrevious value: -"Shell for local execution (e.g. 'powershell.exe', '/bin/bash'). Only used when session_id is null — ignored for SSH. Defaults to cmd.exe on Windows, /bin/bash on Unix"New value: +"Shell for local execution (e.g. 'powershell.exe', '/bin/bash'); ignored for SSH" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap on total call duration in seconds. Only binds while output is actively streaming — a silent command returns at pause_timeout, not total_timeout. Must be ≥ pause_timeout"New value: +"Hard cap on call duration in seconds (≥ pause_timeout)"
- Changed
read_output3 fields changed- changed
Input schema / properties / command_id / descriptionPrevious value: -"The command_id from a status='partial' response. Must be an active command. Raises ValueError if invalid or already completed"New value: +"The command_id from a status='partial' response. Raises ValueError if invalid or already completed" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence before returning. This is the primary dial for polling quiet jobs — raise it (e.g. 30, 60) instead of total_timeout. Must be > 0 and ≤ total_timeout"New value: +"Seconds of silence before returning. Primary dial for polling — raise it (e.g. 30, 60) for quiet jobs instead of total_timeout. Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap on total call duration in seconds. Only binds while output is actively streaming — a silent poll returns at pause_timeout regardless. Must be ≥ pause_timeout"New value: +"Hard cap on call duration in seconds. Only binds while output is streaming — silent polls return at pause_timeout. Must be ≥ pause_timeout"
- Changed
send_control2 fields changed- changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence after sending the key before returning. Raise for slow TUI repaints (e.g. over high-latency SSH). Must be > 0 and ≤ total_timeout"New value: +"Seconds of silence after sending the key before returning (> 0, ≤ total_timeout)" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout"New value: +"Hard cap on call duration in seconds (≥ pause_timeout)"
1 tool update
v1.0.10- Changed
disconnect1 field changed- changed
Input schema / properties / session_id / descriptionPrevious value: -"The session_id returned by connect_ssh. Becomes invalid after this call — further execute() calls with it raise ValueError. Raises ValueError if already disconnected or unrecognized"New value: +"The session_id returned by connect_ssh. After this call, the session_id becomes invalid — further execute() calls with it raise ValueError. Safe to call multiple times: disconnecting an already-closed or unknown session_id silently returns true (idempotent)"
6 tool updates
v1.0.9- Changed
connect_ssh6 fields changed- changed
Input schema / properties / banner_timeout / descriptionPrevious value: -"The timeout in seconds to wait for the MOTD/welcome banner after the connection opens"New value: +"Max seconds to capture the MOTD/welcome banner after login. If exceeded, banner returns '' (not an error). Increase for slow hosts; set to 0 to skip banner capture entirely" - changed
Input schema / properties / host / descriptionPrevious value: -"The hostname or IP address of the SSH server to connect to (e.g., '192.168.1.10' or 'example.com')"New value: +"Hostname or IP of the SSH server (e.g. '192.168.1.10', 'example.com'). DNS resolution happens at connect time; unresolvable hosts raise an error" - changed
Input schema / properties / key_filepath / descriptionPrevious value: -"Optional absolute path to a private key file for key-based auth; must be readable by the server process. If both this and password are supplied, the key is attempted first"New value: +"Absolute path to a private key file (e.g. '/home/user/.ssh/id_rsa'). Must be readable by the server process. Preferred over password for non-interactive use" - changed
Input schema / properties / password / descriptionPrevious value: -"Optional password for password-based authentication. Omit if using key-based authentication"New value: +"Password for password-based auth. If both password and key_filepath are provided, key is tried first, password is the fallback" - changed
Input schema / properties / port / descriptionPrevious value: -"The port number of the SSH server (default is 22)"New value: +"SSH port, 1–65535. Most servers listen on 22; non-standard ports are common for hardened hosts" - changed
Input schema / properties / username / descriptionPrevious value: -"Optional username for authentication. If omitted, the connection will use SSH agent or system defaults"New value: +"Login user for authentication. If omitted, falls back to SSH agent or OS default user. Required when the remote user differs from the local one"
- Changed
disconnect1 field changed- changed
Input schema / properties / session_id / descriptionPrevious value: -"The SSH session_id returned by connect_ssh that you want to close"New value: +"The session_id returned by connect_ssh. Becomes invalid after this call — further execute() calls with it raise ValueError. Raises ValueError if already disconnected or unrecognized"
- Changed
execute5 fields changed- changed
Input schema / properties / command / descriptionPrevious value: -"The shell command to execute. Each call is stateless; for persistent state (cd, venv, env vars), drive a Zellij session instead of chaining &&"New value: +"Shell command to run. Each call is stateless — `cd /foo` does NOT persist. Chain with && for multi-step (e.g. 'cd /foo && ls'), or use a Zellij/tmux session for persistent state" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence to wait before returning a partial response (default is 9.0)"New value: +"Seconds of output silence before returning. Controls how long to wait for a quiet command — raise this (not total_timeout) for slow-starting jobs. Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / session_id / descriptionPrevious value: -"SSH session_id returned by connect_ssh. Omit for local commands — no session needed"New value: +"SSH session_id from connect_ssh. Omit (or null) for local execution. Raises ValueError if the session_id is invalid or was already disconnected" - changed
Input schema / properties / shell / descriptionPrevious value: -"Shell for local execution (e.g. 'powershell.exe', '/bin/bash'). Ignored when session_id is provided. Defaults to cmd.exe on Windows, /bin/bash on Unix"New value: +"Shell for local execution (e.g. 'powershell.exe', '/bin/bash'). Only used when session_id is null — ignored for SSH. Defaults to cmd.exe on Windows, /bin/bash on Unix" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap in seconds on the maximum duration of this call (default is 20.0)"New value: +"Hard cap on total call duration in seconds. Only binds while output is actively streaming — a silent command returns at pause_timeout, not total_timeout. Must be ≥ pause_timeout"
- Changed
read_output3 fields changed- changed
Input schema / properties / command_id / descriptionPrevious value: -"The active command_id returned in a partial status response"New value: +"The command_id from a status='partial' response. Must be an active command. Raises ValueError if invalid or already completed" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence to wait before returning (default is 9.0)"New value: +"Seconds of output silence before returning. This is the primary dial for polling quiet jobs — raise it (e.g. 30, 60) instead of total_timeout. Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap in seconds on the maximum duration of this call (default is 20.0)"New value: +"Hard cap on total call duration in seconds. Only binds while output is actively streaming — a silent poll returns at pause_timeout regardless. Must be ≥ pause_timeout"
- Changed
respond4 fields changed- changed
Input schema / properties / command_id / descriptionPrevious value: -"The active command_id returned in a partial status response that is waiting for input"New value: +"The command_id from a status='partial' response. Must be an active (not yet completed) command. Raises ValueError if invalid or already finished" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence to wait before returning (default is 9.0)"New value: +"Seconds of output silence before returning. Raise this (not total_timeout) when the command is slow to respond after receiving input. Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / text / descriptionPrevious value: -"The text input to send to the command (e.g. 'y' for prompts, passwords, etc.). Newline is auto-appended"New value: +"Text to write to the command's stdin (e.g. 'y', a password, a shell command). A trailing newline is auto-appended if missing. For control keys (Ctrl+C, arrows, etc.) use send_control instead — AI frameworks strip control bytes from strings" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap in seconds on the maximum duration of this call (default is 20.0)"New value: +"Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout"
- Changed
send_control4 fields changed- changed
Input schema / properties / command_id / descriptionPrevious value: -"The active command_id returned in a partial status response"New value: +"The command_id from a status='partial' response. Must be an active command. Raises ValueError if invalid or already completed" - changed
Input schema / properties / pause_timeout / descriptionPrevious value: -"Seconds of output silence to wait before returning (default is 9.0)"New value: +"Seconds of output silence after sending the key before returning. Raise for slow TUI repaints (e.g. over high-latency SSH). Must be > 0 and ≤ total_timeout" - changed
Input schema / properties / signal / descriptionPrevious value: -"The control signal or key to send. Supported values: 'ctrl+c', 'ctrl+z', 'ctrl+d', arrow keys, enter, f1-f12, etc."New value: +"Case-insensitive key name. Values: ctrl+a..ctrl+z, ctrl+[/]/^/_/\\, esc, tab, enter, return, space, backspace, up/down/left/right, home, end, pageup, pagedown, insert, delete, f1..f12, backtab, alt+<char>. Raises ValueError if unrecognized" - changed
Input schema / properties / total_timeout / descriptionPrevious value: -"Hard cap in seconds on the maximum duration of this call (default is 20.0)"New value: +"Hard cap on total call duration in seconds. Only binds while output is actively streaming. Must be ≥ pause_timeout"
4 tool updates
v1.0.8- Removed
create_local - Changed
disconnect1 field changed- changed
Input schema / properties / session_id / descriptionPrevious value: -"The unique session identifier returned by connect_ssh or create_local that you want to close"New value: +"The SSH session_id returned by connect_ssh that you want to close"
- Changed
execute6 fields changed- added
Input schema / properties / session_id / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / session_id / defaultAdded value: +null - changed
Input schema / properties / session_id / descriptionPrevious value: -"The unique session identifier returned by connect_ssh or create_local"New value: +"SSH session_id returned by connect_ssh. Omit for local commands — no session needed" - removed
Input schema / properties / session_id / typeRemoved value: -"string" - added
Input schema / properties / shellAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Shell for local execution (e.g. 'powershell.exe', '/bin/bash'). Ignored when session_id is provided. Defaults to cmd.exe on Windows, /bin/bash on Unix", + "title": "Shell" +} - changed
Input schema / requiredPrevious value: -[ - "session_id", - "command" -]New value: +[ + "command" +]
- Removed
list_sessions
1 tool update
v1.0.7- Changed
connect_ssh2 fields changed- changed
Input schema / properties / key_filepath / descriptionPrevious value: -"Optional absolute path to a private key file (SSH key) for key-based authentication"New value: +"Optional absolute path to a private key file for key-based auth; must be readable by the server process. If both this and password are supplied, the key is attempted first" - changed
Input schema / properties / password / descriptionPrevious value: -"Optional password for password-based authentication. If using key-based authentication, this can be omitted"New value: +"Optional password for password-based authentication. Omit if using key-based authentication"
1 tool update
v1.0.5- Changed
execute1 field changed- changed
Input schema / properties / command / descriptionPrevious value: -"The shell command to execute (e.g., 'ls -la' or 'npm run build'). Can chain multiple commands with && or ;"New value: +"The shell command to execute. Each call is stateless; for persistent state (cd, venv, env vars), drive a Zellij session instead of chaining &&"
7 tool updates
v1.0.3- Changed
connect_ssh6 fields changed- added
Input schema / properties / banner_timeout / descriptionAdded value: +"The timeout in seconds to wait for the MOTD/welcome banner after the connection opens" - added
Input schema / properties / host / descriptionAdded value: +"The hostname or IP address of the SSH server to connect to (e.g., '192.168.1.10' or 'example.com')" - added
Input schema / properties / key_filepath / descriptionAdded value: +"Optional absolute path to a private key file (SSH key) for key-based authentication" - added
Input schema / properties / password / descriptionAdded value: +"Optional password for password-based authentication. If using key-based authentication, this can be omitted" - added
Input schema / properties / port / descriptionAdded value: +"The port number of the SSH server (default is 22)" - added
Input schema / properties / username / descriptionAdded value: +"Optional username for authentication. If omitted, the connection will use SSH agent or system defaults"
- Changed
create_local1 field changed- added
Input schema / properties / shell / descriptionAdded value: +"Optional absolute path or executable name of the shell to use (e.g., 'powershell.exe', '/bin/bash', '/bin/zsh'). If omitted, defaults to cmd.exe on Windows or /bin/bash on Unix/macOS."
- Changed
disconnect1 field changed- added
Input schema / properties / session_id / descriptionAdded value: +"The unique session identifier returned by connect_ssh or create_local that you want to close"
- Changed
execute4 fields changed- added
Input schema / properties / command / descriptionAdded value: +"The shell command to execute (e.g., 'ls -la' or 'npm run build'). Can chain multiple commands with && or ;" - added
Input schema / properties / pause_timeout / descriptionAdded value: +"Seconds of output silence to wait before returning a partial response (default is 9.0)" - added
Input schema / properties / session_id / descriptionAdded value: +"The unique session identifier returned by connect_ssh or create_local" - added
Input schema / properties / total_timeout / descriptionAdded value: +"Hard cap in seconds on the maximum duration of this call (default is 20.0)"
- Changed
read_output3 fields changed- added
Input schema / properties / command_id / descriptionAdded value: +"The active command_id returned in a partial status response" - added
Input schema / properties / pause_timeout / descriptionAdded value: +"Seconds of output silence to wait before returning (default is 9.0)" - added
Input schema / properties / total_timeout / descriptionAdded value: +"Hard cap in seconds on the maximum duration of this call (default is 20.0)"
- Changed
respond4 fields changed- added
Input schema / properties / command_id / descriptionAdded value: +"The active command_id returned in a partial status response that is waiting for input" - added
Input schema / properties / pause_timeout / descriptionAdded value: +"Seconds of output silence to wait before returning (default is 9.0)" - added
Input schema / properties / text / descriptionAdded value: +"The text input to send to the command (e.g. 'y' for prompts, passwords, etc.). Newline is auto-appended" - added
Input schema / properties / total_timeout / descriptionAdded value: +"Hard cap in seconds on the maximum duration of this call (default is 20.0)"
- Changed
send_control4 fields changed- added
Input schema / properties / command_id / descriptionAdded value: +"The active command_id returned in a partial status response" - added
Input schema / properties / pause_timeout / descriptionAdded value: +"Seconds of output silence to wait before returning (default is 9.0)" - added
Input schema / properties / signal / descriptionAdded value: +"The control signal or key to send. Supported values: 'ctrl+c', 'ctrl+z', 'ctrl+d', arrow keys, enter, f1-f12, etc." - added
Input schema / properties / total_timeout / descriptionAdded value: +"Hard cap in seconds on the maximum duration of this call (default is 20.0)"
TDQS
Each tool has a clearly distinct purpose: connect_ssh opens sessions, disconnect closes them, execute runs commands, read_output polls output, respond sends text, send_control sends control keys. There is no overlap or ambiguity.
All tool names follow a consistent verb or verb_noun pattern (connect_ssh, disconnect, execute, read_output, respond, send_control). No mixed conventions or irregular naming.
Six tools perfectly cover the core operations of a terminal server (session management, command execution, I/O, and control) without extraneous or missing tools.
The tool surface covers the full lifecycle of SSH sessions and local command execution: connect, execute, interact (input, control, output), and disconnect. There are no obvious gaps for the stated purpose.
Maintenance
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
Run commands and read/write files on your servers over Termalin's keyless tunnels (hosted MCP).
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
MCP server for Superserve sandboxes: create, exec, and manage Firecracker microVMs
The official MCP Server for the Mux API
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceA secure and pluggable MCP server to run terminal commands on your local machine or cloud server — remotely, safely, and with LLMs or agentic clients.-
- AlicenseAqualityDmaintenanceEnables management of visible, interactive terminal sessions across platforms (macOS, Windows, Linux, WSL). Supports creating, executing commands, capturing output, and managing multiple terminal windows simultaneously.51MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables AI agents to run fully interactive SSH sessions (via tmux) and execute commands like a human operator, with persistent sessions and multiple concurrent connections.6MIT
- AlicenseBqualityBmaintenanceLocal + remote terminal interaction control MCP Server. Lets AI agents control interactive TUI programs the way a human would.2913MIT
Appeared in Searches
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/QiuwenZheng/interminal'
If you have feedback or need assistance with the MCP directory API, please join our Discord server