termalin-web
Run commands and read/write files on your servers over Termalin's keyless tunnels (hosted MCP).
Should I use this
Quality & Safety
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"termalin-web": {
"url": "https://termal.in/api/v1/mcp"
}
}
}Remote endpoints
https://termal.in/api/v1/mcpstreamable-httpWhat it can do
Tool inventory
Tools (8)
🟢hosts_list
List the servers reachable through Termalin (your tunnel agents). Returns id, name, whether the server is online, and the default login user. Use the id with ssh_exec.
Input Schema
{
"type": "object",
"properties": {},
"additionalProperties": false
}🟢generate_password(length)
Generate a strong random password — handy when creating a user or setting a password on a server. Returns the password only; nothing is stored.
Input Schema
{
"type": "object",
"properties": {
"length": {
"type": "integer",
"description": "length (default 20, 8-128)"
}
},
"additionalProperties": false
}🔴ssh_exec(host, command, username, timeoutSeconds)
Run a single shell command on one of your servers and return its combined output and exit code. Runs keyless over Termalin's tunnel — no SSH key, and the server needs no open inbound port. Each call is a fresh shell (cd does not persist — chain with &&). Keep a call under about 90 seconds: for anything longer, start it in the background (nohup … > log 2>&1 &) and check on it with later calls.
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"command": {
"type": "string",
"description": "Shell command to execute"
},
"username": {
"type": "string",
"description": "Login user (defaults to the tunnel's user, else root)"
},
"timeoutSeconds": {
"type": "number",
"description": "Max seconds to wait (default 60). Calls longer than about 90 seconds are usually cut off by the network before they answer — run long jobs in the background instead."
}
},
"required": [
"host",
"command"
],
"additionalProperties": false
}🟢sftp_list(host, path, username)
List a directory on one of your servers over SFTP. Returns each entry's name, whether it's a directory, size and modified time. Runs keyless over Termalin's tunnel, like ssh_exec.
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"path": {
"type": "string",
"description": "Directory to list (default the login home, \".\")"
},
"username": {
"type": "string",
"description": "Login user (defaults to the tunnel's user, else root)"
}
},
"required": [
"host"
],
"additionalProperties": false
}🟢sftp_read(host, path, username)
Read a text file from one of your servers over SFTP and return its contents. Files over 512 KB or non-text (binary) files are refused — use ssh_exec (e.g. sed/tail) for those.
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"path": {
"type": "string",
"description": "Absolute or home-relative file path"
},
"username": {
"type": "string",
"description": "Login user (defaults to the tunnel's user, else root)"
}
},
"required": [
"host",
"path"
],
"additionalProperties": false
}🔴sftp_write(host, path, content, username)
Create or overwrite a text file on one of your servers over SFTP. 'content' is written as UTF-8. Capped at 512 KB; for binary uploads use a terminal/scp instead.
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"path": {
"type": "string",
"description": "Destination file path (created or overwritten)"
},
"content": {
"type": "string",
"description": "UTF-8 text to write"
},
"username": {
"type": "string",
"description": "Login user (defaults to the tunnel's user, else root)"
}
},
"required": [
"host",
"path",
"content"
],
"additionalProperties": false
}🔴data_query(host, engine, query, database, username, ...)
Run a database query on one of your servers — passwordless. It executes the engine's own client on the host over Termalin's keyless tunnel, using the database's local trust (Postgres peer auth via `sudo -u postgres`, MySQL/MariaDB unix-socket via `sudo mysql`, redis-cli, mongosh, sqlite3) — so no database password is needed or stored anywhere. Read-only by default: only SELECT/SHOW-style statements run unless allowWrites is set (full-access keys only). SQL engines return CSV/TSV with a header. For MongoDB pass a shell expression, e.g. db.products.find({}).limit(20).toArray().
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"engine": {
"type": "string",
"enum": [
"postgres",
"mysql",
"mariadb",
"redis",
"mongodb",
"sqlite"
],
"description": "Database engine on that server (default postgres)"
},
"query": {
"type": "string",
"description": "The statement / command / expression to run"
},
"database": {
"type": "string",
"description": "Database name (for sqlite: the .db file path)"
},
"username": {
"type": "string",
"description": "SSH login user (defaults to the tunnel's user, else root)"
},
"allowWrites": {
"type": "boolean",
"description": "Allow a non-read statement (full-access keys only; default false)"
},
"timeoutSeconds": {
"type": "number",
"description": "Max seconds to wait (default 60). Calls longer than about 90 seconds are usually cut off by the network before they answer — run long jobs in the background instead."
}
},
"required": [
"host",
"query"
],
"additionalProperties": false
}🟢data_tables(host, engine, database, username)
List the tables / collections / keys of a database on one of your servers — passwordless, over the same local-client path as data_query.
Input Schema
{
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Server id from hosts_list"
},
"engine": {
"type": "string",
"enum": [
"postgres",
"mysql",
"mariadb",
"redis",
"mongodb",
"sqlite"
],
"description": "Database engine on that server (default postgres)"
},
"database": {
"type": "string",
"description": "Database name (for sqlite: the .db file path)"
},
"username": {
"type": "string",
"description": "SSH login user (defaults to the tunnel's user, else root)"
}
},
"required": [
"host"
],
"additionalProperties": false
}Community
Evidence