Skip to content

Conversation

@WachsenHaus
Copy link

Bug Summary

Error: RuntimeError: The current task is not holding this lock

Location: src/mcp/client/auth/oauth2.py - OAuthClientProvider.async_auth_flow()

Impact: OAuth authentication fails when the browser opens for authorization

Root Cause

The async_auth_flow() method wraps all yield statements inside a single async with self.context.lock: block. When the async generator suspends at yield, the event loop may switch tasks, and anyio.Lock (which tracks task ownership) raises RuntimeError when the generator resumes or is garbage-collected in a different task context.

Solution

Release the lock before each yield and re-acquire it after the generator resumes:

  1. Acquire lock for state preparation
  2. Release lock before yield (generator suspension point)
  3. Re-acquire lock after yield resumes
  4. Handle response with lock held

All existing functionality is preserved:

  • Protected Resource Metadata discovery (SEP-985)
  • OAuth Authorization Server Metadata discovery with fallback
  • Scope selection strategy
  • CIMD (Client Information Metadata Document) support
  • Dynamic Client Registration fallback
  • 403 step-up authorization
  • Token refresh flow

Test Results

All existing tests pass (166 passed, 0 failed):

``````
$ pytest tests/client/ -x -q
166 passed, 3 skipped, 1 xfailed
``````

Reproduction

  1. Configure an MCP server with OAuth authentication
  2. Attempt to authorize (browser opens)
  3. Before fix: RuntimeError: The current task is not holding this lock
  4. After fix: Successfully authorized

async with self.context.lock: 블록이 모든 yield 문을 감싸고 있어 generator suspend/resume 시 RuntimeError 발생.
해결: 각 yield 지점 전후로 lock acquire/release.
기존 기능 유지, 테스트 통과 (166 passed).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant