Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

netcup-scp

License: MIT Python 3.8+ Claude Skill

A friendly command-line tool and a Claude skill for the netcup Server Control Panel (SCP) REST API — manage your netcup root servers and vServers from the terminal or let Claude do it for you.

It ships two layers, both dependency-free (Python standard library only, no pip install):

  • netcup — a friendly CLI with memorable subcommands (netcup server start web-prod), server lookup by name or id, readable tables, confirmation prompts for destructive actions, and automatic task-following.
  • scp.py — the low-level client underneath it: OpenID Connect auth with automatic token refresh, async task polling, user-ID resolution, and a transparent pass-through to any endpoint in the API.

Unofficial. This project is not affiliated with, endorsed by, or supported by netcup GmbH. It talks to the public SCP REST API documented in the netcup community forum. Use at your own risk — several operations are destructive.


Features

  • Zero dependencies — pure Python standard library.
  • Friendly CLInetcup server list, netcup snapshot create, netcup rdns set, … with name resolution, colored tables, and safety prompts.
  • Automatic authentication — turns a stored offline refresh token into short-lived access tokens and caches them; you never juggle tokens per request.
  • Browser device-code login — one command (netcup auth login), works with 2FA.
  • Async task handling — most SCP write operations run in the background; the CLI follows the task to completion and reports the real outcome.
  • Escape hatch — anything the friendly CLI doesn't wrap is one netcup api … away (raw pass-through).
  • Doubles as a Claude skill — drop it into Claude and describe what you want in natural language.

Quick start

git clone https://github.com/fbnlrz/netcup-scp.git
cd netcup-scp
python3 scripts/netcup.py auth login      # one-time browser login

python3 scripts/netcup.py server list
python3 scripts/netcup.py server start web-prod

Install as a global command (ncscp)

Pick whichever fits — after this you can type ncscp from any terminal.

Option A — pip / pipx (Windows, macOS, Linux)

The cleanest route. Installs ncscp (plus netcup and the low-level ncscp-raw) onto your PATH.

pipx install .            # recommended: isolated, auto-adds to PATH
# or:
pip install --user .

On Windows, pip install puts ncscp.exe in your Python Scripts\ folder — available everywhere if Python was installed with "Add python.exe to PATH". If ncscp isn't found afterwards, either use pipx (which handles PATH for you) or add that Scripts\ folder to your PATH. Requires Python 3.8+.

ncscp server list
ncscp server start web-prod

Option B — no install, just a launcher

The repo ships thin launchers in bin/ that call the script in place — no packaging needed, only Python 3.8+.

Windows: add the repo's bin\ folder to your PATH (System Properties -> Environment Variables, or setx PATH "%PATH%;C:\path\to\netcup-scp\bin" in a new shell), then:

ncscp server list

bin\ncscp.cmd uses the py launcher; if you don't have it, edit the file to say python instead.

macOS / Linux: symlink the launcher into a PATH directory:

ln -s "$(pwd)/bin/ncscp" ~/.local/bin/ncscp
ncscp server list

Either way, ncscp is just the friendly CLI (scripts/netcup.py) under a shorter name — every command in this README works the same with ncscp in place of netcup.

Command overview

netcup auth      login | logout | whoami | token | status
netcup server    list [-s] | show <server> | start <server> | stop <server> [--acpi]
                 | restart <server> [--acpi] | suspend <server> | rename <server> [--nickname X] [--hostname Y]
                 | autostart <server> on|off | logs <server> [-n N] | rescue on|off|status <server>
netcup snapshot  list <server> | check <server> | create <server> <name> [--desc ..] [--offline]
                 | revert <server> <name> | delete <server> <name>
netcup rdns      get <ip> | set <ip> <hostname> | delete <ip>
netcup failover  list [--v6] | route <failover-ip> <server> [--v6]
netcup sshkey    list | add <name> <key-or-file> | delete <id|name>
netcup firewall  policies
netcup metrics   <server> cpu|disk|network [--hours N]
netcup task      list [--server X] [--state Y] | show <uuid> | cancel <uuid>
netcup api       <METHOD> <path> [--data JSON|@file] [-q k=v] [--wait]

<server> accepts a numeric id or a name/nickname/hostname (e.g. web-prod). Destructive commands (stop, restart, suspend, snapshot revert/delete, rdns delete, task cancel, …) ask for confirmation; pass -y/--yes to skip it, and --no-wait to fire-and-forget instead of following the task. Add --json to list/show commands for machine-readable output. Run netcup <group> --help for details.

Examples

# find and inspect
netcup server list
netcup server show web-prod

# power (states are ON / OFF / SUSPENDED; restart = stop then start)
netcup server start web-prod
netcup server stop web-prod --acpi          # graceful ACPI shutdown, asks the guest OS
netcup server restart db -y                 # skip confirmation

# snapshots
netcup snapshot check web-prod              # dry-run: is a snapshot possible?
netcup snapshot create web-prod pre-update --desc "before kernel bump"
netcup snapshot revert web-prod pre-update  # DESTRUCTIVE — prompts unless -y

