Before you begin
Use an MCP client that is configured to reach a running console service and keeps its connection open across calls. You need permission to run commands in that service's environment and a bash shell there. The working directory, programs, files and credentials are those of the service, which need not be the computer showing your client.
Ask the client to list its tools. It should offer terminal_run, terminal_open, terminal_send, terminal_read, terminal_watch, terminal_stats, terminal_list and terminal_close. If the tools are missing, fix the connection before sending commands.
Run a harmless command
Ask your agent to print a short marker, such as "run printf hello-console in a terminal". Behind that request, it sends a call like this (the examples on these pages are the params of an MCP tools/call request; your client adds the rest):
{
"name": "terminal_run",
"arguments": { "command": "printf 'hello-console\n'", "shell": "bash", "timeout": 10 }
}The tool result carries its payload as JSON inside text content. Success is timedOut: false, exitCode: 0 and output containing hello-console. The result also includes a generated runId and a terminal session.
No terminal was supplied, so the run is ephemeral and the service tries to close its terminal afterwards. If timedOut is true, read the terminal before retrying, since the command can still be running.
Keep a terminal for several calls
Stay in the same client session and open a named shell:
{ "name": "terminal_open", "arguments": { "name": "console-first-shell", "shell": "bash" } }Save the returned session value and use it in place of TERMINAL_ID:
{ "name": "terminal_run", "arguments": { "session": "TERMINAL_ID", "command": "printf 'same-shell\n'", "timeout": 10 } }A named terminal keeps shell state across commands. It is also a shared interactive process, so keep one controller responsible for it during this exercise.
Close the terminal
{ "name": "terminal_close", "arguments": { "session": "TERMINAL_ID" } }Check each result's success field. The exitCode a close reports is a cleanup value. terminal_list confirms the record is gone.
Read the result envelope
A transport response and a tool result are different layers. First check for a protocol error and the tool's isError flag, then decode the JSON in the text content and read that tool's fields. Tools that act on several terminals return individual results, each with its own success or failure.
idCorrelates one request and response; chosen by the clientsessionOne terminal; copy it from terminal_open or terminal_runrunIdOne command; a foreground capture can be read back with itidsessionterminal_open or terminal_runrunIdWhat you getProof that your agent can run commands, keep a shell between them and clean up after itself.