Skip to main content
Glama
README.md
# server-mcp

English | [Español](README.es.md)

> **Renamed from `servidor-mcp`.** If you installed the old plugin, remove it and install the
> new one: `claude plugin uninstall servidor-mcp@servidor-mcp`,
> `claude plugin marketplace remove servidor-mcp`, then follow [Install](#1-install).
> Your servers, sessions and `~/.srv-mcp/config.toml` keep working as they are.

MCP server that lets AIs (Claude Code, Claude Desktop, Cursor, VS Code…) work on your
Linux servers over SSH, **without giving them your password** and without installing
anything on the server.

```
You:  srv-mcp on dev             → type your password → SSH session open (8h)
AI:   run_command(...)           → uses that open session, no password
You:  srv-mcp off dev            → the AI loses access immediately
```

## Tools the AI gets

| Tool            | What it does                                                         |
|-----------------|----------------------------------------------------------------------|
| `list_servers`  | Registered servers and whether their session is open                 |
| `system_status` | Load, memory, disk, top processes, failed services, Docker           |
| `view_logs`     | journalctl for a service, `docker logs`, a file or the system; with a filter |
| `read_file`     | First or last N lines of a file                                      |
| `write_file`    | Creates/replaces a file, with an automatic `.bak.<date>` backup      |
| `run_command`   | Any (non-interactive) shell command                                  |

Every call shows up in your AI client with the exact command, and is recorded in the
audit log `~/.srv-mcp/logs/<server>.log` (`srv-mcp log <server>`).

## Before you start (done by the server admin)

1. **Create a separate SSH user** for each person on each server (don't share users:
   that way the audit log and permissions belong to each person, and one can be revoked
   without affecting the others).
2. Optional, so they can read service logs (`journalctl`), on each server:
   `sudo usermod -aG systemd-journal <user>`

## Step-by-step guide (each person, on their Mac or Linux)

Requirements: Python 3.11+, OpenSSH and git. The commands work from any folder.

### 1. Install

**Option A: Claude Code plugin (recommended).** Inside Claude Code:

```
/plugin install server-mcp --marketplace Daniel-Riv/server-mcp
```

On versions before 2.1.275, in two steps:
`/plugin marketplace add Daniel-Riv/server-mcp` and then
`/plugin install server-mcp@server-mcp`.

Or from the terminal (also works if you use the desktop app):

```bash
claude plugin marketplace add Daniel-Riv/server-mcp
```
```bash
claude plugin install server-mcp@server-mcp
```

Open a **new session**: on start, the plugin sets up Python by itself (a few seconds the
first time). To have the `srv-mcp` command in your terminal, create the shortcut once:

```bash
mkdir -p ~/bin && ln -sf ~/.claude/plugins/data/server-mcp-server-mcp/srv-mcp ~/bin/srv-mcp
```

(if `~/bin` is not in your PATH: `echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc`).
The command in Claude is `/server-mcp:access-server`. Update it with
`/plugin update server-mcp`.

**Option B: clone the repo** (no plugins, or to use the MCP with other AIs):

```bash
git clone https://github.com/Daniel-Riv/server-mcp.git ~/server-mcp && ~/server-mcp/install.sh
```

The installer creates `.venv` with the dependencies, puts the `srv-mcp` command in `~/bin`
(and adds it to PATH) and installs the skill as `/access-server`.

Don't use both options at once (you'd get the skill twice). **Open a new terminal**
when it finishes. Check with `srv-mcp`: it should print the help.

### 2. Register each server

```bash
srv-mcp setup
```

It asks these questions (type the answer and press Enter):

| Question | What to answer |
|---|---|
| Short name | An alias without spaces, e.g. `main`, `dev`, `prod` |
| IP or domain | The server's address |
| SSH user | **Your** user on that server |
| SSH port | Enter if it is 22 |
| Do you reach it through another server? | Enter if you connect directly from your machine. If you first have to log into another server, type that server's alias (it must be registered first) |
| Read-only? | `y` so the AI can't make changes (recommended for production), `n` if it can |

Example with a main server and two internal machines (dev and prod) reached through it:

