# MikroMCP v1.0.0 — Implementation Plan

## Context

v0.9 shipped 77 tools and fleet operations. v1.0 is the distribution and ecosystem milestone — it doesn't add router surfaces; it makes MikroMCP accessible and production-deployable. The five themes are:

1. A unified `mikromcp` CLI with `doctor` (diagnostics + setup wizard) and `init` (first-time onboarding)
2. Docker image published to Docker Hub + GHCR on every release tag
3. Standalone binaries for Linux/macOS/Windows via `pkg`, attached to GitHub Releases
4. Wiki onboarding guides for non-experts
5. Automated release CI that enforces the full artifact chain (binaries → Docker → GitHub Release → docs)

**Out of scope for v1.0:** Prometheus metrics, CHR integration test harness (deferred to v1.1).

---

## Current state

| Area | Status |
|---|---|
| CLI | None — `src/main.ts` is a pure MCP server, no argument parsing |
| Docker | None — no Dockerfile, no docker-compose |
| Release automation | None — versions bumped manually |
| Binary packaging | None |
| Onboarding docs | Partial — README Quick Start, no step-by-step wiki guides |
| CI | `ci.yml` (lint/typecheck/test/build), `claude.yml`, `claude-code-review.yml` |
| `package.json` bin | `mikrotik-mcp-server` → `dist/main.js` |

---

## Task breakdown

### Task 1 — CLI infrastructure refactor
**Goal:** Add `commander` + `@inquirer/prompts`, restructure the entry point into subcommands without breaking the current MCP server behavior.

**Files to create:**
- `src/cli/index.ts` — commander program; registers `serve`, `doctor`, `init` subcommands; default command is `serve`
- `src/cli/doctor.ts` — exported `runDoctor()` function (Task 2)
- `src/cli/init.ts` — exported `runInit()` function (Task 3)

**Files to modify:**
- `src/main.ts` — replace direct server bootstrap with `import { program } from "./cli/index.js"; program.parse()`; keep `serve` as default so `node dist/main.js` (no args) still works; auto-load `.env` at startup via `dotenv` (if file exists) so users don't need to `source` manually
- `package.json` — add deps: `commander`, `@inquirer/prompts`, `chalk`, `dotenv`; add devDep: `@yao-pkg/pkg`; add `mikromcp` bin pointing to `dist/main.js`; add `package:binaries` script
- `tsup.config.ts` — verify `banner: { js: "#!/usr/bin/env node" }` is present (already is per exploration)

**Backward compatibility:** `node dist/main.js` with no args must still launch the MCP server (commander default command). The `npm start` script is unchanged.

**Tests:**
- `test/unit/cli/cli-routing.test.ts` — verify `serve` is the default command, that `doctor` and `init` subcommands are registered

---

### Task 2 — `mikromcp doctor` command
**Goal:** Interactive health dashboard that checks every layer from config to router connectivity to Claude Desktop registration.

**File:** `src/cli/doctor.ts`

Checks (in order):
1. **Node.js version** — `process.version` ≥ 22; fail fast if not
2. **Config file** — `MIKROMCP_CONFIG_PATH` set; file exists; parses as valid YAML; passes RouterRegistry schema validation (reuse `RouterRegistry` from `src/config/router-registry.ts`)
3. **Env vars** — warn on missing `MIKROMCP_CONFIRMATION_SECRET` (HTTP transport), `ROUTER_<PREFIX>_USER/PASS` for each router; suggest writing a `.env` file if none found
4. **Router connectivity + permissions** — for each router: connect with credentials from env; fetch `system/resource` (REST), then probe each permission tier:
   - **REST API** — basic `GET system/resource` succeeds → ✅
   - **read policy** — `GET ip/address` returns results → ✅ (needed for most list tools)
   - **write policy** — attempt `GET ip/firewall/filter` header check → infer from error pattern
   - **SSH** — attempt TCP connect to port 22 (or configured SSH port) → ✅/⚠️ (needed for `ping`, `traceroute`, `torch`, `run_command`)
   - **FTP** — attempt TCP connect to port 21 → ✅/⚠️ (needed for `upload_file`)
   - **reboot/sensitive** — check identity role vs. tool categories that require `admin`/`superadmin`
   - Report: per-router table of ✅/⚠️/❌ per capability tier with a one-line explanation of which tools are affected by any gap
