github / github/copilot-cli

Authorization header dropped on JSON-RPC tools/call after successful MCP initialize (Streamable HTTP + OAuth 2.1 / DCR)

オープン
#3,015 コメント 0 件 リアクション 1 件 担当者 0 名 GitHub で見る
area:authentication area:mcp
主要言語
Shell
スター
11.2k
フォーク
1.9k
平均マージ
14時間 16分
マージ済み PR(30日)
6

説明

### Describe the bug

## Summary

After a successful OAuth 2.1 + DCR flow against an MCP server using Streamable HTTP, Copilot CLI sends the `Authorization: Bearer …` header on `initialize` but **omits it on subsequent JSON-RPC requests** (`tools/list`, `tools/call`).
The server-side session is shown as "connected" in `/mcp`, but every tool invocation fails with 401.

## Environment

- `copilot --version` → **1.0.37** (latest at time of report)
- macOS (Darwin 25.4.0)
- MCP server: own implementation, Rust, Streamable HTTP via `rmcp` 1.4.0
- Auth: OAuth 2.1 + RFC 7591 (Dynamic Client Registration), public client (PKCE, `token_endpoint_auth_method=none`)
- AS metadata exposed at `/.well-known/oauth-authorization-server` (RFC 8414)
- Same server works correctly with Claude Desktop and Gemini CLI

**Expected**: Tool call succeeds (Bearer sent on the JSON-RPC `tools/call` HTTP request).

**Observed**: Tool call fails. Server logs show the JSON-RPC `tools/call` arrived with no `Authorization` header.

## Server-side evidence

```json
{
"level": "WARN",
"service": "backend",
"target": "rmcp::service",
"message": "response error",
"id": "4",
"error": "ErrorData { code: ErrorCode(-32600), message: \"UNAUTHORIZED: missing Authorization header\", data: None }"
}
```

JSON-RPC id `4` corresponds to a `tools/call` (ids 0–2 are the MCP handshake: `initialize`, `notifications/initialized`, `tools/list`).

The DCR registration of the Copilot CLI client succeeded:

| field | value |
|---|---|
| `client_name` | `GitHub Copilot CLI` |
| `client_type` | `public` |
| `grant_types` | `authorization_code, refresh_token` |
| `redirect_uris` | `http://127.0.0.1:/` |
| `dynamically_registered` | `true` |

So the OAuth flow itself completes — the bug is downstream, in the MCP transport layer not propagating the Bearer to subsequent JSON-RPC HTTP requests.

### Affected version

GitHub Copilot CLI 1.0.37.

### Steps to reproduce the behavior

1. Configure the MCP server in `~/.copilot/mcp-config.json` with `"type": "http"` pointing at a Streamable HTTP MCP that requires Bearer on every request.
2. Start Copilot CLI, `/mcp` lists the server as connected (browser opens, OAuth flow completes, refresh + access tokens stored).
3. Ask Copilot to invoke any tool exposed by the server.

### Expected behavior

Tool call succeeds (Bearer sent on the JSON-RPC `tools/call` HTTP request).

### Additional context

## Cross-client check

The exact same server, with the exact same DCR + OAuth config, works correctly with:

- **Claude Desktop** — Bearer sent on every JSON-RPC request
- **Gemini CLI MCP client** — Bearer sent on every JSON-RPC request

So the server is compliant with the [MCP Streamable HTTP spec (2025-03-26)](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http). The bug is specific to Copilot CLI's handling of the access token
after `initialize`.

## Likely cause

Per the MCP Streamable HTTP spec, **each JSON-RPC message is an independent HTTP POST** to `/mcp`. The `Authorization` header must be attached to **every** request, not just to `initialize` or to the SSE long-lived stream.

It looks like Copilot CLI's OAuthProvider/transport binding only attaches the Bearer at session establishment (or to the SSE stream open), not on subsequent POSTs that carry the JSON-RPC payloads.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

Reproduce the failure using the HTTP MCP entry in ~/.copilot/mcp-config.json and a server requiring Bearer authentication. Start by tracing the Streamable HTTP transport and OAuthProvider binding after initialize; done means Authorization is present on notifications/initialized, tools/list, and tools/call requests and the tool call succeeds.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
rust
領域
api, authentication
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。