termal.in

Reference · MCP tools

MCP tools reference.

Termalin exposes its SSH client as MCP tools an agent can call. There are two surfaces: the local server bundled with the desktop app (termalin-mcp, over stdio) with 22 tools, and the hosted endpoint with 24 — reached at https://termal.in/mcp (OAuth, behind the claude.ai and ChatGPT connectors) or https://termal.in/api/v1/mcp (API key) — the shared core plus multi-host commands, background jobs, monitoring, backups and internal sites. The local server is free on every plan; the hosted endpoint is Pro (or the trial). This page lists every one — its parameters, its limits, and whether it reads or changes state. For the overview and setup, start at the MCP server page.

Which tool on which surface

Seven tools share a name across both surfaces (hosts_list, generate_password, ssh_exec, sftp_list, data_query, data_tables, data_schema); file reads and writes are named differently, the session, tunnel, live-terminal tools and data_list are local only, and multi-host commands, background jobs, monitoring, backups and internal sites are hosted only.

ToolLocalHostedEffectWhat it does
hosts_list ✓ ✓ Reads List the servers the agent may reach
generate_password ✓ ✓ Reads Return a strong random password
ssh_exec ✓ ✓ Changes Run one command and return its output
ssh_exec_many — ✓ Changes Run one command on several servers at once
job_start — ✓ Changes Start a command in the background
job_status — ✓ Reads State, exit code and log tail of a job
job_stop — ✓ Changes Stop a background job
job_list — ✓ Reads List recent jobs on a server
server_metrics — ✓ Reads Latest health numbers, averages and peaks from monitoring
alerts_list — ✓ Reads Open monitoring alerts and what cleared recently
updates_list — ✓ Reads Pending security updates and the known vulnerabilities (CVEs) in what is installed, with how to fix each
backup_create — ✓ Changes Take an encrypted backup of a server now
backup_list — ✓ Reads Backup jobs and recent archives of a server
backup_job_create — ✓ Changes Draft a backup job for the owner to confirm
web_link_create — ✓ Changes Add an internal site to the owner’s cabinet
web_link_list — ✓ Reads List the internal sites in the owner’s cabinet
web_link_update — ✓ Changes Rename an internal site or point it elsewhere
web_link_delete — ✓ Changes Remove an internal site
session_open ✓ — Changes Open a persistent SSH session
session_exec ✓ — Changes Run a command in an open session
session_close ✓ — Changes Close a session
session_list ✓ — Reads List the agent’s open sessions
tunnel_open ✓ — Changes Open a local or SOCKS port forward
tunnel_close ✓ — Changes Close a port forward
tunnel_list ✓ — Reads List open port forwards
sftp_list ✓ ✓ Reads List a directory over SFTP
sftp_get ✓ — Reads Read a file over SFTP (local)
sftp_put ✓ — Changes Write a file over SFTP (local)
sftp_read — ✓ Reads Read a text file over SFTP (hosted)
sftp_write — ✓ Changes Write a text file over SFTP (hosted)
terminal_hosts ✓ — Reads List saved hosts the agent could open
terminal_sessions ✓ — Reads List the user’s open terminal tabs
terminal_open ✓ — Changes Open a live terminal tab in the app
terminal_run ✓ — Changes Run a command in an open tab
terminal_run_many ✓ — Changes Run one command across several tabs
data_list ✓ — Reads List the app’s saved database connections
data_tables ✓ ✓ Reads List tables / collections / keys
data_schema ✓ ✓ Reads Describe one table’s columns
data_query ✓ ✓ Reads * Run a query and return rows

* data_query is read-only by default; a write runs only with a full-access key (hosted) or a connection that grants the agent full access (local).

Servers & passwords

hosts_list local · hosted

List the servers the agent may reach. Local: no parameters; returns id, name, hostname, port, username and auth type — no secrets. Hosted: returns id, name, whether the server is online, runsAs (the login user, root when unset), lastSeen, country, ip (the public address the Connector connects from, null until it has connected), ownerNote (the Connector's "Note for AI") and policy — what the caller may do there: full, allowlist (only listed commands, no file writes; allowedCommands holds the server's own list when it has one) or readonly (no commands, no file writes). policy is the stricter of the key's or app's own setting and the Connector's "What AI may run here". A server whose Connector has AI access switched off is not listed to AI apps or keys. Reads. Hosted also returns tags (the owner’s labels for the server, set in the Connector’s settings: prod, neuroshop…) and groups (the ones Termalin knows by itself: os:linux, distro:ubuntu, release:ubuntu-24.04, country:fr). Optional tag (a string or a list) lists only the servers that have every one of them.

generate_password local · hosted

Return one strong random password — handy when creating a user or setting a password. Parameter: length (optional, default 20, clamped 8–128). Nothing is stored. Reads.

Running commands

ssh_exec local · hosted

Run a single shell command on a server and return its combined output. Each call is a fresh connection, so cd and shell variables don’t carry between calls — chain with cd /path && cmd. Required: host, command. Hosted adds optional username (defaults to the Connector’s login user, else root) and timeout in seconds (default 60, up to 300; timeoutSeconds is the older name for it). A call that runs out says so in its answer; some chat apps stop waiting sooner than 300 s, so for long work reach for job_start instead. Local honours the host’s agent policy; hosted honours the API key’s or AI-app connection’s command rule (Full / Only listed / Read-only) and the Connector’s AI access switch. On a Windows server reached through a Connector the command runs in PowerShell (PowerShell 7 when the server has it, else Windows PowerShell 5.1), as do the job tools; a program’s stderr comes back as plain text and the exit code is the program’s own. Changes state.

ssh_exec_many hosted

Run one command on several servers at once and return each server’s output under its own heading. Required: command, and either hosts (up to 10 ids or names from hosts_list) or tag — every server with all of the given tags or groups, e.g. ["distro:ubuntu", "prod"] (at most 10). Optional timeout per server in seconds (default 60, up to 300; also accepted as timeoutSeconds). Every name is resolved before anything runs, so a typo stops the whole call. Changes state.

Background jobs hosted only

A command that takes longer than one tool call — a build, a migration, a backup. The job runs on the server itself under ~/.termalin/jobs/<id>/ with its log and exit code, so it survives the agent’s turn, the connection, and a Termalin update; only a reboot of that server ends it. The job tools run on Linux, macOS and Windows Connectors (on Windows the command runs in PowerShell). Each job tool takes host and optional username.

job_start hosted

Start command in the background and return a job id. The command runs from the login user’s home directory. Changes state.

job_status hosted

State (running, finished with an exit code, or stopped), start time, the command, and the last lines lines of its log (default 40, up to 500). Required: job. Reads.

job_stop hosted

Stop a running job (TERM, then KILL after two seconds). Required: job. Changes state.

job_list hosted

The twenty most recent jobs of the login user on that server, with their state. Reads.

Monitoring hosted only

Read what Termalin’s monitoring already collected from the user’s servers, about once a minute. Nothing is run on the server when these are called. Both cover servers with metrics switched on, and a key limited to some servers sees only those.

server_metrics hosted

Latest CPU, memory, disk, load and network numbers. Without host: one line per server. With host: that server’s latest sample in full — including the busiest processes, failed services, containers and certificates — and the average and peak over the last hours (default 6). Both parameters are optional. Reads.

alerts_list hosted

What monitoring says is wrong right now — disk filling, memory or load pinned, a failed service, a restarting container, an expiring certificate, a server offline — and what cleared in the last seven days. No parameters. Reads.

updates_list hosted

What is waiting to be installed, from Termalin’s hourly check — nothing is run or installed: how many updates and security updates, the security packages by name and target version, whether the server asks for a reboot, a newer kernel installed but not yet running, and how old the package lists are. Also the known vulnerabilities (CVEs) in what is installed, from a daily match against OSV.dev, Node.js’s advisories and endoflife.date: severity, the version that fixes each, and whether CISA lists it as used in attacks (those come first). Optional host for one server, or tag for a group (e.g. "distro:ubuntu", "prod"); without either, every server. cve (e.g. "CVE-2024-6387") lists only the servers that have it. Each finding carries fix: the update command (and whether to reboot or restart), a fixed build still in testing, the update to run in a lock file’s folder, or the vendor’s workaround (Ubuntu, Red Hat) when there is no fix yet; and epss, the chance of exploitation within 30 days. Covers Linux (apt, dnf, zypper, apk; Amazon Linux from its own notices), Windows (checked against Microsoft’s security updates, with the KB that fixes each CVE), macOS, running containers, applications’ lock files (npm, Composer, Cargo, Python, Go, Ruby, Gradle, Java archives), and about eighty programs and web apps no distribution ships (WinRAR, 7-Zip, WordPress, GitLab, Jenkins, Grafana…). Sources: OSV.dev, CISA KEV, FIRST EPSS, Node.js advisories, endoflife.date, Microsoft (MSRC) and the CVE List for a high or critical CVE in its first hour. Reads.

