Skip to content

systemd Deployment

Scholar MCP provides .deb and .rpm packages with a pre-configured systemd service.

Installation

Download the latest package from the releases page:

sudo dpkg -i scholar-mcp_*.deb
sudo rpm -i scholar-mcp-*.rpm

The package installs:

Path Description
/usr/lib/systemd/system/scholar-mcp.service systemd unit file
/opt/scholar-mcp/venv/ Python virtual environment with the server
/etc/scholar-mcp/env.example Example configuration file
/var/lib/scholar-mcp/ State directory (cache, PDFs)

A dedicated scholar-mcp system user and group are created automatically.

Configuration

Copy the example config and edit it:

sudo cp /etc/scholar-mcp/env.example /etc/scholar-mcp/env
sudo chmod 600 /etc/scholar-mcp/env
sudo nano /etc/scholar-mcp/env

Set the cache directory and (optionally) your Semantic Scholar API key:

SCHOLAR_MCP_CACHE_DIR=/var/lib/scholar-mcp
# Optional but recommended — without a key, requests are limited to ~1 req/s
SCHOLAR_MCP_S2_API_KEY=your-key-here

See Configuration for all available variables.

Starting the service

# Start the service
sudo systemctl start scholar-mcp

# Enable start on boot
sudo systemctl enable scholar-mcp

# Check status
sudo systemctl status scholar-mcp

# View logs
sudo journalctl -u scholar-mcp -f

The service runs in HTTP mode on port 8000 by default.

Security hardening

The systemd unit includes comprehensive security directives:

Directive Effect
ProtectSystem=strict Filesystem is read-only except explicit paths
ProtectHome=yes Home directories are inaccessible
PrivateTmp=yes Private /tmp namespace
ReadWritePaths=/var/lib/scholar-mcp Only the state directory is writable
NoNewPrivileges=yes Cannot gain privileges
PrivateDevices=yes No access to physical devices
ProtectKernelTunables=yes Kernel tunables are read-only
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 Only Unix and IP sockets
SystemCallFilter=@system-service Restricted syscall set
MemoryDenyWriteExecute=no Required for Python JIT

Upgrading

Install the new package version:

sudo dpkg -i scholar-mcp_*.deb
sudo rpm -U scholar-mcp-*.rpm

The post-install script automatically:

  1. Creates or updates the virtual environment
  2. Installs the matching version from PyPI
  3. Reloads systemd
  4. Restarts the service if it was running

Your configuration in /etc/scholar-mcp/env is preserved.

Uninstalling

# Remove package (keeps config and data)
sudo apt remove scholar-mcp

# Remove everything including config
sudo apt purge scholar-mcp
sudo rpm -e scholar-mcp

State data in /var/lib/scholar-mcp/ is intentionally preserved on removal. Delete it manually if no longer needed.

Troubleshooting

Service fails to start

Check the logs:

sudo journalctl -u scholar-mcp --no-pager -n 50

Common causes:

  • Missing config: ensure /etc/scholar-mcp/env exists and is readable
  • Permission denied on cache dir: verify /var/lib/scholar-mcp/ is owned by scholar-mcp:scholar-mcp
  • Port in use: another service is using port 8000; check with ss -tlnp | grep 8000

FastMCP not installed

If the post-install script failed (e.g. no internet during package install):

sudo /opt/scholar-mcp/venv/bin/pip install 'pvliesdonk-scholar-mcp[mcp]'
sudo systemctl restart scholar-mcp