Skip to main content
Glama
vstlmkh

connect-to-server-mcp

by vstlmkh
README.md
<p align="center">
  <img src="https://raw.githubusercontent.com/vstlmkh/connect-to-server-mcp/master/docs/assets/banner.png" alt="connect-to-server-mcp โ€” give your AI agent a safe shell on any server" width="900">
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/connect-to-server-mcp"><img alt="npm version" src="https://img.shields.io/npm/v/connect-to-server-mcp?logo=npm&color=60a5fa"></a>
  <a href="https://www.npmjs.com/package/connect-to-server-mcp"><img alt="npm downloads" src="https://img.shields.io/npm/dm/connect-to-server-mcp?label=downloads&color=5eead4"></a>
  <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-a78bfa">
  <a href="https://github.com/vstlmkh/connect-to-server-mcp/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-22c55e"></a>
</p>

<p align="center">
  <b><a href="https://www.npmjs.com/package/connect-to-server-mcp">๐Ÿ“ฆ npmjs.com/package/connect-to-server-mcp</a></b>
  &nbsp;ยท&nbsp;
  <code>npx connect-to-server-mcp install</code>
</p>

# connect-to-server-mcp

**connect-to-server-mcp** is a Model Context Protocol server that turns any remote machine into something an AI agent can operate. Point it at a host โ€” bare metal, VPS, or cloud instance โ€” with whatever credentials you have (SSH key, password, agent forwarding, or a jump host), and the agent gains a structured toolset for real operations: executing commands, reading and editing files, tailing logs, managing systemd services, and inspecting resource usage. Every action goes through explicit, permission-scoped tools with full audit logging, so the agent's reach stays exactly as wide as you allow.

## Features

- **Any host, any auth** โ€” SSH keys (with passphrase), passwords, the local SSH agent, and jump hosts / bastions.
- **Per-host access modes** โ€” `read_only` refuses anything that looks like it mutates state; `full` unlocks writes. An explicit `allowed_commands` allowlist overrides both.
- **Global guard rails** โ€” `rm -rf /`, `mkfs`, `dd of=/dev/โ€ฆ`, fork bombs and reboots are refused on every host regardless of mode.
- **Audit log** โ€” every attempt, including refusals, appended as JSONL.
- **Purpose-built tools** โ€” logs, services, and health snapshots have dedicated tools, so the agent rarely needs raw shell.

## Tools

| Tool | What it does |
| --- | --- |
| `list_hosts` | List configured hosts with access mode and description |
| `reload_hosts` | Re-read the inventory and drop open connections |
| `check_connection` | Open/reuse the SSH session and report host identity |
| `run_command` | Run a shell command, subject to the host's policy |
| `read_file` / `write_file` | Read or overwrite a remote file over SFTP (writes make a `.bak`) |
| `list_directory` | List a directory with sizes and permissions |
| `tail_log` | Tail a log file or a systemd unit's journal, optionally filtered |
| `service_status` / `service_control` | Inspect or start/stop/restart/enable a systemd unit |
| `system_overview` | Load, memory, disk, top processes, failed units in one call |
| `disconnect` | Close one connection or all of them |

## Install

Pick whichever fits your setup โ€” all three end up running the same server.

### 1. One command (npx)

No Python setup, no clone. The launcher finds `uv` or Python 3.10+ on your machine, provisions what is missing, and registers the server with every Claude client it detects:

```bash
npx connect-to-server-mcp install
```

Targets can be named explicitly, and the scope for the CLI chosen:

```bash
npx connect-to-server-mcp install claude-code --scope user
npx connect-to-server-mcp install claude-desktop
npx connect-to-server-mcp install --config-file ./.mcp.json   # any MCP client
```

`install` also seeds a starter inventory at `~/.config/connect-to-server-mcp/hosts.yaml` if you do not have one. Restart the client afterwards, then run `npx connect-to-server-mcp doctor` if anything looks off โ€” it prints the runtime, config paths, and the exact command the server will be started with.

### 2. Claude Code plugin (marketplace)

```
/plugin marketplace add vstlmkh/connect-to-server-mcp
/plugin install connect-to-server@connect-to-server
```

