fix: atomic lock creation + validate JSON response shape

- Use dict.setdefault() for atomic per-server lock creation
- Add isinstance(body, dict) check before accessing token response fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ishaan Jaffer 2026-02-09 17:15:29 -08:00
parent 3a0b725276
commit e1cd2eabca

View file

@ -39,9 +39,7 @@ class MCPOAuth2TokenCache(InMemoryCache):
self._locks: Dict[str, asyncio.Lock] = {}
def _get_lock(self, server_id: str) -> asyncio.Lock:
if server_id not in self._locks:
self._locks[server_id] = asyncio.Lock()
return self._locks[server_id]
return self._locks.setdefault(server_id, asyncio.Lock())
async def async_get_token(self, server: "MCPServer") -> Optional[str]:
"""Return a valid access token, fetching or refreshing as needed.
@ -97,6 +95,12 @@ class MCPOAuth2TokenCache(InMemoryCache):
response.raise_for_status()
body = response.json()
if not isinstance(body, dict):
raise ValueError(
f"OAuth2 token response for MCP server '{server.server_id}' "
f"returned non-object JSON (got {type(body).__name__})"
)
access_token = body.get("access_token")
if not access_token:
raise ValueError(