```
Your Mac ──▶ main (public IP) ──▶ dev  (internal IP)
                              └──▶ prod (internal IP)
```

| Server | IP | Through another? | Read-only? |
|---|---|---|---|
| `main` | public IP | Enter (direct) | `n` |
| `dev` | internal IP | `main` | `n` |
| `prod` | internal IP | `main` | `y` |

Register the main one first, then the others. Check with `srv-mcp list`.

### 3. Open the session

```bash
srv-mcp on dev
```

- The first time it asks `Are you sure you want to continue connecting (yes/no)?` → `yes`.
- It asks for your password. **Nothing shows while you type it**, that's normal; Enter at the end.
- If the server goes through another one, it first asks for that one's password (if it wasn't open).
- The session lasts 8 hours. `srv-mcp status` shows which ones are open (●).

Check that it works **without asking for a password**:

```bash
srv-mcp run dev "hostname && uptime"
```

### 4. Use it with Claude Code

In a **new** Claude session:

```
/server-mcp:access-server check the status of dev
```

(With option B the command is `/access-server`.) Claude only touches servers when you
type that command. It shows you each command before running it and asks before any
change. When you are done:

```bash
srv-mcp log dev     # what the AI ran
srv-mcp off dev     # cut access
```

### Update

Plugin: `/plugin update server-mcp`. Option B:

```bash
cd ~/server-mcp && git pull && ./install.sh
```

## Where can you connect from?

`srv-mcp` reaches any server **your machine can reach over SSH**: if `ssh user@ip` works
from your computer, `srv-mcp` works too. Nothing is installed on the server.

| Server situation | What you need | What to enter in `srv-mcp setup` |
|---|---|---|
| Public IP (VPS, cloud, server with its own IP) | Nothing else | The public IP; "through another": Enter |
| Private IP, but there is a server with a public IP on that network | Register that entry server first | The private IP; "through another": the entry server's alias |
| Private IP, no entry server | A VPN into that network (company VPN, WireGuard, Tailscale) | With the VPN connected, the private or VPN IP; "through another": Enter |
| Same network (office, same Wi-Fi) | Nothing else | The private IP; "through another": Enter |

If it doesn't connect, check: the firewall or cloud "security group" allows the SSH port
from your IP; the port (if not 22); and that your user exists and can log in.

**Servers on Tailscale:** install Tailscale on your computer, join the same tailnet (or
have the owner share the server with you), and find the server's address with
`tailscale status` (`100.x.y.z` or its MagicDNS name). Use that address in `srv-mcp setup`
with "through another": Enter. Tailscale must be connected while you use it. If the
server uses Tailscale SSH, `srv-mcp on` won't ask for a password.

## sudo

`sudo` with a password doesn't work through the AI (it's not interactive, and the AI never
sees your password). Two options:

1. **You run it yourself (safest).** The AI gives you the command and you run it in your
   terminal with `ssh -t`, which reuses the open session; only `sudo` asks for your password:
   ```bash
   ssh -t dev "sudo systemctl restart nginx"
   ```
2. **`NOPASSWD` for specific commands**, configured by the admin on the server
   (`sudo visudo -f /etc/sudoers.d/<user>`):
   ```
   <user> ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/docker ps
   ```
   Don't add editors or pagers (`vim`, `less`), interpreters (`bash`, `python`), commands
   that copy or write files (`cp`, `tee`) or broad wildcards (`systemctl *`): they allow
   getting a root shell or overwriting any file.

## Common problems

