the-bastion-mcp
by fihufil
README.md
# the-bastion-mcp
the-bastion-mcp is a Model Context Protocol (MCP) server. It lets an AI coding agent (for example
Claude Code or Kilo Code) do two things on remote servers:
- Run one-shot commands.
- Copy single files to a server and from a server.
All access goes through [The Bastion](https://github.com/ovh/the-bastion). The bastion
authenticates, authorizes and records each action.
The MCP server has no allowlists, no deny lists and no read-only mode. The bastion decides which
targets the agent can reach. The target hosts decide what the remote user can do.
## How it works
The project has two parts:
- **The MCP server.** It gives the tools to the agent. It has no Secure Shell (SSH) key.
- **Five backend commands.** They do all checks, write the audit log and use the bastion key.
There are two deployment modes:
| Mode | The backend commands run as | Use |
|------|-----------------------------|-----|
| Split mode | A second operating system (OS) user, through `sudo` | Production. The agent cannot read the bastion key |
| Single-user mode | The current user | Development and tests only |
## Tools
| Tool | What it does |
|------|--------------|
| `list_hosts` | Shows the targets that the bastion account can reach, and the file transfer protocol (`sftp`) of each target |
| `run_command` | Runs one command on one target. Returns the exit code, stdout, stderr, the status and the bastion session ID |
| `upload_file` | Copies one local file to a target, through the sftp support of the bastion |
| `download_file` | Copies one file from a target to a local file, through the sftp support of the bastion |
Each tool except `list_hosts` needs a `reason`. The backend writes the reason to the audit log.
## Requirements
- On the admin machine: Python 3.11 or later, and the OpenSSH `ssh` and `sftp` clients.
- A bastion account for the agent. the-bastion-mcp does not support accounts with
multi-factor authentication (MFA).
## What you configure
You configure two files.
### Backend config
Path: `~/.config/the-bastion-mcp/backend.toml` in the home directory of the user that runs the
backend commands. Template: [backend.example.toml](backend.example.toml).
| Setting | Value |
|---------|-------|
| `[bastion] host` | Hostname or IP address of the bastion |
| `[bastion] port` | SSH port of the bastion. Default: `22` |
| `[bastion] user` | The bastion account, for example `aiagent` |
| `[bastion] identity_file` | The key file of the bastion account. The key must have no passphrase. Mode `0600` |
| `[audit] file` | Path of the local audit log. Default: `~/.the-bastion-mcp/audit.jsonl` |
| `[transfer] transfer_dir` | Directory for the temporary files of the file transfers. Default: `~/.the-bastion-mcp/transfer` |
| `[audit] syslog_address` | Syslog socket. Default: `/dev/log` |
The other settings have default values. The template describes them.
### MCP config
Path: `~/.config/the-bastion-mcp/config.toml` of the user that runs the agent, or the path in
`THE_BASTION_MCP_CONFIG`. Template: [config.example.toml](config.example.toml).
| Setting | Value |
|---------|-------|
| `[backend] list_hosts`, `run_command`, `info`, `upload_file`, `download_file` | The command that runs each backend command, for example `["/opt/the-bastion-mcp/venv/bin/python3", "-I", "-m", "the_bastion_mcp.backend.run_command"]`. For split mode, put `"sudo", "-n", "-u", "user-ssh",` in front of each command |
All five commands are necessary. If one is missing or empty, the MCP server does not start.
## Quick start (single-user mode)
Use this procedure for development and tests only. For split mode, use
[docs/setup.md](docs/setup.md).
1. Install the package:
```bash
python3 -m venv venv
venv/bin/pip install -e .
```
2. Copy the templates:
```bash
install -d -m 0700 ~/.config/the-bastion-mcp ~/.the-bastion-mcp ~/.the-bastion-mcp/transfer
install -m 0600 backend.example.toml ~/.config/the-bastion-mcp/backend.toml
install -m 0600 config.example.toml ~/.config/the-bastion-mcp/config.toml
```
3. In `backend.toml`, set `[bastion] host`, `port`, `user` and `identity_file`.
4. For file transfer, the bastion account needs the `sftp` protocol access on the target. See
[docs/setup.md](docs/setup.md), section 1.
5. In `config.toml`, replace `/opt/the-bastion-mcp/venv/bin/python3` in the five `[backend]`
commands with the absolute path of `venv/bin/python3`.
6. Connect to the bastion one time, to add its host key to `~/.ssh/known_hosts`:
```bash
ssh -i <identity_file> -o IdentitiesOnly=yes <user>@<host> -- --osh info
```
7. Do a check of the setup:
```bash
venv/bin/the-bastion-mcp check --probe
```
8. Register `venv/bin/the-bastion-mcp serve` in your MCP client. See
[docs/setup.md](docs/setup.md), section 4.3.
## Build and install
To build the wheel and the source archive in `dist/`:
```bash
make dev # one time: creates venv/ and installs the development tools
make build
```
To install the wheel on the admin machine:
```bash
python3 -m venv /opt/the-bastion-mcp/venv
/opt/the-bastion-mcp/venv/bin/pip install -c constraints.txt dist/the_bastion_mcp-<version>-py3-none-any.whl
```
`constraints.txt` holds the exact dependency versions. Run `make lock` on the build machine to
write it. Install it together with the wheel. Keep it in the repository.
To remove the build artifacts and the caches, run `make clean`. To also remove `venv/`, run
`make distclean`.
## Development
Run `make help` to see all targets.
| Target | What it does |
|--------|--------------|
| `make dev` | Creates `venv/` and installs the package in editable mode with the development tools |
| `make test` | Runs the unit tests. They use a fake ssh. For the file transfer tests, they also use the local `sftp` and `sftp-server` programs |
| `make test-fast` | Runs the unit tests without the tests that wait for real timeouts |
| `make lint` | Checks the code style |
| `make format` | Corrects the code style |
| `make test-integration` | Runs the integration tests against a real bastion |
To prepare the integration tests:
1. Copy `tests/integration/integration.example.toml` to `tests/integration/integration.toml`.
2. Set your bastion and target in `integration.toml`. Git ignores this file.
3. Run `make test-integration`.
For all settings and for the split-mode tests, see
[docs/integration_tests.md](docs/integration_tests.md).
## License
The Apache License 2.0 applies to this project. See [LICENSE.txt](LICENSE.txt).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues