Servagent

An MCP server that enables a remote AI to take full control of a Linux server: command execution, file management, service administration, and more.

MCP Protocol Python 3.10+ MIT License OAuth 2.0

Remote Execution

Execute any shell command on the remote server with full output capture and timeout control.

📁

File Management

Read, write, edit, move, copy, and delete files. Binary transfer via base64.

Service Control

Start, stop, restart, and inspect systemd services directly through MCP.

🔒

Dual Auth

Bearer API key for simplicity, OAuth 2.0 for standard flows. Both coexist seamlessly.

🚀

Dual Transport

Streamable HTTP and legacy SSE. Compatible with Claude Code, Claude Desktop, LM Studio, and more.

🧰

Skills System

Extend the server's context with custom SKILL.md files for domain-specific knowledge.

Transports

TransportEndpointClients
Streamable HTTP/mcpClaude Code, LM Studio, Claude Desktop (via mcp-remote)
SSE (legacy)/sse + /messages/Older clients
File UploadPOST /uploadAny HTTP client (curl, scripts)

Installation

One-liner Install (Recommended)

Install directly on your server with a single command:

bash
# Simple HTTP installation (by IP)
curl -sSfL https://raw.githubusercontent.com/servagent/servagent/main/install-remote.sh | sudo bash

# HTTPS installation with Let's Encrypt
curl -sSfL https://raw.githubusercontent.com/servagent/servagent/main/install-remote.sh | sudo bash -s -- your-domain.com

# HTTPS + full sudo privileges
curl -sSfL https://raw.githubusercontent.com/servagent/servagent/main/install-remote.sh | sudo bash -s -- --full-access your-domain.com

# Specific version
curl -sSfL https://raw.githubusercontent.com/servagent/servagent/main/install-remote.sh | sudo bash -s -- --version v0.2.0

Install from Git Clone

bash
# Clone the repository
git clone https://github.com/Servagent/servagent.git
cd servagent

# Simple HTTP
sudo bash install.sh

# HTTPS with Let's Encrypt
sudo bash install.sh your-domain.com

# Full sudo privileges + HTTPS
sudo bash install.sh --full-access your-domain.com

The script automatically:

  • Creates a servagent system user
  • Installs in /opt/servagent with a virtualenv
  • Generates an API key (displayed once — save it!)
  • Creates and enables the systemd service
  • If a domain is provided: obtains a Let's Encrypt certificate with auto-renewal

Development Install

bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
cp .env.example .env
# Edit .env to set SERVAGENT_API_KEY
servagent

Prerequisites

  • Linux (Ubuntu/Debian, RHEL/CentOS, etc.)
  • Python ≥ 3.10
  • Root access for service installation

Quick Start

After installation, the server starts automatically:

  • Without domain: http://<server-ip>:8765/mcp
  • With domain: https://your-domain.com/mcp
bash
# Check status
servagent status

# View live logs
sudo journalctl -u servagent -f

# Test with curl
curl -X POST https://your-domain.com/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

CLI Commands

bash
servagent                      # Start the MCP server (default)
servagent run                  # Explicit start
servagent status               # Show service status & config
servagent --version             # Show version
servagent --help                # Show all subcommands

# API Key management
servagent apikey setup         # Generate API key
servagent apikey renew         # Regenerate (invalidates current)
servagent apikey remove        # Disable API key

# OAuth management
servagent oauth setup          # Generate OAuth credentials
servagent oauth renew          # Regenerate credentials
servagent oauth remove         # Disable OAuth

# Maintenance
servagent update               # Update to latest
servagent uninstall            # Uninstall

The servagent status command displays: systemd service state, PID, uptime, and configuration summary. API keys and OAuth secrets are masked (only the last 6 characters are shown).

MCP Tools

Servagent exposes 18 tools, each annotated with MCP ToolAnnotations (read-only, destructive, idempotent) to guide AI clients.

ToolDescription
execute_commandExecute any shell command (bash, python, etc.)
read_fileRead a text file
write_fileWrite content to a text file
edit_fileEdit a file (find & replace)
read_file_binaryRead a binary file (base64)
write_file_binaryWrite a binary file (base64)
upload_fileCopy a file on the remote server
list_directoryList directory contents
move_pathMove a file or directory
copy_pathCopy a file or directory
delete_pathDelete a file or directory
list_processesList running processes
kill_processKill a process by PID
tail_fileTail/follow log files or journalctl
system_infoSystem information
network_infoNetwork information
service_actionSystemd service management (start/stop/restart/status)
get_environmentEnvironment variables
💡 Tool Selection

By default, execute_command, read_file, write_file, and edit_file are exposed (to save context window tokens). Set SERVAGENT_TOOLS=all to expose all 6 tools.

Configuration

All options are configurable via environment variables (prefixed with SERVAGENT_) or in the .env file:

