scomp-mcp: Letting an AI Agent Use a Terminal on a Host It Cannot Reach

Posted on Sep 1, 2026

I have a GPU host in a private network. It has no public IP and no SSH access from my laptop. I also have an AI coding agent on my laptop. The agent is good at builds and benchmarks, but it cannot reach that host.

The scomp agent already connects that host to the scomp relay with an outbound connection. So the missing part was small: a tool that lets a local model use the same terminal sessions, under the same rules. That tool is scomp-mcp.

What it is

scomp-mcp is an MCP server over local stdio. Your MCP host (Claude Code, Codex, or another client) starts it as a child process. It is a normal scoped client of the scomp relay:

Claude Code / Codex / other MCP host
    | MCP JSON-RPC over stdin/stdout
    v
scomp-mcp serve
    | HTTPS + ticket-authenticated WebSocket
    v
scomp relay -> paired agent -> existing tmux/Screen session

It gives the model six tools: scomp_list_hosts, scomp_list_sessions, scomp_open_terminal, scomp_read_terminal, scomp_send_input, and scomp_close_terminal.

It is a terminal, not a command executor

This is the most important design decision. scomp-mcp does not run commands. It types into a terminal that a human started, and it reads what the terminal shows. You must do these steps on the remote host yourself:

tmux new-session -d -s work
scomp --mode full        # or --mode readonly: the model can only watch

The model can attach only to sessions that the agent reports. The agent mode still applies. If you start the agent in readonly mode, the model can read the build log, and it cannot type one character.

There are two consequences, and the tools say both of them in their descriptions:

  • Input delivery does not prove execution. “Delivered” means that the relay got the keystrokes. It does not mean that a shell ran a command, and there is no exit status.
  • Terminal output is untrusted data. A file that the model cats can contain text like “ignore your instructions and…”. Output is program data, not instructions. Old rule, new audience: never trust user input. Now the “user” is a log file, and the reader is a model.

Reading a terminal like a careful human

A terminal is a stream, not a request/response API. These features make it usable for a model:

  • Cursors. Each read returns a cursor. The next read continues from that cursor, so the model does not read the same scrollback twice.

  • Generations. After a reconnect, the stream has a new generation. The read reports resynced, so the model knows that the old cursor is not valid.

  • Waits. wait_ms lets one read wait up to 50 seconds for new output. An empty result after the wait is normal for a quiet build.

  • Markers. To wait for a command, append a unique marker and read until it appears:

    make test; printf 'DONE_%s\n' 7f3a
    

    Then call the read with until: "DONE_7f3a". Build the marker at run time, as above. If you type the marker literally, the echo of your own command line matches it, and you wait for nothing. Every engineer does this once. I did it twice.

  • Tails. On attach, the agent replays its scrollback, which can be tens of kilobytes. resync: "tail" returns only the end. That saves tokens, and tokens are money.

scomp_send_input does not press Enter unless submit: true is explicit. Named keys include enter, tab, escape, ctrl_c, and the arrows. Yes, the model can press Ctrl+C. No, it cannot press the reset button on the server. Some jobs still need a human.

Authorization

scomp-mcp login        # read/write terminal access
scomp-mcp login --read-only
scomp-mcp status

The login opens a browser approval page and prints a code in your terminal. You type that code on the page yourself. Do not approve a request whose code you did not see in your own terminal. On the page, you select the paired hosts, remove any scope that you do not want to grant, and set the lifetime. The default is 30 days, and the server limit is 90 days.

The credential is stored in the user config directory, in scomp/mcp.json, with mode 0600. Do not copy the token into the MCP host configuration. scomp-mcp logout removes it, and the scomp web profile can revoke it.

Connect your MCP host

Claude Code:

claude mcp add scomp --scope local -- "$HOME/.local/bin/scomp-mcp" serve
claude mcp list        # scomp ... ✔ Connected

Codex:

codex mcp add scomp -- "$HOME/.local/bin/scomp-mcp" serve
codex mcp list

Restart the agent session after you add the server. A session that is already running does not load new tools. (This is the MCP version of “did you try to turn it off and on again”.)

For Fedora-family systems, make srpm && make rpm builds an RPM. The package installs one binary and no system service.

How I use it

I use it with Claude Code for long GPU jobs on that private host:

  • pull, build, and run benchmarks;
  • read results with markers;
  • stop a job cleanly with Ctrl+C when a parameter is wrong.

All of this happens in a tmux session that I can also open on my phone. When the model works, I watch the same session from the scomp web client. It is like pair programming, but my partner does not take my chair, and it does not drink my coffee.