jms-cli
A personal CLI tool and Python library for accessing assets behind a JumpServer v4 bastion host: remote command execution, interactive terminal, parallel SFTP file transfer, and rsync/scp incremental sync via an SSH bridge.
Features
jms exec— run commands on assets (SSH or WebSocket backend, auto fallback)jms login— interactive PTY with keepalive (Ctrl+] to exit)jms sftp— parallel SFTP upload/download, chunked large files, cross-server relayjms ssh-pipe—-ebridge forrsync/scp- Multi-server config, MFA (TOTP) support, AES-256-GCM encrypted credentials
- Local MCP stdio server (
jms mcp) exposing config/asset/exec/SFTP as tools for AI assistants - Usable as a Python library (
from jms import JMSSession, connect, ...)
Install
pip install jms-cli # or: uv tool install jms-cli
Requires Python >= 3.10. For development from source:
git clone git@github.com:GCS-ZHN/jms-cli.git
cd jms-cli && uv sync
Quick start
jms config add prod # add a server (interactive, verifies credentials)
jms ls [-q keyword] # list/search assets
jms exec web@prod uname -a # run a command (asset[@server])
jms login web@prod # interactive terminal
jms sftp ./file.tar.gz web@prod:/tmp/ # direction auto-detected, -j N parallel
rsync -avz -e "jms ssh-pipe" ./dir/ web@prod:/data/
Config lives in the platform config dir (platformdirs, e.g.
~/Library/Application Support/jms/config.yaml on macOS, ~/.config/jms/ on
Linux), written with 0600 permissions. Credentials are stored encrypted.
Each command also accepts a hidden --config <path> option to point at a
different config file.
CLI operations
Target syntax is SSH-style: <asset>[@<server>]. Omit @<server> to use the
default server (the first one you added).
Server config
jms config add prod # interactive; verifies credentials before saving
jms config list # show servers; default marked with '*'
jms config set-default prod # change the default server
jms config remove prod # delete a server (-y to skip confirmation)
List / search assets
jms ls # all assets on the default server
jms ls @prod # all assets on server 'prod'
jms ls -q mysql # filter by keyword
Remote command execution
-b ssh|ws|auto selects the backend (auto = SSH first, WebSocket fallback).
The remote exit code is propagated to the local shell.
jms exec web@prod uname -a
jms exec web ls -la /var/log
jms exec web@prod 'echo hello world'
jms exec -b ws web whoami # force WebSocket backend
jms exec -t 60 web 'sleep 30' # longer timeout (default 30s)
Interactive terminal
jms login web@prod # Ctrl+] to exit
jms login web # default server
jms login -b ssh web # force SSH backend (native PTY)
File transfer (SFTP)
Direction is auto-detected from the arguments; -j N sets parallelism.
jms sftp ./data.tar.gz web@prod:/tmp/ # upload
jms sftp web@prod:/tmp/data.tar.gz ./ # download
jms sftp ./src/ web@prod:~/dst/ # directory tree
jms sftp -j 8 ./big/ web@prod:/data/ # 8 parallel workers
jms sftp --no-verify web@prod:/f ./ # skip md5 verification
jms sftp web@prod:/f other@prod:/g # cross-server relay (memory-streamed)
rsync / scp bridge
rsync -avz -e "jms ssh-pipe" ./dir/ web@prod:/data/
scp -o ProxyCommand="jms ssh-pipe %h" ./f web@prod:/data/
Known limitation: rsync downloads over the bridge may hang on files larger
than ~4KB (see DEVELOP.md §5). Use jms sftp for downloads; rsync uploads
work fine.
Library usage
from jms import JMSSession, ServerConfig, resolve_asset, connect, BackendType
server = ServerConfig(name="prod", host="jump.example.com",
username="alice", password="...", otp_secret="...")
sess = JMSSession(server)
sess.login()
asset = resolve_asset(sess, "web")
with connect(sess, asset, backend=BackendType.AUTO) as term:
print(term.execute("uname -a"))
MCP server (AI assistants)
jms mcp starts a local Model Context Protocol
stdio server exposing jms-cli as MCP tools for AI assistants / MCP clients.
Every tool opens a fresh authenticated session per call (stateless, no shared
state). No interactive PTY is used — all tools are headless operations.
Register it in your MCP client config, e.g. opencode (.opencode/opencode.json):
{
"mcp": {
"jumpserver": {
"type": "local",
"command": ["uv", "run", "jms", "mcp"]
}
}
}
Tools
| Tool | Description |
|---|---|
jms_config_list |
List configured servers (default marked with *) |
jms_ls |
List / keyword-search authorized assets |
jms_resolve_asset |
Resolve an asset to connection info (address/account/protocol) |
jms_exec |
Run a command on an asset, return output (timeout param) |
jms_sftp_upload |
Upload a local file to an asset via SFTP |
jms_sftp_download |
Download a file from an asset to the local machine |
jms_sftp_relay |
Relay a file between two assets (memory-streamed, no local disk) |
Each tool accepts an optional server alias (defaults to the configured
default) and an optional config_path. The server-wide default config path
falls back to the JMS_CONFIG env var, then the platform config dir.
Roadmap / TODO
- Admin operations (JumpServer management API): asset CRUD, user
management, permission/grant management — the REST layer (
jms/core/) is designed for these resource modules - GitHub Actions CI (pure unit tests always run; real-server tests
auto-skip without
JMS_TEST_*env vars) - PyPI + GitHub release on tag push
- Dependency audit (
pip-audit) in CI
Development
See DEVELOP.md (Chinese) for architecture, dev principles and testing rules.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jms_cli-0.2.0.tar.gz.
File metadata
- Download URL: jms_cli-0.2.0.tar.gz
- Upload date:
- Size: 193.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a5264e8a54368b82f489164aa95e9e74feeac38a1dbe26a7e8413f22364e053
|
|
| MD5 |
9ee581469bf9df96e3a92691e02b57b9
|
|
| BLAKE2b-256 |
0828ec6f98954cbcf3b32c652009d074ef1e2fe4da2f64dfc4d6d4338de0a148
|
File details
Details for the file jms_cli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: jms_cli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 74.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ca899f1c00a8b2f43216ab1a0170617c45bd017886062bacb498d8fa365405b
|
|
| MD5 |
08c8d155bad4ce6e8d147b35b7d72160
|
|
| BLAKE2b-256 |
2b39e7e529c97b47e1f35b1395172559d620f89985614fd424b1ab485fc00ec5
|