5. **Identities config** — if `MIKROMCP_IDENTITIES_PATH` set and file exists: validate schema; warn if no identity is configured for the current transport; note if all tokens are default/weak
6. **Claude Desktop detection** — check `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) and `~/.config/Claude/claude_desktop_config.json` (Linux/Windows WSL); report whether `mikrotik-mcp-server` is present; if absent, print the JSON snippet to add
7. **Update check** — fetch `https://registry.npmjs.org/mikromcp/latest` and compare `.version` to local `package.json`; warn if outdated with the upgrade command

Output format: colored rows (`✅ / ⚠️  / ❌`) via `chalk`, one line per check, followed by a summary section with fix suggestions for any failures.

**Tests:** `test/unit/cli/doctor.test.ts` — mock `RouterRegistry`, `RouterOSRestClient`, `fetch`, `fs` (for Claude Desktop config); verify each check produces the correct status

---

### Task 3 — `mikromcp init` wizard
**Goal:** Let a first-time user go from zero to a working `routers.yaml`, `identities.yaml`, `.env`, and registered Claude Desktop entry without touching any config file manually.

**File:** `src/cli/init.ts`

Wizard steps (using `@inquirer/prompts`):

**Router config:**
1. Router ID (the key in YAML, e.g. `core-01`)
2. Router host/IP
3. Port (default 80)
4. TLS: enabled (default **no** — simpler for first-time users; if enabled, ask rejectUnauthorized, warn if false)
5. Credential env prefix (e.g. `ROUTER_CORE01`)
6. Tags (comma-separated, optional)
7. RouterOS version (default `7`)

**Identity / token:**
8. Ask whether to create an identity for HTTP transport (skip for stdio)
9. If yes: identity ID (e.g. `admin`), role (`superadmin`/`admin`/`operator`/`readonly`), allowed routers (default `*`), allowed tool patterns (default `*`) — generate a secure random bearer token via `crypto.randomBytes(32).toString("hex")` and bcrypt-hash it for `identities.yaml`

**Env file:**
10. Ask whether to write env vars to `.env` (default yes); if yes, write `ROUTER_<PREFIX>_USER`, `ROUTER_<PREFIX>_PASS`, and optionally `MIKROMCP_CONFIRMATION_SECRET`, `MIKROMCP_TRANSPORT`; add `.env` to `.gitignore` if not already present; print a note to use `dotenv` or `source .env` before starting

**Config files:**
11. Write/append `config/routers.yaml`
12. Write/append `config/identities.yaml` (if identity was created)

**Claude Desktop:**
13. Offer to register with Claude Desktop — patch `claude_desktop_config.json` with the `mcpServers` entry; back up the file first

**Summary:**
14. Print final checklist: env vars set (or `.env` written), files created, `npm start` command, `mikromcp doctor` for verification

**Tests:** `test/unit/cli/init.test.ts` — mock `@inquirer/prompts`, `fs/promises`, `crypto`; verify YAML written correctly, `.env` written correctly, token generated and hashed, Claude Desktop JSON patched, backup created

---

### Task 4 — Dockerfile + docker-compose
**Goal:** Multi-stage image, runnable with a single `docker run` or `docker compose up`.

**Files to create:**

`Dockerfile`:
```
# Stage 1: builder
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: runtime
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
ENTRYPOINT ["node", "dist/main.js"]
```

`.dockerignore` — exclude `src/`, `test/`, `docs/`, `.git`, `node_modules`, `*.md`

