Bridge a verified resource-server identity into the Anubis MCP frame.
AttestoMCP.Plug.Authenticate (or AttestoPhoenix.Plug.Authenticate)
verifies the access token and assigns a protocol-shaped context onto the
conn under :attesto_context. The Anubis HTTP transport copies
conn.assigns into frame.assigns, so that context is reachable as
frame.assigns[:attesto_context] inside the server.
Anubis's own authorization machinery - the tools/list visibility filter,
Frame.scopes/1, Frame.has_scope?/2, any per-tool scope gate - reads the
identity from frame.context.auth (an Anubis.Server.Context field), which
is nil until a host populates it. put_auth/1 performs that one
projection: frame.assigns[:attesto_context] -> frame.context.auth, in the
auth-claims map shape Anubis.Server.Context documents.
The projection is purely mechanical. It carries no application policy - no scope-superset/admin expansion, no role mapping, no tenant or audit logic, no "which tools are visible" rules. Those belong in the host app; this only surfaces the verified claims in the place Anubis reads them.
Host wiring
Call it once at the top of the server's handle_request/2 (or any callback
that needs the identity):
def handle_request(request, frame) do
frame = AttestoMCP.Anubis.put_auth(frame)
# ... Anubis authorization now sees the verified identity ...
endThe module is compile-guarded on Anubis.Server.Frame: a resource server
that does not depend on anubis_mcp never compiles it (mirroring how
attesto core gates its optional Plug surface on Plug.Conn).
Summary
Functions
Project the verified :attesto_context into frame.context.auth.
Functions
@spec put_auth(Anubis.Server.Frame.t()) :: Anubis.Server.Frame.t()
Project the verified :attesto_context into frame.context.auth.
Idempotent and non-destructive:
- if
frame.context.authis already set, the frame is returned unchanged (a host or an earlier call owns it); - if
frame.assigns[:attesto_context]is absent (unauthenticated request, STDIO transport, or the auth plug did not run), the frame is returned unchanged.
Otherwise frame.context.auth is set to the Anubis.Server.Context
auth-claims map projected from the context.