MCP: fix in-process tool calls and keep caller token in batch calls

- httpx.ASGITransport is async-only; the sync client made every
  tools/call fail with "'ASGITransport' object has no attribute
  '__enter__'". Run the in-process request on the API loop from the
  tool worker thread instead.
- http_json_many fanned out on a plain thread pool without the caller's
  context, so batch requests fell back to the server MCP token file.
  Copy the context per request so RBAC uses the caller's token.
- Real-TCP regression: tools/call getTopologyTree must reach the API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
oliver 2026-10-16 22:09:28 +08:00
parent 52679a7cfc
commit 92bfad3e34
3 changed files with 89 additions and 33 deletions

View file

@ -77,8 +77,13 @@ async def _on_call_tool(
try:
# Handlers are sync and may nest ASGI calls; run off the event loop thread
# so BaseHTTPMiddleware on the outer MCP request cannot deadlock.
import asyncio
import anyio
from .asgi_client import bind_main_loop
bind_main_loop(asyncio.get_running_loop())
result = await anyio.to_thread.run_sync(call_tool, name, dict(args))
except Exception as exc:
result = {