npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@neoline/hostbridge

v2.0.1

Published

HostBridge MCP server for persistent allowlisted SSH and shell sessions.

Readme

hostbridge

A local MCP server for AI agents to operate allowlisted interactive shells, usually SSH sessions. It keeps PTYs alive in memory, so an agent can open a session once, run quick commands, start long-running background jobs, and poll logs until completion.

This repo is portable: it ships with no personal server paths or built-in hosts. Each user declares their own connection targets in ~/.hostbridge/hosts.json or a path set by HOSTBRIDGE_HOSTS_FILE.

Tools

  • hosts_list — reload and show configured connection targets and local script availability when applicable.
  • hosts_reload — explicitly reload configured connection targets without restarting the MCP server.
  • session_open(host_id, connect_timeout=30) — open a persistent interactive shell for one configured host.
  • sessions_list() — list live sessions in this MCP process.
  • sessions_close_all() — close every live session in one call; useful for shutdown and cleanup.
  • command_run(session_id, command, timeout=60) — run a foreground command and wait for completion.
  • task_start(session_id, command) — start a remote background job under $HOME/.hostbridge/jobs/<task_id>.
  • task_status(session_id, task_id, tail_lines=80) — poll job state, exit code, and log tail.
  • task_stop(session_id, task_id) — terminate a running background job and reap its process.
  • session_write(session_id, text) — send a raw line for interactive edge cases.
  • session_read(session_id, timeout=1.0, max_chars=20000) — read available raw output after interactive writes.
  • file_write_text(session_id, remote_path, content) — write a UTF-8 text file through the active shell, up to 100MiB.
  • file_read_text(session_id, remote_path) — read a UTF-8 text file through the active shell, up to 100MiB.
  • file_upload(session_id, local_path, remote_path) — upload a local file with chunked shell/base64 transfer, up to 100MiB.
  • file_download(session_id, remote_path, local_path) — download a remote file with chunked shell/base64 transfer, up to 100MiB.
  • session_close(session_id) — close a persistent session.

Every tool returns a structured payload with a stable error_code on failure (HOST_NOT_FOUND, SESSION_NOT_FOUND, POLICY_DENIED, TASK_NOT_FOUND, TIMEOUT, INTERNAL).

Install and configure v1

Install from npm or Python, then create a schema-v1 configuration and start the daemon:

npm install -g @neoline/hostbridge
hostbridge setup
hostbridge daemon start
hostbridge doctor

The public CLI is intentionally small: setup, migrate, doctor, hosts, daemon, mock-ssh, and version. Configure MCP clients manually to run npx -y @neoline/hostbridge; when no CLI command is supplied the same entrypoint serves MCP over stdio.

Add a host as one validated JSON object:

hostbridge hosts add '{"id":"gpu","label":"GPU","ssh":{"host":"[email protected]"},"transport":"auto"}'
hostbridge hosts list
hostbridge hosts check gpu

File transfer model

HostBridge file transfer is shell-based because recorded login paths may be JumpServer menus, OTP flows, wrapper scripts, or docker exec sessions rather than standard SSH/SFTP connections. The first-class transfer tools stream chunked base64 through the already-open shell session, verify hashes, and work for text or binary artifacts up to 100MiB:

file_upload(session_id, "/absolute/local/script.py", "/remote/work/script.py")
file_download(session_id, "/remote/work/result.log", "/absolute/local/result.log")

Give file tools local and remote paths; do not paste base64 into tool arguments. Files larger than 100MiB are deliberately rejected with guidance to use remote pull instead, for example curl, wget, git clone, modelscope download, or another remote-native downloader. The MCP file tools intentionally keep this shell/base64 backend for non-standard login flows. The optional mock-ssh bridge below exposes SFTP/SCP protocol compatibility on top of the same backend for clients which require SSH file-transfer channels.

Mock SSH bridge

Some clients, including compute providers, know how to connect to SSH targets but cannot run HostBridge's MCP connector inside their local sandbox. hostbridge mock-ssh exposes one configured HostBridge host as a local SSH server while keeping the actual remote access path behind HostBridge. This is useful when the client-side SSH implementation runs outside a restricted sandbox.

hostbridge mock-ssh start a800_95

By default HostBridge selects a free local port from 2222-2299, creates host/client keys under ~/.hostbridge/mock-ssh/<host_id>/, and writes a managed Host hostbridge-<host_id> block into ~/.ssh/config. The command prints the chosen alias, port, config path, and identity file:

hostbridge mock-ssh forwarding host 'a800_95'
listening on ssh://127.0.0.1:2222
ssh host alias: hostbridge-a800_95
ssh config: /Users/alice/.ssh/config
identity file: /Users/alice/.hostbridge/mock-ssh/a800_95/client_ed25519_key

Point the compute provider at the printed SSH alias, for example ssh:hostbridge-a800_95. To remove the managed SSH config block later:

hostbridge mock-ssh remove a800_95

Advanced options are still available for fixed deployments: --listen-host, --port, --key-dir, --ssh-host-alias, --ssh-config, and --no-ssh-config.

The bridge supports:

  • SSH exec requests, suitable for compute call_command APIs.
  • Interactive shell channels.
  • SFTP upload/download/list/stat/mkdir/remove/rename operations.
  • OpenSSH scp in its default SFTP-backed mode.
  • Legacy OpenSSH scp -O mode through AsyncSSH's SCP server.

Each SSH channel opens its own HostBridge backend session and closes it when the channel ends, so an interactive shell exit does not kill later exec or file-transfer requests. The SFTP/SCP implementation is a compatibility layer backed by HostBridge's shell/base64 transfer primitives, so it keeps working across JumpServer/menu/wrapper login flows where direct remote SFTP is unavailable. It inherits the same transfer size limit (100MiB by default); for larger files, start a remote-native pull from the target host.

Daemon lifecycle

HostBridge always keeps remote sessions in the local daemon. The MCP server process is only a lightweight stdio adapter for agent clients and talks to the daemon over a Unix domain socket. If the daemon is not already running, the MCP adapter starts it lazily on the first tool call.

hostbridge daemon start
hostbridge daemon status
hostbridge daemon stop

The daemon uses a Unix domain socket with a small JSON-line RPC protocol by default, not HTTP and not a TCP port:

~/.hostbridge/daemon.sock

When launched through the npm wrapper on macOS, HostBridge sets HOSTBRIDGE_DAEMON_SOCKET to /private/tmp/hostbridge-$USER/daemon.sock so sandboxed MCP launchers do not accidentally isolate the daemon under a rewritten HOME. Python-only launches keep the ~/.hostbridge/daemon.sock default unless you set HOSTBRIDGE_DAEMON_SOCKET or HOSTBRIDGE_DAEMON_DIR.

This avoids fixed port conflicts, removes the local HTTP surface, and keeps the control API local to the current machine. The daemon directory should be private to the local user. To point daemon management commands at a custom socket path:

hostbridge daemon start --socket /tmp/hostbridge.sock

For MCP clients, prefer setting the environment variable instead of relying on symlinks:

{
  "env": {
    "HOSTBRIDGE_DAEMON_SOCKET": "/private/tmp/hostbridge-shengzhoukong/daemon.sock"
  }
}

Sessions can outlive a single agent client process. HostBridge records an optional HOSTBRIDGE_AGENT_ID owner on sessions and refuses cross-owner operations unless a force-close path is used. Set HOSTBRIDGE_MAX_SESSIONS_PER_HOST to cap concurrent live sessions per configured host (default 0, unlimited).

Configuration lifecycle

hostbridge setup creates an empty schema-v1 file with mode 0600. It does not run an interactive login recorder. Use hostbridge hosts add for new entries and hostbridge migrate OLD NEW for legacy files. The daemon loads one validated config at startup; restart it after configuration changes.

Use transport: "auto" for normal operation, pty for JumpServer/menu/wrapper flows, or ssh for native AsyncSSH/SFTP-capable targets. Commands receive stdin explicitly through the protocol; HostBridge no longer guesses whether a command reads stdin.

Configure hosts

Create ~/.hostbridge/hosts.json:

mkdir -p ~/.hostbridge
cat > ~/.hostbridge/hosts.json <<'JSON'
{
  "schema_version": 1,
  "hosts": [
    {
      "id": "gpu_direct",
      "label": "GPU direct SSH",
      "ssh": {
        "host": "[email protected]"
      }
    }
  ]
}
JSON

The daemon validates this file at startup. Restart the daemon after editing it.

Direct SSH, no jump host

{
  "hosts": [
    {
      "id": "gpu",
      "label": "GPU server",
      "ssh": {
        "host": "[email protected]"
      }
    }
  ]
}

SSH with port, key, and jump host

{
  "hosts": [
    {
      "id": "gpu_jump",
      "label": "GPU via bastion",
      "ssh": {
        "host": "[email protected]",
        "port": 2222,
        "identity_file": "~/.ssh/gpu_key",
        "proxy_jump": "bastion.example.com",
        "extra_args": ["-o", "ServerAliveInterval=30"]
      }
    }
  ]
}

