Add opaque MCP connection selection contracts - #44
Draft
dsfaccini wants to merge 1 commit into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
#41 asks for per-user authentication to HTTP MCP servers from the web UI. The broader feature should eventually cover OAuth and compatibility credentials without exposing raw MCP credentials, arbitrary headers, or server URLs to the chat request.
MCP
2026-07-28removes protocol sessions,initialize,Mcp-Session-Id, and the standalone GET stream. Authentication remains per request: a bearer token is sent on every protected HTTP request. See the release announcement, Streamable HTTP specification, and authorization specification.Pydantic AI cannot yet exercise that wire revision on
main. pydantic-ai#6738 is the FastMCP 4 / MCP SDK v2 compatibility work. pydantic-ai#7372 records the independent main-based transport contracts and strict dependency gates.What this PR implements
This PR establishes the safe browser-to-BFF selection contract that does not depend on FastMCP:
/api/configuremay advertise non-secret MCP connection summaries (idandname).mcpConnections.mcpHeadersnormcpAuth.All tests in this PR pass. There are no UI xfails because authenticated MCP execution is not blocked only by a dependency: it also requires a production BFF contract and application authentication. An xfail would prematurely encode an unsettled credential API.
Security boundary
The browser must eventually send an opaque connection ID, not a credential, token, endpoint, or arbitrary header map. The application BFF must authenticate the route, resolve the connection against the authenticated principal and tenant, keep credentials server-side, and construct outbound MCP authorization independently for every request. Pydantic AI's UI guidance makes the host route the authentication boundary and treats client-supplied state as untrusted. See the UI security model and message-history trust guidance.
The global ID set in
tests/server/server.pyis only a deterministic test fixture. It is not a production authorization design and must not be copied as one: membership in a process-wide set would not prevent one authenticated user selecting another user's connection. Production resolution must be principal-scoped and must reject that cross-user case.Arbitrary user-supplied MCP URLs additionally require SSRF/redirect/egress controls; the current MCP transport does not inherit Pydantic AI's safe download path. MCP documents the relevant client-side SSRF risks.
Follow-up sequence
Mcp-Session-Id.MRTR,
subscriptions/listen, private/public cache policy, OAuth storage, Basic/API-key/custom-header compatibility, and endpoint SSRF policy are deliberately deferred until their backend owners and public contracts exist.Verification
No dependency versions are changed in this PR.