`docker-compose.example.yml` — mounts `./config:/app/config:ro`; passes env vars via `.env`; uses `ghcr.io/alikarami/mikromcp:latest`

**Files to modify:**
- `README.md` — replace "Docker image is planned" placeholder with actual usage

---

### Task 5 — GitHub Releases + multi-arch binaries + Docker push
**Goal:** A single release workflow that builds everything and publishes it when a `v*.*.*` tag is pushed.

**File to create:** `.github/workflows/release.yml`

```yaml
on:
  push:
    tags: ['v*.*.*']

jobs:
  build-binaries:
    # matrix: linux-x64, linux-arm64, macos-x64, macos-arm64, win-x64
    # steps: npm ci → npm run build → npx @yao-pkg/pkg dist/main.js --target <target> --output mikromcp-<os>-<arch>
    # upload-artifact per binary

  docker:
    # docker/setup-buildx-action
    # docker/login-action for GHCR + Docker Hub
    # docker/build-push-action with platforms: linux/amd64,linux/arm64
    # tags: ghcr.io/AliKarami/mikromcp:latest + :version, docker.io/<DOCKERHUB_USER>/mikromcp:latest + :version

  release:
    needs: [build-binaries, docker]
    # gh release create ${{ github.ref_name }} with all binary artifacts
    # body: auto-generated from conventional commits since last tag
```

**Secrets to add in GitHub repo settings:**
- `DOCKERHUB_USERNAME`
- `DOCKERHUB_TOKEN`
- `GHCR_TOKEN` (or use `GITHUB_TOKEN` with `packages: write` permission — preferred)

**Files to modify:**
- `.github/workflows/ci.yml` — add `env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"` at the workflow level to silence the Node 20 deprecation warning

---

### Task 6 — Wiki onboarding guides
**Goal:** A first-time user with no MCP experience can follow one page from scratch to a working AI assistant + router.

**Files to create (all under `docs/wiki/`):**

`Getting-Started.md` — end-to-end "zero to working" guide:
1. Enable RouterOS REST API (System → Users → allowed address, `/ip/service enable api-ssl`)
2. Create a RouterOS API user with the right policies
3. Clone/install MikroMCP
4. Run `mikromcp init` (links to Task 3)
5. Verify with `mikromcp doctor`
6. Connect to your AI assistant (links to per-assistant pages)

