Skip to content

Commit 3c2c694

Browse files
xTITUSMAXIMUSXxTITUSMAXIMUSX
andauthored
Feat/packaging (#2)
* Add packaging and deployment: Dockerfile, publish workflows, install docs - Dockerfile (stdio MCP server, non-root) + .dockerignore - docker-publish workflow to GHCR on version tags - PyPI trusted-publishing workflow on release - README: install (pipx/clone/Docker), env reference, and MCP client config (command- and Docker-based) Verified: image builds, runs vymcp as a stdio MCP server (initialize + tools/list handshake), and reaches VyManager over the network. * Trim README to the essentials --------- Co-authored-by: xTITUSMAXIMUSX <chevlle_hottrod_09@hotmail.com>
1 parent 8e0d417 commit 3c2c694

5 files changed

Lines changed: 119 additions & 108 deletions

File tree

.dockerignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.git/
2+
.github/
3+
.venv/
4+
venv/
5+
tests/
6+
dist/
7+
build/
8+
*.egg-info/
9+
__pycache__/
10+
*.py[cod]
11+
.pytest_cache/
12+
.mypy_cache/
13+
.ruff_cache/
14+
.env
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Publish Docker image
2+
3+
on:
4+
push:
5+
tags: ["v*.*.*"]
6+
workflow_dispatch:
7+
8+
jobs:
9+
docker:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
packages: write
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Log in to GHCR
18+
uses: docker/login-action@v3
19+
with:
20+
registry: ghcr.io
21+
username: ${{ github.actor }}
22+
password: ${{ secrets.GITHUB_TOKEN }}
23+
24+
- name: Image metadata
25+
id: meta
26+
uses: docker/metadata-action@v5
27+
with:
28+
images: ghcr.io/${{ github.repository }}
29+
tags: |
30+
type=semver,pattern={{version}}
31+
type=raw,value=latest
32+
33+
- name: Build and push
34+
uses: docker/build-push-action@v6
35+
with:
36+
context: .
37+
push: true
38+
tags: ${{ steps.meta.outputs.tags }}
39+
labels: ${{ steps.meta.outputs.labels }}

.github/workflows/publish-pypi.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Publish to PyPI
2+
3+
# One-time setup: create the project on PyPI and add this repo as a Trusted
4+
# Publisher (PyPI -> project -> Publishing), then no API token is needed.
5+
6+
on:
7+
release:
8+
types: [published]
9+
workflow_dispatch:
10+
11+
jobs:
12+
pypi:
13+
runs-on: ubuntu-latest
14+
environment: pypi
15+
permissions:
16+
id-token: write # OIDC for trusted publishing
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.12"
22+
- run: pip install build
23+
- run: python -m build
24+
- uses: pypa/gh-action-pypi-publish@release/v1

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# VyMCP speaks MCP over stdio, so run the container attached:
2+
# docker run -i --rm -e VYMANAGER_BASE_URL=... -e VYMANAGER_API_TOKEN=... vymcp
3+
FROM python:3.12-slim
4+
5+
WORKDIR /app
6+
7+
# Install the package (build deps are fetched in an isolated PEP 517 env).
8+
COPY pyproject.toml README.md LICENSE ./
9+
COPY src ./src
10+
RUN pip install --no-cache-dir .
11+
12+
# Run as a non-root user.
13+
RUN useradd --create-home --uid 1000 vymcp
14+
USER vymcp
15+
16+
# Configuration comes from the environment (see .env.example); never baked in.
17+
ENTRYPOINT ["vymcp"]

README.md

Lines changed: 25 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -2,107 +2,33 @@
22

33
[![CI](https://github.com/Community-VyProjects/VyMCP/actions/workflows/ci.yml/badge.svg)](https://github.com/Community-VyProjects/VyMCP/actions/workflows/ci.yml)
44

5-
> Model Context Protocol (MCP) server for VyOS routers, powered by [VyManager](https://github.com/Community-VyProjects/VyManager).
5+
> MCP server for VyOS routers, powered by [VyManager](https://github.com/Community-VyProjects/VyManager).
66
7-
VyMCP lets AI agents and MCP-aware tools (Claude, IDEs, automation) **read and manage VyOS routers** through a safe, audited interface. Rather than talking to routers directly, VyMCP wraps the VyManager API — so every action inherits VyManager's per-user authentication, role-based access control, audit logging, and version-aware (VyOS 1.4 / 1.5) configuration handling.
7+
VyMCP lets AI agents read and manage VyOS routers through the VyManager API — inheriting VyManager's authentication, RBAC, audit, and commit-confirm safety. It never talks to routers directly.
88

9-
> **Status: alpha.** Read tools cover every VyManager feature; guarded write tools cover ~86 features through a generic, discovery-driven proposer (plus curated firewall-group tools). The transport is stdio today (hosted HTTP/SSE is planned). Interfaces may still change.
9+
> **Status: alpha.** stdio transport; interfaces may change.
1010
11-
---
11+
## Install
1212

13-
## Why a server, not a direct integration
14-
15-
VyMCP deliberately **does not** connect to VyOS devices itself. It is a thin, stateless translation layer in front of VyManager's REST API. This keeps a single, enforced source of truth for everything that matters in an enterprise environment:
16-
17-
- **Per-user identity** — a VyMCP request acts as a real VyManager user, never a shared service account.
18-
- **RBAC** — a token can never exceed its owner's permissions.
19-
- **Audit** — every configuration change is attributed to the user, token, and instance.
20-
- **Commit-confirm safety** — writes ride VyManager's existing safety rails.
21-
- **Version awareness** — VyOS 1.4 vs 1.5 differences are handled by VyManager, not reimplemented here.
22-
23-
```
24-
MCP client (Claude / IDE / agent)
25-
│ MCP over HTTP+SSE (or stdio)
26-
27-
VyMCP ── stateless translation layer
28-
│ Authorization: Bearer vym_…
29-
│ X-VyOS-Instance-Id: <instance>
30-
31-
VyManager API ── RBAC · audit · commit-confirm · 1.4/1.5 mappers
32-
33-
34-
VyOS 1.4 / 1.5
13+
```bash
14+
pipx install git+https://github.com/Community-VyProjects/VyMCP # provides `vymcp`
3515
```
3616

37-
## Security model
38-
39-
VyMCP authenticates to VyManager with a **personal access token** that a user mints in the VyManager UI (Sites → API Tokens). Tokens are least-privilege by design:
40-
41-
- **Read-only scope** — a token can be restricted so it can never make configuration changes.
42-
- **Instance/site scoping** — a token can be limited to specific routers or sites (always within the user's own grants).
43-
- **Per-call targeting** — the target router is selected per request via the instance the token is allowed to reach.
44-
45-
This means you can hand VyMCP a token that, for example, can only *read* a single production router — and that limit is enforced by VyManager, not by VyMCP.
46-
47-
## Tools
48-
49-
**Read (always available):**
50-
51-
| Tool | Purpose |
52-
|---|---|
53-
| `list_instances` | The instances this token can reach (returns `instance_id`s for the other tools). |
54-
| `list_features` | Every VyOS feature VyMCP can read. |
55-
| `get_capabilities(feature, instance_id)` | Version-aware capability flags for a feature. |
56-
| `get_config(feature, instance_id)` | Normalized configuration for a feature. |
57-
58-
**Write (only when `VYMANAGER_ENABLE_WRITES=true`):** changes go through a mandatory
59-
**propose → apply** flow — a `propose_*` tool validates and returns a `plan_id` without
60-
touching anything, then `apply_change(plan_id, confirm=true)` executes that one reviewed
61-
plan. Plans are single-use, time-limited, and bound to their target instance.
62-
63-
| Tool | Purpose |
64-
|---|---|
65-
| `describe_feature_operations(feature)` | The operations available for a feature (op names, arg counts, descriptions, and any required top-level/subject fields). |
66-
| `propose_operations(feature, instance_id, operations, fields)` | Generic proposer — build a change for **~86 features** from the discovered vocabulary (no effect until applied). |
67-
| `propose_create_address_group` / `propose_add_address_group_members` / `propose_remove_address_group_members` / `propose_delete_address_group` | Curated firewall address-group proposers (nicer ergonomics for a common case). |
68-
| `apply_change(plan_id, confirm)` | Apply a proposed plan, protected by VyManager's commit-confirm when available. |
69-
| `confirm_change(instance_id)` | Keep a pending commit-confirm change (settles the device, stops the rollback). |
70-
| `discard_changes(instance_id)` | Drop unsaved changes — only when no commit-confirm is pending. |
71-
| `get_pending_changes(instance_id)` | Show the commit-confirm rollback window and any pending change. |
72-
73-
`propose_operations` covers every feature whose batch handler dispatches uniformly — the routing, firewall, NAT, service, VPN, system surface plus interface sub-types. A few features with bespoke handlers (`route`, bridge firewall, `ethernet`) are intentionally **not** exposed generically, because their custom per-op wiring can't be driven safely by introspection alone; manage those in the VyManager UI.
74-
75-
### Guardrails
17+
Or `pip install .` from a clone, or run the Docker image `ghcr.io/community-vyprojects/vymcp` (attached, with `-i`).
7618

77-
- **Read-only by default** — write tools are not even registered unless `VYMANAGER_ENABLE_WRITES=true`, on top of the token's own read-only scope (a read-only token is rejected by VyManager regardless).
78-
- **Vocabulary-bound, not arbitrary**`propose_operations` only accepts operations that exist in the feature's discovered vocabulary (validated against VyManager's own contract); there is no "set any path" tool.
79-
- **Propose → apply**`apply_change` requires `confirm=true` and a valid plan id, so the model can only apply a change a human has seen.
80-
- **Never auto-confirms** — applied changes ride VyManager's commit-confirm timer. That timer is a *lockout safety net*: if a change cuts off access to the router, the device auto-reverts (reboots) and you regain access. To keep a change, call `confirm_change`; to undo one that didn't lock you out, `confirm_change` then apply the inverse change.
19+
## Configure
8120

82-
## Requirements
21+
Set environment variables (see `.env.example`):
8322

84-
- A reachable [VyManager](https://github.com/Community-VyProjects/VyManager) instance.
85-
- A VyManager API token (Sites → API Tokens; read-only recommended to start).
86-
- One or more VyOS 1.4 / 1.5 routers registered in VyManager.
87-
- Python 3.10+.
23+
| Variable | Required | Purpose |
24+
|---|---|---|
25+
| `VYMANAGER_BASE_URL` | yes | VyManager API URL |
26+
| `VYMANAGER_API_TOKEN` | yes | A `vym_` token (Sites → API Tokens; read-only recommended) |
27+
| `VYMANAGER_ENABLE_WRITES` | no | Enable write tools (default off) |
8828

89-
## Getting started
29+
`VYMANAGER_VERIFY_SSL` (default `true`) and `VYMANAGER_TIMEOUT` (default `30`) are optional.
9030

91-
Install:
92-
93-
```bash
94-
pip install -e . # or: pip install -e ".[dev]" for tests
95-
```
96-
97-
Configure via environment variables (see `.env.example`):
98-
99-
```bash
100-
export VYMANAGER_BASE_URL="https://vymanager.example.com"
101-
export VYMANAGER_API_TOKEN="vym_…" # read-only recommended
102-
# export VYMANAGER_ENABLE_WRITES=true # opt in to write tools
103-
```
104-
105-
Register with an MCP client (stdio). Example client config:
31+
## Connect an MCP client
10632

10733
```json
10834
{
@@ -118,29 +44,20 @@ Register with an MCP client (stdio). Example client config:
11844
}
11945
```
12046

47+
## Tools
48+
49+
- **Read** (always): `list_instances`, `list_features`, `get_capabilities`, `get_config`.
50+
- **Write** (only when `VYMANAGER_ENABLE_WRITES=true`): `describe_feature_operations` + `propose_operations` cover ~86 features; `apply_change` / `confirm_change` / `discard_changes` / `get_pending_changes` drive the rollout.
51+
52+
Writes are safe by design: off by default, capped to the token's scope, and gated by a **propose → apply** flow. `apply_change` requires explicit confirmation and rides VyManager's commit-confirm auto-rollback (a lockout safety net) — it never auto-confirms.
53+
12154
## Development
12255

12356
```bash
12457
pip install -e ".[dev]"
125-
pytest # deterministic; no live device needed
126-
ruff check .
127-
mypy
58+
pytest && ruff check . && mypy
12859
```
12960

130-
## Roadmap
131-
132-
- [x] stdio server + token auth to VyManager
133-
- [x] Read tools across all features
134-
- [x] Guarded write tools (propose → apply → commit-confirm)
135-
- [x] Generic, discovery-driven writes across ~86 features
136-
- [ ] Cover the remaining bespoke-handler features (`route`, bridge firewall, `ethernet`)
137-
- [ ] Hosted remote transport (HTTP/SSE) with per-user auth
138-
- [ ] Packaging and deployment docs
139-
140-
## Related projects
141-
142-
- **[VyManager](https://github.com/Community-VyProjects/VyManager)** — the web UI and API that VyMCP builds on.
143-
14461
## License
14562

146-
See `LICENSE` for details.
63+
GPLv3 — see [`LICENSE`](LICENSE).

0 commit comments

Comments
 (0)