feat(mcp): add fj mcp service install/uninstall for systemd user unit #62

Merged
Claude-Run merged 1 commit from feat/FJCLI-48-mcp-service-systemd into main 2026-07-02 17:38:49 +02:00
Member

Add a Service subcommand to fj mcp that manages the MCP HTTP server as a per-user systemd unit (~/.config/systemd/user/fj-mcp.service), so a user can stand up (or tear down) an always-on Forgejo MCP endpoint with one command instead of hand-writing a unit and wiring env vars.

install resolves the host (global --host, then FORGEJO_HOST, then the built-in default), the bind address (--http-addr, default 127.0.0.1:8080), the write policy (--allow-edit/--allow-delete/--allow-global-write, baked into ExecStart), and the bearer token. When --http-token is omitted a 256-bit CSPRNG token is generated and printed once to stderr; supplied verbatim otherwise and never echoed. The token is written to ~/.config/fj/mcp.env (mode 0600, parent dir 0700) and pulled into the unit via EnvironmentFile=%h/.config/fj/mcp.env so the secret never lands in the world-readable unit file. ExecStart points at the absolute path of the running fj binary (current_exe). Without --no-start it runs daemon-reload then enable --now; --no-start writes the unit and reloads only.

uninstall disables+stops the unit (idempotent when absent), removes the unit file, and reloads the daemon; mcp.env is left in place unless --purge is passed. systemctl non-zero exits (outside the idempotent uninstall case) surface the captured stderr.

The systemd/unit logic lives entirely in the binary crate; fj-core and fj-mcp gain no systemd dependency, preserving the MCP-reuse contract. systemd user services are Linux-only, so install/uninstall return a clear error on other targets (the pure helpers stay platform-agnostic and unit-tested). README documents the commands, the token file location, and the loginctl enable-linger hint.

#FJCLI-48

Add a `Service` subcommand to `fj mcp` that manages the MCP HTTP server as a per-user systemd unit (`~/.config/systemd/user/fj-mcp.service`), so a user can stand up (or tear down) an always-on Forgejo MCP endpoint with one command instead of hand-writing a unit and wiring env vars. `install` resolves the host (global `--host`, then `FORGEJO_HOST`, then the built-in default), the bind address (`--http-addr`, default `127.0.0.1:8080`), the write policy (`--allow-edit`/`--allow-delete`/`--allow-global-write`, baked into `ExecStart`), and the bearer token. When `--http-token` is omitted a 256-bit CSPRNG token is generated and printed once to stderr; supplied verbatim otherwise and never echoed. The token is written to `~/.config/fj/mcp.env` (mode 0600, parent dir 0700) and pulled into the unit via `EnvironmentFile=%h/.config/fj/mcp.env` so the secret never lands in the world-readable unit file. `ExecStart` points at the absolute path of the running `fj` binary (`current_exe`). Without `--no-start` it runs `daemon-reload` then `enable --now`; `--no-start` writes the unit and reloads only. `uninstall` disables+stops the unit (idempotent when absent), removes the unit file, and reloads the daemon; `mcp.env` is left in place unless `--purge` is passed. `systemctl` non-zero exits (outside the idempotent uninstall case) surface the captured stderr. The systemd/unit logic lives entirely in the binary crate; `fj-core` and `fj-mcp` gain no systemd dependency, preserving the MCP-reuse contract. systemd user services are Linux-only, so `install`/`uninstall` return a clear error on other targets (the pure helpers stay platform-agnostic and unit-tested). README documents the commands, the token file location, and the `loginctl enable-linger` hint. #FJCLI-48
feat(mcp): add fj mcp service install/uninstall for systemd user unit
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 53s
Create release / Create release from merged PR (pull_request) Has been skipped
655e2acfcd
Add a `Service` subcommand to `fj mcp` that manages the MCP HTTP server as a per-user systemd unit (`~/.config/systemd/user/fj-mcp.service`), so a user can stand up (or tear down) an always-on Forgejo MCP endpoint with one command instead of hand-writing a unit and wiring env vars.

`install` resolves the host (global `--host`, then `FORGEJO_HOST`, then the built-in default), the bind address (`--http-addr`, default `127.0.0.1:8080`), the write policy (`--allow-edit`/`--allow-delete`/`--allow-global-write`, baked into `ExecStart`), and the bearer token. When `--http-token` is omitted a 256-bit CSPRNG token is generated and printed once to stderr; supplied verbatim otherwise and never echoed. The token is written to `~/.config/fj/mcp.env` (mode 0600, parent dir 0700) and pulled into the unit via `EnvironmentFile=%h/.config/fj/mcp.env` so the secret never lands in the world-readable unit file. `ExecStart` points at the absolute path of the running `fj` binary (`current_exe`). Without `--no-start` it runs `daemon-reload` then `enable --now`; `--no-start` writes the unit and reloads only.

`uninstall` disables+stops the unit (idempotent when absent), removes the unit file, and reloads the daemon; `mcp.env` is left in place unless `--purge` is passed. `systemctl` non-zero exits (outside the idempotent uninstall case) surface the captured stderr.

The systemd/unit logic lives entirely in the binary crate; `fj-core` and `fj-mcp` gain no systemd dependency, preserving the MCP-reuse contract. systemd user services are Linux-only, so `install`/`uninstall` return a clear error on other targets (the pure helpers stay platform-agnostic and unit-tested). README documents the commands, the token file location, and the `loginctl enable-linger` hint.

#FJCLI-48
Claude-Run deleted branch feat/FJCLI-48-mcp-service-systemd 2026-07-02 17:38:50 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pandoras-box/forgejo-cli!62
No description provided.