Backups hosted only

Encrypted server backups through the Connector — files, and on Linux and macOS a PostgreSQL or MySQL/MariaDB dump in the same archive (set up in the cabinet under Account → Backups: paths, databases, schedule, how many to keep, where to store). Archives are encrypted in the owner's account; the agent can start a backup, draft a new job for the owner to confirm, and see the list — it never reads an archive. For connections and keys with full access.

backup_create hosted

Take a backup of one server now and wait for it (up to about a minute; a longer one keeps running and shows up in backup_list). Call it before a risky change — a migration, a config rewrite, a bulk delete — and say so in label. Required: host. Optional: job (when the server has several backup jobs), label. Uses the owner's storage allowance. Changes state.

backup_list hosted

The backup jobs of a server and its recent archives: when each ran, whether it succeeded, how big it is and where it is stored. Required: host. Reads.

backup_job_create hosted

Draft a backup job for the owner to confirm — files and/or databases, a schedule, how many copies to keep and where to store them. It doesn't run on its own: the owner confirms the draft in the cabinet with one click, where the encryption key is made in their browser as for any job, and only then does it run. A draft expires after 7 days and counts toward the plan's job limit. Required: server. Optional: the paths, databases, schedule, keep count and destination. Needs a connection or key with full access, on a Connector open to AI with full access. Changes state.

Internal sites hosted only

An internal site is a web service only a server's own network can reach — a dashboard on localhost:3000, an admin panel on 10.0.0.5:8080. Termalin gives it its own address that only the owner opens, signed in, through the server's Connector. With these tools an agent puts such a site into the owner's cabinet; it never opens or reads the site, and it can't give anyone else access — sharing by email stays with the owner in the cabinet. Adding, changing and removing need a connection or key with full access, on a Connector open to AI with full access; a Connector that is read-only or limited to an allow list for AI refuses. Sites an agent added show Added by and the app's or key's name in the cabinet and the app, and count toward the same account total as the owner's own.

Add an internal site. Required: server (id or exact name from hosts_list), target (host:port as the server sees it, e.g. localhost:3000 or 10.0.0.5:8080; a path may follow). Optional: https_inside (the site itself speaks https, default false), name. Only private addresses are accepted, the same check as the cabinet. One site opens every page of an app: if the server already has an internal site on the same host:port, that site is returned with reused: true instead of a copy, and its open_url lands on the path you gave (e.g. localhost:3000/reports/q3.pdf) — to send the user to another page or file of the same app, call it again with that path. Returns the site's id, its open_url (https://termal.in/account#open-site=<id>, with &page=/path when a path was given) and its address (url). Give the user open_url: it signs them in to Termalin, then opens the site. The site's own address shows “This link doesn't work” to anyone without a session, the owner included, until it is opened from the account. Changes state.

