Content
# jumpserver-ssh-mcp
`jumpserver-ssh-mcp` is a MCP Server that allows Agents to securely execute remote commands through direct SSH or JumpServer entry points.
The product direction is **MCP only**:
- `gateway` represents a JumpServer/environment entry point.
- The entry point matching plugin is responsible for adapting to different JumpServer interactive interfaces.
- After reaching the target machine shell, the existing SSH execution, security inspection, auditing, and output collection mechanisms are reused.
- No new CLI product workflow is added; the CLI retained in the warehouse is only used for compatibility and local smoke check.
## Current Status
This project was originally a `ssh-assist-mcp` prototype, which already has:
- `ssh.run_command`
- `ssh.run_script`
- `ssh.rsync_upload`
- `ssh.rsync_download`
- `ssh.file_push`
- `ssh.file_pull`
- Basic security policies and audit logs
- Basic JumpServer interactive gateway execution
Now, the JumpServer entry layer is being productized:
- Matcher plugin contract and registry
- Built-in generic JumpServer matcher
- User-written declarative matcher
- Multiple JumpServer/environment gateways free switching
- MCP resources expose matcher writing documentation, examples, schema, and troubleshooting instructions
- README and `docs/install/*` provide Codex, Kimi CLI, and opencode installation entry points
## Installation Entry Points
The installation documentation is a regular warehouse file, so **MCP can be viewed before installation**:
- [Install MCP on any Agent](docs/install/agent.md)
- [Codex installation and configuration](docs/install/codex.md)
- [Kimi CLI installation and configuration](docs/install/kimi-cli.md)
- [opencode installation and configuration](docs/install/opencode.md)
Recommended order:
1. First, follow [Install MCP on any Agent](docs/install/agent.md) to connect `jumpserver-ssh-mcp` to the Agent client.
2. Then, have the Agent install or read `skills/jumpserver-agent-skill`.
3. The Agent creates a profile, configures the gateway, probe, and smoke test according to the skill, and writes a matcher if necessary.
After MCP installation is complete, the Agent can read runtime documents through MCP resources, such as matcher writing guides, examples, schema, and troubleshooting.
## Quick Initialization
When installing from the source code, first clone the project to a stable directory:
```bash
git clone <repo-url> jumpserver_ssh_mcp
cd jumpserver_ssh_mcp
```
Create a virtual environment and install the MCP server:
```bash
uv venv
uv pip install -e '.[mcp]'
```
Confirm that the startup command exists:
```bash
.venv/bin/jumpserver-ssh-mcp
```
Prepare the local profile. Run-time files are uniformly placed in the user directory to avoid overwriting the local configuration when updating the source code warehouse:
```bash
mkdir -p ~/jumpserver-ssh-mcp/{config,logs,matchers}
cp config/example.yaml ~/jumpserver-ssh-mcp/config/local.yaml
```
Configuration file description:
- `config/example.yaml`: Recommended starting example, only contains the minimum fields that humans need to maintain.
- `config/full-example.yaml`: Complete reference example, for Agent or advanced users to view all optional fields.
- `~/jumpserver-ssh-mcp/config/local.yaml`: Local real configuration, not placed in the source code warehouse.
Then, modify `~/jumpserver-ssh-mcp/config/local.yaml` to a real JumpServer:
```yaml
gateways:
pro-jumpserver:
command: ssh -i ~/.ssh/pro.pem ops@jump.example.com -p2222
matcher: builtin-generic
```
Configure in any MCP-supported Agent client:
```text
server name: jumpserver-ssh-mcp
command: /path/to/jumpserver_ssh_mcp/.venv/bin/jumpserver-ssh-mcp
env.SSH_ASSIST_PROFILE: /Users/you/jumpserver-ssh-mcp/config/local.yaml
env.SSH_ASSIST_AUDIT_LOG: /Users/you/jumpserver-ssh-mcp/logs/jumpserver-ssh-mcp-audit.jsonl
```
After configuration, restart or reload the Agent client, and then verify:
```text
ssh.matcher_list
```
If you can see the gateway in the profile, it means MCP initialization is complete.
## Upgrade from v0.1.0
From `0.2.1`, it is recommended to put the runtime files in `~/jumpserver-ssh-mcp/`. If the old version has explicitly configured `SSH_ASSIST_PROFILE` in the MCP client, it will continue to use this path preferentially after upgrading.
If the old configuration is still in the source code warehouse, you can migrate a copy:
```bash
mkdir -p ~/jumpserver-ssh-mcp/{config,logs,matchers}
cp config/local.yaml ~/jumpserver-ssh-mcp/config/local.yaml
```
For compatibility with old installations, if there is no explicit `SSH_ASSIST_PROFILE`, it will search in order:
1. `~/jumpserver-ssh-mcp/config/local.yaml`
2. `config/local.yaml`
3. `config/example.yaml`
## Gateway is an Environment Entry Point
When calling MCP tools, use `gateway` to select which JumpServer/environment to enter:
```text
gateway=prod-jumpserver -> Production JumpServer/environment
gateway=test-jumpserver -> Test JumpServer/environment
gateway=ops-jumpserver -> Operation and maintenance JumpServer/environment
```
It is recommended that operation and maintenance class calls explicitly pass `gateway`, so that audit logs can clearly record which environment entry point the Agent entered.
## Agent Session Ownership and Residual Cleaning
When executing commands through the JumpServer gateway, the Agent can pass `owner_id` to the SSH tool, such as `codex-thread-<id>`.
`owner_id` is used to register this gateway SSH subprocess in the local running directory:
```text
~/jumpserver-ssh-mcp/run/sessions/<owner_id>/
```
The next time the same `owner_id` starts the gateway SSH, MCP will clean up the residual child processes that have exceeded the grace time under the same owner. Records of different owners will not be cleaned up, so they will not be mistakenly killed by other Agents or manually opened SSH.
Recommendations:
- Each Agent thread or task uses a stable and unique `owner_id`.
- Do not reuse the `owner_id` of other Agents.
- When the process ends normally, times out, or receives `SIGINT`, `SIGTERM`, or process exit, MCP will also clean up the gateway child process it has registered.
- `kill -9` or system crash cannot trigger process internal cleaning; the next call with the same owner will try to clean up the residual.
## Where to Put Matcher Plugins
Built-in generic matchers and reference matchers will be distributed with the Python package and are available by default after installation:
- `builtin-generic`
- `ttyuyin-opt-account`
- `qmzy-asset-list-id`
User-written matchers are recommended to be placed in the user's running directory:
- User running directory: `~/jumpserver-ssh-mcp/matchers/`
Then, configure in the profile:
```yaml
matchers:
custom_dirs:
- ~/jumpserver-ssh-mcp/matchers
```
Each gateway can bind its own matcher:
```yaml
default_gateway: jumpserver-test
gateways:
jumpserver-test:
command: ssh -i ~/.ssh/jumpserver-test.pem ops@jump-test.example.com -p2222
matcher: builtin-generic
```
## What Matcher Can Do
Matcher is only responsible for matching the JumpServer login entry point and cannot execute target machine commands.
It can return these actions:
- Send the target host/IP
- Select the target from the host candidate list
- Select the account from the account table
- Report that the shell has been reached
- Report that the match failed and return desensitized transcript fragments to the Agent to repair the plugin
Remote commands are still uniformly executed by `ssh.run_command`/`ssh.run_script`. File transfer prioritizes using `ssh.file_push`/`ssh.file_pull`; `ssh.rsync_upload`/`ssh.rsync_download` is only suitable for direct SSH + rsync scenarios.
## MCP Tools
Existing SSH tools:
- `ssh.run_command`
- `ssh.run_script`
- `ssh.rsync_upload`
- `ssh.rsync_download`
- `ssh.file_push`
- `ssh.file_pull`
File transfer:
- `ssh.file_push`: Single file upload, supports direct SSH and JumpServer gateway, does not depend on remote rsync, default upper limit 50MB.
- `ssh.file_pull`: Single file download, supports direct SSH and JumpServer gateway, does not depend on remote rsync, default upper limit 50MB.
- `ssh.rsync_upload`/`ssh.rsync_download`: Reserved for direct SSH large file or directory synchronization; interactive JumpServer gateway does not support rsync protocol flow.
Matcher tools:
- `ssh.matcher_list`
- `ssh.matcher_validate`
- `ssh.matcher_probe`
- `ssh.matcher_test_transcript`
`ssh.matcher_probe` only verifies whether the matcher can reach the target shell through the JumpServer without executing target machine commands.
## Security and Audit
Remote commands will be evaluated by `SafetyPolicy`.
High-risk operations must be explicitly confirmed. The audit log base path defaults to `~/jumpserver-ssh-mcp/logs/jumpserver-ssh-mcp-audit.jsonl`, and can also be specified through `SSH_ASSIST_AUDIT_LOG`; actual writing will be rolled over to `~/jumpserver-ssh-mcp/logs/jumpserver-ssh-mcp-audit-YYYY-MM-DD.jsonl` according to UTC date.
Do not write private key content, plaintext password, token into the profile, matcher, documentation, or audit log.
## Development Verification
Run unit tests:
```bash
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -p 'test_*.py'
```
Run MCP server:
```bash
SSH_ASSIST_PROFILE=config/example.yaml .venv/bin/jumpserver-ssh-mcp
```
The old prototype entry `ssh-assist-mcp` is temporarily retained as a compatible alias.
Build wheel:
```bash
uv build --wheel
```