1. Generate a token
In your NightOwl dashboard, open the Tokens page from the platform top nav (alongside Account, Teams, Subscription). Give the token a label that will help you recognize it later (e.g. "Laptop — Claude Code") and copy the token immediately. NightOwl shows the plaintext token exactly once; after that only the label, creation date, and last-used time are visible.
Tokens are tied to your user account and inherit your team membership. Revoking a token from the same page invalidates it instantly for all clients that were using it.
2. Connect your client
The endpoint is app-scoped: /mcp/<app-id>. Each connection talks to exactly one NightOwl app. Copy the app ID from the Apps page in the dashboard.
Claude Code
claude mcp add --transport http nightowl \
https://your-nightowl-host/mcp/<app-id> \
--header "Authorization: Bearer <token>"Codex
[mcp_servers.nightowl]
url = "https://your-nightowl-host/mcp/<app-id>"
bearer_token_env_var = "NIGHTOWL_MCP_TOKEN"Codex — export the token
# Add to ~/.zshrc (or ~/.bashrc), then `source` it
export NIGHTOWL_MCP_TOKEN="<token>"Codex — CLI alternative (skip the TOML edit)
codex mcp add nightowl \
--url https://your-nightowl-host/mcp/<app-id> \
--bearer-token-env-var NIGHTOWL_MCP_TOKENCursor (native HTTP)
{
"mcpServers": {
"nightowl": {
"url": "https://your-nightowl-host/mcp/<app-id>",
"headers": {
"Authorization": "Bearer ${env:NIGHTOWL_MCP_TOKEN}"
}
}
}
}Windsurf, Zed, and other stdio-only clients (via mcp-remote)
{
"mcpServers": {
"nightowl": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-nightowl-host/mcp/<app-id>",
"--header",
"Authorization: Bearer <token>"
]
}
}
}
In Claude Code, run /mcp after adding the server to verify it connected. You should see the six tools listed. In Cursor, the tools appear in the AI panel under the NightOwl server entry after the JSON is saved.
3. Tool reference
Every tool operates on the app ID in the URL. AI clients never need to pass app_id as an argument.
| Tool | What it does |
|---|---|
| list_issues | Filter issues by type, status, environment, priority, assignee, or search term. Returns compact summaries. |
| get_issue | Full issue detail including latest exception, stack trace, recent occurrences, comments, and activity timeline. |
| get_stack_trace | Parsed stack frames flagged app vs vendor. Optional trace_id for a specific occurrence. |
| get_issue_occurrences | Time-bucketed counts over 24h / 7d / 30d, plus breakdown by environment and unique users affected. |
| update_issue_status | Change status (open / resolved / ignored), priority, or assignee. Fires configured alert webhooks. |
| add_issue_comment | Post a markdown comment. Pass resolve:true to auto-resolve the issue in the same call. |
4. Safety model
AI agents writing to production monitoring data deserves a careful threat model. NightOwl's guarantees:
- Scoped tokens. Tokens can only access apps where the owning user is a team member. The URL's app ID is checked against team membership on every call.
- Audit trail. Every mutating tool call writes an activity record with
actor_type=mcpandactor_metacarrying the token label and client user-agent. The dashboard timeline renders AI-authored actions distinctly. - Instant revoke. Deleting a token from the Tokens page blocks all in-flight and future calls using it.
- Webhook parity. Status changes made via MCP fire the same alert channels (Slack, Discord, webhook, email) that a human change would — your oncall still sees them.
- Ability-gated. Only tokens minted with the
mcpability can reach the server. Dashboard session cookies and other PATs cannot.
5. Example triage session
With the server connected, ask your AI assistant a question that spans your NightOwl data and your codebase:
> What are the top three open exceptions in production right now,
and is any of them caused by code I changed in the last week?
The assistant calls list_issues with {status: "open", environment: "production", limit: 3}, then get_issue for each hit, then runs git log locally to cross-reference authorship. Root cause in one turn.
When you've fixed one, the assistant can close the loop:
> Mark issue #4812 as resolved and leave a comment explaining
that the null check in OrderService was the fix.
One add_issue_comment call with resolve:true. The comment, the status change, and the resulting webhook all happen atomically — and show up in the issue timeline attributed to MCP rather than to you directly.