Existing shell script wrapper

Use this if you already have a .sh or expect wrapper that opens an interactive remote shell.

{
  "hosts": [
    {
      "id": "legacy_gpu",
      "label": "Legacy GPU wrapper",
      "script": "~/.ssh/connect_gpu.sh"
    }
  ]
}

The wrapper does not need executable permission; the MCP runs it with /bin/sh.

Advanced command mode

Use this for non-SSH interactive shells, containers, or custom connection tools. The MCP calls the executable directly without shell=True.

{
  "hosts": [
    {
      "id": "container",
      "label": "Local container shell",
      "command": "docker",
      "args": ["exec", "-it", "training-box", "bash"]
    }
  ]
}

Host config rules

  • id may contain only letters, numbers, _, -, and ..
  • Each host must define exactly one practical connection style: ssh, script, or command.
  • ssh.host can be any target accepted by ssh, such as [email protected] or an alias from ~/.ssh/config.
  • ssh.identity_file and script expand ~ for the local user running the MCP server.
  • For a different config path, set HOSTBRIDGE_HOSTS_FILE=/path/to/hosts.json in the MCP server environment.

MCP client config

Register the stdio entrypoint in each client. HostBridge v1 does not mutate client configuration files.

Codex example in ~/.codex/config.toml:

[mcp_servers.hostbridge]
command = "npx"
args = ["-y", "@neoline/hostbridge"]
[mcp_servers.hostbridge.env]
HOSTBRIDGE_AGENT_ID = "codex"

Claude Desktop style config:

{
  "mcpServers": {
    "hostbridge": {
      "command": "npx",
      "args": ["-y", "hostbridge"],
      "env": {"HOSTBRIDGE_AGENT_ID": "claude-code"}
    }
  }
}

To use a project-specific host file:

[mcp_servers.hostbridge.env]
HOSTBRIDGE_HOSTS_FILE = "/absolute/path/to/hosts.json"

See examples/ for copyable config templates.

Policy, audit, and idle reaping

hostbridge ships a lightweight policy layer that runs inside the daemon process. It is on by default and can be tuned or disabled via environment variables or a JSON config file.

Environment variables:

| Variable | Effect | | --- | --- | | HOSTBRIDGE_DISABLE_POLICY=1 | Disable policy checks and audit logging entirely. | | HOSTBRIDGE_POLICY_FILE=/path/to/policy.json | Override policy config path (default ~/.hostbridge/policy.json). | | HOSTBRIDGE_DENYLIST=pat1:pat2 | Append extra deny regex patterns (colon-separated). | | HOSTBRIDGE_IDLE_TIMEOUT=900 | Idle timeout in seconds before an inactive session is reaped (default 1800). | | HOSTBRIDGE_AUDIT_LOG=/path/to/audit.jsonl | Override audit log path (default ~/.hostbridge/audit.jsonl). |

Default denylist blocks obviously destructive commands (rm -rf /, mkfs, dd of=/dev/sd*, fork bombs, shutdown, reboot). A denied command returns error_code=POLICY_DENIED with the matched pattern, and is recorded in the audit log alongside session/task lifecycle events.

Policy config file (optional):

{
  "idle_timeout_seconds": 1800,
  "use_default_denylist": true,
  "command_denylist": ["\\bmytool\\b"],
  "audit_log_path": "~/.hostbridge/audit.jsonl"
}

See SECURITY.md and docs/THREAT_MODEL.md for the trust model and audited events.

Typical agent workflow

  1. Call hosts_list and choose a configured host id.
  2. Add missing hosts with hostbridge hosts add '<json>', then restart the daemon.
  3. Call session_open once for the chosen host.
  4. Only after a connection failure, run hostbridge hosts check <host_id>.
  5. Use command_run for quick work and task_start / task_status for long jobs.
  6. Use text tools for UTF-8 and upload/download tools for streamed binary transfers.
  7. Close the session when finished.

Security notes

  • Host access is allowlisted by config; MCP callers cannot provide arbitrary local connection commands at runtime.
  • The server never reads or logs passwords from underlying SSH/script prompts.
  • Commands still run with your remote shell privileges. Use only with trusted local MCP clients.
  • Background task logs and exit codes are stored on the remote host in $HOME/.hostbridge/jobs/.
  • The policy layer blocks a built-in destructive denylist and writes structured audit events. It is defense-in-depth, not a sandbox.

Contributing

See CONTRIBUTING.md. Run tests with python -m pytest -q. The full suite should pass before pushing.

License

MIT. See LICENSE.