# reverse DNS
netcup rdns set 203.0.113.5 host.example.com

# route a failover IP to another server (fence / move workflow)
netcup failover list
netcup failover route 198.51.100.7 db

# SSH keys
netcup sshkey add laptop ~/.ssh/id_ed25519.pub

Need something not wrapped by a subcommand? Drop to the raw API — same auth and task-following:

netcup api GET /api/v1/servers --query limit=5
netcup api PATCH /api/v1/servers/12345 --data '{"uefi":true}' --wait
netcup api PUT '/api/v1/servers/12345/interfaces/aa:bb:cc:dd:ee:ff/firewall' --data @firewall.json --wait

{userId} in any path is substituted automatically. See references/workflows.md for task recipes and references/endpoints.md for the complete endpoint catalog.

Use as a Claude skill

Download netcup-scp.skill from the Releases page and import it into Claude, or install from source by pointing Claude at this repository (the repo root is the skill — SKILL.md plus the scripts/ and references/ folders). Then just ask:

"Start my netcup server v2202… and take a snapshot first."

Claude reads SKILL.md, resolves the server, confirms the destructive step, and drives the client for you. (Claude uses the low-level scp.py directly for precision; netcup is the ergonomic layer for humans.)

Build the .skill bundle yourself at any time — it's just a zip of the repo contents under a top-level folder:

cd .. && zip -r netcup-scp.skill netcup-scp -x '*/__pycache__/*' '*.git*'

Authentication

The client needs a Bearer access token on every request. Access tokens live ~5 minutes and are refreshed automatically from a long-lived offline refresh token. Credentials are resolved in this order:

  1. netcup auth login (recommended) — OAuth 2.0 device-code flow. Prints a verification URL; approve it in your browser and grant SCP access. The offline refresh token is saved to ~/.config/netcup-scp/credentials.json (mode 0600). This is the only method that works cleanly when 2FA is enforced.
  2. NETCUP_SCP_REFRESH_TOKEN — an offline refresh token you already have.
  3. NETCUP_SCP_USER + NETCUP_SCP_PASSWORD — your customer number and password (Keycloak password grant). Works, but netcup discourages it and it will not work with 2FA. Prefer the options above.

An offline refresh token stays valid as long as it is used at least once every 30 days; after that, log in again.

netcup auth login      # obtain and store a refresh token (device-code flow)
netcup auth status     # show the active credential source and verify it
netcup auth whoami     # print your internal SCP user ID
netcup auth token      # print a valid access token (e.g. for manual curl)
netcup auth logout     # revoke the refresh token server-side and delete local credentials

Forgotten or leaked tokens can also be revoked in the netcup account console under Applications → scp → Remove access.


Configuration

Environment variable Default Purpose
NETCUP_SCP_REFRESH_TOKEN Use this offline refresh token instead of the file.
NETCUP_SCP_USER Customer number (password-grant fallback).
NETCUP_SCP_PASSWORD Password (password-grant fallback).
NETCUP_SCP_USER_ID (auto via userinfo) Skip internal user-ID resolution.
NETCUP_SCP_HOST https://www.servercontrolpanel.de Override the API host.
XDG_CONFIG_HOME ~/.config Where netcup-scp/ credentials are stored.
NO_COLOR (unset) Set to disable colored output.

Credential files (credentials.json, token_cache.json) live under ${XDG_CONFIG_HOME:-~/.config}/netcup-scp/ and are written with 0600 permissions.


Repository layout

netcup-scp/
├── SKILL.md               # Claude skill manifest (instructions + concepts)
├── scripts/
│   ├── netcup.py          # the friendly CLI (subcommands, tables, confirmations)
│   └── scp.py             # the low-level client / API pass-through (stdlib only)
├── bin/
│   ├── ncscp              # POSIX launcher (put bin/ on PATH -> `ncscp`)
│   └── ncscp.cmd          # Windows launcher
├── references/
│   ├── workflows.md       # task-oriented recipes
│   ├── endpoints.md       # complete endpoint catalog (generated from the OpenAPI spec)
│   └── schemas.md         # request-body fields and enums
├── pyproject.toml         # `pip install .` -> ncscp / netcup / ncscp-raw commands
├── README.md
├── LICENSE
└── .gitignore

Security

  • The offline refresh token is a long-lived credential. Keep ~/.config/netcup-scp/ private (files are 0600).
  • If a token may be exposed, run netcup auth logout (revokes it server-side) or remove access in the console.
  • The SCP options page lets you restrict API access to specific source IPs — recommended.
  • Never commit tokens. The bundled .gitignore excludes the credential file patterns as a safety net.

Support

If this project saved you some time, you can support its continued development:

Ko-fi Buy Me a Coffee

Every coffee is genuinely appreciated. ☕

Contributing

Issues and pull requests are welcome. The endpoint catalog and schema reference are generated from netcup's published OpenAPI specification (SCP release 2026.0624.115833 at the time of writing); regenerate them when netcup ships API changes.

License

MIT © fbnlrz

About

Dependency-free CLI and Claude skill for the netcup Server Control Panel (SCP) REST API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages