Private connectivity
Tailscale Serve terminates tailnet-only HTTPS. Explicit grants admit the diagnostic identity to TCP 443. An excluded node is denied even while the allowed path is healthy. No Funnel is used.
An implemented engineering lab
A distributed engineering team needs help diagnosing its private Git service. The assistant needs useful evidence. It does not need administrative authority.
3fixed, read-only MCP tools
1Linux VPS · $12/month compute
0administrative tools in MCP
Humanseparate SSH authorization
01 / System design
The private service, the diagnostic interface and the recovery path have different jobs. This public page serves only reviewed static files.
Tailscale Serve terminates tailnet-only HTTPS. Explicit grants admit the diagnostic identity to TCP 443. An excluded node is denied even while the allowed path is healthy. No Funnel is used.
The Python MCP server exposes three tools with no arguments. Fixed health endpoints and a read-only snapshot replace arbitrary shell commands, paths and network targets.
A human identity has a separate Tailscale SSH rule in check mode for the existing root account. The AI node has no SSH grant. Root recovery retains administrative authority.
02 / Actual failure, actual diagnosis
OpenCode with an OpenAI model used genuine MCP responses from an isolated diagnostic client. The operator controlled the fault and recovery independently, with a recovery guard active.
The AI called the three diagnostic tools. Gitea and proxy health were both HTTP 200; state and log snapshots were fresh.
The separate operator stopped the Gitea container. Caddy and MCP remained running. A real proxy request returned HTTP 502.
The AI observed Gitea exited, proxy healthy, 502 / 200 health and sanitized upstream-error events. It identified the outage without claiming to know why Gitea stopped.
The authorized operator restored Gitea through Tailscale SSH. No MCP tool initiated recovery. The independent timeout guard did not need to fire.
The AI called MCP again: 200 / 200, running state and fresh snapshots. Separate anonymous application-API checks confirmed the same test repository ID and README blob.
“The new evidence indicates a Gitea outage while the proxy itself remains healthy.”
Nine actual MCP calls across baseline, outage and recovery. Repository persistence was checked by the operator, not by the three diagnostic tools. This proves continuity of the compared fixture, not integrity of every stored record.
03 / Authorization under test
These results came from distinct tailnet nodes and roles, with healthy allowed controls. A timeout by itself would not establish an authorization denial.
| Client / path | Expected | Observed |
|---|---|---|
| Diagnostic identity → private MCP / HTTPS | Allow | PASS Discovery and all three tools worked |
| Diagnostic identity → server SSH | Deny | PASS Connection denied by network policy |
| Excluded node → private MCP / HTTPS | Deny | PASS Denied alongside healthy allowed controls |
| Human operator → root / Tailscale SSH | Allow with check rule | PASS Actual recovery completed |
| Human operator → unapproved SSH user | Deny | PASS Explicit SSH policy rejection |
| Public network → private service ports | Deny | PASS M4 public probes blocked; no cloud inbound rules |
| MCP caller → shell / restart / file tools | Unavailable | PASS Unknown-tool responses; extra arguments rejected |
The public-port row describes M4 before public-site deployment. M5 adds only a separate static HTTPS listener; it requires fresh public/private regression checks before acceptance.
Every admitted MCP caller gets the same three read-only diagnostics. Human SSH authorization is a separate policy. The OpenCode agent also denies shell, file access, delegation and other tools; those settings alone are not operating-system isolation.
04 / Implementation & evidence
Real service behavior is more useful than a scripted answer. Narrow interfaces make the investigation inspectable and the limitations visible.
service_healthTwo fixed HTTP endpoints. No redirects or caller-supplied targets. App health is distinguished from proxy health.
recent_logsUp to ten sanitized log events. No raw messages, headers, tokens or repository contents are returned. Events remain untrusted data.
operational_stateContainer state, health and restart counts from a timestamped snapshot. Missing, malformed or stale data produces an explicit safe error.
Gitea 28.2.0 rootless, Caddy 2.11.7, Python 3.12.15, official MCP SDK 2.3.0, OpenCode 1.19.3 and Tailscale 1.104.2. MCP SDK client negotiated protocol 2026-07-28; the OpenCode connection's negotiated protocol was not separately recorded. Container images and Python dependencies are pinned.
Evidence is a reviewed, de-identified projection of the accepted M4 checkpoint. It includes actual timestamps and outcomes, rather than private node addresses, authentication artifacts or raw service logs.
Read the compact evidence recordThe customer outcome
The assistant explains what it observed, where the evidence stops, and when a human operator is needed.