`RouterOS-API-Setup.md` — detailed RouterOS side: enable api-ssl, TLS cert options (self-signed vs Let's Encrypt), required policies per tool category, firewall rules to allow the API from the MikroMCP host

`Connecting-to-Claude-Desktop.md` — screenshot-friendly guide: find `claude_desktop_config.json`, add the `mcpServers` entry, restart Claude, verify with `/list_interfaces`

`Connecting-to-AI-Assistants.md` — covers Claude Code (`claude mcp add`), Cursor (`.cursor/mcp.json`), Codex (`CODEX_MCP_SERVERS` env var), generic HTTP transport setup

---

### Task 7 — Release checklist automation + CLAUDE.md + CI fix
**Goal:** Future releases are impossible to forget artifacts.

**Files to modify:**

`CLAUDE.md` — add a **Release checklist** section after "Keeping documentation in sync":
```markdown
## Release checklist

Run before `git tag v<X.Y.Z> && git push origin v<X.Y.Z>`:

1. [ ] `npm version <major|minor|patch>` — bumps package.json + package-lock.json
2. [ ] Update version string in `src/mcp/server.ts`
3. [ ] Update README badge `version-v<X.Y.Z>`
4. [ ] Flip `🔜` → `✅` in ROADMAP.md and docs/wiki/Roadmap.md
5. [ ] Update Available-Tools wiki for any new/changed tools
6. [ ] Commit: `chore: bump version to X.Y.Z`
7. [ ] `git tag vX.Y.Z && git push origin main && git push origin vX.Y.Z`
8. [ ] CI release.yml auto-runs: builds binaries, pushes Docker, creates GitHub Release
```

`.env.example` — new file listing every supported env var with a one-line comment per var (all values blank); committed to repo, referenced from README and `mikromcp init` output

`.github/workflows/ci.yml` — add `env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"` at top-level workflow env

---

### Task 8 — Stability policy + security docs
**Goal:** Clear contracts for API consumers and operators.

**Files to create:**

`docs/stability-policy.md`:
- Tool name/input schema are stable from v1.0 — no breaking changes without a major version bump
- `structuredContent` fields: additive changes are non-breaking; removals require deprecation notice in one minor release first
- Internal implementation details (circuit breaker config, log format) are not covered

`docs/security.md`:
- Threat model (MCP client trust, RouterOS credential exposure, HTTP transport attack surface)
- Least-privilege RouterOS policy table (which tools need which policies)
- Recommended deployment (bind to 127.0.0.1, confirmation secret, TLS fingerprint pinning, RBAC)
- Responsible disclosure contact

---

## Task ordering and dependencies

```
Task 1 (CLI infra)
    ├── Task 2 (doctor)     ← depends on Task 1
    └── Task 3 (init)       ← depends on Task 1
Task 4 (Docker)             ← independent
Task 5 (release.yml)        ← depends on Task 4 (Docker build step)
Task 6 (wiki guides)        ← independent
Task 7 (CLAUDE.md/CI fix)   ← independent
Task 8 (stability/security) ← independent
```

Parallelizable groups:
- **Group A:** Tasks 1 → 2 → 3 (sequential)
- **Group B:** Tasks 4 → 5 (sequential)
- **Group C:** Tasks 6, 7, 8 (all parallel)

Groups A, B, C can run in parallel with each other after their own dependencies are met.

---

## Critical files

| File | Role |
|---|---|
| `src/main.ts` | Entry point — to be refactored to delegate to CLI |
| `src/cli/index.ts` | New — commander program |
| `src/cli/doctor.ts` | New — doctor command |
| `src/cli/init.ts` | New — init wizard |
| `src/config/router-registry.ts` | Reused in doctor for config validation |
| `src/adapter/rest-client.ts` | Reused in doctor for connectivity checks |
| `src/config/secrets.ts` | Reused in doctor for credential resolution |
| `src/config/identity-registry.ts` | Reused in init for identities.yaml schema |
| `package.json` | Deps, bin, scripts |
| `tsup.config.ts` | Build config |
| `Dockerfile` | New |
| `.dockerignore` | New |
| `docker-compose.example.yml` | New |
| `.github/workflows/release.yml` | New — release automation |
| `.github/workflows/ci.yml` | Modified — Node 24 env fix |
| `docs/wiki/Getting-Started.md` | New |
| `docs/wiki/RouterOS-API-Setup.md` | New |
| `docs/wiki/Connecting-to-Claude-Desktop.md` | New |
| `docs/wiki/Connecting-to-AI-Assistants.md` | New |
| `CLAUDE.md` | Release checklist section added |
| `docs/stability-policy.md` | New |
| `docs/security.md` | New |
| `.env.example` | New — template with all MIKROMCP_* and ROUTER_* vars documented |

---

## Verification

After all tasks complete:

1. `npm test && npm run typecheck && npm run lint` — all pass
2. `npm run build && node dist/main.js` — MCP server starts (backward compat)
3. `node dist/main.js doctor` — runs doctor, shows colored output
4. `node dist/main.js init` — runs wizard, generates routers.yaml
5. `docker build -t mikromcp:test . && docker run --rm mikromcp:test` — container starts
6. Push a `v1.0.0-rc.1` tag → release.yml triggers → GitHub Release created with binaries and Docker images
7. `mikromcp doctor` shows ✅ for all checks on a configured system
