io.github.open-mcp-ai/termcp MCP Server
io.github.open-mcp-ai/termcp
AI-native terminal platform: drive real terminals locally or over SSH through MCP, SKILLS, or REST API.
What is the io.github.open-mcp-ai/termcp MCP server?
Termcp is an MCP server that lets AI agents control real terminal sessions on local or remote machines over SSH. It provides a browser-based Web UI for human observation and takeover, while agents interact through MCP tools or a REST API, enabling multi-turn interaction with TUIs, REPLs, and interactive tools.
Termcp is a platform for collaborative human-AI terminal management. It maintains long-lived sessions that both humans and AI agents can control, with a shared Web UI dashboard, MCP integration for agents, and REST/WebSocket APIs for scripts. Sessions support SSH connections, port forwarding, file transfer, and real-time visual monitoring, making it ideal for orchestrating complex multi-host workflows where humans and AI work together.
How to install io.github.open-mcp-ai/termcp
Copy-paste configuration for popular MCP clients.
Tools & capabilities
Tools this server exposes to the agent.
shell_exec— Execute a command in a session and retrieve output by tail or offset cursorshell_input— Send input (keystrokes, text) to a running sessionshell_notify— Receive a wake-up signal when a process exits, output arrives, or silence occurssession_create— Create a new terminal session on a local or remote host via SSH profilesession_list— List all active and dead sessions with their metadatasession_close— Close an active sessionsession_read— Read output from a closed (dead) sessionssh_config_list— List available SSH connection profilesssh_config_create— Create a new SSH profile (if --mcp-manage-ssh-configs is enabled)ssh_config_edit— Edit an existing SSH profile (if --mcp-manage-ssh-configs is enabled)ssh_config_delete— Delete an SSH profile (if --mcp-manage-ssh-configs is enabled)file_list— Browse files and directories on a remote or local hostfile_upload— Upload files to a session's hostfile_download— Download files from a session's hostforward_create— Set up port forwarding (-L, -R, -D) for a sessionforward_list— List active port forwards for a session
Use cases
- Drive interactive tools like vim, GDB, msfconsole, or Python REPLs across multiple conversation turns without losing session state
- Orchestrate multi-host deployments and system administration tasks with parallel SSH sessions, all visible in one dashboard
- Collaborate with AI agents on production systems by observing every command in the browser and taking over instantly when needed
- Automate complex workflows that require real terminal interaction, password prompts, or MFA challenges with human-in-the-loop approval
- Manage SSH connections and port forwarding centrally without exposing credentials to agents
io.github.open-mcp-ai/termcp MCP server FAQ
Termcp is an AI-native terminal platform that lets AI agents (via MCP) and humans (via Web UI) control real terminal sessions on local or remote machines. It maintains persistent sessions that support interactive tools, SSH connections, file transfer, and port forwarding.
Yes, Termcp is open-source under the MIT license and free to use. It runs as a single lightweight Go binary with no external dependencies.
Install Termcp locally or on a server, then configure your AI client to connect via MCP using the OCI image `ghcr.io/open-mcp-ai/termcp:0.2.4` or by running the binary directly. The server exposes MCP tools over HTTP SSE on the configured port (default 18765).
By default, Termcp binds to loopback (127.0.0.1) with no auth. If you bind to a non-loopback address, you must set an auth token or hash via `--auth-token`, `--auth-hash`, or environment variables.
No. Passwords and private keys are stored server-side only and never exposed to agents. Agents open sessions by profile name; the MCP read interface returns profile names only. Config-writing tools are disabled by default and require `--mcp-manage-ssh-configs` to enable.
Termcp is written in pure Go with no CGO and runs on macOS, Linux, and Windows (x86_64 and ARM64). It uses native PTY on POSIX systems and ConPTY on Windows, with identical behavior across all platforms.
README (reference)
Source of truth, from the repository.
Introduction
Termcp is an AI-native terminal platform: many hosts and many sessions at once, fully visualized. Those sessions are managed and maintained by humans and AI together, each side free to take over from or hand back to the other at any time; connection profiles are maintained independently by the platform, so an Agent can use a connection without ever reading its credentials.
- You (human) — a browser-based Web UI for live observation and instant takeover of any session;
- AI Agents — drive the same real terminals through MCP or SKILLS;
- Scripts / programs — a full REST API plus WebSocket channel for programmatic session, forward, and file operations.
On the platform layer, long-lived sessions with read-only replay, parallel multi-host / multi-session orchestration, and a full SSH connection lifecycle keep the whole loop observable, programmable, and easy to hand off between human and AI. Cross-platform and cloud-native, written in pure Go with no CGO: it ships as a single lightweight binary that runs persistently with low overhead, and goroutine concurrency keeps it high-throughput and low-latency.
Demo Video
https://github.com/user-attachments/assets/d06a3c36-250a-4eeb-aefa-e80d13d1551c
Why Termcp
Multi-session visual management
A powerful Web UI manages many hosts and many sessions in one place: start it locally with a single command or deploy the container to the cloud — the browser gets the same interface either way.
- Multi-session dashboard: every running session listed by name, switch or take over at any time.
- Real-time observation: watch
htop's live display,vim's editing process, or an installer's prompts in the browser, just like a local terminal. - Tabs and tiling workspace: one SSH session can open several shells, each its own tab; sessions can also be tiled side by side and tracked together.
- Port forwarding at a glance: local/remote ports and protocols for every session, all in one panel.
- File management: browse, upload, download, rename and create directories from the UI.
- Centralized connection templates: a unified SSH config store; the Agent opens sessions by profile name and never reads the config itself.
- Read-only replay of closed sessions: output stays browsable after a session closes, crashes, or survives a restart.
AI-native by design
Seamless human–agent interaction and pair operation: the Agent is a standing user of the terminal, alongside you and your scripts.
An Agent natively runs only one-shot commands, while real work is largely multi-turn interaction — SSH login needs a password first, a Python REPL is debugged line by line, an installer asks [Y/n], tools like top/htop/impacket need a terminal. Termcp hands the Agent a real terminal: one session stays alive and gets reused, so TUIs, REPLs, GDB, msfconsole and vim can be driven continuously the way a human would — through MCP or through the instance's own Agent Skill over plain curl.
- One session layer, peer entrances. MCP, SKILLS and REST/WebSocket sit at the same level as the Web UI, sharing the same real sessions. You can watch every Agent step in the browser and take over at any time; the Agent in turn can pause and hand a password/MFA prompt to you.
- Built for token and turn budgets. Tool schemas are compact and can be deferred-loaded (see
docs/mcp-tools.md);shell_outputpages by tail/offset cursors so only the slices you ask for ever enter the context window;shell_notifysends a bare wake-up signal. - Self-describing instances. Every running Termcp serves its own
/api.mdand/skills.md(no token needed) and registers them as MCP resources plus alearn-apiprompt, so a fresh Agent can drive this exact instance straight away, using only these two files. - Secrets stay server-side. Passwords, private keys and passphrases written through
ssh_configare stored only on the host, and the MCP read interface returns profile names only; the SSH-config write tools stay off unless the operator opts in with--mcp-manage-ssh-configs. - Failure-tolerant, resumable work. A closed, crashed or restarted session stays in the session list as a read-only DEAD tile with its output readable, so an Agent (or you) can pick up from the interrupted state; reconnecting the same
termcp://<entry>starts a fresh session. - Humans always keep the option to step in.
notify_userreaches you directly, privileged prompts are meant to be typed by you in the Web UI, and writes to one shell are serialized, so a human and an Agent can type on the same terminal with their inputs applied in order.
Quick Navigation
- Features
- Quick Start
- Usage
- Docker Deployment
- Connecting AI Clients (MCP)
- Agent Skill (curl-only, no MCP)
- Connecting Scripts / Programs (REST API)
- Examples
- Tool Reference
- Known Limitations & Security Model
Features
- ⚡ One-command install, pure Go, no CGO —
go install github.com/open-mcp-ai/termcp@latest; builds withCGO_ENABLED=0and binds no system shared libraries, so one static binary runs anywhere and cross-compiles natively (ConPTY on Windows, POSIX PTY on macOS / Linux — same behaviour everywhere). - 🔌 One port, four entrances — Web UI (humans), MCP / SKILLS (Agents), and REST + WebSocket (scripts) share one port.
- 🤝 Human–AI relay — You and the Agent share one live session and you can take over or interrupt at any time; the Agent pauses at
sudo/ password / MFA prompts for you to type in the Web UI; input is serialized so keystrokes never collide. - 🟦 Multi-turn interaction on a real terminal — The process keeps running, so an Agent drives TUIs, REPLs, GDB, msfconsole, or vim across conversation turns; a full PTY (ConPTY on Windows) behaves the same on every platform.
- 🟫 Local or remote, one workflow — Zero-config access to the Termcp host (
ssh_config="internal") or any remote machine over SSH profiles; commands, file transfer (SFTP plus resumable HTTP URLs), and port forwarding (-L/-R/-D) all run over that single connection. - 🟧 Built-in visual management — Browser live terminals, session dashboard, tabbed shells, tiling workspace, read-only replay of closed sessions, file and forward panels;
/api.htmlholds the API / MCP / SKILLS cheat sheet. - 🟨 Multiple Agents, no lost output — Parallel readers of one session keep independent cursors; a closed session (explicit close, exit, crash, or restart) stays in the registry as a read-only DEAD tile with its full output intact, so you can still replay, page through, or delete it whenever you like. After a drop, open a fresh session from the same entry (
termcp://<entry>) and carry on. - 🟥 Proactive notifications, no polling —
shell_notifywakes the Agent on process exit, silence, or new output — signal only, no payload (pull the text when needed);channel="sampling"sendssampling/createMessagedirectly. - 🌐 Multi-language Web UI — The interface follows the browser language on first load and can be overridden from the header; the choice is remembered, and switching never reloads the page or rebuilds open terminals.
- 🔍 Optional review mode — Under it, the Agent's command executions and file changes run only after human approval — for production hosts.
- 🔒 Credential-safe by design — Passwords, private keys, and passphrases written through
ssh_configare never readable back, so plaintext never enters the Agent's context; config-writing tools stay off unless--mcp-manage-ssh-configsis set.
Quick Start
Quick Install (Go toolchain required)
The fastest way to install — one command, no clone, no build:
go install github.com/open-mcp-ai/termcp@latest
go install resolves the module through the Go proxy (use GOPROXY=https://goproxy.cn,direct in mainland China) and drops the termcp binary into $(go env GOPATH)/bin — make sure that directory is on your PATH. Termcp is written in Go, so install is go install or a prebuilt Release binary: it needs no Node or Python runtime. Being a Go module, it also supports source-level integration: go get github.com/open-mcp-ai/termcp to bring it in as a dependency, or fork and build a customized binary from source. Then run:
termcp
Download
Head to the Releases page and download the pre-built binary for your platform:
| Platform | File |
|---|---|
| Linux (x86_64) | termcp-linux-amd64 |
| Linux (ARM64) | termcp-linux-arm64 |
| macOS (Intel) | termcp-darwin-amd64 |
| macOS (Apple Silicon) | termcp-darwin-arm64 |
| Windows (x86_64) | termcp-windows-amd64.exe |
| Windows (ARM64) | termcp-windows-arm64.exe |
Build
# Clone
git clone https://github.com/open-mcp-ai/termcp.git
cd termcp
# Build (pure Go — no CGO needed, cross-compiles to any platform)
CGO_ENABLED=0 go build -o termcp .
# Pure-API build (-tags no_webui): REST, MCP and WebSocket only. The browser UI
# is neither embedded nor served (GET / is a 404); /api.md and /skills.md stay.
CGO_ENABLED=0 go build -tags no_webui -o termcp-api .
# Run (defaults: loopback, port 18765; data goes to ~/.termcp)
./termcp
Open http://127.0.0.1:18765 in your browser to enter the Web UI.
Usage
Command Line
termcp [flags]
| Flag | Default | Description |
|---|---|---|
--host | 127.0.0.1 | HTTP bind address. 0.0.0.0 listens on all interfaces. A non-loopback bind requires an auth token/hash (startup fails otherwise). |
--port | 18765 | HTTP port. Shared by the Web UI, MCP SSE, MCP streamable HTTP, and the docs/skill endpoints (/api.md, /skills.md). |
--data-dir | ~/.termcp | Persistence directory (sessions, SSH configs). Auto-created. Default overridable via $TERMCP_DATA_DIR. |
--log-level | info | Log level: debug / info / warn / error. debug shows all MCP tool calls; failed tool calls and session-create errors log at warn/error regardless. |
--no-internal | false | Disable the built-in loopback SSH profile. |
--assets | ~/.termcp/assets | External static assets directory for the Web UI and docs. A file present there overrides the embedded copy; a file it does not contain falls back to the embed. A missing directory is normal and changes nothing. Default overridable via $TERMCP_ASSETS_DIR. |
--mcp-manage-ssh-configs | false | Enable MCP tools to create/edit/delete SSH configs (secrets are never exposed). |
--auth-token | (unset) | Static token for HTTP authentication (or $TERMCP_AUTH_TOKEN). Every client — API, MCP, browser — must present it. Mutually exclusive with --auth-hash. |
--auth-hash | (unset) | Salted SHA-256 hash of the token (sha256-<salt_hex>-<digest_hex>) so the server never holds the plaintext (or $TERMCP_AUTH_HASH). Generate with termcp --gen-auth-hash. Mutually exclusive with --auth-token. |
--disable-auth | false | Turn HTTP authentication off on purpose, including on a non-loopback bind (or $TERMCP_DISABLE_AUTH_TOKEN=1). Pair it with a loopback port so only local callers can reach the port. Combining it with --auth-token/--auth-hash is an error rather than a silently-won argument. |
--mcp-defer-tools | false | Tag low-frequency MCP tools (file_*, forward, shell_resize, …) with defer_loading so clients fetch their schemas on demand, shrinking the initial tools/list. Off by default: clients that ignore the marker — or talk to Termcp through a gateway that drops it — would otherwise never see those tools. See Deferred tool loading. |
--gen-auth-hash | (action) | Generate the salted SHA-256 hash of a token for --auth-hash, then exit (token from an argument, or from stdin without echo on a terminal). |
--version | (action) | Print version, commit, and build date, then exit. The version follows the git tag automatically (release builds inject it via -ldflags; plain go build / go install module@vX.Y.Z falls back to the module version embedded by the Go toolchain). |
These flags are your capability gates: --no-internal narrows Agents to remote hosts only, and --mcp-manage-ssh-configs is what opens SSH-config write access. Tighten or loosen what Agents can touch per scenario. See Authentication below.
Examples
# Listen on all interfaces
./termcp --host 0.0.0.0 --auth-token "your-long-random-token"
# Listen on all interfaces with only a salted hash stored server-side
./termcp --host 0.0.0.0 --auth-hash "$(./termcp --gen-auth-hash)"
# Allow AI agents to manage SSH configs
./termcp --mcp-manage-ssh-configs
# Disable the built-in loopback profile (agents may only reach remote hosts)
./termcp --no-internal
Authentication
A single static token protects the whole HTTP surface — the Web UI, REST API, MCP SSE, MCP streamable HTTP, and the browser WebSocket. (The read-only docs /api.md and /skills.md stay public, so an agent can fetch them before it has a token.) Configuring it is optional for loopback-only binds (127.0.0.1 keeps its no-setup default); exposing a non-loopback bind without a token is a startup error.
# Plaintext: flag or env var
./termcp --auth-token "your-long-random-token"
TERMCP_AUTH_TOKEN="your-long-random-token" ./termcp
# Hashed (recommended): the server keeps only sha256-<salt>-<digest>.
# `termcp --gen-auth-hash` reads the token from stdin without echo on a terminal,
# so it never lands in shell history:
./termcp --gen-auth-hash
TERMCP_AUTH_HASH='sha256-...' ./termcp
How each client presents the token:
| Client | Credential |
|---|---|
| API / MCP / curl | Authorization: Bearer <token> header |
| Browser (Web UI) | Native login prompt on 401 — the username is ignored (leave it empty), the token is the password. A termcp_token cookie is then set automatically so same-origin WebSocket handshakes authenticate too. |
Behavior notes:
--auth-tokenand--auth-hashare mutually exclusive; a flag value overrides the environment variable of the same setting.- A colon inside the token is fine: the server also accepts the whole decoded
user:passstring when it equals the token, so clients that split at the first colon (e.g.curl -u user:pass) still authenticate.curl -u :<token>remains the canonical form. - Without a token or hash, startup fails on any non-loopback host (
0.0.0.0, a LAN IP, or a hostname other thanlocalhost), so an accidentally exposed instance can never run unauthenticated. --disable-auth(orTERMCP_DISABLE_AUTH_TOKEN=1) explicitly lifts that requirement. It is the escape hatch for loopback-only setups — demo videos, screen recordings, single-user workstations — where the token protects nothing. Because it is a deliberate override, combining it with--auth-token/--auth-hashis a startup error rather than a silently-won argument, and the startup log switches from the informational auth line to a warning.- Browsers use HTTP Basic, which is Base64, not encryption. When serving Termcp beyond your own machine, terminate TLS in a reverse proxy in front of it — the
termcp_tokencookie then gets theSecureflag automatically only when the request arrived over TLS.
Connecting to Remote Hosts
Zero setup: ssh_config="internal" drives the Termcp host itself. To reach a remote machine, create an SSH profile — in the Web UI's new-connection dialog (it ships a TOML template and a Test connection button), or via the REST API PUT /api/connections/<name> with a TOML body:
kind = "remote"
host = "192.168.1.100"
user = "pi"
trust_unknown_host = true # first connect to an unknown host
# EITHER a password:
password = "..."
# OR the private key's PEM content itself — a path like "~/.ssh/id_ed25519" will NOT work:
private_key = """-----BEGIN OPENSSH PRIVATE KEY-----
<paste the full content of ~/.ssh/id_ed25519>
-----END OPENSSH PRIVATE KEY-----"""
key_passphrase = "..." # only if the key is passphrase-protected
# Optional bastion (ProxyJump) hop:
[jump]
host = "bastion.example.com"
user = "ops"
password = "..."
Profiles live in data-dir/ssh_configs/<name>/config.toml; list them with ssh_config(action=list). Credentials written this way are never readable back. Agents can create profiles too, but only when Termcp was started with --mcp-manage-ssh-configs.
Docker Deployment
Run the official image
The registry image runs as non-root termcp (uid/gid 1000) with /home/termcp declared a VOLUME — all state (sessions, SSH configs, transcripts) defaults to ~/.termcp. It carries only the binary: no baked-in entrypoint or exposed port, so the run command decides the bind address.
docker run -d --name termcp -p 18765:18765 -v termcp-data:/home/termcp -e TERMCP_AUTH_TOKEN=change-me-to-a-long-random-secret ghcr.io/open-mcp-ai/termcp:latest termcp --no-internal --host 0.0.0.0 --port 18765
Shell examples are single-line on purpose: a
\continuation is valid bash but a syntax error in PowerShell, so every command pastes as-is into bash, zsh, and PowerShell.
--host 0.0.0.0 is reachable from outside the container, so an auth token is required. MCP endpoint: http://localhost:18765/stream. With a bind mount instead of a named volume, chown the host directory first: chown -R 1000:1000 /path/on/host.
Docker without a token (loopback only)
For a throwaway demo, a screen recording, or a single-user workstation, the token is friction with no benefit. Publish the port on the host loopback only and tell Termcp explicitly that the missing credentials are intentional:
docker run -d --name termcp -p 127.0.0.1:18765:18765 -v termcp-data:/home/termcp ghcr.io/open-mcp-ai/termcp:latest termcp --no-internal --host 0.0.0.0 --port 18765 --disable-auth
Two details make this safe rather than merely convenient. -p 127.0.0.1:18765:18765 binds the published port to the host's loopback, so the container stays reachable to this machine and invisible to the LAN — the container itself still listens on 0.0.0.0 because that is the only address routable from outside its network namespace. And --disable-auth is required precisely because Termcp refuses to start unauthenticated on a non-loopback bind: the flag is the operator taking responsibility, which is why it also downgrades the startup log to a warning. The equivalent environment form is -e TERMCP_DISABLE_AUTH_TOKEN=1 instead of the flag.
Multi-stage build: add Termcp to any container
Drop this Dockerfile into your application project: the build stage installs Termcp with go install, then COPY --from copies the binary into the target image — no Go runtime needed there.
# syntax=docker/dockerfile:1
ARG GO_IMAGE=golang:1.25-alpine
FROM ${GO_IMAGE} AS termcp-build
# Module proxy; use https://proxy.golang.org,direct outside China
ARG GOPROXY=https://goproxy.cn,direct
ENV GOPROXY=${GOPROXY} GOBIN=/out CGO_ENABLED=0
# Pin to a concrete version in production, e.g. @vX.Y.Z
RUN go install github.com/open-mcp-ai/termcp@latest
# Any target base image
FROM alpine
COPY --from=termcp-build /out/termcp /usr/local/bin/termcp
Swap GOPROXY or GO_IMAGE with --build-arg if you need another module proxy or base-image mirror.
Startup command examples
Containers must bind 0.0.0.0, and a non-loopback bind requires authentication (TERMCP_AUTH_TOKEN / TERMCP_AUTH_HASH) or startup fails.
docker build --build-arg GOPROXY=https://goproxy.cn,direct -t my-app-with-termcp .
docker run -d --name my-app-termcp -p 18765:18765 -v termcp-data:/data -e TERMCP_AUTH_TOKEN=change-me-to-a-long-random-secret --entrypoint /usr/local/bin/termcp my-app-with-termcp --host 0.0.0.0 --port 18765 --data-dir /data
docker logs -f my-app-termcp
Append --mcp-manage-ssh-configs to open the SSH-config write tools to Agents.
If Termcp must share a container with another main process, start it from the existing entrypoint or process manager; otherwise run it as a separate service and reach it at http://termcp:18765/stream.
Docker Compose startup
services:
termcp:
build: .
entrypoint: ["/usr/local/bin/termcp"]
command: ["--host", "0.0.0.0", "--port", "18765", "--data-dir", "/data"]
environment:
- TERMCP_AUTH_TOKEN=change-me-to-a-long-random-secret
ports:
- "18765:18765"
volumes:
- termcp-data:/data
volumes:
termcp-data:
docker compose up -d --build
Connecting AI Clients (MCP)
Termcp speaks both MCP transports on the same port (18765). Choose whichever your client supports — the tool surface is identical.
Termcp is a long-running service: the same port serves the Web UI, any number of MCP clients, and session persistence. It therefore offers HTTP transports only — Streamable HTTP and SSE — and does not support stdio (there is no local subprocess mode).
Alternative: the Agent Skill drives the same sessions over plain curl — the instance serves it at /skills.md. The MCP server is one interface layer of the platform, embeddable into any MCP-capable host — Claude Code, Cursor, Codex, Open WebUI, or your own client.
Option A — Streamable HTTP (/stream)
The modern MCP transport; a single endpoint, no separate message path. Use this for Claude Code, Open WebUI, and most current clients.
{
"mcpServers": {
"termcp": {
"type": "http",
"url": "http://your-server:18765/stream"
}
}
}
claude mcp add --transport http termcp http://localhost:18765/stream
- Same machine:
http://127.0.0.1:18765/stream. - Open WebUI in Docker, Termcp on the host:
http://host.docker.internal:18765/stream(macOS/Windows), or the host's LAN IP. - Both in Docker on the same network (see Docker Deployment):
http://termcp:18765/stream.
Option B — SSE (/sse)
The legacy SSE transport. Configure only /sse; the SDK posts JSON-RPC to /message automatically.
{
"mcpServers": {
"termcp": {
"type": "sse",
"url": "http://your-server:18765/sse"
}
}
}
claude mcp add --transport sse termcp http://localhost:18765/sse
Cheat sheet
- Streamable HTTP →
http://<host>:18765/stream - SSE →
http://<host>:18765/sse(JSON-RPC goes toPOST /message)
The Web UI's API / MCP / SKILLS page (/api.html) offers copy-ready config for both transports, plus the Agent-docs and skill-download addresses for this instance.
Agent Skill (curl-only, no MCP)
Don't want to configure an MCP client? The instance ships an installable
Agent Skill that teaches any agent to drive Termcp with curl alone —
including the termcp:// locators users paste from the Web UI.
# Public endpoint: no token needed for the download itself
curl -fsS http://<host>:18765/skills.md -o /tmp/termcp-SKILL.md
# Claude Code reads ~/.claude/skills/<name>/SKILL.md
mkdir -p ~/.claude/skills/termcp && cp /tmp/termcp-SKILL.md ~/.claude/skills/termcp/SKILL.md
# Other agents that follow the shared convention read ~/.agents/skills/<name>/SKILL.md
mkdir -p ~/.agents/skills/termcp && cp /tmp/termcp-SKILL.md ~/.agents/skills/termcp/SKILL.md
Restart the agent session after installing (skills are loaded at session start).
Claude Code has no per-skill CLI command — adding is "drop the file in", removing
is rm -rf ~/.claude/skills/termcp (or claude plugin install/uninstall when the
skill ships as a plugin).
Once installed, a request as simple as "open termcp://rock64 and run uname -a"
works end to end: the skill resolves the locator via
GET /api/resolve?url=..., creates the session with that ssh_config, sends the
command, and polls the output. The same skill is registered as the MCP resource
<origin>/skills.md, and /api.html shows the exact install command for the
instance you are looking at.
Connecting Scripts / Programs (REST API)
Skip MCP and use the same session layer programmatically: the full REST API and live WebSocket channel.
# List sessions (same --auth-token protection)
curl -H "Authorization: Bearer $TERMCP_AUTH_TOKEN" http://127.0.0.1:18765/api/sessions
# Create a session
curl -X POST http://127.0.0.1:18765/api/sessions -H "Authorization: Bearer $TERMCP_AUTH_TOKEN" -H 'Content-Type: application/json' -d '{"ssh_config":"internal","command":"bash","mode":"pty"}'
# Read output / upload files / port forwards — see docs/api.md
Live terminal I/O runs over WebSocket /api/ui/ws; files support direct HTTP URLs with Range resume. Full endpoint list in docs/api.md.
With authentication enabled
When the server runs with --auth-token/--auth-hash, every MCP request needs the token as an Authorization: Bearer header:
claude mcp add --transport http termcp http://your-server:18765/stream --header "Authorization: Bearer $TERMCP_AUTH_TOKEN"
{
"mcpServers": {
"termcp": {
"type": "http",
"url": "http://your-server:18765/stream",
"headers": { "Authorization": "Bearer <your-token>" }
}
}
}
Keep the token out of URLs and out of shared configs/screenshots. curl and scripts use the same header:
curl -H "Authorization: Bearer $TERMCP_AUTH_TOKEN" http://your-server:18765/api/sessions
Tool Reference
Termcp exposes 31 MCP tools. Full parameters, return shapes, and error codes live in docs/mcp-tools.md.
| Area | Tools |
|---|---|
| Sessions (connection containers) | session_start, session_list, session_info, session_terminate (close; keeps the DEAD entry readable), session_delete (permanent) |
| Shells (terminal channels) | shell_open, shell_list, shell_close, shell_input, shell_key, shell_output, shell_resize, shell_reader_register, shell_reader_unregister |
| Notifications | shell_notify (wakes the AI Agent), notify_user (toasts the human at the Web UI) |
| SSH profiles | ssh_config (list; create/edit/copy/delete with --mcp-manage-ssh-configs) |
| Port forwarding | forward (-L / -R / -D / list / close) |
| Files (SFTP) | file_read, file_write, file_stat, file_delete, file_rename, file_mkdir, file_urls, file_perm, file_link, file_fs, file_getwd |
| Transcript index | message (span list; bytes via shell_output) |
| Host discovery | shell_detect |
Run a command as shell_input + shell_key(key="enter") + shell_output. Failed tools return isError=true with a JSON body carrying a stable error_code.
Deferred tool loading
An MCP client fetches every tool's JSON schema in tools/list, so tool-heavy servers pay for that in context budget. The MCP spec offers an escape hatch: mark low-frequency tools with defer_loading, and a client loads their schema on demand. Termcp's 31 tools split into a hot path of 12 (session lifecycle + shell input/output — always listed) and 19 wide, low-frequency surfaces (the 11 SFTP file_* tools, forward, shell_resize/shell_detect/shell_notify, shell_reader_register/shell_reader_unregister, message, ssh_config).
--mcp-defer-tools turns the marker on and is off by default, so:
- Default — all 31 tools are listed eagerly with full schema. This is what every client that does not implement deferred loading needs — including any Codex that talks to Termcp through a gateway such as AxonHub, which can drop the
defer_loadingmarker. With the marker lost, those tools are not reloadable on demand and would simply vanish from the model's view. --mcp-defer-tools— the 19 low-frequency tools carrydefer_loading; the 12 core tools stay eager so thesession_start → shell_input → shell_outputloop never requires a search round trip. Clients that support on-demand loading (mcp-go based clients, Claude Code) pay only for the schemas they actually use.
Same 31 tools either way: enabling the flag never removes tools, it only withholds schemas from the initial listing.
Known Limitations & Security Model
- File and forward tools need a live connection. On a closed (DEAD) session they return
session_not_running; output reading still works viashell_output, and a session's port forwards are closed automatically when it goes DEAD. - Basic authentication needs TLS outside localhost. The browser login challenge uses HTTP Basic, whose credentials are only Base64-encoded. Put a TLS-terminating reverse proxy in front of Termcp when exposing it beyond a trusted local network; the static token is still never logged or placed in a URL.
🚨 Security boundary
- Do not put an Agent on a production host unattended. If you must, turn review mode on. Every write it makes over MCP — terminal input, file transfer, port forward — then waits in the Web UI for a human to accept or reject it, forcing a person into the loop for every change.
- Review mode is not a guarantee of safety. Review mode needs human confirmation, but a script execution or a file upload can still slip through when the reviewer is careless.
Star History
<p align="center"> <a href="https://star-history.com/#open-mcp-ai/termcp&Date"> <img src="https://api.star-history.com/svg?repos=open-mcp-ai/termcp&type=Date" alt="Star History Chart" width="760"> </a> </p>License
Released under the MIT License. You are free to use, modify, and distribute it, provided the copyright notice and permission notice are retained. Thanks to the linux.do community for the discussions and support.
<p align="center"> <img src="https://capsule-render.vercel.app/api?type=waving&color=0:2786FF,100:6E4AFF&height=110§ion=footer" width="100%" alt="footer"> </p>
Related MCP servers

OpenMetadata
Open context layer for AI: metadata, lineage, governance, and memory for trusted data discovery and reasoning.

openITCOCKPIT
openITCOCKPIT monitoring: host and service state, history, downtimes, acknowledgements, patches

OpenAccountants
Open-source tax guides reviewed by named, licensed accountants — AI can cite and stand behind answers.
Accountant-reviewed tax guides for 134+ countries that AI can cite with named credentials.
An MCP server that provides visual memory and context storage with knowledge graph capabilities
View repository →
나라장터 입찰공고
나라장터 입찰공고정보서비스(공공데이터포털 data.go.kr) Open API를 감싼 로컬 MCP 서버