VariableDefaultDescription
SERVAGENT_HOST0.0.0.0Listen interface
SERVAGENT_PORT8765Listen port
SERVAGENT_API_KEYemptyAPI key (Bearer token). Required in production.
SERVAGENT_WORK_DIRcwdDefault working directory
SERVAGENT_COMMAND_TIMEOUT300Command timeout (seconds)
SERVAGENT_MAX_OUTPUT_SIZE1000000Maximum output size (bytes)
SERVAGENT_UPLOAD_MAX_SIZE100000000Max upload file size (100 MB)
SERVAGENT_TLS_CERTFILEemptyPath to TLS certificate
SERVAGENT_TLS_KEYFILEemptyPath to TLS private key
SERVAGENT_TOOLSexecute_command,read_file,write_file,edit_fileTools to expose (all for all 6)
SERVAGENT_LOG_LEVELINFOLog level
SERVAGENT_OAUTH_ISSUER_URLemptyOAuth issuer URL (include /mcp)
SERVAGENT_OAUTH_CLIENT_IDemptyOperator OAuth Client ID
SERVAGENT_OAUTH_CLIENT_SECRETemptyAssociated Client Secret
SERVAGENT_OAUTH_DB_PATH~/.servagent/oauth.dbOAuth SQLite database path

Skills

Skills allow you to enrich the context sent to the LLM with information specific to your server: hosted domains, SMTP credentials, available services, etc.

Each skill is a directory containing a SKILL.md file whose content is injected into the MCP instructions:

Structure
skills/
├── webserver/
│   └── SKILL.md
├── smtp/
│   └── SKILL.md
└── docker/
    └── SKILL.md

Example: webserver skill

skills/webserver/SKILL.md
# webserver
Domain: myserver.com (points to this server)
Web root: /var/www/myserver.com
Nginx config: /etc/nginx/sites-available/myserver.com
SSL: Let's Encrypt, auto-renew via certbot timer

Example: SMTP skill

skills/smtp/SKILL.md
# smtp
This server can send emails via SMTP.
- Host: smtp.gmail.com
- Port: 587
- User: bot@myserver.com
- Password: xxxx-xxxx-xxxx
- Use: `msmtp` or `swaks` CLI (already installed)
⚠️ Note

The skills/ directory content is git-ignored as it may contain sensitive, server-specific information.

Connecting MCP Clients

Claude Code
Claude Desktop
Other Clients
SSE (Legacy)

Claude Code natively supports remote MCP servers via Streamable HTTP:

