Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MCP Server (stdio)

sshx mcp serves the sshx execution contract over the Model Context Protocol so MCP-capable agents (Claude Desktop, IDE agents, custom clients) can call sshx as native tools instead of shelling out.

sshx mcp

The server speaks MCP over stdio only. It is spawned and owned by the MCP client, holds no SSH connections, keeps no state, and exits when the client closes the stream. Every tool call re-enters the sshx binary as a one-shot child process — the same process model, safety gates, keyring access, and audit trail as the CLI.

Client Configuration

Claude Desktop / generic MCP client entry:

{
  "mcpServers": {
    "sshx": {
      "command": "sshx",
      "args": ["mcp"]
    }
  }
}

Tools

ToolMaps toNotes
sshx_runsshx run --jsonSelectors, command or byte-preserving script (shebang or shell selects the interpreter), bounded fan-out, dry-run, force + bypass_reason
sshx_sqlsshx sql --jsonGuarded single-statement SQL via remote psql/sqlite3/mysql
sshx_applysshx apply --jsonGuarded single-file replace; accepts from_path or inline content (including an empty string)
sshx_inspectsshx inspect --jsonBuilt-in capabilities and trusted local plugins
sshx_textsshx text --jsonBounded file/journal dissection; exception blocks, presets, line windows
sshx_sftpSFTP flagsupload / download / list / mkdir / remove
sshx_transfer--transferServer-to-server streaming through the local machine
sshx_host_list--host-list --jsonRead-only sshx.hosts.v1 inventory

For row-filtered SQL, a backup that would widen to a full-table snapshot is blocked by default. Set allow_full_table_backup: true on sshx_sql only when that broader before-image is intentional; this does not authorize an UPDATE/DELETE without WHERE.

Tool results contain the CLI’s versioned JSON verbatim (for example sshx.result.v1 from sshx_run), so success, error_kind, completion, and retry guidance keep exactly the semantics documented for the CLI. A non-zero child exit marks the MCP result as a tool error while preserving the structured payload.

When the MCP client supplies a progressToken on sshx_run, the server runs the child with --jsonl and offers target_finished events as bounded, best-effort MCP notifications/progress notifications. Progress total is the selected target count. The final tool document stays the CLI result: a single-target call still returns sshx.result.v1; multi-target calls still return the JSONL stream.

--pty is permanently out of scope for MCP. A PTY merges stderr into stdout and is incompatible with --json. Agents should keep using sshx_run / sshx_sql / sshx_apply rather than an interactive terminal.

Bound plans, deadlines, and delivery

Remote tools accept expect_plan, host_timeout_seconds, and global_timeout_seconds, matching the CLI flags. timeout_seconds keeps its command/session meaning. Run also accepts fail_fast and max_failures; these stop new admission only, not already active targets. Opaque commands/scripts remain mutation risk regardless of caller intent. SQL accepts optional bypass_reason to record existing policy approvals; this does not introduce a new mandatory reason for old SQL invocations. Run’s optional request_id is caller correlation, not the unique execution_id. Inspection supports the same dry_run preview flow.

Preview with dry_run: true, inspect plan.bindable / plan.unresolved, and execute the same inputs with the reviewed expect_plan. Inline payload staging paths are not payload identity; bytes are. Public IP/key/trust requirements, conservative whole-trust-store invalidation, and remote SQL discovery restrictions are the same as the CLI. Common execution IDs, fingerprint, change state and verification are CLI facts, not an MCP-specific schema.

The adapter has a separate 30-minute process watchdog. A shorter explicit global timeout receives two minutes of reporting grace, capped by that watchdog; a command timeout is not multiplied into a new fan-out limit. Cancellation requests cooperative child shutdown with bounded escalation. Platform-specific local process shutdown does not prove remote termination. Escalation follows a three-second grace period and targets the owned process tree (Unix process group or Windows job object), not unrelated processes.

Progress delivery is bounded independently of stdout draining; progress notifications are not the authoritative completion record. Malformed, oversized or truncated JSONL, missing final completion, or output-delivery failures are adapter errors, not successful synthesized results. Keep the execution outcome separate from an adapter failure before deciding to retry. See Plans, Outcomes, and Safe Retries. Current adapter caps are 64 MiB stdout/individual event records, 1 MiB stderr, 100,000 retained events, and a 64-entry progress queue. Progress write/delivery has a 250 ms grace; a stalled stdio session closes instead of leaving a blocked SDK writer. These are delivery limits, not remote output or effect verification guarantees.

Security Model

  • Same gates, same evidence. Safety checks, host-key verification, keyring credential roles, and audit all run in the child process exactly as in direct CLI use. Run’s force / no_safety_check require explicit bypass_reason; apply retains its critical-path reason requirement and SQL retains its existing approval flags with an optional recorded reason.
  • Audit attribution. Child invocations carry entry: "mcp" in their audit events, so MCP-originated executions are distinguishable from interactive CLI use. The marker is metadata only — it never changes trust or safety decisions.
  • No secret surface. Password management (--password-set and friends) is deliberately not exposed as a tool. Configure credentials with the CLI first; MCP tools only ever reference keyring keys.
  • No trust relaxations by omission. Accepting unknown host keys is not a tool parameter. Trust hosts explicitly beforehand (for example with sshx --host-test or one supervised CLI run).
  • stdio only. There is no HTTP/SSE transport, no listening socket, and no resident service; this boundary is documented in AGENT.md §3.

Typical Flow

  1. Configure and trust hosts with the CLI (--host-add, --host-import, --host-test).
  2. Store credentials in the OS keyring (--password-set=...).
  3. Point the MCP client at sshx mcp.
  4. The agent discovers inventory (sshx_host_list), previews with dry_run: true, executes, and branches on the structured result.