MCP Server

MCP Server

Tindra ships a built-in Model Context Protocol server. Connect any MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, and others) and query issues, transactions, monitors, logs, and releases, or make changes, without leaving the tool you're already in.

Connecting

Tindra exposes a remote MCP server over Streamable HTTP:

https://your-hostname.tindra.sh/mcp

For Tindra Managed that is https://yourname.tindra.sh/mcp. Self-hosted, it is POST /mcp on whatever host and port you bound.

Nothing to install. No local process. Authentication uses the same API tokens as everything else: create one in Settings > API Tokens and send it as a Bearer header.

Authorization: Bearer tindra_your_token_here

Tokens are project-scoped. Read queries return data for that project only. See API Tokens.

Claude Code

One command, using the built-in HTTP transport:

claude mcp add --transport http tindra https://your-hostname.tindra.sh/mcp \
  --header "Authorization: Bearer tindra_your_token_here"

Add --scope user to make it available in every project, or --scope project to write it to .mcp.json for your team. Verify with claude mcp list, which should report ✔ Connected. Project-scoped servers show ⏸ Pending approval until you approve them once inside claude.

Codex CLI

In ~/.codex/config.toml. bearer_token_env_var names the environment variable Codex reads the token from, so the token itself stays out of the config file:

[mcp_servers.tindra]
url = "https://your-hostname.tindra.sh/mcp"
bearer_token_env_var = "TINDRA_TOKEN"

Cursor

In .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

{
  "mcpServers": {
    "tindra": {
      "url": "https://your-hostname.tindra.sh/mcp",
      "headers": {
        "Authorization": "Bearer tindra_your_token_here"
      }
    }
  }
}

Cursor also resolves ${env:NAME} inside headers, so you can write "Bearer ${env:TINDRA_TOKEN}" and keep the token out of a committed mcp.json.

VS Code (GitHub Copilot)

In .vscode/mcp.json. Using an input keeps the token out of the committed file. VS Code prompts for it once and stores it in the secret store:

{
  "inputs": [
    {
      "id": "tindra-token",
      "type": "promptString",
      "description": "Tindra API token",
      "password": true
    }
  ],
  "servers": {
    "tindra": {
      "type": "http",
      "url": "https://your-hostname.tindra.sh/mcp",
      "headers": {
        "Authorization": "Bearer ${input:tindra-token}"
      }
    }
  }
}

Claude Desktop

Claude Desktop's custom connectors expect OAuth, so bearer tokens go through the mcp-remote bridge. Add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "tindra": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://your-hostname.tindra.sh/mcp",
        "--header",
        "Authorization:${TINDRA_AUTH}"
      ],
      "env": {
        "TINDRA_AUTH": "Bearer tindra_your_token_here"
      }
    }
  }
}

Two things matter here and are easy to get wrong:

  • The header must be passed with --header. mcp-remote does not read an environment variable on its own, it only expands ${...} inside the argument you give it. Setting the env var alone results in a 401.
  • The --header argument must contain no spaces at all, which is why the word Bearer lives in the environment variable rather than in the argument. Claude Desktop on Windows does not escape spaces correctly when spawning npx and would pass a mangled header.

Restart Claude Desktop and the Tindra tools appear.

Other MCP clients

Any client with remote MCP support works. Point it at https://your-hostname.tindra.sh/mcp, choose the http (Streamable HTTP) transport, and set the Authorization: Bearer header. Only clients with no remote transport at all need the mcp-remote bridge shown above.

Read vs write access

Most MCP tools are read-only and work with any valid token.

Three tools perform mutations: update_issue, bulk_update_issues, and create_alert_rule. These require a writable token. When creating a token, check Allow write access to enable mutations. Read-only tokens get a 403 from any write tool.

Available tools

Read tools

Tool What it returns
get_overview Health summary: open issue count, error rate, monitor states, recent alert activity
list_issues Issues with event counts, filterable by status, level, and search text
get_issue Issue detail plus the event payload (exception, stack trace, breadcrumbs, request, user, contexts). Pass offset to inspect older occurrences (0 = newest).
list_transactions Transaction summaries sorted by P95 latency
get_transaction Full span waterfall for a single transaction
list_span_summaries Aggregated span data (DB, cache, job spans) across all transactions
list_monitors Cron monitors with current state (ok, missed, error)
get_monitor Single monitor with check-in history
list_releases Releases with new and regressed issue counts
list_alerts Alert rules with channels and last-fired time
list_issue_events Recent occurrences (timestamps, environment, release). Use get_issue with offset for the full payload.
get_logs Structured log search, filterable by level, environment, and trace ID

Write tools

Write tools require a writable token.

Tool What it does
update_issue Change an issue's status (resolve, ignore, re-open) or assignee
bulk_update_issues Apply a status change to multiple issues at once
create_alert_rule Create a new alert rule with conditions and notification channel

get_issue

Required: id. Optional: offset (integer, newest first, default 0).

The event payload is source-map resolved and matches what the issue detail UI shows. N+1 issues also include perf_events.

create_alert_rule

Required: name, trigger, channel.

Argument Notes
trigger new_issue, regressed, new_or_regressed, event_count, log_count, cron_missed, cron_error, uptime_down, or uptime_recovered
channel webhook, slack, discord, teams, or email
threshold / window_mins Required for event_count and log_count. Log count windows max out at 60 minutes.
filter_level Required for log_count: fatal, error, or warning
filter_search Log body search. Required when log_count min level is warning.
project_id Required for log_count. Defaults to the token's project, or all projects for session auth.
cooldown_mins Minutes between repeated firings. Default 60.

See Alert Rules for the full constraints.

Verifying the connection

A plain curl tells you whether your token is accepted, before you debug the client:

curl -sS https://your-hostname.tindra.sh/mcp \
  -H "Authorization: Bearer tindra_your_token_here" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

You should get back a JSON-RPC result listing the tools. A 401 means the token is missing, wrong, or revoked.

Troubleshooting

The client tries to open a browser for login. It saw a WWW-Authenticate header on a 401 and started an OAuth flow. Tindra does not use OAuth for MCP. Your token never reached the server. Check that the header is actually configured.

405 Method Not Allowed. The client is configured for the older SSE transport and is opening a GET connection. Tindra speaks Streamable HTTP, which is POST only. Set the transport to http, not sse.

Tools are listed but every write call fails. The token is valid but read-only. Create a new token with Allow write access checked.

Self-hosted instances

The MCP server is built into the Tindra binary and enabled by default. No extra configuration is needed. The endpoint is available at POST /mcp on whatever port Tindra is listening on.