| Symptom | Cause and fix |
|---|---|
| `command not found: srv-mcp` | The terminal was opened before installing. Open a new one (or use `~/bin/srv-mcp`). |
| `Permission denied (publickey,password)` | The session isn't open or expired: `srv-mcp on <server>`. |
| `Could not resolve hostname <name>` | That alias doesn't exist; check `srv-mcp list` (use the exact name you registered). |
| `srv-mcp setup` "hangs" | It is waiting for your answer: type it in the terminal and press Enter. |
| `journalctl` shows `-- No entries --` | Your user is not in the `systemd-journal` group (see "Before you start"). |
| The AI says "is in 'read-only' mode" | That server is read-only; change it in `~/.srv-mcp/config.toml`. |
| The command doesn't show up in Claude | Open a new session. Plugin: check it is enabled in `/plugin`. Option B: run `./install.sh` again. |
| `Can't find the server-mcp Python environment` | Plugin: open a new session so it sets itself up (needs Python 3.11+). Option B: run `./install.sh`. |
| `sudo` fails | See [sudo](#sudo). |

## Other AIs (Claude Desktop, Cursor…): MCP server

The skill uses `srv-mcp run/health/logs/read/write`, with the same rules and audit log as
the MCP server. If you'd rather Claude Code use it without `/`, install with
`./install.sh --mcp`.

For other clients, the server command is the absolute path to `.venv/bin/server-mcp`.

In the client's MCP config file:
```json
{
  "mcpServers": {
    "server-mcp": { "command": "/path/to/server-mcp/.venv/bin/server-mcp" }
  }
}
```
- Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Cursor: `~/.cursor/mcp.json`

## Command reference

```bash
srv-mcp setup             # register a server
srv-mcp list              # registered servers
srv-mcp on <server>       # open session (asks for password)
srv-mcp status            # which sessions are open
srv-mcp log <server>      # what the AIs ran
srv-mcp off <server>      # close session
srv-mcp run <server> "command"   # run by hand with the same rules
```

To remove a server, delete its block (`# srv-mcp: <alias>` … `# srv-mcp: end <alias>`)
from `~/.ssh/config` and its section in `~/.srv-mcp/config.toml`, if any.

## Permissions (`~/.srv-mcp/config.toml`)

Everything is allowed by default. Each user changes it in their own file
(see [config.example.toml](config.example.toml)):

```toml
mode = "read-only"                     # "full" (default) or "read-only"
blocked = ['\breboot\b', 'rm -rf']     # regexes that are always rejected
timeout = 120                          # seconds per command

[servers."prod"]                       # per-server settings (setup creates it if you choose read-only)
mode = "read-only"
blocked = ['virsh destroy']
```

Changes apply on the next call; nothing needs restarting. Config files from versions
≤ 0.2 (in Spanish: `modo = "lectura"`, `[servidores."prod"]`, `bloqueados`) still work.

"read-only" mode rejects commands that look like they modify the server (rm, mv,
`systemctl restart`, `apt install`, `docker stop/rm/down`, `>` redirects…). It is a
safety net against AI mistakes, **not a security boundary**. The real boundary is the SSH
user: for truly restricted access, create a user without sudo on the server and register
it with `srv-mcp setup`.

## Security

- Only you type the password, in your terminal; a local socket stays in `~/.ssh/cm/`
  that only your user on the Mac can use.
- Only servers registered with `srv-mcp setup` are accepted.
- While the session is open, the AI can do anything your SSH user can do. Close it with
  `srv-mcp off` when you're done.
- `sudo` with a password doesn't work (not interactive). See [sudo](#sudo).

## Development

```bash
.venv/bin/pip install -e ".[dev]" && .venv/bin/pytest
```
The tests use a fake ssh (`tests/fake_ssh`) that runs commands locally.

TDQS

A3.7/5.0

Scored across 6 tools

Disambiguation4/5

Each tool targets a distinct operation (listing servers, running commands, health summary, logs, file read, file write) and the boundaries are explained in the descriptions. There is some functional overlap, since ejecutar_comando could technically do log tailing or file reads, but the specialized tools exist as safer/easier conveniences and are clearly named.

Naming Consistency4/5

Names follow a Spanish verb_noun pattern consistently (listar_servidores, ejecutar_comando, ver_logs, leer_archivo, escribir_archivo), with snake_case throughout. The one deviation is estado_sistema, which is a noun phrase rather than verb_noun, but it remains readable and predictable.

Tool Count5/5

Six tools is a well-scoped set for remote server administration: connectivity, command execution, health overview, logs, and file read/write. No tool feels redundant or gratuitous.

Completeness4/5

The core lifecycle for operating a remote server is covered: discover servers, run commands, inspect health and logs, read and write files. The main gap is the lack of a directory-listing or file-transfer operation, so agents must guess paths or fall back to ejecutar_comando with ls/cat, which is a workable but indirect path.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues