ADR-0058: An MCP client acts for its person¶
Status: Accepted Date: 2026-10-12 Deciders: Alex Nodeland
Follows ADR-0056, and lattice RFC-0001's subject table.
Context¶
An application's authorize hook decides who an actor is. A person can connect an MCP client with their own token, and a client can connect with credentials of its own, such as a service principal's key. reflexr's ExternalAgentActor said only which client acted, so a hook couldn't tell a person's client from a client acting for no one, and artifactr's actor, which says whom a client acts for, had no twin in reflexr.
Decision¶
ExternalAgentActorgainson_behalf_of: UserActor | None, as artifactr's has: the person the client acts for, if it acts for one. An application's MCP resolver sets it when a person connects with their own token, and anauthorizehook checks such a client as that person.- Nothing else changes: the client is still the participant, so attribution and de-duplication are as before, and a client with credentials of its own leaves it unset.
Options considered¶
| Option | For | Against |
|---|---|---|
on_behalf_of on the actor (chosen) |
The same shape as artifactr's, so one application maps both libraries' actors alike | Every actor's JSON has one more field |
A naming convention for client_id |
No change to the model | A hook would parse ids, and a person's id could collide with a client's |
Consequences¶
- Easier: a person's MCP client is checked as them in both libraries.
- Harder: the protocol's schema changes, with a field that defaults to none.