.mcp.json
{
  "mcpServers": {
    "servagent": {
      "type": "streamable-http",
      "url": "https://your-domain.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Claude Desktop only supports local MCP servers via stdio. Use mcp-remote as a bridge:

claude_desktop_config.json
{
  "mcpServers": {
    "servagent": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://your-domain.com/mcp",
        "--header",
        "Authorization: Bearer YOUR_API_KEY"
      ]
    }
  }
}
💡 Info

mcp-remote creates a local stdio server that relays requests to the remote HTTP server. Requires Node.js.

Clients that natively support Streamable HTTP (LM Studio, etc.):

json
{
  "mcpServers": {
    "servagent": {
      "url": "https://your-domain.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

For older clients that only support SSE:

json
{
  "mcpServers": {
    "servagent": {
      "url": "https://your-domain.com/sse",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

File Upload

The POST /upload endpoint allows sending files to the remote server via multipart/form-data:

bash
curl -X POST https://your-domain.com/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@my-file.tar.gz" \
  -F "path=/opt/app/my-file.tar.gz" \
  -F "create_dirs=true"
FieldRequiredDescription
fileYesThe file to send
pathYesDestination path on the remote server
create_dirsNoCreate parent directories (default: true)

Authentication

Servagent supports two authentication mechanisms that coexist:

MechanismProtectsConfiguration
Bearer token (API_KEY)/mcp, /sse, /messages/, /uploadSERVAGENT_API_KEY
OAuth 2.0/mcp (access token), /mcp/register (Basic Auth)SERVAGENT_OAUTH_*

Authentication Matrix

EndpointBearer API_KEYOAuth access_tokenBasic CLIENT:SECRET
/.well-known/*public
/mcp
/mcp/registerrequired
/sse
/messages/
/upload

API Key Management

bash
servagent apikey setup         # Generate API key and write to .env
servagent apikey renew         # Regenerate (invalidates current)
servagent apikey remove        # Comment out API key in .env

OAuth 2.0

The server supports OAuth 2.0 for the /mcp endpoint, enabling compatible MCP applications to connect via the standard OAuth protocol (authorization code + PKCE).

Enabling OAuth

bash
# Auto-detects the issuer URL
servagent oauth setup

# Explicit issuer URL
servagent oauth setup --issuer-url https://your-domain.com/mcp

Connecting from Claude.ai

  1. Go to SettingsConnectorsAdd a custom connector
  2. Fill in: Name, Remote MCP server URL (https://your-domain.com/mcp), OAuth Client ID, OAuth Client Secret
  3. Confirm — Claude.ai automatically performs the OAuth flow

Connecting from ChatGPT

  1. Go to SettingsConnectorsAdd a custom connector
  2. Fill in: Name, MCP server URL, Client ID, Client Secret
  3. Confirm — ChatGPT performs the OAuth flow with its redirect URI

OAuth Endpoints

EndpointDescription
/.well-known/oauth-authorization-serverOAuth metadata (RFC 8414)
/.well-known/oauth-protected-resourceProtected resource metadata (RFC 9728)
/authorizeAuthorization endpoint
/tokenCode/refresh token exchange
/registerDynamic client registration (RFC 7591)
/revokeToken revocation (RFC 7009)

Dual Purpose of CLIENT_ID / CLIENT_SECRET

  1. Static OAuth client: Pre-registered at startup for Claude.ai, ChatGPT, and similar UIs that use credentials directly without calling /mcp/register.
  2. /mcp/register protection: HTTP Basic Auth for dynamic client registration by scripts and SDKs.

Managing OAuth

bash
servagent oauth renew              # Regenerate credentials
servagent oauth remove             # Disable OAuth
servagent oauth remove --keep-db   # Disable but keep database

HTTPS / TLS

TLS is built directly into the installation script. Pass the domain as an argument to enable HTTPS with Let's Encrypt:

bash
# During installation
sudo bash install.sh your-domain.com

# Or after installation
sudo bash setup-tls.sh your-domain.com
💡 Prerequisites

The domain must point to the server's IP and port 80 must be open for the Let's Encrypt HTTP-01 challenge.

Nginx Reverse Proxy (Alternative)

Useful when other web services run on the same server:

bash
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
sudo cp nginx.conf.example /etc/nginx/sites-available/servagent
sudo ln -s /etc/nginx/sites-available/servagent /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
💡 Tip

Behind a reverse proxy, set SERVAGENT_HOST=127.0.0.1 to automatically disable DNS-rebinding protection.

Security Notes

⚠️ Warning

This server gives full control over the host machine. Secure it properly.

  • Always set SERVAGENT_API_KEY in production
  • Always use TLS in production
  • Restrict port access via firewall (ufw, iptables)
  • The service runs under a dedicated user (servagent)
  • By default, the user has no sudo privileges (NoNewPrivileges=true)
  • The --full-access option grants sudo NOPASSWD: ALL

Update

bash
servagent update                # Update from current branch
servagent update develop        # Update from a specific branch
servagent update --force         # Force reinstallation

The script: pulls latest changes, copies sources, reinstalls the package, restarts the service, and verifies it’s running. If no changes are detected, it stops without restarting.

Uninstall

bash
servagent uninstall              # Interactive
servagent uninstall -y           # Non-interactive
servagent uninstall --keep-certs # Keep Let's Encrypt certificates

Removes: systemd service, certbot timer, Nginx config, sudoers file, /opt/servagent, system user, and Let's Encrypt certificates (unless --keep-certs).

Contributing

Contributions are welcome! Here is the recommended workflow:

  1. Fork the repository and create a branch: feat/new-tool, fix/auth-bug, docs/improve-readme
  2. Install in development mode: pip install -e .
  3. Make your changes, test locally
  4. Update documentation (README, CLAUDE.md) if needed
  5. Submit a pull request against main

Adding a New MCP Tool

  1. Define the tool function in tools.py with ToolAnnotations
  2. Add the tool name to ALL_TOOL_NAMES
  3. Register it in register_tools()
  4. Document it in README.md and .env.example

Commit Convention

Use imperative mood: Add tail_file tool, Fix Bearer token validation, Update README

Architecture

cli.py

CLI entry point (click). Subcommands: run, status, update, uninstall, apikey, oauth.

server.py

Starlette ASGI app. Dual transport (Streamable HTTP + SSE). Dynamic instructions builder.

tools.py

18 MCP tool definitions with ToolAnnotations. Conditional registration via register_tools().

config.py

Configuration via pydantic-settings. Lazy loading. SERVAGENT_* env vars.

auth.py

Authentication middleware. Bearer token + Basic Auth + OAuth pass-through. HMAC timing-safe.

oauth_provider.py

OAuth 2.0 server with SQLite. Static client pre-registration. Auto-approve model.

Project Structure

tree
servagent/
  src/servagent/
    __init__.py              # Version
    cli.py                   # CLI entry point (click)
    config.py                # Configuration (pydantic-settings)
    auth.py                  # Authentication middleware
    oauth_provider.py        # OAuth 2.0 provider + SQLite
    tools.py                 # All MCP tools
    server.py                # Server module + transports
  skills/                    # Skills directory (.gitignored)
  pyproject.toml             # Metadata and dependencies
  install.sh                 # Production installation
  install-remote.sh          # One-liner install (curl | bash)
  uninstall.sh               # Complete uninstallation
  setup-tls.sh               # HTTPS setup
  generate-oauth-credentials.sh
  nginx.conf.example         # Nginx config template
  .env.example               # Configuration template

Resources

MCP Protocol

modelcontextprotocol.io — Official documentation, guides, and specification.

Agent Skills

agentskills.io — Agent Skills documentation and specification.

GitHub Repository

github.com/servagent/servagent — Source code, issues, and releases.