The internal sites on the servers the caller may reach: id, name, server, target, open_url, address, who added it (the owner or an app's name), when, and how many people the owner shared it with — a number, never their addresses. Sites on a Connector closed to AI are left out. No parameters. Reads.

Change an internal site by id (from web_link_list or web_link_create): rename it, or point it at another host:port or start page when the app moved — instead of removing it and adding a new one. It keeps its address and the people the owner shared it with. When it now leads somewhere else, everyone signed in to it is signed out and opens it again. Required: id. Optional: name (empty clears it), target, https_inside; give at least one. To send the user to another page of the same app, don't change the site — call web_link_create with that path. Changes state.

Remove an internal site by id. Its address stops working at once, for the owner and anyone it was shared with; the service on the server is not touched. Required: id. Changes state.

Persistent sessions local only

session_open local

Open a persistent SSH session and keep it connected, so follow-up commands skip the auth handshake. It is the agent’s own headless connection — no app needed. Required: host. Returns a sessionId. A blocked host refuses. Changes state.

session_exec local

Run a command on an open session and return its output. Each command still runs on a fresh channel, so cwd/env don’t persist. Required: session, command. An allowlist host is re-checked per command. Changes state.

session_close local

Close a persistent session and disconnect it. Required: session. Changes state.

session_list local

List the persistent sessions the agent currently has open. No parameters. Returns sessionId, hostId and host. Reads.

Port forwards local only

tunnel_open local

Open a port forward on an open session. Required: session. type is local (default — a local port that reaches remoteHost:remotePort as the server sees it; needs remoteHost and remotePort) or dynamic (a local SOCKS5 proxy that egresses from the server). localPort optional (0 picks a free one). Returns a tunnelId and the local listenAddr. Allowed on full-access hosts only, so an allowlist host can’t be turned into a pivot. Changes state.

tunnel_close local

Close a port forward. Required: tunnel. Changes state.

tunnel_list local

List the port forwards currently open. No parameters. Returns tunnelId, sessionId, kind, listenAddr and target. Reads.

Files over SFTP

sftp_list local · hosted

List a directory over SFTP. Required: host. Local also requires path and returns name, path, isDir, size, permissions and modified time. Hosted makes path optional (defaults to the login home, .) and adds optional username. Reads.

sftp_get local

Read a file over SFTP. Required: host, path. UTF-8 text comes back as text; binary comes back base64. Capped at 4 MB — MCP results travel into a model’s context, so reads stay modest. The hosted equivalent is sftp_read. Reads.

sftp_put local

Write a file over SFTP, creating or overwriting it. Required: host, path, content. Optional base64 writes decoded binary. Allowed on full-access hosts only. The hosted equivalent is sftp_write. Changes state.

sftp_read hosted

Read a text file over SFTP and return its contents. Required: host, path. Optional username. Files over 512 KB or non-text (binary) files are refused — use ssh_exec (tail, sed) for those. Reads.

sftp_write hosted

Create or overwrite a text file over SFTP. Required: host, path, content (written as UTF-8). Missing folders on the way are created, on Linux, macOS and Windows servers; optional create_dirs: false refuses instead and names the missing folder. Optional username. Capped at 512 KB; for binary uploads use a terminal or scp. Changes state.

The live desktop app local only

These drive the running desktop app through its consent-gated control server. terminal_hosts and terminal_sessions need “Agent in Terminal” enabled; terminal_open, terminal_run and terminal_run_many need the “Let agents run commands” consent.

terminal_hosts local

List the saved hosts the agent could open a session for. No parameters. Returns hostId, name, connectionType, authMethod and canOpenHeadless (false means opening it needs you — a password or a locked key). Reads.

terminal_sessions local

List the terminal tabs you currently have open that the agent can act in. No parameters. Returns tabId, hostId, title, connected and attached. Reads.

terminal_open local

Open a new terminal session for a host on the agent’s own initiative — a background tab in your app that glows so you can see it’s the agent’s. Required: hostId. Hosts needing a password or a locked key open but stay unconnected until you finish. Changes state.

terminal_run local

Run a command in one of your open terminal tabs, as if you typed it; the tab glows while the agent acts. Required: tabId, command. Optional timeoutSeconds (default 120, up to 3600 — set it generously for builds). Returns the captured output. Changes state.

terminal_run_many local

Run the same command across several open tabs at once (mass operations, Ansible-style). Required: tabIds (array), command. Optional timeoutSeconds (default 120, up to 3600). Returns per-session output or error. Changes state.

Databases

The local data tools work the saved “Data” connections in the app (id from data_list) and need the app running and unlocked; they’re off by default and read-only unless a connection grants full access. The hosted data tools work a server’s own database client over the keyless tunnel (host id from hosts_list), using the database’s local trust — no database password is sent or stored.

data_list local

List the saved database connections (PostgreSQL, MySQL/MariaDB, SQLite, SQL Server, ClickHouse, MongoDB, Redis, Elasticsearch, RabbitMQ, Cassandra, Neo4j, InfluxDB). No parameters. Returns each connection’s id, name, engine and whether the agent may write. Reads.

data_tables local · hosted

List the tables / collections / keys of a database. Local: required hostId (from data_list), optional database. Hosted: required host (from hosts_list), optional engine (postgres default, or mysql/mariadb/redis/mongodb/sqlite), database, username. Reads.

data_schema local · hosted

Describe one table’s columns (name, type, nullable, primary key). Local: required hostId, table; optional schema, database. Hosted: required host, table; optional engine, database, username. Reads.

data_query local · hosted

Run a query and return the rows, in the connection’s own language (SQL, a Redis command, a MongoDB shell expression, Cypher, InfluxQL, and so on). Local: required hostId, query; optional database, maxRows (default 200). Hosted: required host, query; optional engine (postgres default), database, username, allowWrites (full-access keys only), timeoutSeconds (default 60, up to 300). Read-only by default — only SELECT/SHOW-style statements run unless writes are granted.

Connect an agent

Point your client at whichever surface matches where the agent runs — the local server for hosts you export from the app (free, app running), the hosted endpoint for servers running a Connector (Pro or trial).

  • Claude Code — claude mcp add --transport http termalin https://termal.in/mcp for the hosted endpoint, or claude mcp add termalin -- <path>/termalin-mcp for the local server
  • Codex — codex mcp add termalin --url https://termal.in/mcp
  • Cursor — add "url": "https://termal.in/mcp" under mcpServers in mcp.json, or point it at the local binary
  • claude.ai and ChatGPT — the Termalin listing in their connector / apps directory (OAuth at termal.in/mcp); enable it in the conversation’s tools (+) menu
  • Any HTTP client without OAuth — an API key against https://termal.in/mcp with Authorization: Bearer tk_live_…. The cabinet shows ready snippets for Claude Code, Cursor, VS Code, Claude Desktop (via npx mcp-remote), Manus / n8n / LangChain and curl, plus a Test key button

Hosted runs are limited to about 60 command runs a minute per account; use job_start for anything long rather than looping.

FAQ

How many MCP tools does Termalin have?

The local server bundled with the desktop app (termalin-mcp, stdio) exposes 22 tools. The hosted endpoint exposes 24, over two URLs onto the same handler: https://termal.in/mcp (OAuth — the one behind the claude.ai and ChatGPT connectors) and https://termal.in/api/v1/mcp (API key). The hosted 24: hosts_list, ssh_exec, ssh_exec_many, job_start, job_status, job_stop, job_list, server_metrics, alerts_list, updates_list, backup_create, backup_list, backup_job_create, web_link_create, web_link_list, web_link_update, web_link_delete, sftp_list, sftp_read, sftp_write, data_query, data_tables, data_schema and generate_password.

Why does file reading use a different name on each surface?

The local server reads and writes files with sftp_get and sftp_put (a local read is capped at 4 MB and may return base64 for binary). The hosted endpoint uses sftp_read and sftp_write, which are text-only and capped at 512 KB — a small pipe into an agent’s context, not a file-transfer channel. Everything else that shares a name behaves the same on both.

Which tools change state and which only read?

Reads: hosts_list, session_list, tunnel_list, sftp_list, sftp_get, sftp_read, terminal_hosts, terminal_sessions, data_list, data_tables, data_schema, job_status, job_list, server_metrics, alerts_list, updates_list, backup_list, web_link_list, generate_password. Changes: ssh_exec, ssh_exec_many, job_start, job_stop, backup_create, backup_job_create, web_link_create, web_link_update, web_link_delete, session_open/exec/close, tunnel_open/close, sftp_put, sftp_write, terminal_open/run/run_many. data_query is read-only by default and only runs a write with full access.

Can the agent run these without my keys or my desktop?

The local tools authenticate through Termalin’s key custodian — no private key is handed to the agent. The hosted tools reach servers enrolled with a keyless Connector using a short-lived certificate, with no desktop app running. See SSH for AI agents for the custody model.