fix: unblock the MCP session, and authenticate to the AI gateway with OIDC
Two things, both discovered by instrumenting the failure rather than trusting the message it printed. The MCP session never failed on protocol. macOS resolves any `.local` name through mDNS first and takes a flat ~5.0s doing it, which sits exactly on httpx's 5s default connect timeout; fastmcp reported the resulting ConnectTimeout only as "Failed to initialize server session". Earlier tests used `curl --resolve`, which bypasses DNS entirely and made it look like DNS had been eliminated. Settings.http_timeout (60s) now covers the shared client, the client fastmcp builds, and MCPToolset's init_timeout. list-products, get-product and create-product now enumerate over the real gateway. Inference used a static "unused" api_key against a gateway whose openid-connect plugin requires audience ["llm-proxy"]. The model call now carries a token exchanged for llm-proxy-audience, so it is attributable to the same (agent, end user) pair as every tool call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,9 @@ issues #172/#194/#235, CrewAI's MCPServerAdapter) has the same answer.
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from pydantic_ai.mcp import MCPToolset, StreamableHttpTransport
|
||||
|
||||
from .config import Settings
|
||||
@@ -55,6 +57,15 @@ async def build_toolsets(
|
||||
injection that talks the agent into reaching the wrong domain fails at
|
||||
Kong rather than succeeding quietly.
|
||||
"""
|
||||
def client_factory(**kwargs: Any) -> httpx.AsyncClient:
|
||||
# fastmcp builds this client itself and would otherwise take httpx's
|
||||
# 5s default connect timeout. See Settings.http_timeout for why that is
|
||||
# not survivable against `.local` names, and what the failure looks like
|
||||
# when it bites: a bare "Failed to initialize server session".
|
||||
kwargs["verify"] = settings.verify
|
||||
kwargs["timeout"] = httpx.Timeout(settings.http_timeout, connect=settings.http_timeout)
|
||||
return httpx.AsyncClient(**kwargs)
|
||||
|
||||
toolsets: list[MCPToolset] = []
|
||||
for target in targets(settings):
|
||||
token = await exchanger.exchange(subject_token, target.audience_scope)
|
||||
@@ -64,8 +75,10 @@ async def build_toolsets(
|
||||
url=target.url,
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
verify=settings.verify,
|
||||
httpx_client_factory=client_factory,
|
||||
),
|
||||
id=target.name,
|
||||
init_timeout=settings.http_timeout,
|
||||
)
|
||||
)
|
||||
return toolsets
|
||||
|
||||
Reference in New Issue
Block a user