Troubleshooting

Concrete fixes for the things people actually hit first. Each entry is what you see → why → what to do. If something here describes a capability that isn’t fully shipped, it says so and links to the honest build status.


Your agent connects to Nightjar but sees 0 tools

What you see. Your MCP client (Claude Code, Claude Desktop, a custom client) reports the nightjar server as connected, but no tools are available — the agent can’t call session_start, navigate, and the rest, so it can’t drive a browser.

Why. The MCP handshake completed at the HTTP level but the initialize call returned a JSON-RPC error, which most clients surface as “connected, 0 tools” rather than a hard failure. There are two common causes:

  1. Authentication. The hosted endpoint validates your API key at initialize. A missing, mistyped, revoked, or expired njk_ key in the server’s Authorization: Bearer … config is rejected as unauthorized.
  2. Protocol version. The server negotiates the mainstream MCP protocol versions (2024-11-05, 2025-03-26, 2025-06-18). A client that negotiates a different version is rejected as an unsupported protocol version.

How to tell which. Run your client with MCP debugging — for Claude Code, claude --mcp-debug — and look at the initialize response for the nightjar server:

  • an unauthorized / auth error → it’s the key (cause 1);
  • an unsupported protocol version error → it’s the version (cause 2).

Fix.

  • Key: confirm the Authorization: Bearer njk_… value in your MCP server config is a current, un-revoked key. If in doubt, mint a fresh one and update the config:
    nightjar-control issue-key …      # mint a new njk_ key
    Then restart/reconnect the MCP server so it re-runs initialize with the new key.
  • Version: use a current MCP client release (current Claude Code negotiates 2025-06-18, which is supported). After any change, fully reconnect the server so the client re-fetches the tool list.

“host is not in the network reachability allowlist”

What you see. Your agent navigates to http://127.0.0.1:…, a Docker hostname, or a LAN address, and instead of your service the page body reads:

Nightjar: host is not in the network reachability allowlist

Why. By default a cloud session reaches public sites only — your localhost and LAN are not reachable until you say so. The allowlist is read once, at session launch, so a session that was already running when you changed the setting keeps its old list.

Fix (today — manual until the one-command path lands). Either declare the host on your network, or enable org-wide intranet mode, then start a fresh session:

PATCH /v1/networks/{networkId}
{ "declaredHosts": ["127.0.0.1"] }     # a bare host/IP allows any port; "127.0.0.1:5173" = that port
PUT /v1/governance
{ "intranetMode": true }               # reaches undeclared loopback/LAN; needs the org:admin scope

Then open a new session (the allowlist and intranet flag are resolved at launch). See the local reach guide for the full walk-through — note the smooth one-command path there is a Target (planned), and these manual steps are the path that works today.


Credential fill is refused (origin-denied or field-denied)

What you see. A credential_fill call fails with an origin-denied or editable-field error rather than filling the value.

Why. Credential fill is deliberately gated, and both gates are enforced before any keystroke:

  • Origin — the credential is filled only on an origin in the intersection of the credential’s own origin-allowlist and the grant’s allowed origins. A live origin outside that set is denied.
  • Editable field — the target element must be an editable input; a non-editable target is denied.

Fix. Confirm the live page origin is on the credential’s origin-allowlist and on the grant you’re using, and that your selector targets an editable field. The secret value is never returned to the agent and never appears in the journal — only a value-free record that a fill occurred — so a missing fill shows up as a denial, not a leaked value.


“Identity is in use” / a second session can’t assume the same identity

What you see. A session that assumes an identity starts fine, but a second session assuming the same identity is refused.

Why. Assuming an identity acquires an exclusive single-writer lease — one live session per identity at a time — so two sessions can’t drive the same logged-in persona simultaneously.

Fix. End the first session (or wait for its lease to release), then start the second. For parallel work, use different identities, or run anonymous sessions where no identity is needed.


Still stuck?

Check the build status first — if a capability is marked Target, it isn’t shipped yet, so the issue may be expected. For a suspected security issue, email security@nightjar.cloud; to report abuse, abuse@nightjar.cloud.