The plugin lives in [`plugin/`](plugin) and starts the published npm package through its own launcher, so it works as soon as it is enabled โ€” independently of which directory the client runs in.

### 3. Manual client config

Add this to `claude_desktop_config.json` (Claude Desktop) or any other MCP client:

```json
{
  "mcpServers": {
    "connect-to-server": {
      "command": "npx",
      "args": ["-y", "connect-to-server-mcp"],
      "env": { "CONNECT_MCP_CONFIG": "~/.config/connect-to-server-mcp/hosts.yaml" }
    }
  }
}
```

Or register it with the Claude CLI directly:

```bash
claude mcp add connect-to-server -e CONNECT_MCP_CONFIG=~/.config/connect-to-server-mcp/hosts.yaml \
  -- npx -y connect-to-server-mcp
```

### From source

```bash
git clone https://github.com/vstlmkh/connect-to-server-mcp.git
cd connect-to-server-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
connect-to-server-mcp          # stdio transport
```

## Configure

Copy [`docs/examples/hosts.yaml`](docs/examples/hosts.yaml) to `~/.config/connect-to-server-mcp/hosts.yaml`, or point `CONNECT_MCP_CONFIG` at a file of your choosing. Any `${VAR}` in the file is expanded from the environment at load time โ€” keep secrets out of version control.

```yaml
audit_log: ~/.local/state/connect-to-server-mcp/audit.jsonl

hosts:
  - name: prod-web
    hostname: 203.0.113.10
    username: deploy
    private_key: ~/.ssh/id_ed25519
    known_hosts: ~/.ssh/known_hosts
    mode: read_only

  - name: staging
    hostname: staging.internal
    username: root
    private_key: ~/.ssh/id_ed25519
    mode: full
    working_dir: /srv/app
```

Environment variables the launcher understands:

| Variable | Purpose |
| --- | --- |
| `CONNECT_MCP_CONFIG` | Path to the host inventory YAML |
| `CONNECT_MCP_PYTHON` | Interpreter to run the server with, bypassing uv/venv discovery |
| `CONNECT_MCP_SOURCE` | pip/uv spec to install instead of the published package |

## Troubleshooting

**`sh: connect-to-server-mcp: command not found` when the client starts the server.**
npm refuses to run `npx connect-to-server-mcp` from inside a checkout of this repository: it sees the
matching name in the local `package.json`, assumes the binary is already provided locally, and looks for a
`node_modules/.bin` link that a plain clone does not have. This only affects sessions whose working
directory is the repo itself. Install globally and register that instead:

```bash
npm install -g connect-to-server-mcp
npx connect-to-server-mcp install        # picks up the global binary automatically
```

`npx connect-to-server-mcp doctor` points this out when it detects the situation. The Claude Code plugin is not affected: its launcher always spawns npm from a neutral directory.

## Safety model

The policy layer is a guard rail against an agent wandering, **not** a security boundary. The real boundary is the remote account's own permissions: give each host a dedicated user with the narrowest sudo rules that let it do its job, and start every host in `read_only` until you have a reason to widen it.

## Development

```bash
pytest          # tests
ruff check .    # lint
mypy src        # types
```

## License

MIT

TDQS

A3.5/5.0

Scored across 12 tools

Disambiguation5/5

Every tool targets a distinct operation: host inventory, connection lifecycle, general shell commands, file reading/writing/listing/tailing, systemd status/control, and health snapshots. Although run_command is broad, each specialized tool has a clear role and boundary, so misselection is unlikely.

Naming Consistency3/5

Most tools use an imperative verb-noun pattern like list_hosts and read_file, but service_status, service_control, and system_overview use noun-noun forms, and disconnect is a bare verb. This mixed convention is still readable but not as predictable as a consistent pattern.

Tool Count5/5

With 12 tools, the server is well-scoped for its stated purpose: inventory, connections, shell, file operations, services, and system health all have dedicated coverage. This count is neither too thin nor overly heavy.

Completeness4/5

The tool set covers core remote-host workflows: list/reload hosts, connect/disconnect, run commands, read/write/list/tail files, manage systemd services, and get a system overview. Missing capabilities like file delete/move/upload or inventory editing are generally workaroundable with run_command or external config management, so the surface is nearly complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues