Connect an agent
For agents: you are probably already connected. Call
whoami()— it returns how you are authenticated, the organization slug(s) you can reach, and your scopes. Thenlist_projects(org="…"). If a call fails withtoken lacks …, ask a human for a token with that scope; you cannot mint one yourself.
The endpoint
POST https://api.bugwatch.io/mcp
Authorization: Bearer bwt_…
content-type: application/json
- Transport: Streamable HTTP, stateless — one POST per JSON-RPC 2.0 message (batches are accepted). There is no SSE stream;
GETandDELETE /mcpanswer405. - Protocol version
2025-06-18. Notifications (messages without anid) get202and no body. - Authentication is the same API token as the REST API. A session cookie from the dashboard also works, which is how the dashboard's own agent panel calls it.
- The server declares
tools,resources, andpromptscapabilities and returns shortinstructionsoninitialize.
Create the token in Settings → API tokens with one of the presets described in Tokens & scopes. Read-only is enough for exploration and get_fix_context.
Client configuration
Claude Code (.mcp.json in the repo, or ~/.claude.json):
{
"mcpServers": {
"bugwatch": {
"type": "http",
"url": "https://api.bugwatch.io/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Cursor (.cursor/mcp.json):
{
"mcpServers": {
"bugwatch": {
"url": "https://api.bugwatch.io/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Claude Desktop (stdio only, so bridge with mcp-remote):
{
"mcpServers": {
"bugwatch": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://api.bugwatch.io/mcp", "--header", "Authorization: Bearer <token>"]
}
}
}
curl (any language, no client library):
curl -sS https://api.bugwatch.io/mcp -H 'Authorization: Bearer <token>' -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'
The dashboard's Settings → Agents page renders these with your real token placeholder filled in, and every issue, release, and rule page has a "Copy MCP call" action that emits the exact tools/call body.
Signing in instead of pasting a token
A client that supports OAuth — most MCP clients do — needs no token at all. Point it at the MCP endpoint and it will open a browser, ask you to sign in, show you what it is requesting, and get its own credential.
Nothing to configure. The client discovers everything from the server:
| It asks for | It learns |
|---|---|
GET /.well-known/oauth-protected-resource |
Which authorization server to use |
GET /.well-known/oauth-authorization-server |
Where to register, authorize and get a token |
POST /oauth/register |
Its own client_id — no pre-registration, no support ticket |
Then it sends you to a consent screen naming the client and the exact permissions, you choose which organization it may act in, and it receives an access token.
What you are approving
The client acts as you, in one organization. It can never do more than you can: the permissions are narrowed three times — to what the client asked for, to what it registered for, and to what your role actually holds. A viewer approving a client that asked to write alert rules grants a read-only token, and the token says so.
org:admin is never granted over OAuth. It implies every other permission, and registration is open to any client, so it is not something to hand out by consent. An agent that needs it uses a token a human made deliberately.
Your role is re-checked when the token is issued, not just when you approve. If you are removed from the organization between the two, no token is issued; if you are demoted, the token carries the narrower set.
Revoking it
An OAuth-issued token is an ordinary API token — it appears in Settings → Tokens under the client's name, and you revoke it there like any other. There is no separate list of connected apps to remember to check.
Tokens expire after 30 days, at which point the client repeats the flow.
If you are implementing a client
PKCE with code_challenge_method=S256 is required; plain is refused. Public clients only — token_endpoint_auth_method=none — since a client on somebody's laptop cannot keep a secret. Redirect URIs must be https, or http on a literal loopback address (127.0.0.1 or [::1]) for a native client; localhost is not accepted, because the name resolves through DNS and the addresses do not. Redirect URIs are matched exactly against what you registered, with the loopback port the only thing allowed to vary.
Send the resource parameter (RFC 8707) on both the authorization and the token request, and the server will check they agree. Authorization responses carry iss (RFC 9207), including error responses, and the server advertises that it does.
An authorization code is single-use and lives 60 seconds. Using one twice revokes the token the first use produced — a code travels over a redirect, so a replay means it leaked, and the safe reading is that somebody else has the token.
What the server exposes
- Tools — one per REST route, generated from a single registry. The full list with arguments, scope, and example call: MCP tool reference (JSON:
/mcp-tools.json). Each tool is dispatched through the REST handler it maps to, so validation, scope checks, and errors are identical to the API's. - Resources — every documentation page as
bugwatch://docs/<slug>(text/markdown), plus templates forbugwatch://{org}/{project}/issues/{shortId},…/fix-context, and…/events/{eventId}. - Prompts —
fix_issue,triage,release_check; see Agent workflows.
Tool results are compact text with dashboard deep links. Two tools deliberately return large JSON: get_fix_context (everything needed to fix an issue) and get_event (a full processed event, often 10–40 KB). Prefer the former.
Audit trail
Every mutating tool call writes an agent_actions row — tool, arguments (channel secrets reduced to their kind), token, user, outcome, duration. Issue-scoped mutations (resolve_issue, ignore_issue, unresolve_issue) also append to the issue's activity feed as mcp_action, so humans see "Agent ran resolve_issue via token ci-bot" next to the status change. Read it with list_agent_activity(org="acme") or in Settings → Agents → Activity.
Recommended first turn
whoami— confirm org and scopes.list_projects— pick the project slug.search_docsbefore guessing at any setup question.search_issues(status="unresolved")andget_fix_contextbefore proposing code changes.