How to authenticate Sentry MCP on a headless server without a local browser?
The Sentry MCP server authenticates through an OAuth callback at http://localhost:5173/oauth/callback, which is impossible on headless servers, Docker containers, and remote VMs with no local browser. The request for OAuth Device Code Flow was closed without that flow shipping, so how can I authenticate Sentry MCP on a headless machine using Claude Code?
Originally asked on GitHub: https://github.com/getsentry/toolkit/issues/546
5 answers
The OAuth Device Code Flow request is closed as completed, but no Device Code Flow was shipped in this thread: the maintainers instead planned a web-based alternative (#648) limited to Sentry's cloud service, and a later maintainer comment notes that plan would require proxying API requests. Until that lands, the confirmed workaround is to authenticate on a machine with a browser and copy the credentials to the headless machine.
On the host machine, add the server and finish the OAuth flow:
bashclaude mcp add --transport http sentry https://mcp.sentry.dev/mcpThen extract the stored credentials (macOS keychain):
bashsecurity find-generic-password -s "Claude Code-credentials" -w | python3 -m json.toolCopy the
mcpOAuth→sentry|...block into~/.claude/.credentials.jsonon the headless machine and restart Claude Code. One commenter confirmed the same process works when authenticating on a Windows host and copying the file to headless Ubuntu.Two other facts from the thread: SSH port forwarding is unreliable here because the MCP OAuth flow picks the callback port randomly and changing it invalidates the URL, and a maintainer said a simple Bearer token is already usable today with the stdio distribution. A user also reported that regular Sentry public integration OAuth tokens mostly work with the local stdio server, except
read_organizationsreturnedNone; the maintainer replied it should return the organization unless tenant constraints suppress the tool.Copied OAuth credentials grant access to your Sentry data, so restrict access to the credentials file and don't log it.
Did this work for you?What @gndk tried on GitHub (Worked)
Authenticated on the host with
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp, extracted the credentials withsecurity find-generic-password -s "Claude Code-credentials" -w | python3 -m json.tool, copied themcpOAuth->sentry|...block into~/.claude/.credentials.jsonon the headless VM, and restarted Claude Code.Source: https://github.com/getsentry/toolkit/issues/546#issuecomment-3863643062 (opens external site)
Did this work for you?What @awojtas tried on GitHub (Worked)
Authenticated Sentry MCP on a Windows host with Claude Code, then copied the details from
~/.claude/.credentials.jsonto a headless Ubuntu machine.Source: https://github.com/getsentry/toolkit/issues/546#issuecomment-3881294691 (opens external site)
Did this work for you?What @gndk tried on GitHub (Didn't work)
SSH port forwarding to a local VM failed because the MCP OAuth flow picks the callback port randomly, and manually changing the port invalidates the URL.
Source: https://github.com/getsentry/toolkit/issues/546#issuecomment-3863643062 (opens external site)
Did this work for you?What @vrmiguel tried on GitHub (Partly worked)
Used regular Sentry public integration OAuth tokens with the local stdio MCP server; most functionality worked, but
read_organizationsreturnedNoneinstead of the expected organization. The maintainer said it should return the organization unless tenant constraints suppress the tool.Source: https://github.com/getsentry/toolkit/issues/546#issuecomment-3572244207 (opens external site)
Did this work for you?
Related questions
- GitHub MCP's list_issues overrides Sentry MCP's list_issues - how do I fix the collision?
- Claude Code Sentry MCP auth: Cloudflare 403 captcha instead of OAuth
- Does the remote Sentry MCP endpoint support a bearer access token instead of OAuth?
- How do I let AI agents add comments to Sentry issues via getsentry/toolkit MCP?
- Hosted Sentry MCP OAuth rejects Claude Code loopback callback with dynamic port: Invalid redirect URI