Skip to content

MCP OAuth "Sign in" fails with "MCP server probe returned HTTP 400" for stateful servers (Atlassian /v2/mcp) when a valid token is already stored #5014

Description

@nischalpanwalametrc

Summary

Since runtime 1.0.90-0 (GitHub Copilot desktop app 1.1.24, Windows 11), the Atlassian MCP server shows Sign in in the MCP panel, and clicking it fails with:

Authentication failed
atlassian: RPC error -32603: Request session.mcp.oauth.login failed with message: MCP request failed: MCP server probe returned HTTP 400 Bad Request

The server itself works: regular sessions connect (server/discover returned an unusable JSON response; retrying with legacy initialize → Service initialized ... atlassian-mcp-server) and Jira/Confluence tools run fine with the stored token.

Config

"atlassian": { "type": "http", "url": "https://mcp.atlassian.com/v2/mcp", "tools": ["*"] }

OAuth via dynamic client registration; a valid access + refresh token is stored in ~/.copilot/mcp-oauth-config/.

Root cause (reproduced by hand)

The OAuth probe (remote_probe.rs) sends a JSON-RPC ping without an Mcp-Session-Id. Atlassian's endpoint is a stateful Streamable HTTP server:

POST to https://mcp.atlassian.com/v2/mcp Response
ping, no token 401 + WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource/v2/mcp"
ping, valid token (MCP-Protocol-Version 2026-07-28, 2025-11-25, or omitted) 400 {"jsonrpc":"2.0","error":{"code":-32600,"message":"Request must be an initialize request if no session ID is provided."}}
initialize, valid token 200 + Mcp-Session-Id

So sign-in fails only when the user is already authenticated: the probe passes auth and then hits the server's session check, and the 400 is treated as fatal instead of "authenticated".

curl -i -X POST https://mcp.atlassian.com/v2/mcp \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" -H "MCP-Protocol-Version: 2026-07-28" \
  -d '{"jsonrpc":"2.0","id":1,"method":"ping","params":{}}'

Why "Sign in" is shown in the first place

The app's MCP status session (global scope) never re-attaches the stored token for this third-party server. Its first connect gets 401, the host logs MCP OAuth non-first-party server; cancelling host-token and kicking daemon-owned reconnect so the status badge can resolve, and the reconnect gets 401 again, so the status stays "needs auth". Regular sessions in the same app handle the same initial 401 internally and connect. On 1.0.87-0 the same kick was followed by MCP refresh generation bumped and a token refresh within seconds.

Expected

  • The probe treats a 400 with JSON-RPC -32600 "initialize required / no session ID" (or any non-401/403 reply to an authenticated request) as authenticated, or probes with initialize and then DELETEs the session, matching the connector's server/discover → legacy initialize fallback.
  • The MCP status session reuses stored third-party OAuth tokens the way regular sessions do, so the badge doesn't ask for a sign-in that isn't needed.

Steps to reproduce

  1. Configure the Atlassian server as above and sign in once, so tokens are stored.
  2. Restart the app and open the MCP servers panel. Atlassian shows "Sign in", although tools work in sessions.
  3. Click Sign in. The error above appears.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions