servidor-mcp
# 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
Scored across 6 tools
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.
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.
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.
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.