feat(32.1-01): publish one MCP scope list and call context

- pact gains MemberTokenScopeCatalog, MCPAdvertisedScopes and MCPCall
- an empty MCP ScopesSupported resolves to the five fixed names including backend
- pier copies advertised scopes and sets MCPCall beside WithDispatch
This commit is contained in:
2026-10-28 14:32:31 +01:00
parent 2cea3127cc
commit 63d05e8acb
11 changed files with 322 additions and 27 deletions

View File

@@ -35,7 +35,9 @@ const tokenInvalid = "pier: the caller's token is no longer valid"
// callInfo is what a dispatched call copies from the outer MCP request: the
// client address, the Host, the forwarding, real-ip and language headers,
// plus the session the call belongs to, for the audit line.
// plus the session the call belongs to, for the audit line. stateless is
// set on the stateless path so the MCP call's session id stays empty
// instead of a synthesized SDK session id.
type callInfo struct {
remoteAddr string
host string
@@ -45,6 +47,7 @@ type callInfo struct {
realIP string
acceptLanguage string
session string
stateless bool
}
// callInfoFrom reads callInfo off an HTTP request.
@@ -205,6 +208,11 @@ func (d *dispatcher) run(ctx context.Context, id Identity, info callInfo, t *too
if credential == nil && t.guardName == BackendGuard {
credential = id.credential
}
sessionID := info.session
if sessionID == ephemeralSession {
sessionID = ""
}
callCtx = pact.WithMCPCall(callCtx, pact.MCPCall{Subject: *subject, SessionID: sessionID, Tool: t.name})
callCtx = bouncer.WithDispatch(callCtx, &bouncer.Dispatch{Guards: disp.Guards, Principal: principal, Credential: credential})
var req *http.Request