Troubleshooting:

Start with the local operator surfaces before changing config:
  tunnel-client health --url-file /tmp/tunnel-client-health.url
  curl -fsS http://127.0.0.1:8080/healthz
  curl -fsS http://127.0.0.1:8080/readyz
  open http://127.0.0.1:8080/ui

How to read the result:
  - /healthz is liveness only. "200 live" means the process is running.
  - /readyz includes startup gates for OAuth discovery and MCP probing.
  - The admin UI shows status, OAuth discovery state, channel routing, logs, and metrics.

Common startup errors:
  - "control plane API key is required": set CONTROL_PLANE_API_KEY, OPENAI_API_KEY,
    or --control-plane.api-key=env:.../file:...
  - "tunnel ID is required": set CONTROL_PLANE_TUNNEL_ID or --control-plane.tunnel-id=...
  - "invalid tunnel ID": use tunnel_ followed by 32 lowercase hexadecimal characters.
  - "MCP server URL is required": set MCP_SERVER_URL or --mcp.server-url=...

If /readyz is not 200:
  - "oauth discovery pending": startup is still fetching MCP OAuth metadata.
  - "oauth discovery failed": inspect the metadata URL and authorization server logs.
  - "mcp probe failed": verify the MCP target is reachable from the tunnel-client host.

If /readyz is 200 with a ready detail:
  - "mcp initialize requires auth": the MCP endpoint is reachable and expects auth.
  - "mcp startup probe timed out": startup continues, but the MCP target is slow.

Connector setup checks:
  - Keep tunnel-client run ... running while creating or testing the ChatGPT connector.
  - Confirm the connector selected the same tunnel id the daemon is using.
  - Check /readyz, not only /healthz.
  - MCP connector traffic is POST-based JSON-RPC; a GET 404 is not a useful stream test.

Useful diagnostics:
  tunnel-client health --url-file /tmp/tunnel-client-health.url
  tunnel-client health --port 8080
  tunnel-client doctor --profile <name> --explain
  tunnel-client doctor --profile <name> --json
  tunnel-client runtimes status <alias>
  tunnel-client help doctor

Export recent logs:
  curl -fsSJO "http://127.0.0.1:8080/api/logs/export?minutes=30"

The log archive is redacted and includes recent logs, a point-in-time metrics
snapshot, runtime status, system details, and OAuth discovery state.

Full reference:
  docs/troubleshooting.md
