Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ Bearer token、カスタムヘッダー、OAuth 2.1 認証情報をリモート
- §3.4–3.5 `authorization_pending` / `slow_down`(interval +=5 s)/ `expired_token` / `access_denied` ハンドリング
- DCR の `grant_types` に `urn:ietf:params:oauth:grant-type:device_code` を登録(RFC 7591 §2)
- [RFC 7591](https://www.rfc-editor.org/rfc/rfc7591) Dynamic Client Registration
- §3 クライアント登録リクエスト(公開クライアント、`token_endpoint_auth_method: none`)
- §3 クライアント登録リクエスト。AS メタデータの `token_endpoint_auth_methods_supported` から最適な認証方式を選択(`none` → `client_secret_post` → `client_secret_basic` の優先順
- §3.2.1 `client_secret_expires_at` に対応、期限切れ時に自動再登録
- [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749) OAuth 2.0
- §2.3.1 `client_secret_basic`:percent-encode した認証情報を `Authorization: Basic` ヘッダーで送信(コード交換・トークンリフレッシュ・Device Authorization Grant ポーリングに適用)
- [RFC 6750](https://www.rfc-editor.org/rfc/rfc6750) Bearer Token の利用
- §2.1 `Authorization: Bearer <token>` リクエストヘッダー
- **バックオフ付きリトライ** — 接続エラー時に最大3回リトライ
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ Bearer tokens, custom headers, and OAuth 2.1 credentials are forwarded to the re
- §3.4–3.5 token polling with `authorization_pending` / `slow_down` (interval +=5 s) / `expired_token` / `access_denied` handling
- DCR registers `urn:ietf:params:oauth:grant-type:device_code` in `grant_types` (RFC 7591 §2)
- [RFC 7591](https://www.rfc-editor.org/rfc/rfc7591) Dynamic Client Registration
- §3 client registration request (public client with `token_endpoint_auth_method: none`)
- §3 client registration request; `token_endpoint_auth_method` chosen from `token_endpoint_auth_methods_supported` in AS metadata (prefers `none` → `client_secret_post` → `client_secret_basic`)
- §3.2.1 `client_secret_expires_at` handling — auto re-register on expiry
- [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749) OAuth 2.0
- §2.3.1 `client_secret_basic`: `Authorization: Basic` header with percent-encoded credentials (applied to code exchange, token refresh, and Device Authorization Grant polling)
- [RFC 6750](https://www.rfc-editor.org/rfc/rfc6750) Bearer Token usage
- §2.1 `Authorization: Bearer <token>` request header
- **Retry with backoff** — retries up to 3 times on connection errors
Expand Down
2 changes: 2 additions & 0 deletions WORKAROUNDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ Works around known issues in Claude Code's HTTP transport:
- **Cannot connect to servers that only support static bearer tokens** — mcp-remote always initiates an OAuth discovery handshake before any tool call; servers that authenticate via static bearer tokens (e.g. [Zabbix MCP Server](https://github.com/initMAX/zabbix-mcp-server)) respond with 404 on `/.well-known/oauth-authorization-server` and the proxy gives up before the bearer-auth path is ever reached ([zabbix-mcp-server#36](https://github.com/initMAX/zabbix-mcp-server/issues/36)); mcp-stdio connects directly with `--bearer-token YOUR_TOKEN http://your-server:8080/mcp`, skipping OAuth entirely.
- **OAuth token exchange fails with URL-encoded responses** — TypeScript SDK's token exchange assumes the response is always JSON; servers that return `application/x-www-form-urlencoded` (e.g. GitHub OAuth) cause a JSON parse error, blocking authentication ([typescript-sdk#759](https://github.com/modelcontextprotocol/typescript-sdk/issues/759)); mcp-stdio's `_parse_token_response()` checks the `Content-Type` header and parses `application/x-www-form-urlencoded` via `urllib.parse.parse_qs`, so GitHub MCP and similar servers work without extra configuration.
- **No proactive token refresh window** — mcp-remote (and `adaptOAuthProvider` in TypeScript SDK) only refreshes the access token after a 401 has already fired, with no early-refresh leeway. ASes that issue refresh tokens whose lifetime is barely longer than the access token's leave no margin for clock skew, so a refresh attempt can race the token expiry and fail ([mcp-remote#252](https://github.com/geelen/mcp-remote/issues/252), [typescript-sdk#1954](https://github.com/modelcontextprotocol/typescript-sdk/issues/1954)). mcp-stdio's `ensure_token()` performs proactive refresh: a cached access token is treated as expired when its expiry is within `--oauth-refresh-leeway` seconds (default 60, configurable via flag or `MCP_OAUTH_REFRESH_LEEWAY`), so the refresh hits well before the AS revokes the token.
- **Session affinity cookies not forwarded across requests** — mcp-remote creates a new HTTP client per request, so load-balancer session cookies (e.g. `AWSALB`, `AWSALBCORS`) returned in a `Set-Cookie` response header are discarded; subsequent requests land on a different backend node, breaking server-side session state ([mcp-remote#168](https://github.com/geelen/mcp-remote/issues/168)). mcp-stdio reuses a single `httpx.Client` instance across all requests within a session; httpx automatically stores `Set-Cookie` values and re-sends them on subsequent requests to the same origin, so ALB and similar sticky-session cookies are forwarded transparently without any extra configuration.
- **No OAuth support in headless/SSH environments** — mcp-remote's OAuth flow requires opening a browser window, making it unusable in SSH sessions, CI/CD pipelines, or other browserless environments; there is no Device Authorization Grant support ([mcp-remote#228](https://github.com/geelen/mcp-remote/issues/228)). mcp-stdio supports RFC 8628 Device Authorization Grant via `--oauth-device`: it displays a short user code and verification URI on stderr so the user can authenticate from any browser, while the device polls the token endpoint in the background.
- **`resource` indicator gets a trailing slash appended** — TypeScript SDK normalises the resource URL via `new URL(...).href`, converting `https://api.example.com` to `https://api.example.com/`; Atlassian authv2 and similar servers reject this with `InvalidTargetError: Incorrect resource parameters` ([typescript-sdk#1968](https://github.com/modelcontextprotocol/typescript-sdk/issues/1968), [mcp-remote#261](https://github.com/geelen/mcp-remote/issues/261)); mcp-stdio passes `resource=server_url` verbatim in both code exchange and refresh requests — Python's URL handling does not add trailing slashes.
- **DCR hardcodes `token_endpoint_auth_method: none`, breaking confidential-client servers** — mcp-remote always registers with `token_endpoint_auth_method: none` and sends `client_id`/`client_secret` in the POST body; authorization servers that publish only `client_secret_basic` in `token_endpoint_auth_methods_supported` (e.g. Microsoft Entra ID v2, some enterprise OIDC providers) reject the resulting token request ([mcp-remote#184](https://github.com/geelen/mcp-remote/issues/184), [mcp-remote#217](https://github.com/geelen/mcp-remote/issues/217)); mcp-stdio reads `token_endpoint_auth_methods_supported` from RFC 8414 AS metadata, picks the best supported method (`none` → `client_secret_post` → `client_secret_basic`), registers with that method via DCR, and applies it consistently across code exchange, token refresh, and Device Authorization Grant polling — `client_secret_basic` sends credentials as `Authorization: Basic base64(percent_encode(client_id):percent_encode(client_secret))` per RFC 6749 §2.3.1.

## Windows

Expand Down
Loading
Loading