Metadata-Version: 2.4
Name: mtk-router-sdk
Version: 0.1.4
Summary: MTK Router Automation Platform — Python SDK and CLI for MikroTik RouterOS (multi-slot VPN, discovery, bootstrap, optional mtk-serve HTTP API).
Author: MTK Router Automation Platform contributors
License-Expression: MIT
Project-URL: Homepage, https://pypi.org/project/mtk-router-sdk/
Project-URL: Changelog, https://pypi.org/project/mtk-router-sdk/#history
Keywords: mtk-router-automation,mikrotik,routeros,network,vpn,automation,router
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: paramiko<4,>=3.4
Requires-Dist: httpx<0.29,>=0.27
Requires-Dist: starlette>=0.37
Requires-Dist: uvicorn[standard]>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.3; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Provides-Extra: service
Requires-Dist: httpx<0.29,>=0.27; extra == "service"
Requires-Dist: starlette>=0.37; extra == "service"
Requires-Dist: uvicorn[standard]>=0.27; extra == "service"
Provides-Extra: lan-scan
Requires-Dist: scapy<3,>=2.5.3; extra == "lan-scan"
Dynamic: license-file

# MTK Router Automation Platform

Greenfield product for **MikroTik RouterOS**: multi-slot Wi‑Fi, per-slot VPN policy routing, discovery-driven configuration, optional AI **intent** API, and operator dashboard — delivered as a **Python library**, **HTTP service**, **TypeScript SDK**, and **CLI**.

**Normative specification:** [docs/ROUTER_SDK.md](docs/ROUTER_SDK.md) (API semantics, locks, bootstrap, security model).

## Documentation map

| Document | Audience |
|----------|----------|
| [docs/README.md](docs/README.md) | Index of all docs |
| [docs/CONFLUENCE_TEAM_PAGE.md](docs/CONFLUENCE_TEAM_PAGE.md) | **Full team page (Confluence-ready)**: problem statement, architecture, Python/JS guides, complete feature list, device support — share with anyone |
| [docs/QUICK_START.md](docs/QUICK_START.md) | **5-minute setup**: get running fast |
| [docs/EXAMPLES.md](docs/EXAMPLES.md) | **Copy-paste code**: Python, TypeScript, CLI |
| [docs/GLOSSARY.md](docs/GLOSSARY.md) | **Terms**: slots, routing marks, bootstrap, leases |
| [docs/CLI_REFERENCE.md](docs/CLI_REFERENCE.md) | **All CLI commands**: flags, options, examples |
| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | **Fix common issues**: connection, VPN, proxy |
| [docs/ROUTER_SDK.md](docs/ROUTER_SDK.md) | Full product & technical specification |
| [docs/USER_GUIDE.md](docs/USER_GUIDE.md) | Operators: install, configure, run |
| [docs/USE_CASES.md](docs/USE_CASES.md) | Scenario-first: doctor, bootstrap, HTTP, leases, intents, TS client |
| [docs/ADOPTION_GUIDE.md](docs/ADOPTION_GUIDE.md) | **Start here**: diagrams, Python + JS snippets, SSH vs HTTP, gaps |
| [docs/VPN_SETUP_AND_TEST.md](docs/VPN_SETUP_AND_TEST.md) | **Live VPN**: bootstrap, `vpn-debug`, `slot-vpn`, `scripts/verify_vpn_live.py` |
| [docs/PROXY_TESTING.md](docs/PROXY_TESTING.md) | **API proxy**: intercept/modify responses per-client IP, full HTTP logging, HTTPS certs |
| [docs/TESTING_SDK.md](docs/TESTING_SDK.md) | **Testing toolkit**: network simulation, DNS override, profiles, scenarios, **test dashboard**, pytest |
| [docs/PPV_TESTING_AND_MOCKING.md](docs/PPV_TESTING_AND_MOCKING.md) | **PPV / entitlement**: record-replay & proxy possibilities vs DRM and billing |
| [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md) | **`MTK_*` env vars** (SSH, HTTP service, secrets, bootstrap, strict parsing, dashboard **`env_ui`**) |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | System diagram & component boundaries |
| [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) | Contributors: repo layout, build, test |
| [docs/TESTING_GUIDE.md](docs/TESTING_GUIDE.md) | How to write and run tests (**`pytest -m smoke`** vs full **`pytest`**) |
| [docs/RELEASE_PROCESS.md](docs/RELEASE_PROCESS.md) | Versioning, tagging, release checklist |
| [docs/PUBLISHING_PYPI_AND_NPM.md](docs/PUBLISHING_PYPI_AND_NPM.md) | **PyPI + npm**: build, `twine` / `npm publish`, tokens, 2FA, errors |
| [docs/COMPLIANCE_AND_PRIVACY.md](docs/COMPLIANCE_AND_PRIVACY.md) | Logging, capture, AI, data handling |
| [docs/AI_LOCAL_ASSISTANT.md](docs/AI_LOCAL_ASSISTANT.md) | Local LLM (Ollama), guided first-time setup |
| [docs/API_REFERENCE.md](docs/API_REFERENCE.md) | OpenAPI, SDK doc entry points |
| [docs/FEATURE_LIST.md](docs/FEATURE_LIST.md) | Complete feature inventory, gaps, quality metrics |
| [docs/ROUTER_OPTIONAL_CAPABILITIES.md](docs/ROUTER_OPTIONAL_CAPABILITIES.md) | What works without a router (e.g. proxy), what does not, design vs “blocking” |
| [docs/ROADMAP_TESTER_FEATURES.md](docs/ROADMAP_TESTER_FEATURES.md) | **Future**: network simulation, chaos engineering, test scenarios |
| [docs/GOVERNANCE.md](docs/GOVERNANCE.md) | Maintainer / decision process |
| [docs/rfcs/](docs/rfcs/) | RFC process + templates (big design proposals) |
| [docs/adr/](docs/adr/) | ADR process + templates (record architecture choices) |
| [CONTRIBUTING.md](CONTRIBUTING.md) | How to contribute |
| [SECURITY.md](SECURITY.md) | Vulnerability reporting |
| [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | Community standards |
| [CHANGELOG.md](CHANGELOG.md) | Release history |
| [SUPPORT.md](SUPPORT.md) | How to get help |
| [LICENSE](LICENSE) | MIT |

## Status

- **Specification:** [docs/ROUTER_SDK.md](docs/ROUTER_SDK.md).
- **Python SDK (alpha):** SSH transport, discovery, JSON **site** config, **bootstrap engine** (plan + `--apply`), CLI below, **pytest** suite with fakes, optional **HTTP** service (`mtk-serve`), **TypeScript** HTTP client `clients/typescript/`, optional **Node.js** direct-SSH client `clients/node-ssh/` (no `baseUrl`).
- **HTTP / REST (alpha):** Spec-style **`/v1/*`** routes on **`mtk-serve`**: discovery, **dashboard snapshot**, wireless/VPN/DHCP/policy tables, **PUT `/v1/config/slots`**, **POST `/v1/bootstrap`** (+ dry-run), **slot leases** (`reject` or **`MTK_SLOT_LOCK_MODE=fifo_queue`**), **runtime VPN** (`POST /v1/slots/{id}/vpn` + `X-Slot-Lease`), **per-client block** (`POST /v1/client/block` — firewall DROP, runtime only), **`POST /v1/ai/intent`**, **`WS /v1/stream`**, **`GET /readyz`**, **`POST/DELETE /v1/session`** (SSH target override). Optional **`MTK_SERVICE_TOKEN`** enforces **`Authorization: Bearer`**. Static **dashboard** at **`/dashboard/`**.
- **Bootstrap + wifiwave2:** Discovery records **`wireless.menu_kind`** (`wireless` | `wifi`); bootstrap uses **`/interface wifi`** security + VAP menus when the profile reports **wifiwave2** (syntax may still need tuning per board — validate on hardware).
- **OpenAPI + CI:** **`GET /openapi.json`** merges core + v1 paths; GitHub Actions runs **Python 3.10–3.12** (ruff, mypy, pytest), **`clients/typescript`** **`npm run build`**, and **`clients/node-ssh`** **`npm ci`** smoke load.
- **Still to build / polish:** slot **DELETE** / **`PATCH /v1/config`**, human-in-the-loop approvals, richer DHCP/slot analytics, **sniffer IPv6** / HTTP download of **.pcap**. **CLI** **`mtk slot-vpn`** and **`mtk sniffer`** (IPv4 filter, capture file on router) work over **SSH** without **`mtk-serve`**. The npm HTTP client stays hand-written for ergonomics; **`openapi.d.ts`** is regenerated from **`openapi.json`**; CI checks drift.

### Install the SDK (editable)

Requires **Python 3.10 or newer** (use a single `python`/`python3` that meets that — do not run `python` with `3.10+` as if it were a script name).

```bash
python3 -m venv .venv && source .venv/bin/activate
python -m pip install -e ".[dev]"
# Optional: Scapy L2 ARP for vendor-agnostic LAN device lists (testing dashboard / `GET /v1/lan/host-peers`; often needs root on Linux): `pip install -e ".[dev,lan-scan]"` — see docs/ENVIRONMENT.md (`MTK_LAN_SCAPY*`).
export MTK_HOST=192.168.88.1 MTK_USER=admin MTK_PASSWORD='your-password'
mtk doctor
```

`mtk doctor` only applies to **MikroTik RouterOS** over SSH; if `MTK_HOST` points at another device, the CLI explains that instead of a generic failure.

### CLI commands

| Command | Purpose |
|--------|---------|
| `mtk init-site` | Interactive wizard → writes a site JSON (`-o file.json`) with `connection`, `vpn_registry`, and `slots` explained step by step |
| `mtk doctor` | Discovery + human summary + JSON snapshot |
| `mtk doctor --site FILE` | Same, but SSH target comes from the file’s optional `connection` block (see below). **Do not** paste shell comments on the same line in **zsh** unless `setopt INTERACTIVE_COMMENTS` is on, or `# …` is passed as extra arguments. |
| `mtk interfaces` | `/interface … print terse` as JSON |
| `mtk ip` | `/ip address … print terse` as JSON |
| `mtk l2tp` | `/interface l2tp-client … print terse` as JSON (secrets redacted; **`--show-secrets`** to print raw) |
| `mtk vpn-debug [tunnel]` | L2TP print + monitor + ping + log tail — **human** sections by default; **`--json`** for machine output |
| `mtk vpn-reset [tunnel]` | Disable then enable L2TP client (drop stuck IPsec/L2TP); **`--pause SEC`** between steps |
| `mtk exec '/path …'` | One arbitrary RouterOS command; JSON with exit + stdout/stderr |
| `mtk bootstrap site.json` | Dry-run: merged plan (no changes). Add **`--apply`** to run idempotent scripts on the router (destructive — test on lab gear first). |
| `mtk slot-vpn --site FILE SLOT_ID GATEWAY` | Set policy-route **gateway** for that slot’s **routing-mark** (SSH). Or **`--ssid SSID`** instead of **`SLOT_ID`** (SSID must match an **enabled** slot in the site file). |
| `mtk sniffer start --site FILE --slot N --ip IPv4` | Start **`/tool sniffer`** with **`filter-ip-address`**; **`.pcap`** on router. Or **`--ssid SSID`** instead of **`--slot`**. See **`mtk sniffer stop`** / **`status`**. |
| `mtk client-resolve --site FILE --ip ADDR` | Print JSON: map client IP → slot (subnets in site; SSH to router for DHCP **`dhcp_<id>`** unless **`--no-ssh`**). Pairs with HTTP **`GET /v1/client/resolve`** and **`POST /v1/by-client/...`**. |
| `mtk sniffer stop` / `mtk sniffer status` | Stop sniffer or print **`/tool sniffer print`** as JSON |
| `mtk client-block block IP` | Block internet for a client (firewall DROP, runtime only, no persistence) |
| `mtk client-block unblock IP` | Remove block for a client |
| `mtk client-block list` / `status IP` | List all blocked / check one IP |
| `mtk proxy set IP PATH JSON` | Set mock API response for endpoint (per-client, like Charles Proxy) |
| `mtk proxy error IP PATH --status 500` | Simulate error response |
| `mtk proxy log` | View proxied requests with full HTTP details |

**SSH settings:** You can put an optional top-level `connection` object in the site JSON (`host`, `username`, `password_ref` or `password`, `port`, `timeout`). Values may be literals or `env:VAR`. **If both exist, environment variables win** (`MTK_HOST`, `MTK_USER`, `MTK_PASSWORD`, `MTK_PORT`, `MTK_TIMEOUT`) so production can override a file safely. **Full env reference:** [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md).

**Router IP without `MTK_HOST`:** If you omit `MTK_HOST` and there is no `connection.host` in the site file, the SDK probes likely LAN routers (gateway, `192.168.88.1`, etc.) for SSH. Override with **`MTK_HOST`**, or set **`MTK_AUTO_SSH_PROBE=0`** to disable TCP probes, or **`MTK_SKIP_GATEWAY_DETECT=1`** to prefer `192.168.88.1` when not on that subnet.

**Bootstrap skips (optional):** `MTK_BOOTSTRAP_SKIP_SSH_SERVICE=1` skips merging slot subnets into **`/ip service ssh address`**; `MTK_BOOTSTRAP_SKIP_INPUT_SSH=1` skips the guest/slot **input** firewall rule for SSH. **`MTK_BOOTSTRAP_TIMEOUT`** sets per-step SSH timeout seconds (default `120`).

Example site file: [examples/site.example.json](examples/site.example.json). It is a **template only** (`REPLACE_WITH_*` placeholders, fake hostnames on purpose). Copy it to a local file (e.g. `my-site.json`, add to `.gitignore`), put your **real** VPN endpoints under `vpn_registry`, your SSIDs under `slots`, and keep passwords out of the file — use `env:MTK_WIFI_PSK`, `env:MTK_VPN_USER`, `env:MTK_VPN_PASSWORD` (or inline refs only on trusted machines). The `_meta` block is documentation for humans; the SDK ignores unknown top-level keys.

### HTTP service (optional)

After `pip install mtk-router-sdk` (PyPI) or `python -m pip install -e ".[dev]"` from the repo (for tests and lint tools):

```bash
export MTK_HOST=… MTK_USER=admin MTK_PASSWORD=…
# optional: export MTK_SITE_CONFIG=/path/to/site.json
# optional: export MTK_SERVICE_TOKEN=secret   # then send Authorization: Bearer …
mtk-serve   # default port 8765, override with MTK_HTTP_PORT
```

- `GET /` — JSON index (links to OpenAPI, dashboard, health, **readyz**, v1)  
- `GET /dashboard/` — minimal operator UI (snapshot, doctor)  
- `GET /openapi.json` — **OpenAPI 3.1** (core + **`/v1/*`**)  
- `GET /healthz` — liveness  
- `GET /readyz` — readiness (SSH discovery succeeds)  
- `GET /v1/version` — SDK version  
- `GET /v1/doctor` — discovery JSON (`503` if router error or missing env)  
- **`/v1/...`** — see OpenAPI or [ROUTER_SDK.md §6.2](docs/ROUTER_SDK.md) (leases, bootstrap, intents, WebSocket stream, …)

### TypeScript client

- **HTTP (browser / any `fetch`):** `clients/typescript/` — `MtkHttpClient` + `baseUrl` pointing at `mtk-serve` (`npm install && npm run build` there).
- **Node without HTTP:** `clients/node-ssh/` — `MtkSshClient` uses `MTK_*` env and SSH (`ssh2`); see `clients/node-ssh/README.md`.

### Legacy GUI

The old CustomTkinter prototype was renamed to [`legacy_mikrotik_commander.py`](legacy_mikrotik_commander.py) so **`pyproject.toml`** owns packaging. Run it only if you still need that UI: `python legacy_mikrotik_commander.py`.

## Quick orientation

- **Python** integrators: import `mtk_router_sdk` (`RouterClient`, `SshTransport`, parsers); CLI **`mtk`**.
- **JavaScript/TypeScript** integrators: npm **`@mtk-router/router-client`** (`MtkClient`) → HTTPS → service (not SSH in the browser).
- **Operators**: run **`mtk-router-service`** on a trusted LAN host; use dashboard or API with TLS + auth.

## License

See [LICENSE](LICENSE).
